Set Up OpenConnect VPN Server (ocserv) on CentOS 8/RHEL 8 with Let’s Encrypt

This tutorial is going to show you how to run your own VPN server by installing OpenConnect VPN server on CentOS 8/RHEL 8. OpenConnect VPN server, aka ocserv, is an open-source implementation of the Cisco AnyConnnect VPN protocol, which is widely used in businesses and universities. AnyConnect is an SSL-based VPN protocol that allows individual users to connect to a remote network.

Why Set Up Your Own VPN Server?

  • Maybe you are a VPN service provider or a system administrator, which behooves you to set up your own VPN server.
  • You don’t trust the no logging policy of VPN service providers, so you go the self-host route.
  • You can use VPN to implement network security policy. For example, if you run your own email server, you can require users to log in only from the IP address of the VPN server by creating an IP address whitelist in the firewall. Thus, your email server is hardened to prevent hacking activities.
  • Perhaps you are just curious to know how VPN server works.

install openconnect ocserv VPN server centos 8

Features of OpenConnect VPN server

  • Lightweight and fast. In my test, I can watch YouTube 4K videos with OpenConnect VPN. YouTube is blocked in my country (China).
  • Runs on Linux and most BSD servers.
  • Compatible with Cisco AnyConnect client
  • There is OpenConnect client software for Linux, macOS, Windows, and OpenWRT. For Android and iOS, you can use the Cisco AnyConnect Client.
  • Supports password authentication and certificate authentication
  • Supports RADIUS accounting.
  • Supports virtual hosting (multiple domains)
  • Easy to set up

I particularly like the 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 Linux distro on my computer and want to quickly unblock websites or hide my IP address, I simply run the following command to connect to my OpenConnect VPN server.

sudo openconnect -b vpn.mydomain.com

The openconnect client software is available for Debian, Ubuntu, Fedora, RHEL, CentOS, Arch Linux, and OpenSUSE. You can easily install it with your package manager.

sudo apt install openconnect
sudo dnf install openconnect
sudo pacman -S openconnect

Requirements

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 Kamatera VPS, which features:

  • 30 days free trial.
  • Starts at $4/month (1GB RAM)
  • High-performance KVM-based VPS
  • 9 data centers around the world, including United States, Canada, UK, Germany, The Netherlands, Hong Kong, and Isreal.

Follow the tutorial linked below to create your Linux VPS server at Kamatera.

Once you have a VPS running CentOS 8, follow the instructions below.

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

Step 1: Install OpenConnect VPN Server (ocserv) on CentOS 8

Log into your CentOS 8 server via SSH. Then run the following commands to install the ocserv package from the EPEL repository.

sudo dnf install epel-release
sudo dnf install ocserv

Step 2: Open Ports in Firewall

Firewall on CentOS is enabled by default. It’s customary to configure ocserv to listen on port 443, so run the following commands to open TCP and UDP port 443.

sudo firewall-cmd --permanent --add-port=443/tcp
sudo firewall-cmd --permanent --add-port=443/udp

We also need to open TCP port 80 to obtain TLS certificate from Let’s Encrypt.

sudo firewall-cmd --permanent --add-port=80/tcp

Reload firewall for the changes to take effect.

sudo systemctl reload firewalld

Step 3: Install Let’s Encrypt Client (Certbot) on CentOS 8 Server

The gnutls-utils package installed along with ocserv 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.

Run the following command to install the Let’s Encrypt client (certbot) on CentOS 8.

sudo dnf install certbot

To check the version number, run

certbot --version

Sample output:

certbot 1.14.0

Step 4: Obtain a Trusted TLS Certificate from Let’s Encrypt

I recommend using the standalone or webroot plugin to obtain TLS certificate.

Standalone Plugin

If there’s no web server running on your CentOS 8 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. Set DNS A record for vpn.example.com at your domain registrar’s website, then run the following command to obtain certificate.

sudo certbot certonly --standalone --preferred-challenges http --agree-tos --email [email protected] -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.
  • --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 from the following screenshot, I successfully obtained the certificate.

ocserv centos 8 letsencrypt

Using webroot Plugin

If your CentOS 8 server has a web server listening on port 80 and 443, 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 web server, then create virtual host under /etc/httpd/conf.d/ directory.

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

And paste the following lines into the file.

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

        DocumentRoot /var/www/html/
