Set up OpenConnect VPN Server (ocserv) on Ubuntu 16.04/18.04 with Let’s Encrypt

This tutorial is going to show you how to install OpenConnect VPN server on Ubuntu 16.04/18.04. OpenConnect VPN server, aka ocserv, is an open-source implementation of Cisco AnyConnnect VPN protocol, which is popular among businesses and universities. AnyConnect is a SSL-based VPN protocol that allows individual users to connect to a remote network.

Features of OpenConnect VPN server:

  • Lightweight and fast. In my test, I can watch YouTube in 4k with OpenConnect VPN. YouTube is blocked in my country.
  • Compatible with Cisco AnyConnect client
  • Supports password authentication and certificate authentication
  • Easy to set up

I particularly like that fact that compared to other VPN technologies, it is very easy and convenient for the end-user to use OpenConnect VPN. Whenever I install a Debian-based Linux distro on my computer and want to quickly unblock websites or hide my IP address, I install OpenConnect client and connect to the server with just two lines of commands:

sudo apt install openconnect

sudo openconnect -b vpn.mydomain.com

The gnutls-bin software package provides tools to create your own CA and server certificate, but we will obtain and install Let’s Encrypt certificate. The advantage of using Let’s Encrypt certificate is that it’s free, easier to set up and trusted by VPN client software.

Prerequisites

To follow this tutorial, you will need a VPS (Virtual Private Server) that can access blocked websites freely (Outside of your country or Internet filtering system). I recommend Vultr VPS (This is my referral link. You can get $50 free credit by creating an account at Vultr via my referral link). They offer 512M memory high performance KVM VPS for just $2.5 per month, which is perfect for your private VPN server. Once you have a VPS, install Ubuntu 16.04 or Ubuntu 18.04 on it and follow the instructions below.

You also need a domain name. I registered my domain name from NameCheap because the price is low and they give whois privacy protection free for life.

Update: The new Vultr $2.5/month plan includes IPv6 address only. You can select the $3.5/month plan at the New York (NJ) data center to have both IPv4 and IPv6 address.

Installing OpenConnect VPN Server on Ubuntu 16.04/18.04

Log into your Ubuntu 16.04/18.04 server. Then use apt to install the ocserv package,which is included in Ubuntu repository since 16.04.

sudo apt install ocserv

Once installed, the OpenConnect VPN server is automatically started. You can check its status with:

systemctl status ocserv

