OpenConnect server, also known as ocserv, is a VPN server that communicates over SSL. By design, its goal is to become a secure, lightweight, and fast VPN server. OpenConnect server uses the OpenConnect SSL VPN protocol. At the time of writing, it also has experimental compatibility with clients that use the AnyConnect SSL VPN protocol.
Why AnyConnect? Although the AnyConnect protocol is relatively easy to detect, it is widely used by many large corporations with significant economic impact. Therefore, it is currently safer and more reliable than PPTP, OpenVPN, and some other legacy VPN protocols.
2026 Update & Modern Recommendations
The manual compilation and SysVinit scripts detailed in this guide are primarily for legacy systems or custom builds. If you are setting up ocserv on a modern Debian/Ubuntu system today, it is strongly recommended to use standard package tools:
- Install via APT: Skip source compilation and install directly using
sudo apt update && sudo apt install ocserv.- Use Systemd: Service management is handled automatically via Systemd (
sudo systemctl enable --now ocserv).- Use Trusted Certificates (Let’s Encrypt): Instead of self-signed certificates (which trigger client security warnings), use Certbot to issue trusted certificates:
Then referencesudo apt install certbot sudo certbot certonly --standalone -d vpn.yourdomain.com/etc/letsencrypt/live/vpn.yourdomain.com/fullchain.pemandprivkey.peminocserv.conf.
Update On Jan 2018:
A Docker image has been created for fast deployment, so you can skip reading the lengthy content below if you prefer.
Here, we will mainly talk about how to set up ocserv on a Debian system.
1. Compile ocserv
The official website of ocserv is http://www.infradead.org/ocserv/ . Currently (as of 2015/09/30), the website is down for unknown reasons. However, a backup mirror is available at https://github.com/fanyueciyuan/ocserv-backup. The latest version in this archive is 0.10.8.
The required packages for compiling ocserv are pkg-config and libgnutls28-dev. Since ocserv has many additional features, it is better to install all dependencies at once to avoid re-compiling later:
apt-get install build-essential pkg-config libgnutls28-dev libwrap0-dev libpam0g-dev libseccomp-dev libreadline-dev libnl-route-3-dev liblz4-dev
Next, extract and configure:
tar xvJf ocserv-0.10.8.tar.xz
cd ocserv-0.10.8
./configure --prefix=/usr/local/ocserv --sysconfdir=/etc/ocserv/
To keep the system tidy, we install it into a dedicated directory. As a result, we need to create symbolic links (ln) for the binary and man pages:
sudo ln -s /usr/local/ocserv/share/man/man8/occtl.8 /usr/local/share/man/man8/occtl.8
sudo ln -s /usr/local/ocserv/share/man/man8/ocpasswd.8 /usr/local/share/man/man8/ocpasswd.8
sudo ln -s /usr/local/ocserv/share/man/man8/ocserv.8 /usr/local/share/man/man8/ocserv.8
sudo ln -s /usr/local/ocserv/sbin/ocserv /usr/local/bin/ocserv
sudo ln -s /usr/local/ocserv/bin/occtl /usr/local/bin/occtl
sudo ln -s /usr/local/ocserv/bin/ocpasswd /usr/local/bin/ocpasswd
Now compile and install:
make
sudo make install
2. Configure ocserv
Sample configuration files are located in the doc directory. Before configuring the server, we need to generate CA certificates and server certificates.
First, install gnutls-bin:
cd ~
apt-get install gnutls-bin
mkdir certificates
cd certificates
Create the CA template file ca.tmpl:
cn = "VPN CA"
organization = "Chillrain Node"
serial = 1
expiration_days = 3650
ca
signing_key
cert_signing_key
crl_signing_key
Generate the CA private key and CA certificate:
certtool --generate-privkey --outfile ca-key.pem
certtool --generate-self-signed --load-privkey ca-key.pem --template ca.tmpl --outfile ca-cert.pem
Next, create the server template file server.tmpl:
cn = "your domain name or ip"
organization = "Chillrain Node"
expiration_days = 3650
signing_key
encryption_key
tls_www_server
Generate the server private key and server certificate:
certtool --generate-privkey --outfile server-key.pem
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
Copy the certificates and the sample configuration file to /etc/ocserv:
mkdir /etc/ocserv
sudo cp server-cert.pem server-key.pem /etc/ocserv
cp ~/ocserv-0.10.8/doc/sample.config /etc/ocserv/ocserv.conf
Edit /etc/ocserv/ocserv.conf. Key settings to update:
# Default to plain password mode
auth = "plain[/etc/ocserv/ocpasswd]"
try-mtu-discovery = true
# Server certificate paths
server-cert = /etc/ocserv/server-cert.pem
server-key = /etc/ocserv/server-key.pem
# Ports: Using 1443 to avoid conflicts if standard HTTPS port 443 is used by a web server
tcp-port = 1443
udp-port = 1443
# Security best practice: Do not run as root
run-as-user = nobody
run-as-group = daemon
# Local IP subnet allocation
ipv4-network = 10.8.0.0
ipv4-netmask = 255.255.255.0
# DNS server
dns = 8.8.8.8
# Push route entries
route = 0.0.0.0/128.0.0.0
route = 128.0.0.0/128.0.0.0
cisco-client-compat = true
Note on Default Routing
Regarding default routes, the official documentation suggests commenting out all route pushes if you want all client traffic routed through the VPN. However, when using Cisco AnyConnect 3.0, doing so causes the client to remove all LAN and broadcast routes, making the VPN server itself unreachable.
Pushing the split default routes resolves this issue:
0.0.0.0/128.0.0.0=0.0.0.0/1(Covers128.0.0.0to255.255.255.255)128.0.0.0/128.0.0.0=128.0.0.0/1(Covers0.0.0.0to127.255.255.255)
3. Create User & Configure NAT Routing
Create a user account:
ocpasswd -c /etc/ocserv/ocpasswd username
Add iptables NAT rules for packet forwarding:
sudo iptables -t nat -A POSTROUTING -o eth0 -s 10.8.0.0/24 -j MASQUERADE
To automatically apply iptables rules on startup:
cat << EOF | sudo tee -a /etc/network/if-pre-up.d/iptables
iptables -t nat -A POSTROUTING -o eth0 -s 10.8.0.0/24 -j MASQUERADE
EOF
sudo chmod a+x /etc/network/if-pre-up.d/iptables
Enable IPv4 forwarding in /etc/sysctl.conf:
net.ipv4.ip_forward=1
Apply the sysctl settings:
sysctl -p /etc/sysctl.conf
4. System Init Script (SysVinit)
Create the startup script at /etc/init.d/ocserv:
#!/bin/sh
### BEGIN INIT INFO
# Provides: ocserv
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
### END INIT INFO
PATH=/bin:/usr/bin:/sbin:/usr/sbin
DAEMON=/usr/local/bin/ocserv
PIDFILE=/var/run/ocserv.pid
DAEMON_ARGS="-c /etc/ocserv/ocserv.conf"
case "$1" in
start)
if [ ! -r $PIDFILE ]; then
echo -n "Starting OpenConnect VPN Server Daemon: "
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
$DAEMON_ARGS > /dev/null
echo "ocserv."
else
echo -n "OpenConnect VPN Server is already running.\n\r"
exit 0
fi
;;
stop)
echo -n "Stopping OpenConnect VPN Server Daemon: "
start-stop-daemon --stop --quiet --pidfile $PIDFILE --exec $DAEMON
echo "ocserv."
rm -f $PIDFILE
;;
force-reload|restart)
echo "Restarting OpenConnect VPN Server: "
$0 stop
sleep 1
$0 start
;;
status)
if [ ! -r $PIDFILE ]; then
exit 3
fi
PID=$(cat $PIDFILE | sed 's/ //g')
EXE=/proc/$PID/exe
if [ -x "$EXE" ] && [ "$(ls -l "$EXE" | cut -d'>' -f2,2 | cut -d' ' -f2,2)" = "$DAEMON" ]; then
exit 0
elif [ -r $PIDFILE ]; then
exit 1
else
exit 3
fi
;;
*)
echo "Usage: /etc/init.d/ocserv {start|stop|restart|force-reload|status}"
exit 1
;;
esac
exit 0
Set executable permissions and configure boot startup:
sudo chmod a+x /etc/init.d/ocserv
sudo update-rc.d ocserv defaults
Start the ocserv service:
sudo /etc/init.d/ocserv start
5. Alternative: Client Certificate Authentication
If you prefer using client certificates for authentication instead of passwords, generate user certificates as follows:
certtool --generate-privkey --outfile user-key.pem
cat << EOF > user.tmpl
cn = "VPN"
unit = "VPN"
expiration_days = 365
signing_key
tls_www_client
EOF
certtool --generate-certificate --load-privkey user-key.pem --load-ca-certificate ca-cert.pem --load-ca-privkey ca-key.pem --template user.tmpl --outfile user-cert.pem
# Export to PKCS#12 (.p12) format for client import
openssl pkcs12 -export -inkey user-key.pem -in user-cert.pem -certfile ca-cert.pem -out user.p12 -password pass:
