Install OpenConnect VPN Server with Trusted Certificate from Let's Encrypt

OpenConnect VPN server, or ocserv, is an SSL VPN server compatible with Cisco AnyConnect. It can easily be installed in a cheap OpenVZ Virtual Private Server (VPS) with TUN capability. However, most online tutorials for installing OpenConnect VPN server rely on certtool to generate a self-signed certificate via OpenSSL. Afterwards, since the self-signed certificate is not trusted by operating systems, either the VPN client must be configured to skip certificate checking, or the self-signed certificate must be imported as a trusted certificate on the VPN client machine. Both practices are insecure. Bypassing certificate checking would allow an attacker to impose as the VPN server. Importing a trusted certificate does not seem wrong at first, but in case the private key is compromised, an attacker would be able to impose as any server to the client, including online shopping and bank websites, using a certificate signed by that private key. Remember that the self-signed certificate's private key is stored on the VPS filesystem, it is much less secure than Hardware Security Modules used at real CAs to store private keys, and therefore it is a bad idea to trust such certificates in client machines.

Let's Encrypt is a free, automated, and open Certificate Authority (CA). It allows anyone to obtain a domain-verified certificate within minutes, and without paying anything. Certificates from Let's Encrypt are trusted by most modern operating systems. They are ideal for securing an OpenConnect VPN server.

This article explains how to request a proper trusted certificate from Let's Encrypt for use with ocserv, how to install OpenConnect VPN Server and use the Let's Encrypt certificate, and how to configure Cisco AnyConnect client to connect to ocserv. These steps are verified with an OpenVZ Ubuntu 16.04 64bit VPS provided by SecureDragon. It is required to enable TUN devices for the VPS, typically through a button in SolusVM or other control panel provided by the hosting company.

Request Let's Encrypt Certificate for OpenConnect VPN Server

Before requesting a certificate from Let's Encrypt, you must have a Virtual Private Server with an IPv4 address, and have a domain name (could be subdomain) resolved to the server so that you are able to ping the server via the domain name.

After the requirements above are met, the first step is to install certbot, a program for requesting Let's Encrypt certificates. Executing the following commands as root installs certbot:

add-apt-repository ppa:certbot/certbot
apt-get update
apt-get install certbot

Then, we can proceed to request a certificate:

certbot certonly --standalone -d ocserv.ml

It is necessary to stop any process running on TCP port 80 or 443 when running the above command, including Apache, nginx, Python or NodeJS web servers, and ocserv if you have installed it already. See certbot site for more information on how to request a certificate without stopping your web server.

You will see the following message if the certificate is obtained successfully:

certificate obtained from Let's Encrypt

Install OpenConnect VPN Server with Let's Encrypt Certificate

To install ocserv, execute the following as root:

apt-get install ocserv

Then, edit /etc/ocserv/ocserv.conf:

auth = "plain[/etc/ocserv/ocpasswd]"
tcp-port = 443
udp-port = 443
run-as-user = nobody
run-as-group = daemon
socket-file = /var/run/ocserv-socket
server-cert = /etc/letsencrypt/live/ocserv.ml/fullchain.pem
server-key = /etc/letsencrypt/live/ocserv.ml/privkey.pem
max-clients = 8
max-same-clients = 0
try-mtu-discovery = true
device = vpns
ipv4-network = 192.168.91.0/28
dns = 8.8.8.8
cisco-client-compat = true

Options server-cert and server-key should point to the certificate paths shown in certbot output.

If you want to change ocserv's listening port number to avoid conflicts with websites running on port 443:

  1. In /etc/ocserv/ocserv.conf, set tcp-port and udp-port to the desired port number.
  2. In /lib/systemd/system/ocserv.socket, set ListenStream and ListenDatagram to the same port number.
  3. Run systemctl daemon-reload to inform systemd that the port number has been changed.

Next step is creating usernames and passwords with ocpasswd:

add ocserv user with ocpasswd

Finally, restart ocserv for the settings to take effect:

systemctl restart ocserv

Setup IP Routing for OpenConnect VPN Server

ocserv has been configured and is ready for connections, but if you try at this moment, Cisco AnyConnect clients can only communicate with the VPN server, but would not be able to reach the Internet. It is necessary to setup Network Address Translation (NAT) in order to gain Internet access:

iptables -t nat -A POSTROUTING -s 192.168.91.0/28 -j SNAT --to-source 198.51.100.8
apt-get install iptables-persistent

Substitute 198.51.100.8 with the public IPv4 address of your server. If apt-get install iptables-persistent has no effect, run dpkg-reconfigure iptables-persistent instead. Answer YES at the following dialog, so that the iptables settings will be re-applied automatically if the server reboots:

save iptables configuration

Connect to ocserv with Cisco AnyConnect Client

It is easy to connect to ocserv via Cisco AnyConnect client app.

add ocserv server

VPN connected

AnyConnect statistics

It works! There is no need to go into settings and permit untrusted servers, because the server has a trusted certificate from Let's Encrypt.