Set up OpenConnect server on Ubuntu

Set up OpenConnect server on Ubuntu

update ocserv, sample configurations

Got the following error while connecting to the previously configured OpenConnect server (ocserv).

GnuTLS error: A packet with illegal or unsupported version was received.

Probably because I’ve upgraded a few libraries. After upgrading ocserv to the latest version (0.12.5), this problem got solved. Here, put down a short note on ocserv settings in case I have to reinstall it again…

Install ocserv

At present, using apt install ocserv will just give you an earlier version, but it’s fine to use this version.

sudo apt update

sudo apt install build-essential pkg-config libghc-nettle-dev libghc-gnutls-dev libprotobuf-c-dev libev-dev

sudo apt install ocserv openconnect

You can also install the latest version from the source:

Download latest ocserv

Check the recent release at

tar -xf ocserv-0.12.5.tar.xz
cd ocserv-0.12.5

Compile & install ocserv

Make sure you have installed all the packages in any notice from configure. I passed the configure with the following installations1:

sudo apt update
sudo apt install build-essential pkg-config libghc-nettle-dev libghc-gnutls-dev libprotobuf-c-dev libev-dev
sudo make
sudo make install

ocserv --version

Obtain TLS certificate with Let’s Encrypt

Install Let’s Encrypt client

sudo apt install software-properties-common
sudo add-apt-repository ppa:certbot/certbot

sudo apt update
sudo apt install certbot

Obtain cert with Nginx

If your Ubuntu server already has a web server listening on port 80 and 443, and you want ocserv to use a different port, then it’s a good idea to use the webroot plugin to obtain a certificate because the webroot plugin works with pretty much every web server.2

Since I’m running Nginx, let’s go ahead to obtain a cert with it. First, we need to create a virtual host, for example.

sudo nano /etc/nginx/conf.d/

Paste the following lines into the file.

server {
    listen 80;

    root /var/www/;

    location ~ /.well-known/acme-challenge {
        allow all;

Save and close the file. Then create the web root directory.

sudo mkdir -p /var/www/

Set www-data (Nginx user) as the owner of the web root.

sudo chown www-data:www-data /var/www/ -R

Reload Nginx to make changes take effect.

sudo systemctl reload nginx

Then, run the following command to get a Let’s Encrypt certificate using webroot plugin.

sudo certbot certonly --webroot --agree-tos --email your-email-address \
-d -w /var/www/

Edit ocserv configuration file

sudo nano /etc/ocserv/ocserv.conf

In the configuration file, find and modify the following lines:

# use separate accounts instead of system accounts to login
auth = "plain[passwd=/etc/ocserv/ocpasswd]"

# change the port number
tcp-port = 443
udp-port = 443

# locate the Let's Encrypt server certificate and server key file
server-cert = /etc/letsencrypt/live/
server-key = /etc/letsencrypt/live/

# change clients limits
max-clients = 16
max-same-clients = 2

# enable MTU discovery
try-mtu-discovery = true

# set default domain
default-domain =

# config ipv4-network (optional)
ipv4-network =
ipv4-netmask =

# tunnel all DNS queries
tunnel-all-dns = true

# set DNS server
dns =
dns =
dns =

# comment out all the route
#route =
#route =
#route = fef4:db8:1000:1001::/64
#no-route =

Save and close the file, then restart ocserv.

# check the configuration
ocserv -c /etc/ocserv/ocserv.conf -f -d 1

sudo systemctl restart ocserv

Fix DTLS handshake failure

If you’re going to use ports other than 443, it’s better to disable the ocserv.socket.

sudo cp /lib/systemd/system/ocserv.service /etc/systemd/system/ocserv.service

sudo nano /etc/systemd/system/ocserv.service

Delete the following two lines:



Save and close the file, then reload systemd.

sudo systemctl daemon-reload

sudo systemctl stop ocserv.socket
sudo systemctl disable ocserv.socket

sudo systemctl restart ocserv.service

Create ocserv accout

sudo ocpasswd -c /etc/ocserv/ocpasswd username
# you'll prompt to set password

Enable IP forwarding

sudo nano /etc/sysctl.conf

# comment out the following line
net.ipv4.ip_forward = 1

Save and close the file, then apply the changes with following command to preserve the changes across system reboots.

sudo sysctl -p

Firewall for IP masquerading

ip addr
# find the name of the server's main network interface, something like ens3, eth0

sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

sudo iptables -t nat -L POSTROUTING

I’ve cleared the iptables, and manage the firewall through the service provider’s web interface. Read this post may help you manage your firewall through iptables (ip6tables).

You can preserve the iptables rules using a systemd service.

# switch to root user
iptables-save > /etc/iptables.rules

Then create a systemd service.

nano /etc/systemd/system/iptables-restore.service

Paste the following content.

Description=Restore iptables

ExecStart=/sbin/iptables-restore /etc/iptables.rules
ExecReload=/sbin/iptables-restore /etc/iptables.rules


Then, enable this service.

sudo systemctl daemon-reload
sudo systemctl enable iptables-restore

Remember that you have to save iptables rules to the file after making any changes.

And, if you’re also use IPV6, do the same processes again with ip6tables.

HAproxy settings (optional)

If you have configured ocserv to listen on ports other than 443 and you need to connect to ocserv with specify the port number, you can use HAproxy to help.

Install the latest HAproxy

Find the latest HAproxy stable release at: Currently, it’s 2.0.

sudo add-apt-repository ppa:vbernat/haproxy-2.0
sudo apt update

sudo apt install haproxy

Configure HAproxy

Before that, enable listen-proxy-proto in ocserv.

sudo nano /etc/ocserv/ocserv.conf

Find the change the following item.

# comment out udp port since it's bypassed by HAproxy

# udp-port = 443

listen-proxy-proto = true

Close and save the file, then go to set HAproxy.

sudo nano /etc/haproxy/haproxy.cfg

Setting SNI request as follows:

frontend env_ssl_frontend
	bind *:443
	mode tcp
	tcp-request inspect-delay 5s
	tcp-request content accept if { req_ssl_hello_type 1 }

	use_backend ocserv if { req_ssl_sni -i }

backend ocserv
	mode tcp
	option ssl-hello-chk
	server ocserv localhost:6666 send-proxy-v2

In the example, the port number is setting to 6666, change to your assigned port number in ocserv.conf.

Note that the send-proxy-v2 is required for ocserv.

Then restart programs.

sudo systemctl restart ocserv
sudo systemctl restart haproxy

Now, you can connect to your ocserv without specify the port number.

Ads by Google


Frank Lin

Hey, there! This is Frank Lin (@flinhong), one of the 1.41 billion . This 'inDev. Journal' site holds the exploration of my quirky thoughts and random adventures through life. Hope you enjoy reading and perusing my posts.


Setup an IKEv2 server with strongSwan



Setup an IKEv2 server with strongSwan

IKEv2, or Internet Key Exchange v2, is a protocol that allows for direct IPSec tunnelling between networks. It is developed by Microsoft and Cisco (primarily) for mobile users, and introduced as an updated version of IKEv1 in 2005. The IKEv2 MOBIKE (Mobility and Multihoming) protocol allows the client to main secure connection despite network switches, such as when leaving a WiFi area for a mobile data area. IKEv2 works on most platforms, and natively supported on some platforms (OS X 10.11+, iOS 9.1+, and Windows 10) with no additional applications necessary.