Sample output:

 ocserv.service - OpenConnect SSL VPN server
   Loaded: loaded (/lib/systemd/system/ocserv.service; enabled; vendor preset: enabled
   Active: active (running) since Thu 2017-11-30 05:45:07 UTC; 11s ago
     Docs: man:ocserv(8)
 Main PID: 19235 (ocserv-main)
   CGroup: /system.slice/ocserv.service
           ├─19235 ocserv-main                                                  
           └─19242 ocserv-secm 

If it’s not running, then you can start it with:

sudo systemctl start ocserv

By default OpenConnect VPN server listens on TCP and UDP port 443. If it’s being used by web server, then the VPN server can’t be started. We will see how to change the port in OpenConnect VPN configuration file later.

Installing Let’s Encrypt Client (Certbot) on Ubuntu 16.04/18.04 Server

Run the following commands to install the latest version of certbot from the official PPA. software-properties-common is required if you want to install packages from PPA. It may be missing on your Ubuntu server.

sudo apt install software-properties-common

sudo add-apt-repository ppa:certbot/certbot

sudo apt update

sudo apt install certbot

To check version number, run

certbot --version

Sample output:

certbot 0.31.0

Obtaining a TLS Certificate from Let’s Encrypt

Standalone Plugin

If there’s no web server running on your Ubuntu 16.04/18.04 server and you want OpenConnect VPN server to use port 443, then you can use the standalone plugin to obtain TLS certificate from Let’s Encrypt. Run the following command. Don’t forget to set A record for your domain name.

sudo certbot certonly --standalone --preferred-challenges http --agree-tos --email your-email-address -d vpn.example.com

Explanation:

  • certonly: Obtain a certificate but don’t install it.
  • --standalone: Use the standalone plugin to obtain a certificate
  • --preferred-challenges http: Perform http-01 challenge to validate our domain, which will use port 80. By default the standalone plugin will perform tls-sni challenge, which uses port 443. Since port 443 is already used by OpenConnect VPN server, we need to change the default behavior.
  • --agree-tos: Agree to Let’s Encrypt terms of service.
  • --email: Email address is used for account registration and recovery.
  • -d: Specify your domain name.

As you can see the from the following screenshot, I successfully obtained the certificate.

install openconnect ubuntu server

Using webroot Plugin

If your Ubuntu 16.04/18.04 server has a web server listening on port 80 and 443, and you want OpenConnect VPN server 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 and we don’t need to install the certificate in the web server.

First, you need to create a virtual host for vpn.example.com.

Apache

If you are using Apache, then

sudo nano /etc/apache2/sites-available/vpn.example.com.conf

And paste the following lines into the file.

<VirtualHost *:80>        
        ServerName vpn.example.com

        DocumentRoot /var/www/vpn.example.com
</VirtualHost>

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

sudo mkdir /var/www/vpn.example.com

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

sudo chown www-data:www-data /var/www/vpn.example.com -R

Enable this virtual host.

sudo a2ensite vpn.example.com

Reload Apache for the changes to take effect.

sudo systemctl reload apache2

Once virtual host is created and enabled, run the following command to obtain Let’s Encrypt certificate using webroot plugin.

sudo certbot certonly --webroot --agree-tos --email your-email-address -d vpn.example.com -w /var/www/vpn.example.com

Nginx

If you are using Nginx, then

sudo nano /etc/nginx/conf.d/vpn.example.com.conf

Paste the following lines into the file.

server {
      listen 80;
      server_name vpn.example.com;

      root /var/www/vpn.example.com/;

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

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

sudo mkdir /var/www/vpn.example.com

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

sudo chown www-data:www-data /var/www/vpn.example.com -R

Reload Nginx for the changes to take effect.

sudo systemctl reload nginx

Once virtual host is created and enabled, run the following command to obtain Let’s Encrypt certificate using webroot plugin.

sudo certbot certonly --webroot --agree-tos --email your-email-address -d vpn.example.com -w /var/www/vpn.example.com

Editing OpenConnect VPN Server Configuration File

Edit ocserv configuration file.

sudo nano /etc/ocserv/ocserv.conf

First, configure password authentication. By default, password authentication through PAM (Pluggable Authentication Modules) is enabled, which allows you to use Ubuntu system accounts to login from VPN clients. This behavior can be disabled by commenting out the following line.

auth = "pam[gid-min=1000]"

If we want users to use separate VPN accounts instead of system accounts to login, we need to add the following line to enable password authentication with a password file.

auth = "plain[passwd=/etc/ocserv/ocpasswd]"

After finishing editing this config file, we will see how to use ocpasswd tool to generate the /etc/ocserv/ocpasswd file, which contains a list of usernames and encoded passwords.

Note: Ocserv supports client certificate authentication, but Let’s Encrypt does not issue client certificate. You need to set up your own CA to issue client certificate.

Next, if you don’t want ocserv to use TCP and UDP port 443, then find the following two lines and change the port number. Otherwise leave them alone.

tcp-port = 443
udp-port = 443

Then find the following two lines. We need to change them.

server-cert = /etc/ssl/certs/ssl-cert-snakeoil.pem
server-key = /etc/ssl/private/ssl-cert-snakeoil.key

Replace the default setting with the path of Let’s Encrypt server certificate and server key file.

server-cert = /etc/letsencrypt/live/vpn.example.com/fullchain.pem
server-key = /etc/letsencrypt/live/vpn.example.com/privkey.pem

Then, set the maximal number of clients. Default is 16. Set to zero for unlimited.

max-clients = 16

Set the number of devices a user is able to login from at the same time. Default is 2. Set to zero for unlimited.

max-same-clients = 2

Next, find the following line. Change false to true to enable MTU discovery, which can optimize VPN performance.

try-mtu-discovery = false

After that, set the default domain to vpn.example.com.

default-domain = vpn.example.com

The IPv4 network configuration is as follows by default. This will cause problems because most home routers also set the IPv4 network range to 192.168.1.0/24.

ipv4-network = 192.168.1.0
ipv4-netmask = 255.255.255.0

We can use another private IP address range (10.10.10.0/24) to avoid IP address collision, so change the value of ipv4-network to

ipv4-network = 10.10.10.0

Now uncomment the following line to tunnel all DNS queries via the VPN.

tunnel-all-dns = true

Change DNS resolver address. You can use Google’s public DNS server.

dns = 8.8.8.8

Note: It’s a good practice to run your own DNS resolver on the same server, especially if you are a VPN provider. If there’s a DNS resolver running on the same server, then specify the DNS as

dns = 10.10.10.1

10.10.10.1 is the IP address of OpenConnect VPN server in the VPN LAN. This will speed up DNS lookups a little bit for clients because the network latency between the VPN server and the DNS resolver is eliminated.

Then comment out all the route parameters (add # symbol at the beginning of the following four lines), which will set the server as the default gateway for the clients.

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

Save and close the file  Then restart the VPN server for the changes to take effect.

sudo systemctl restart ocserv

Fixing DTLS Handshake Failure

On Ubuntu 16.04 and Ubuntu 18.04, ocserv daemon ocserv.socket does not respect “listen-host” value from configuration file, which will cause the following error when clients connect to VPN server.

DTLS handshake failed: Resource temporarily unavailable, try again.

To fix this error, we need to edit the ocserv.service file. We first copy the original file in /lib/systemd/system/ directory to /etc/systemd/system/ directory, then edit it, because we don’t want new version of ocserv package to override our modifications. (To learn more about systemd unit files, run man systemd.unit.)

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

Comment out the following two lines.

Requires=ocserv.socket

Also=ocserv.socket

Save and close the file. Then reload systemd

sudo systemctl daemon-reload

Stop ocserv.socket and disable it.

sudo systemctl stop ocserv.socket

sudo systemctl disable ocserv.socket

Restart ocserv service.

sudo systemctl restart ocserv.service

The ocserv systemd service won’t output any message if it fails to restart, so we need to check the status to make sure it’s actually running.

systemctl status ocserv

Creating VPN Accounts

Now use the ocpasswd tool to generate VPN accounts.

sudo ocpasswd -c /etc/ocserv/ocpasswd username

You will be asked to set a password for the user and the information will be saved to /etc/ocserv/ocpasswd file. To reset password, simply run the above command again.

Enable IP Forwarding

In order for the VPN server to route packets between VPN client and the outside world, we need to enable IP forwarding. Edit sysctl.conf file.

sudo nano /etc/sysctl.conf

Add the following line at the end of this file.

net.ipv4.ip_forward = 1

Save and close the file. Then apply the changes with the below command. The -p option will load sysctl settings from /etc/sysctl.conf file. This command will preserve our changes across system reboots.

sudo sysctl -p

Configure Firewall for IP Masquerading

We need to set up IP masquerading in the server firewall, so that the server becomes a virtual router for VPN clients. I will use UFW, which is a front end to the iptables firewall. Install UFW on Ubuntu with:

sudo apt install ufw

First, you need to allow SSH traffic.

sudo ufw allow 22/tcp

Then edit /etc/default/ufw file.

sudo nano /etc/default/ufw

Change the default forward policy from “DROP” to “ACCEPT”.

DEFAULT_FORWARD_POLICY="ACCEPT"

Save and close the file. Next, find the name of your server’s main network interface.

ip addr

As you can see, it’s named ens3 on my Ubuntu server.

openconnect ubuntu command line

To configure IP masquerading, we have to add iptables command in a UFW configuration file.

sudo nano /etc/ufw/before.rules

By default, there are some rules for the filter table. Add the following lines at the end of this file. Replace ens3 with your own network interface name.

# NAT table rules
*nat
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -o ens3 -j MASQUERADE

# End each table with the 'COMMIT' line or these rules won't be processed
COMMIT

In Nano text editor, you can go to the end of the file by pressing Ctrl+W, then pressing Ctrl+V.

The above lines will append (-A) a rule to the end of of POSTROUTING chain of nat table. It will link your virtual private network with the Internet. And also hide your network from the outside world. So the Internet can only see your VPN server’s IP, but can’t see your VPN client’s IP, just like your home router hides your private home network.

Save and close the file. Then enable UFW.

sudo ufw enable

If you have enabled UFW before, then you can use systemctl to restart UFW.

sudo systemctl restart ufw

Now if you list the rules in the POSTROUTING chain of the NAT table by using the following command:

sudo iptables -t nat -L POSTROUTING

You can see the Masquerade rule.

ocserv iptables masquerading

Open Port 443 in Firewall

Run the following command to open TCP and UDP port 443. If you configured a different port for ocserv, then change 443 to your configured port.

sudo ufw allow 443/tcp
sudo ufw allow 443/udp

Now OpenConnect VPN server is ready to accept client connections.

How to Install and Use OpenConnect VPN client on Ubuntu 16.04/18.04 Desktop

Run the following command to install OpenConnect VPN command line client on Ubuntu desktop.

sudo apt install openconnect

You can Connect to VPN from the command line like below. -b flag will make it run in the background after connection is established.

sudo openconnect -b vpn.example.com:port-number

You will be asked to enter VPN username and password. If connection is successfully established, you will see the following message.

Got CONNECT response: HTTP/1.1 200 CONNECTED
CSTP connected. DPD 90, Keepalive 32400
Connected tun0 as 192.168.1.139, using SSL
Established DTLS connection (using GnuTLS). Ciphersuite (DTLS1.2)-(RSA)-(AES-256-GCM).

To stop the connection, run:

sudo pkill openconnect

To run the client non-interactively, use the following syntax.

echo -n password | sudo openconnect -b vpn.example.com -u username --passwd-on-stdin

If you want to use Network Manager to manage VPN connection, then you also need to install these packages.

sudo apt install network-manager-openconnect network-manager-openconnect-gnome

If you are successfully connected to the VPN server, but your public IP address doesn’t change, that’s because IP forwarding or IP masquerading is not working. I once had a typo in my iptables command, which caused my computer not being able to browse the Internet.

Auto-Connect on System Startup

To let OpenConnect VPN client automatically connect to the server at boot time, we can create a systemd service unit.

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

Put the following lines to the file. Replace the red text.

[Unit]
  Description=OpenConnect VPN Client
  After=network-online.target
  Wants=network-online.target

[Service]
  Type=simple
  ExecStart=/bin/bash -c '/bin/echo -n password | /usr/sbin/openconnect vpn.example.com -u username --passwd-on-stdin'
  ExecStop=/bin/bash -c '/sbin/resolvconf -d tun0 && /usr/bin/pkill -SIGINT openconnect && /sbin/ip route flush 12.34.56.78'
  Restart=always
  RestartSec=2

[Install]
  WantedBy=multi-user.target

Save and close the file. Then enable this service so that it will start at boot time.

sudo systemctl enable openconnect.service

Explanation of the file content:

  • After=network-online.target and Wants=network-online.target make this service run after network is up.
  • In reality, this service can still run before network is up. We add Restart=always and RestartSec=2 to restart this service after 2 seconds if this service fails.
  • Systemd doesn’t recognise pipe redirection, so in the ExecStart directive, we wrap the comand in single quotes and run it with the Bash shell.
  • Since OpenConnect VPN client will run as a systemd service, which runs in the background, there’s no need to add -b flag to the openconnect command.
  • The ExecStop directive is for stopping VPN connection. First, we use resolvconf command to revert DNS server settings. tun0 is the default name for the TUN device, which you can see with ip link command. Then we use pkill command to stop openconenct process. Lastly, we restore the Linux kernel routing table with the ip route flush command. Replace 12.34.56.78 with the IP address of your VPN server.

To start this Systemd service immediately, run

sudo systemctl start openconnect

To stop this Systemd service, run

sudo systemctl stop openconnect

OpenConnect GUI Client for Windows and MacOS

They can be downloaded from OpenConnect GUI Github Page.

Speed

OpenConnect VPN is pretty fast. I can use it to watch 4k videos on YouTube.

ocserv letsencrypt

Auto-Renew Let’s Encrypt Certificate

Edit root user’s crontab file.

sudo crontab -e

Add the following line at the end of the file. It’s necessary to restart ocserv service for the VPN server to pick up new certificate and key file.

@daily certbot renew --quiet && systemctl restart ocserv

Optimization

OpenConnect by default uses TLS over UDP protocol (DTLS) to achieve faster speed, but UDP can’t provide reliable transmission. TCP is slower than UDP but can provide reliable transmission. One optimization tip I can give you is to disable DTLS, use standard TLS (over TCP), then enable TCP BBR to boost TCP speed.

To disable DTLS, comment out (add # symbol at the beginning) the following line in ocserv configuration file.

udp-port = 443

Save and close the file. Then restart ocserv service.

sudo systemctl restart ocserv.service

To enable TCP BBR, please check out the following tutorial.

In my test, standard TLS with TCP BBR enabled is two times faster than DTLS.

Troubleshooting

Note that if you are using OpenVZ VPS, make sure you enable the TUN virtual networking device in VPS control panel.

If you encounter any problem, then check OpenConnect VPN server log.

sudo journalctl -xe -u ocserv.service

I found that if I change port 443 to a different port, the great firewall of China will block this VPN connection. Sometimes the speed drops to around 1Mbps, probably due to the fact that the great firewall of China is interrupting VPN connections because if I use Shadowsocks proxy on the same server, I can watch YouTube at 50Mbps.

Let OpenConnect VPN server and web server use port 443 at the same time

Normally a port can only be used by one process. However, we can use HAproxy (High Availability Proxy) and SNI (Server Name Indication) to make ocserv and Apache/Nginx use port 443 at the same time.

First, edit ocserv configuration file.

sudo nano /etc/ocserv/ocserv.conf

Uncomment the following line. This will allow ocserv to obtain the client IP address instead of HAproxy IP address.

listen-proxy-proto = true

Then find the following line.

#listen-host = [IP|HOSTNAME]

Change it to

listen-host = 127.0.0.1

This will make ocserv listen on 127.0.0.1 because later HAproxy will need to listen on the public IP address. Save and close the file. Then restart ocserv.

sudo systemctl restart ocserv

Next, we also need to make the web server listen on localhost only, instead of listening on public IP address. If you use Nginx, edit the server block file.

sudo nano /etc/nginx/conf.d/www.example.com.conf

In the SSL server block, find the following directive.

listen 443 ssl;

Change it to

listen 127.0.0.2:443 ssl;

This time we make it listen on 127.0.0.2:443 because 127.0.0.1:443 is already taken by ocserv. Save and close the file. Then restart Nginx.

sudo systemctl restart nginx

Now install HAproxy.

sudo apt install haproxy

Edit configuration file.

sudo nano /etc/haproxy/haproxy.cfg

Copy and paste the following lines to the end of the file. Replace 12.34.56.78 with the public IP address of your server. Replace vpn.example.com with the domain name used by ocserv and www.example.com with the domain name used by your web server.

frontend https
   bind 12.34.56.78: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 vpn.example.com }
   use_backend nginx if { req_ssl_sni -i www.example.com }
   use_backend nginx if { req_ssl_sni -i example.com }

   default_backend ocserv

backend ocserv
   mode tcp
   option ssl-hello-chk
   server ocserv 127.0.0.1:443 send-proxy-v2

backend nginx
   mode tcp
   option ssl-hello-chk
   server nginx 127.0.0.2:443 check

Save and close the file. Then restart HAproxy.

sudo systemctl restart haproxy

In the configuration above, we utilized the SNI (Server Name Indication) feature in TLS to differentiate VPN traffic and normal HTTPS traffic.

  • When vpn.example.com is in the TLS Client Hello, HAProxy redirect traffic to the ocserv backend.
  • When www.example.com is in the TLS Client Hello, HAProxy redirect traffic to the nginx backend.
  • If the client doesn’t specify the server name in TLS Client Hello, then HAproxy will use the default backend (ocserv).

You can test this setup with the openssl tool. First, run the following command multiple times.

echo | openssl s_client -connect your-server-IP:443 | grep subject

We didn’t specify server name in the above command, so HAproxy will always pass the request to the default backend (ocserv), and its certificate will be sent to the client. Next, run the following two commands.

echo | openssl s_client -servername www.example.com -connect your-server-IP:443 | grep subject

echo | openssl s_client -servername vpn.example.com -connect your-server-IP:443 | grep subject

Now we specified the server name in the commands, so HAproxy will pass request accordingly. Note that the Cisco AnyConnect App doesn’t support TLS SNI, so it’s better to set ocserv as the default backend in HAProxy configuration file.

When renewing Let’s Encrypt certificate for your website, it’s recommended that you use the http-01 chanllenge instead of tls-sni-01 chanllege, because HAproxy is listening on port 443 of the public IP address, so it can interfere with the renew process.

sudo certbot renew --preferred-challenges http-01

Fixing HAproxy Error

If your Nginx web server doesn’t show up in your browser and you see the following messages in haproxy log (/var/log/haproxy.log)

Server nginx/nginx is DOWN, reason: Socket error, info: "Connection reset by peer

backend nginx has no server available!

Layer6 invalid response

It maybe because your backend Nginx web server is using a TLS certificate with OCSP must staple extension. Nginx doesn’t send the OCSP staple information on the first HTTP request. To make it work, be sure to add a resolver in your Nginx virtual host configuration like below.

{
     ....
     ssl_trusted_certificate /etc/letsencrypt/live/www.example/chain.pem;
     ssl_stapling on;
     ssl_stapling_verify on;

    resolver 8.8.8.8;
    ....
}

Save and close the file. Then restart Nginx.

sudo systemctl restart nginx

Also consider removing health check for the backend server in HAproxy. So change

server nginx 127.0.0.2:443 check

To

server nginx 127.0.0.2:443

Save and close the file. Then restart HAproxy.

sudo systemctl restart haproxy

Upgrading to the latest version of HAproxy can help too. Previously when I was using HAproxy 1.6 from the default Ubuntu repository, the log file didn’t show much information. To install the latest version, run the following commands:

sudo add-apt-repository ppa:vbernat/haproxy-1.8

sudo apt update

sudo apt install haproxy

How to Disable TLS 1.0 and TLS 1.1 in ocserv

The PCI council deprecated TLS 1.0 in June 30, 2018 and main stream web browsers are going to disable TLS 1.0 and TLS 1.1 in 2020. We should do the same with VPN server. Edit the main configuration file.

sudo nano /etc/ocserv/ocserv.conf

Find the following line:

tls-priorities = "NORMAL:%SERVER_PRECEDENCE:%COMPAT:-VERS-SSL3.0"

To disable TLS 1.0 and TLS 1.1 in OpenConnect VPN server, just add -VERS-TLS1.0 and -VERS-TLS1.1 in the line.

tls-priorities = "NORMAL:%SERVER_PRECEDENCE:%COMPAT:-VERS-SSL3.0:-VERS-TLS1.0:-VERS-TLS1.1"

Save and close the file. Then restart ocserv.

sudo systemctl restart ocserv

Now ocserv will only accept TLS 1.2. For further information on configuring the TLS parameter in ocserv, please see GnuTLS priority strings.

To check if TLS 1.0 is supported in your OpenConnect VPN server, run the following command.

openssl s_client -connect vpn.your-domain.com:443 -tls1

And check TLS 1.1

openssl s_client -connect vpn.your-domain.com:443 -tls1_1

If you see the following message in the output, that means the TLS version is not supported.

New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported

I tried to enable TLS 1.3, but it is not supported yet in the ocserv package on Ubuntu.

Per User or Per Group Configuration

Ocserv allows per user and per group configurations. To enable this feature, uncomment the following two lines in /etc/ocserv/ocserv.conf file.

config-per-user = /etc/ocserv/config-per-user/
config-per-group = /etc/ocserv/config-per-group/

Save and close the file. Then create the per user and per group config directory.

sudo mkdir /etc/ocserv/config-per-user/
sudo mkdir /etc/ocserv/config-per-group/

Next, you can create a file under these two directories. For example, create the user1 file to allow custom configuration for user1.

sudo nano /etc/ocserv/config-per-user/user1

You can also create the group1 file to allow custom configuration for the group named group1.

sudo nano /etc/ocserv/config-per-group/group1

You can add something like below in the file.

route = 10.10.10.0/255.255.255.0

This means that after user1 connect to this VPN server, only traffic to the 10.10.10.0/24 network will be routed via VPN server. Traffic to other IP addresses are routed via the original gateway. I use this trick to allow my another VPS (virtual private server) to connect to this VPN server without disrupting normal traffic, so the tun device (vpns0) of my VPN server is always turned on, which means my VPN server will always have the private IP address 10.10.10.1.

Save and close the file. Restart ocserv for the changes to take effect.

Wrapping Up

That’s it! I hope this tutorial helped you install and configure OpenConnect VPN on Ubuntu 16.04 and Ubuntu 18.04. As always, if you found this post useful, then subscribe to our free newsletter to get more tips and tricks 🙂

Rate this tutorial
[Total: 28 Average: 4.9]

42 Responses to “Set up OpenConnect VPN Server (ocserv) on Ubuntu 16.04/18.04 with Let’s Encrypt

  • Ramin Farmani
    1 year ago

    I follow your instruction but still receive this error on client

    DTLS handshake failed: Resource temporarily unavailable, try again.

    what else I can do

  • “I found that if I change port 443 to a different port, the Internet filtering system of my country will block this VPN connection.”
    So what is your country?

  • Ubuntu 16 has and old version of ocserv.
    It’s version (0.10.11-1build1) and there are a lot of improvements since that version in the current one (0.12.2)
    Now I’m working on compiling it to work on ubuntu, but seems like ocserv is more compatible with debian. Still I got some errors if I want to run it as service using systemctl.

    Is this the only vpn working in china? Microsoft SSTP is working? OpenVPN port 443 working?

    • I now only use self-hosted OpenConnect VPN and Shadowsocks proxy in China. They are very stable.

      I used OpenVPN before with a VPN provider. It worked but can be easily interrupted by the great firewall. I have never used Microsoft SSTP.

  • also I wanted to tell you that the email your system sends, is going to spam folder.

    • My email server complies with all legitimate email-sending practices. It takes time to build a good email reputation. Microsoft is very strict on accepting emails. Initially the emails are likely to go into spam folder. If many people mark my emails as not spam, then my emails are more likely to go to inbox.

  • Shadowsocks proxy is not blocked in China? You can make OpenVPN connects to it and then it can work without being filtered by the great firewall?

  • andrescol
    1 year ago

    Greetings, friend. great tutorial. I stayed here: sudo openconnect -b vpn.example.com:port-number. When the command is issued, the message:

    Got inappropriate HTTP CONNECT response: HTTP/1.1 401 Unauthorized
    Creating SSL connection failed

    What I can do? tks

  • reza kazemi
    11 months ago

    thank you very much

  • Mufaddal
    10 months ago

    I’m getting an error.

    error: unknown user: nobody

    Could you please guide me on what could be the problem?

  • i just set up OpenConnect VPN server on ubuntu 18.04. Users are able to connect and get an IP address assigned by the OpenConnect server. Corp network is 172.16.4.0/23 OpenConnect server is 172.16.4.10 vpn clients get 10.1.1.0/24 addresses. From the vpn client i can ping 10.1.1.1 and 172.16.4.10, but can’t ping any other corp servers on the 17.16.4.0/23 network
    ICMP packets get to the corp servers, but get dropped because the corp servers don’t know how to route to 10.1.1.0/24 subnet

    any help is greatly appreciated

    • if I do route add 10.1.1.0 mask 255.255.255.0 172.16.4.10 on any of the corp servers I am able to communicate with the corp servers from the VPN client

  • Hello,

    How can we disable TLS 1.0 in the OpenConnect VPN server config?

  • Xiao,

    Thanks for the TLS disablement update.

    There is a few more things we would like to disable. Are you able to assist with disabling elliptic curves? P-192 (prime192v1) (192 bits) to be specific and a list of ciphers

    TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
    TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
    TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
    TLS_DHE_RSA_WITH_AES_256_CCM

    Thanks

  • I have set up the server successfully but I can’t route traffic through the VPN server. I can only ping the server successfully but can’t ping any other IP.

  • Jan 29 11:52:02 ip-172-31-30-232 ocserv[5028]: sec-mod: sec-mod initialized (socket: /var/run/ocserv-socket.5018)
    Jan 29 11:52:02 ip-172-31-30-232 ocserv[5018]: main: tlslib.c:854: error loading file ‘/etc/letsencrypt/live//fullchain.pem ‘
    Jan 29 11:52:02 ip-172-31-30-232 systemd[1]: ocserv.service: Main process exited, code=exited, status=1/FAILURE
    Jan 29 11:52:02 ip-172-31-30-232 ocserv[5018]: main: tlslib.c:1000: error loading the certificate or key file
    Jan 29 11:52:02 ip-172-31-30-232 ocserv[5028]: sec-mod: error receiving msg head from main
    Jan 29 11:52:02 ip-172-31-30-232 ocserv[5028]: sec-mod: error processing sync command from main
    Jan 29 11:52:02 ip-172-31-30-232 systemd[1]: ocserv.service: Failed with result ‘exit-code’.
    Jan 29 11:52:02 ip-172-31-30-232 systemd[1]: ocserv.service: Start request repeated too quickly.
    Jan 29 11:52:02 ip-172-31-30-232 systemd[1]: ocserv.service: Failed with result ‘exit-code’.
    Jan 29 11:52:02 ip-172-31-30-232 systemd[1]: Failed to start OpenConnect SSL VPN server.

    Hi,

    I am following your instructions to the letter but I run into this issue when trying to setup ocserv server.
    Has something changed since this guide was posted?

    Thanks

    • This line:

      Jan 29 11:52:02 ip-172-31-30-232 ocserv[5018]: main: tlslib.c:854: error loading file ‘/etc/letsencrypt/live//fullchain.pem ‘

      indicates that you didn’t correctly specify the path to TLS certificate. If you go to the /etc/letsencrypt/live/ directory, you will understand what went wrong.

      • Hi Guo An,

        Thanks for the speedy response. I should have mentioned that I removed the site’s domain from the nginx log.

        • * From the ocserv log before posting it.

          Because of the execution of the certbot command as sudo, I suspect that this may be a permissions issue, because as a regular user I cannot access the certificates directory.

          However, I have tried the following:

          – Running ocserv as a root user (just for testing)
          – changing permissions and owner of the certificates.

          ocserv is still unable to read the certificates, at this point I’m not sure if it’s an issue with the certificate.

      • you have a space ‘/etc/letsencrypt/live//fullchain.pem ‘ remove space

    • The problem is that ocserv can’t load the TLS certificate file. Please make sure the TLS certificate exist in the /etc/letsencrypt/live/vpn.example.com/ directory and double check your /etc/ocserv/ocserv.conf file.

      From the log, I suspect that you added a whitespace at the end of the TLS certificate path.

      • What do you think about outline vpn

        • I haven’t set up outline VPN yet. From I have learned, Outline is based on Shadowsocks, which is a SOCKS5 proxy, not a VPN. Shadowsocks is very popular with Chinese netizens, used as a tool to bypass the Great Firewall. I have been using Shadowsocks for 3 years. It’s super fast.

        • Murat
          8 months ago

          it is super easy to set up. Can you please write a review about it

  • Anonymous
    9 months ago

    Thank you, real detailed guide.

  • Username
    8 months ago

    Love this guide. Is there anything we can do to enable having an IPV6 address along with an IPV4 address?

  • Linux Newbie
    6 months ago

    Thanks, this is really a great guide 🙂

  • Excellent guide! Thank you so much!!

  • I hope this help
    I have successfully upgrade to TLS1.3
    https://www.ookangzheng.com/use-tls1-3-with-ocserv-anyconnect-on-debian/

  • Hi Xiao Guo An
    Thanks for fantastic post. I installed ocserv on ubuntu 18.04 and its worked like charm.
    I want to create bunch user(more than 500 user) and I need to set some expiration period date after first users connection(like 3 month, 6 month etc… after first connection to the server).
    Could you please guide me to do that?

    Thanks.

  • Tanzil Hussain
    4 months ago

    how can I use the sql database to connect VPN users with ocserv server without using ocpassd file?

  • Hello, thanks for the great article. One comment, do not disable UDP because you think it’s unreliable. Your payload (in the tunnel) decides if its require an unreliable connection and if yes it uses in the tunnel TCP.

    So if a TCP (in tunnel) package (e.g. HTTP package) gets lost it’s resent automatically again caused by the payload and not because of the VPN tunnel an that within an fast UDP frame. UDP performs much faster because it does not wait for ACKs on long distances and assume you stream video via UDP – if a package get’s lost it doesn’t make sense to resend it, if you put TCP around it resends it (and throws it away on destination but blocks your link).

  • G.R.Regis
    3 weeks ago

    I’ve tried this on a couple of servers now, my home server and a VPS I rent that both run Ubuntu 18.04, and I get the following error on each:

     Sep 21 02:47:28 myserver systemd[1]: Dependency failed for OpenConnect SSL VPN server.
    Sep 21 02:47:28 myserver systemd[1]: ocserv.service: Job ocserv.service/start failed with result 'dependency'.

    I tried googling for an answer, and all I could see was that there was an issue with the ports being used. Now I have webservers running on each (apache on one and nginx on the other) and I changed the port for ocserv to 8443 on each as per the tutorial for each type of server. I even tried creating /etc/systemd/system/ocserv.socket.d/port.conf file to no avail. Any help is apprceiated. 谢谢.

    • Double check your configuration file and the /etc/systemd/system/ocserv.service file. I can’t help fix an error that I didn’t encounter myself.

  • G.R.Regis
    3 weeks ago

    After thinking about it a bit, I realized I didn’t reboot the server (it never prompted me to), so I tried that and it fixed the issue.

Leave a Comment

  • Comments with links are moderated by admin before published.
  • Your email address will not be published.
  • Use <pre> ... </pre> HTML tag to quote the output from your terminal/console.
  • Please use the community (https://community.linuxbabe.com) for questions unrelated to this article.
  • If you ask me more than 5 questions, I expect you to make a donation, or I would stop answering your questions.