</VirtualHost>

Save and close the file. Reload Apache for the changes to take effect.

sudo systemctl reload httpd

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 [email protected] -d vpn.example.com -w /var/www/html/

Nginx

If you are using Nginx web server, then create virtual host under /etc/nginx/conf.d/.

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 /usr/share/nginx/html/;

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

Save and close the file. 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 [email protected] -d vpn.example.com -w /usr/share/nginx/html/

Step 5: Edit 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 CentOS system accounts to login from VPN clients. This behavior can be disabled by commenting out the following line.

auth = "pam"

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. If you want to enable certificate authentication, you need to set up your own CA to issue client certificate.

Next, find the following two lines.

tcp-port = 443
udp-port = 443

Comment out the UDP port. (We will use TCP BBR algorithm to boost TCP speed.)

tcp-port = 443 
#udp-port = 443

If you don’t want ocserv to use TCP port 443 (there’s a web server using port 443?), then change the TCP port number. Otherwise leave it alone.

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

server-cert = /etc/pki/ocserv/public/server.crt
server-key = /etc/pki/ocserv/private/server.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

It’s recommended to enable LZ4 compression, so uncomment the following line.

compression = true

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

max-clients = 0

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 = 0

By default, keepalive packets are sent every 32400 seconds (9 hours). I prefer to use a short time (30 seconds) to reduce the chance of VPN connection dropout.

keepalive = 30

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

try-mtu-discovery = true

You can set the time that a client is allowed to stay idle before being disconnected via the following two parameters. If you prefer the client to stay connected indefinitely, then comment out these two parameters.

idle-timeout=1200
mobile-idle-timeout=2400

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 (such as 10.10.10.0/24) to avoid IP address collision, so uncomment the above two lines and change the value of ipv4-network to 10.10.10.0.

ipv4-network = 10.10.10.0
ipv4-netmask = 255.255.255.0

Find the following two lines and uncomment them, so VPN clients will be given private IPv6 addresses.

ipv6-network = fda9:4efe:7e3b:03ea::/48
ipv6-subnet-prefix = 64

If you see the following line

ipv6-network = fda9:4efe:7e3b:03ea::/64

Please change it to:

ipv6-network = fda9:4efe:7e3b:03ea::/48

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
dns = 8.8.4.4

or Cloudflare’s public DNS server.

dns = 1.1.1.1
dns = 1.0.0.1

Note: If you are a VPN service provider, it’s a good practice to run your own DNS resolver. 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 # character at the beginning of the following 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

Finally, scroll down to the end of the file (In Nano text editor, you can go to the end of the file by pressing Ctrl+W, then pressing Ctrl+V), and comment out the user-profile parameter, because the user profile XML file is not needed by OpenConnect clients or the Cisco AnyConnect client on iOS and Android.

#user-profile = profile.xml

Note: If user-profile is enabled, the Cisco AnyConnect client on iOS will produce the following error when connecting to the OpenConnect VPN server.

Failed to download the AnyConnect profile. Please try again.

Save and close the file.

Step 6: 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.

Now we can start the ocserv serice.

sudo systemctl start ocserv

And enable auto-start at boot time.

sudo systemctl enable ocserv

You can check its status with:

systemctl status ocserv

Sample output:

 ocserv.service - OpenConnect SSL VPN server
   Loaded: loaded (/usr/lib/systemd/system/ocserv.service; enabled; vendor preset: disabled)
   Active: active (running) since Fri 2020-01-03 19:04:53 CST; 15s ago
     Docs: man:ocserv(8)
 Main PID: 19851 (ocserv-main)
    Tasks: 2 (limit: 5061)
   Memory: 3.2M
   CGroup: /system.slice/ocserv.service
           ├─19851 ocserv-main
           └─19853 ocserv-sm

Hint: If the above command doesn’t quit immediately, you can press the Q key to gain back control of the terminal.

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

Step 7: Enable IP Forwarding in Linux Kernel

In order for the VPN server to route packets between VPN clients and the Internet, we need to enable IP forwarding by running the following command.

echo "net.ipv4.ip_forward = 1" | sudo tee /etc/sysctl.d/60-custom.conf

Also, run the following two commands to enable TCP BBR algorithm to boost TCP speed.

echo "net.core.default_qdisc=fq" | sudo tee -a /etc/sysctl.d/60-custom.conf

