OpenConnect (ocserv) server setup notes
Contents
ShadowSocks, V2Ray, SoftEther, and WireGuard all already had notes, so I put OpenConnect here as well.
What OpenConnect is
OpenConnect is an open-source compatible implementation of Cisco AnyConnect SSL VPN. It lets you use the same AnyConnect client that is commonly used in enterprise VPNs.
Compared with other protocols:
- SSL/TLS-based: it looks like HTTPS traffic, so it is harder to block
- DTLS support: high-speed UDP transport is available
- Enterprise-oriented: compatible with Cisco AnyConnect clients
It is often confused with IKEv2, but IKEv2 is IPsec-based and is easier for GFW-style filtering to detect. OpenConnect is SSL/TLS-based, so it is a different beast.
Server setup
These steps are for CentOS 7.
Install
sudo yum install -y ocserv
Prepare certificates
If you use Let’s Encrypt as recommended, place the issued certificates like this:
cd /etc/ocserv
sudo vi /etc/ocserv/server-cert.pem # contents of fullchain.pem
sudo vi /etc/ocserv/server-key.pem # contents of privkey.pem
Note: If you are targeting China, use a valid certificate. Self-signed certificates are easier to flag as suspicious TLS.
Edit the configuration
sudo vi /etc/ocserv/ocserv.conf
Main changes:
# Switch authentication from PAM to file-based auth
#auth = "pam[gid-min=1000]"
auth = "plain[/etc/ocserv/ocpasswd]"
# Connection limits
max-clients = 0
max-same-clients = 3
# Enable MTU discovery
#try-mtu-discovery = false
try-mtu-discovery = true
# Certificate paths
#server-cert = /etc/ssl/certs/ssl-cert-snakeoil.pem
#server-key = /etc/ssl/private/ssl-cert-snakeoil.key
server-cert = /etc/ocserv/server-cert.pem
server-key = /etc/ocserv/server-key.pem
# Routing (comment out all routes for full tunnel)
#route = 10.10.10.0/255.255.255.0
#route = 192.168.0.0/255.255.0.0
#route = fef4:db8:1000:1001::/64
#no-route = 192.168.5.0/255.255.255.0
# Cisco client compatibility
cisco-client-compat = true
# Client IP pool
ipv4-network = 192.168.10.0
ipv4-netmask = 255.255.224.0
# DNS
#dns = 192.168.1.2
dns = 1.1.1.1
dns = 8.8.8.8
dns = 8.8.4.4
Kernel parameters
sudo vi /etc/sysctl.conf
Enable the following:
net.ipv4.ip_forward=1
net.ipv4.conf.all.proxy_arp=1
Apply them:
sysctl -p
Firewall
On CentOS 7, I switched from firewalld to iptables.
# Disable firewalld
systemctl stop firewalld
systemctl mask firewalld
# Install and enable iptables
yum install -y iptables-services
systemctl start iptables.service
systemctl enable iptables.service
systemctl start ip6tables.service
systemctl enable ip6tables.service
Add rules:
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
sudo iptables -A INPUT -p udp --dport 443 -j ACCEPT
sudo iptables -t nat -A POSTROUTING -o eth0 -s 192.168.10.0/19 -j MASQUERADE
Note: Replace eth0 with your server’s actual network interface name.
Save the rules:
iptables-save > /etc/sysconfig/iptables
Or edit /etc/sysconfig/iptables directly:
sudo vi /etc/sysconfig/iptables
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -s 192.168.10.0/19 -o eth0 -j MASQUERADE
COMMIT
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
-A INPUT -p udp -m udp --dport 443 -j ACCEPT
COMMIT
Restart:
service iptables restart
Add a user
sudo ocpasswd -c /etc/ocserv/ocpasswd username
Enter the password twice.
Start the service
# Stop the socket unit if you are starting manually
sudo systemctl stop ocserv.socket
# Start manually
sudo ocserv -c /etc/ocserv/ocserv.conf
Or manage it with systemd:
sudo systemctl enable ocserv
sudo systemctl start ocserv
User management
Check status
sudo occtl show status
sudo occtl show users
User operations
# Lock
sudo ocpasswd -c /etc/ocserv/ocpasswd -l username
# Unlock
sudo ocpasswd -c /etc/ocserv/ocpasswd -u username
# Delete
sudo ocpasswd -c /etc/ocserv/ocpasswd -d username
Bulk user creation with expect
If you need to add many users, an expect script is handy.
yum install -y expect
Create ex.exp:
#!/usr/bin/expect
set Id [lindex $argv 0]
set pw [lindex $argv 1]
spawn ocpasswd -c /etc/ocserv/ocpasswd ${Id}
expect {
"Enter password:" {
send "${pw}\n"
}
}
expect {
"password:" {
send "${pw}\n"
}
}
interact
exit 0
Run it:
expect ex.exp username password
Self-signed certificate generation
This is for environments where Let’s Encrypt is not available. For China-facing access, a real certificate is strongly recommended.
cd /etc/ocserv
Create a CA template:
sudo vi ca.tmpl
cn = "VPN CA"
organization = "example.com"
serial = 1
expiration_days = 3650
ca
signing_key
cert_signing_key
crl_signing_key
Generate the CA certificate:
sudo certtool --generate-privkey --outfile ca-key.pem
sudo certtool --generate-self-signed --load-privkey ca-key.pem --template ca.tmpl --outfile ca-cert.pem
Create a server certificate template:
sudo vi server.tmpl
cn = "vpn.example.com"
organization = "example.com"
expiration_days = 3650
signing_key
encryption_key
tls_www_server
Generate the server certificate:
sudo certtool --generate-privkey --outfile server-key.pem
sudo certtool --generate-certificate --load-privkey server-key.pem --load-ca-certificate ca-cert.pem --load-ca-privkey ca-key.pem --template server.tmpl --outfile server-cert.pem
Client connection
Cisco AnyConnect
You can use the official Cisco AnyConnect client as-is.
- Windows / macOS / Linux: install Cisco AnyConnect
- iOS / Android: install “Cisco AnyConnect” from the App Store or Google Play
Enter the server’s domain name and authenticate with a username and password.
OpenConnect client
The open-source client also works.
# Ubuntu / Debian
sudo apt install openconnect
# Connect
sudo openconnect vpn.example.com
Recommended settings in 2025
Use Let’s Encrypt
Self-signed certificates are easier for GFW-style filtering to detect. A real certificate makes the server look like a normal HTTPS site.
Consider disabling DTLS
UDP traffic (DTLS) can be easier to detect. If you want to run TLS only, set the following in ocserv.conf:
udp-port = 0
ocserv version
The version in CentOS 7’s yum repositories may be old. If you need the latest release, build from source.
-> Continue with: IKEv2 (strongSwan) server setup notes
-> Summary: Comparison of VPN protocols for China-facing connectivity