Are you looking to setup and install your own SSL / TLS VPN server which works from all over the world even with restrictive firewalls and countries then this is a good alternative for Wireguard which is easily blocked.
Tested on Debian 12. Use your own VPN subdomain or a dynamic DNS hostname and point to the IPv6 / IPv4 address of your VPN server.
Installation of OpenConnect (ocserv) VPN server.
Create a new bash file in /root/vpnsetup.sh nano /root/vpnsetup.sh and paste the content from below.
#!/bin/bash
# Text color
RD=$(echo "\033[01;31m")
YW=$(echo "\033[33m")
GN=$(echo "\033[1;92m")
CL=$(echo "\033[m")
BFR="\\r\\033[K"
HOLD="+"
CM="${GN}✓${CL}"
CROSS="${RD}✗${CL}"
msg_info() {
local msg="$1"
echo -e " ${HOLD} ${YW}${msg}${CL}"
}
msg_ok() {
local msg="$1"
echo -e "${BFR} ${CM} ${GN}${msg}${CL}"
}
msg_error() {
local msg="$1"
echo -e "${BFR} ${CROSS} ${RD}${msg}${CL}"
}
# chmod 755 setup.sh
# ./setup.sh
clear
echo "=========================================="
echo "========= VPN SERVER SETUP ============="
echo "=========================================="
echo -n "Start VPN server setup? [y/N]? "
read answer
if [ "$answer" != "${answer#[Yy]}" ] ;then
echo "Starting VPN server setup"
else
echo "Exiting VPN server setup"
exit
fi
sleep 1
echo -n "Install and setup Ocserv VPN Server [y/N]? "
read answer
if [ "$answer" != "${answer#[Yy]}" ] ;then
apt install ocserv
#echo "Ocserv server installed!"
msg_ok "Ocserv server installed!"
openssl ecparam -out /etc/ocserv/server-key.pem -name prime256v1 -genkey
openssl req -new -days 365 -nodes -x509 -subj "/C=US/ST=Local/L=Local/O=Local/CN=vpn.example.com" -key /etc/ocserv/server-key.pem -out /etc/ocserv/server-cert.pem
msg_ok "Self signed TLS certificate setup done!"
IPv6Subnet=$(printf "2001:db8:%s"; openssl rand -hex 4 | sed 's/\(....\)/\1:/g; s/.$//');
IPv6Subnet+="::/64"
sed -i -e "s?#server-cert = /etc/ocserv/server-cert.pem?server-cert = /etc/ocserv/server-cert.pem?g" /etc/ocserv/ocserv.conf
sed -i -e "s?#server-key = /etc/ocserv/server-key.pem?server-key = /etc/ocserv/server-key.pem?g" /etc/ocserv/ocserv.conf
sed -i -e "s?keepalive = 32400?keepalive = 300?g" /etc/ocserv/ocserv.conf
sed -i -e "s?try-mtu-discovery = false?try-mtu-discovery = true?g" /etc/ocserv/ocserv.conf
sed -i -e "s?idle-timeout = 1200?#idle-timeout = 1200?g" /etc/ocserv/ocserv.conf
sed -i -e "s?mobile-idle-timeout = 2400?#mobile-idle-timeout = 2400?g" /etc/ocserv/ocserv.conf
sed -i -e "s?tls-priorities = \"NORMAL:%SERVER_PRECEDENCE:%COMPAT:-VERS-SSL3.0:-VERS-TLS1.0:-VERS-TLS1.1:-VERS-TLS1.3\"?#tls-priorities = \"NORMAL:%SERVER_PRECEDENCE:%COMPAT:-VERS-SSL3.0:-VERS-TLS1.0:-VERS-TLS1.1:-VERS-TLS1.3\"?g" /etc/ocserv/ocserv.conf
sed -i -e "s?#tls-priorities = \"NORMAL:%SERVER_PRECEDENCE:%COMPAT:-RSA:-VERS-SSL3.0:-ARCFOUR-128\"?tls-priorities = \"NORMAL:%SERVER_PRECEDENCE:%COMPAT:-VERS-ALL:+VERS-TLS1.3\"?g" /etc/ocserv/ocserv.conf
sed -i -e "s?ipv4-network = 192.168.1.0?ipv4-network = 10.37.54.0?g" /etc/ocserv/ocserv.conf
sed -i -e "s?#ipv6-network = fda9:4efe:7e3b:03ea::/48?ipv6-network = $IPv6Subnet?g" /etc/ocserv/ocserv.conf
sed -i -e "s?#ipv6-subnet-prefix = 128?ipv6-subnet-prefix = 128?g" /etc/ocserv/ocserv.conf
sed -i -e "s?#tunnel-all-dns = true?tunnel-all-dns = true?g" /etc/ocserv/ocserv.conf
sed -i -e "s?# dns = fc00::4be0?dns = 2606:4700:4700::1111?g" /etc/ocserv/ocserv.conf
sed -i -e "s?dns = 192.168.1.1?dns = 1.1.1.1?g" /etc/ocserv/ocserv.conf
sed -i -e "s?#route = default?route = default?g" /etc/ocserv/ocserv.conf
sed -i -e "s?route = 10.0.0.0/8?#route = 10.0.0.0/8?g" /etc/ocserv/ocserv.conf
sed -i -e "s?route = 172.16.0.0/12?#route = 172.16.0.0/12?g" /etc/ocserv/ocserv.conf
sed -i -e "s?route = 192.168.0.0/16?#route = 192.168.0.0/16?g" /etc/ocserv/ocserv.conf
sed -i -e "s?cisco-client-compat = true?cisco-client-compat = false?g" /etc/ocserv/ocserv.conf
sed -i -e "s?dtls-legacy = true?dtls-legacy = false?g" /etc/ocserv/ocserv.conf
systemctl restart ocserv
msg_ok "Ocserv config done!"
iname=$(ip route | grep default | sed -e "s/^.*dev.//" -e "s/.proto.*//" | sed 's/ //g')
echo "Configuring Nftables..."
tee > /etc/nftables.conf <<EOF
#!/usr/sbin/nft -f
flush ruleset
# ----- IPv4 -----
table ip filter {
chain input {
type filter hook input priority 0;
# accept traffic originated from us
ct state {established, related} accept
# loopback
iifname lo accept
# accept all icmp
meta l4proto icmp accept
meta l4proto igmp accept
# allow incoming broadcast and multicast (e.g. NTP)
pkttype { broadcast,multicast} accept
tcp dport { 22, 443 } accept
udp dport { 443, 68 } accept
meta l4proto udp reject
meta l4proto tcp reject
reject
}
chain forward {
type filter hook forward priority 0;
iifname "$iname" oifname "vpns*" accept;
iifname "vpns*" oifname "$iname" accept;
}
chain output {
type filter hook output priority 0;
}
}
# ----- IPv6 -----
table ip6 filter {
chain input {
type filter hook input priority 0;
# accept traffic originated from us
ct state {established, related} accept
# loopback
iifname lo accept
# accept all icmp
meta l4proto ipv6-icmp accept
ip6 ecn not-ect accept
tcp dport { 22, 443 } accept
udp dport { 443, 546 } accept
meta l4proto udp reject
meta l4proto tcp reject
reject
}
chain forward {
type filter hook forward priority 0;
iifname "$iname" oifname "vpns*" accept;
iifname "vpns*" oifname "$iname" accept;
}
chain output {
type filter hook output priority 0;
}
}
# ----- IPv4 NAT -----
table ip nat {
chain PREROUTING {
type nat hook prerouting priority filter; policy accept;
}
chain POSTROUTING {
type nat hook postrouting priority srcnat; policy accept;
oifname "$iname" masquerade
}
}
# ----- IPv6 NAT -----
table ip6 nat {
chain PREROUTING {
type nat hook prerouting priority filter; policy accept;
}
chain POSTROUTING {
type nat hook postrouting priority srcnat; policy accept;
oifname "$iname" masquerade
}
}
EOF
systemctl enable nftables
systemctl start nftables
# Enable forwarding
sed -i -e "s?#net.ipv4.ip_forward=1?net.ipv4.ip_forward=1?g" /etc/sysctl.conf
sed -i -e "s?#net.ipv6.conf.all.forwarding=1?net.ipv6.conf.all.forwarding=1?g" /etc/sysctl.conf
echo "net.ipv6.conf.$iname.accept_ra=2" >> /etc/sysctl.conf
sysctl -p
#echo "Ocserv setup done!"
msg_ok "Ocserv setup done!"
else
msg_info "Skipped"
fi
#sleep 1
echo -n "Add VPN user [y/N]? "
read answer
if [ "$answer" != "${answer#[Yy]}" ] ;then
echo -n "Enter Username: "
read username
ocpasswd -c /etc/ocserv/passwd $username
#echo "New user added!"
msg_ok "New user added!"
answer=yes
while [ "$answer" = yes ]
do
echo -n "Add another user? [y/N]? "
read answer
if [ "$answer" != "${answer#[Yy]}" ] ;then
echo -n "Enter Username: "
read username
ocpasswd -c /etc/ocserv/passwd $username
#echo "New user added!"
msg_ok "New user added!"
sleep 1
answer=yes
fi
done
else
msg_info "Skipped"
fi
#sleep 1
echo -n "Delete VPN user [y/N]? "
read answer
if [ "$answer" != "${answer#[Yy]}" ] ;then
echo -n "Enter Username: "
read username
ocpasswd -c /etc/ocserv/passwd -d $username
echo "$username user deleted!"
else
msg_info "Skipped"
fi
#sleep 1
clear
echo "=========================================="
echo "======== VPN SERVER SETUP DONE =========="
echo "=========================================="
Give execution permission to the bash script chmod +x /root/vpnsetup.sh
Start the installation by running the command bash /root/vpnsetup.sh
To add or remove more users run the setup file again just skip installing the server again. The script above generates a self signed certificate and when you connect to your VPN server you will see warning before you connect to it which you can ignore if you are OK with it. If you want a valid certificate then read below.
LetsEncrypt certificates
It is highly recommended to use a valid SSL/TLS certificate to secure your server, for example LetsEncrypt Change the paths for certificate to LetsEncrypt.
Install acme.sh
curl https://raw.githubusercontent.com/acmesh-official/acme.sh/master/acme.sh | sh -s -- --install-online -m email@example.com --home ~/acme.sh
mkdir -p /etc/LetsEncrypt/vpn
acme.sh --issue --dns dns_acmedns -d 'vpn.example.com' --cert-file /etc/LetsEncrypt/vpn/cert.pem --key-file /etc/LetsEncrypt/vpn/key.pem --fullchain-file /etc/LetsEncrypt/vpn/fullchain.pem --reloadcmd "systemctl reload ocserv" --preferred-chain "ISRG Root X2" --keylength ec-256 --syslog 6
Now edit the paths for the correct LetsEncrypt certificates in the config file /etc/ocserv/ocserv.conf
server-cert = /etc/LetsEncrypt/vpn/fullchain.pem
server-key = /etc/LetsEncrypt/vpn/key.pem
OpenConnect Clients
Android: link
Linux: link
Windows: link
iOS: link
Let me know if you have any comments or if there is any error in this guide.