echo "net.ipv4.tcp_congestion_control=bbr" | sudo tee -a /etc/sysctl.d/60-custom.conf

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

sudo sysctl -p /etc/sysctl.d/60-custom.conf

Step 8: Configure IP Masquerading in Firewall

Run the following command to enable IP masquerading for the 10.10.10.0/24 subnet in the server firewall.

sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.10.10.0/24" masquerade'
sudo systemctl reload firewalld

This will hide your VPN 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.

Now OpenConnect VPN server is ready to accept client connections.

Install and Use OpenConnect VPN client on CentOS 8/Fedora Desktop

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

sudo dnf install openconnect

On CentOS 8, you need to enable the EPEL repository in order to install the client.

sudo dnf install epel-release
sudo dnf install openconnect

Then you can connect to VPN server from the command line like below. -b flag will make it run in the background after the connection is established.

sudo openconnect -b vpn.example.com

By default, openconnect client sends request to port 443 of the server. If you configured a different port for the server, then you can add the port number.

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 as 10.10.10.139, using SSL + lz4
Continuing in background; pid 2137
Established DTLS connection (using GnuTLS). Ciphersuite (DTLS1.2)-(PSK)-(AES-256-GCM).

If the connection failed, you can check the ocserv log to find out why. (Perhaps you didn’t enter the password correctly.)

sudo journaltcl -eu ocserv

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 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.

Auto-Connect on System Startup

To make 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'
  KillSignal=SIGINT
  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 recognize pipe redirection. So in the ExecStart directive, we wrap the command 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 KillSignal directive tells Systemd to send the SIGINT signal when the systemctl stop openconnect command is issued. This will perform a clean shutdown by logging the session off, and restoring DNS server settings and the Linux kernel routing table.

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. As you can see, the connection speed is 63356 Kbps, which translates to 61 Mbit/s.

ocserv vpn speed test singapore server

And here’s the test results on speedtest.net.

ocserv vpn speed test singapore

Speed 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.

You may also want to disable DTLS to bypass firewall restrictions because DTLS uses UDP port 443. Standard TLS uses TCP port 443.

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. It’s written for Ubuntu, but also works for CentOS. Note that you need to disable DTLS in ocserv, or TCP BBR won’t work.

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

Another very important factor affecting speed is how good the connection between your local computer and the VPN server is. If you live in the middle east and the VPN server is located in the U.S, the speed would be slow. Choose a data center that’s close to where you live.

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 to run the Cron job daily. If the certificate is going to expire in 30 days, certbot will try to renew the certificate. 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

Troubleshooting Tips

Note that if you are using OpenVZ VPS, make sure you enable the TUN virtual networking device in VPS control panel. (If you use Vultr VPS, then you have KVM-based VPS, so you don’t have to worry about this.)

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

sudo journalctl -eu ocserv.service

I found that if I change port 443 to a different port, the great firewall of China will block this VPN connection.

If ocserv tells you that it can’t load the /etc/ocserv/ocserv.conf file, you can stop ocserv.

sudo systemctl stop ocserv

Then run it in the foreground with debugging enabled.

sudo /usr/sbin/ocserv --foreground --pid-file /run/ocserv.pid --config /etc/ocserv/ocserv.conf --debug=10

Then output might give you some clues why ocserv isn’t working.

If you are successfully connected to the VPN server, but you can’t browse the Internet, that’s because IP forwarding or IP masquerading is not working.

No Tap-Windows Adapter installed on this system

If you use the OpenConnect GUI Windows client and found the “No Tap-Windows Adapter installed on this system” error in the logs (View – Log Window), this is likely because you have install other VPN clients afterward like OpenVPN.

To fix this error, you need to uninstall OpenConnect GUI client and reinstall it. In the setup wizard, you will have the option to install the TAP driver.

openconnect windows tap driver

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

Please read the following article:

How to Disable TLS 1.0 and TLS 1.1 in ocserv

The PCI council deprecated TLS 1.0 in June 30, 2018 and mainstream 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, replace it with:

tls-priorities = "NORMAL:%SERVER_PRECEDENCE:%COMPAT:-RSA:-VERS-SSL3.0:-ARCFOUR-128:-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.3 and 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

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. This is known as split tunneling, which is useful when:

  • You just want the VPN clients to be able to browse internal resources and don’t want all the traffic to go through the VPN server.
  • You need to build a private network for cloud servers.
  • The client needs to connect to multiple VPNs. One VPN could use split tunneling and the other use a full tunnel.

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

How to Set Up VPN Relay

Suppose there are two servers: server A and server B.

  • You have a good connection to server A. Latency is very low and no packet is dropped.
  • You have a bad connection to server B. Latency is high and there’s packet being dropped.
  • The connection between server A and server B is good.

Naturally, you want to install VPN on server A. But what if you want the Internet to see your traffic coming from server B’s IP address? Well, you can install ocserv VPN on server B, then set up HAProxy on server A to proxy the traffic between your computer and server B.

On server A, install HAProxy.

sudo dnf install haproxy

Edit main configuration file.

sudo nano /etc/haproxy/haproxy.cfg

Create a front end and back end just like before. Replace 12.34.56.78 with server A’s public IP address. Replace 12.34.56.79 with server B’s public IP address.

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 }

   default_backend ocserv

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

Save and close the file. On server B, you should configure ocserv to listen on the public IP address and enable proxy protocol just like before. After that, edit the A record of vpn.example.com. It should be pointed to the IP address of server A.

Restart HAProxy and Ocserv and it should be working.

Note: If server B also uses HAProxy, then you should remove the send-proxy-v2 parameter in the above HAProxy configuration.

Virtual Hosting

To add a new virtual host in ocserv, first you need to use the method in step 4 to obtain a TLS certificate for the new virtual host. Then edit ocserv configuration file.

sudo nano /etc/ocserv/ocserv.conf

Go to the bottom of this file. In Nano text editor, you can press Ctrl+W, then Ctrl+V to jump to the bottom of a file. Add the following lines. Replace vpn2.example.com with the hostname of the second virtual host.

[vhost:vpn2.example.com]
#Allow password authentication and certificate authentication
enable-auth = "plain[passwd=/etc/ocserv/ocpasswd]"
auth = "certificate"

tcp-port = 443

#uncomment the two lines if ocserv runs behind HAProxy.
#listen-host = 127.0.0.1
#listen-proxy-proto = true

# SSL/TLS configuration
ca-cert = /etc/ocserv/ssl/ca-cert.pem
server-cert = /etc/letsencrypt/live/vpn2.example.com/fullchain.pem
server-key = /etc/letsencrypt/live/vpn2.example.com/privkey.pem
cert-user-oid = 0.9.2342.19200300.100.1.1

#Networking configuration. Use a different network range for this virtual host. 
device = vpns
ipv4-network = 10.10.20.0
ipv4-netmask = 255.255.255.0
route = default
dns = 8.8.8.8
tunnel-all-dns = true

compression = true
max-clients = 0
max-same-clients = 0
try-mtu-discovery = true
idle-timeout=1200
mobile-idle-timeout=2400

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

Save and close the file. Then restart ocserv.

sudo systemctl restart ocserv

Note that the ocserv daemon might tell you some parameters will be ignored for virtual host. However, I found that some of the ignored parameters are actually needed. For example, if you delete the device = vpns line from the virtual host, you might encounter the following error when establishing VPN connection to the virtual host.

VPN service unavailable; reason: Server configuration error

And the VPN server would produce the following error message in the log.

no networks are configured; rejecting client

Note that the AnyConnect VPN client on iOS doesn’t support TLS SNI, so iOS users will connect to the default virtual host.

How to Run Multiple Instances of ocserv

One ocserv process can bind to only one TCP or UDP port on your server. If you want to allow ocserv to bind to multiple TCP or UDP ports, then you need to run multiple ocserv processes. It’s very simple. Copy the /usr/lib/systemd/system/ocserv.service to a new file.

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

Then edit the new file.

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

Change

/etc/ocserv/ocserv.conf

to

/etc/ocserv/ocserv2.conf

Save and close the file. Next, you can edit the /etc/ocserv/ocserv2.conf file and add your custom configurations. Once you are done, start the second ocserv service.

sudo systemctl start ocserv2

Wrapping Up

That’s it! I hope this tutorial helped you install and configure OpenConnect VPN on CentOS 8/RHEL 8 server. As always, if you found this post useful, then subscribe to our free newsletter to get more tips and tricks. Take care 🙂

Rate this tutorial
[Total: 7 Average: 5]

48 Responses to “Set Up OpenConnect VPN Server (ocserv) on CentOS 8/RHEL 8 with Let’s Encrypt

  • Is there a way I can see who is connected to the vpn server, for how long it’s connected ?

  • I am trying to connect to the server via iOS AnyConnect.

    here is the info that I get from occtl -debug

    show sessions all

    session     user    vhost             ip               user agent  created   status
    uVfDbl    saeed  default x.x.x.x AnyConnect AppleSSLVPN_D  30m:00s authenticated
    
    default: disconnect user 'saeed' (1844) from x.x.x.x with IP 10.10.10.122 (reason: unspecified error, time:    10s)
    default: connected user 'saeed' (1859) from x.x.x.x with IP 10.10.10.122
    default: disconnect user 'saeed' (1859) from x.x.x.x with IP 10.10.10.122 (reason: unspecified error, time:     8s)
    default: connected user 'saeed' (1874) from x.x.x.x with IP 10.10.10.122
    default: disconnect user 'saeed' (1874) from x.x.x.x with IP 10.10.10.122 (reason: unspecified error, time:     4s)
    default: connected user 'saeed' (1891) from x.x.x.x with IP 10.10.10.122
    default: disconnect user 'saeed' (1891) from x.x.x.x with IP 10.10.10.122 (reason: unspecified error, time:    11s)
    

    Despite of the fact that my session does not drop, It constantly get disconnected on the backend.
    I have no explanation for it, do you?

    • Xiao Guoan (Admin)
      4 years ago

      I can also found this error in my ocserv log sudo journalctl -eu ocserv, both when using OpenConnect and Anyconnect clients. I don’t know what it means, but it doesn’t affect web browsing or any user experience.

  • Tanzil Hussain
    4 years ago

    After setup server, i am connecting with IP instead of domain coz I don’t want to use with domain and its giving a warning of the untrusted server.
    a year ago it was sorted i forget that command that was something.

    no-cert-check = true
    in /etc/ocserv/ocserv.conf file

    but that is not working now could you please guide me on which line I can put in ocserv.conf file so it will not give any warning.
    thanks a lot

    • Xiao Guoan (Admin)
      4 years ago

      If you don’t use a valid SSL/TLS certificate on the ocserv server, then you need to tell the clients to ignore certificate security warning.

    • I want this vpn server but i didn’t know how to create plz contact me at +971544544742

  • Following this tutorial, i can setup ocserv on a centos8 in google cloud. the connection between anyconnect client and vpns1 ethernet is good. however, the forwarding between vpns1 ethernet and etho in host looks never work, despite I tried many firewalld/iptables rules as following. can someone give me some suggestions to solve this problem bothered me several days. Thanks a lot in advance!

    firewall-cmd --permanent --zone=public --add-port=443/tcp
    firewall-cmd --permanent --zone=public --add-port=443/udp
    firewall-cmd --permanent --zone=public --add-masquerade
    firewall-cmd --reload

    or

    systemctl stop firewalld
    systemctl disable firewalld
    yum -y install iptables-services
    
    iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
    iptables -I FORWARD -o eth0 -s 10.20.30.0/24 -j ACCEPT
    iptables -I INPUT -s 10.20.30.0/24 -j ACCEPT
    iptables-save > /etc/sysconfig/iptables
    systemctl restart iptables

    or

    iptables -t nat -A POSTROUTING -s 10.20.30.0/24 -o eth0 -j MASQUERADE
    iptables -A FORWARD -i vpns+ -j ACCEPT
    iptables -A FORWARD -o vpns+ -j ACCEPT
    iptables-save > /etc/sysconfig/iptables
    systemctl restart iptables
    • Xiao Guoan (Admin)
      4 years ago

      CentOS 8 on Google Cloud servers doesn’t use the public zone. It uses the trusted zone. You can run the following command to check the current active zone.

      sudo firewall-cmd --list-all

      Sample outout:

      trusted
        target: ACCEPT
        icmp-block-inversion: no
        interfaces: 
        sources: 
        services: 
        ports: 
        protocols: 
        masquerade: no
        forward-ports: 
        source-ports: 
        icmp-blocks: 
        rich rules: 
      

      As you can see, masquerading is disabled. To enable masquerading, run the following commands.

      sudo firewall-cmd --zone=trusted --permanent --add-masquerade
      
      sudo systemctl reload firewalld
  • How to see the connected vpn users and manage them from gui

    • Xiao Guoan (Admin)
      4 years ago

      There’s no GUI for OpenConnect VPN. You have to develop a GUI by yourself.

  • asif shaikh
    4 years ago

    can you please add TLS1.2 parameter configuration ?

  • amaresh Pattanayak
    4 years ago

    can you share an article how to setup VPN for IP v6?

  • I get an error in CentOS7 when cheking via

     sudo systemctl status ocserv 

    :

     error connecting to sec-mod socket 'ocserv.sock.1056e6c7': No such file or directory 

    client connects, and clien’t IP changes. but it will not open the pages that are censored. I’m using google’d DNS in configuration. you have any idea how to solve it?

    • Xiao Guoan (Admin)
      4 years ago
       error connecting to sec-mod socket 'ocserv.sock.1056e6c7': No such file or directory 

      This is normal, because the ocserv.sock file is placed under the chroot directory (/var/lib/ocserv). The ocserv daemon tries to find the socket file in the global directory hierarchy. If it can’t be found there, ocserv will find the file in the chroot directory.

      If the client’s public IP address changed to the VPN server’s public IP address, then the VPN is working correctly. If you can’t open the censored page, it means your VPN server is located in the censored area, or the page is censored by other methods, not by IP address.

  • Hi, thanks for this great guide,
    i wanted to know if in ocserv we can allow it to be used with a proxy like squid & tiny proxy
    so as all the packets/data packets goes through tcp only or http packets with tcp in wireshark log instead of tls shown in wireshark logs.
    i have a setup like mobile client connects to ocserv server but currently it only shows http-over-tls in application data.
    it would be helpfull just wanted this detail so as to make it more secure.

    Thanks in advance.

  • hi

    how can we use socks5 with ocserv, can you share any steps or config changes to be done at ocserv.conf file & client-side.

    thanks

  • 兄弟知道怎么开启ipv6支持么?

  • 感谢老哥

  • Hi.
    How can i log active sessions ? like client ip,time and more.

  • Steven Yang
    3 years ago

    Is it possible to use radius for ocserv on CentOS 8?

    On previous versions of CentOS I can use radiusclient-ng but there is no such package on 8.

  • IPv6 is not enabled in this tutorial and if my ISP supports IPv6, the connection is not secure and my address is leaked.
    I tried uncommenting the below line in ocserv.conf and restart the service, but it did not solve the problem.

    #ipv6-network = fda9:4efe:7e3b:03ea::/48

  • satanix7
    2 years ago

    how to prevent IP leak, DNS leak and webrtc leak in ocserv?

    • Xiao Guoan (Admin)
      2 years ago

      If you followed this tutorial, then ocserv doesn’t have IP leak, DNS leak or webRTC leak problem. You can test on this page: https://ipleak.net

      If you have IPv6 address, then enable IPv6 in ocserv, so it won’t leak IPv6 address.

  • The VPN connects on CentOS 8 but it seems that the NAT forwarding is not working.

    I can only talk to the server itself when I connect to the VPN but not any other website/server such as Google.

    Please advise

  • Huge thanks to the author. This article has been tremendously useful for me.

    I have just a problem. As mentioned in the article, when using a port other than 443 for ocserv, major oppressive firewalls block it, not for every website of course, but they obviously mess with your connection and give you a bad time. So, my question has two parts: first, are there tweaks or configurations to be made to ocserv to make it harder for ISPs to block it? Second, given that ISPs cannot often block 443 and the fact that I have a web server already consuming that port, is there a way to use the server’s 443 port for both my webserver and ocserv?

  • The VPN I created is painfully slow. I had it tested by others on different platforms and they complain too.
    Even worse, it does not open all websites, which is kind of odd. I tried to confirm as much as possible to your tutorial.
    What could be the reason?

    Here’s a connection log displayed for systemctl status openconnect.service:

    Dec 25 12:41:33 machine bash[8016]: SSL negotiation with mydomain.xyz
    Dec 25 12:41:34 machine bash[8016]: Connected to HTTPS on mydomain.xyz with ciphersuite (TLS1.3)-(ECDHE-SECP256R1)-(RSA-PSS-RSAE-SHA256)-(>
    Dec 25 12:41:34 machine bash[8016]: XML POST enabled
    Dec 25 12:41:34 machine bash[8016]: Please enter your username.
    Dec 25 12:41:34 machine bash[8016]: POST https://mydomain.xyz:4443/auth
    Dec 25 12:41:34 machine bash[8016]: Please enter your password.
    Dec 25 12:41:34 machine bash[8016]: POST https://mydomain.xyz:4443/auth
    Dec 25 12:41:35 machine bash[8016]: Got CONNECT response: HTTP/1.1 200 CONNECTED
    Dec 25 12:41:35 machine bash[8016]: CSTP connected. DPD 1800, Keepalive 30
    Dec 25 12:41:35 machine bash[8016]: Connected as 10.10.10.101, using SSL, with DTLS disabled
    
    • Xiao Guoan (Admin)
      2 years ago

      OpenConnect VPN protocol itself is very fast. However, there are other factors that can impact speed.

      The most important factor affecting speed is how good is the connection between your local computer and the VPN server. If you live in the middle east and the VPN server is located in the U.S, the speed would be slow. Choose a data center that’s close to where you live.

      Also, use TCP port 443 because it has higher priority in QoS (Quality of Service) control.

  • Hello
    Thanks for your comprehensive tutorial.
    I would be grateful if you could answer my question.
    How and with what command can we see the list of users that we have already created in ocserv in Centos7?

    • Xiao Guoan (Admin)
      2 years ago
      cat /etc/ocserv/ocpasswd
      • Hi, thanks for your answer, I have another question and I would appreciate it if you could answer that as well.
        Is there any solution to let us limit the access of users who connect via VPN to our network? for example, in a way that they could only access certain IP addresses within our network and not all?

  • Robert
    1 year ago

    Great tutorial. However, I found the following error message in ocserv logs (sudo journalctl -eu ocserv).

    GnuTLS error (at worker-vpn.c:861): A packet with illegal or unsupported version was received.
    

    Do you know what this means?

    • Xiao Guoan (Admin)
      1 year ago

      This is probably because some random script kiddies sending invalid requests to your server. You can ignore this error message. Your VPN works as usual.

  • hello Dear Xiao Guoan

    sorry for my poor English

    Thank you for creating this very informative and rich article.

    As you know nowadays Iranian people are in extremely heavy censorship firewall. Almost every VPN connection failed. I configure ocserver as you instruct in both ubuntu and centos. both are work absolutely well with windows client of openconnect.

    Unfortunately non of them can connect through Android client although my windows pc connected to the internet by my mobile hot spot. so although I use the same data provider in both of my mobile and windows pc, windows pc can connect but Android cant. Do you know what should I do?

    I can give you full access to my vps server if you want to find the problem and solution.

    *** but in case of needed here I attached my openconnect log file to this comment attachment.

    *** The other thing I experienced is if I use “VPN Client Pro” app which provides a built-in openconnect connection I can connect successfully for about 30 sec with data transferred amazingly good but after that the connection will terminated or remain connected but without any internet. I provided you a pic of its level 2 log file in attachments.

    Your help will very effective during this period of time for us.

    Thank you in advanced

    • Xiao Guoan (Admin)
      1 year ago

      Hi Sia,

      I see your VPN server didn’t have a domain name associated with it. I just allocated one of my own sub-domain to it and it works.

      Also I see your max-same-clients is set to 2, which is too low. I just set it to unlimited (0).

      • I Thank you so much dear Xiao. your are amazing. Thank you.

  • mustafa
    1 year ago

    Hi Sir,

    How can create user account with expiration date ? and how can delete a user account?

  • Hi

    Many thanks for your article . it is very useful. I have a problem on android device. I dont have any internet after connecting to my server with anyconnect on android devices.

  • “On server B, you should configure ocserv to listen on the public IP address and enable proxy protocol just like before”

    which before exactly?
    I didn’t see any other text about this matter in this article or any reference mentioned about it

  • Thank you so much man.

  • Worked like a charm on AlmaLinux – thanks!

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.
  • I don't have time to answer every question. Making a donation would incentivize me to spend more time answering questions.

The maximum upload file size: 2 MB. You can upload: image. Links to YouTube, Facebook, Twitter and other services inserted in the comment text will be automatically embedded. Drop file here