How to Install OpenConnect VPN Server on Ubuntu 22.04
On this page
- Prerequisites
- Step 1 - Configure Firewall
- Step 2 - Install Git
- Step 3 - Install OpenConnect
- Step 4 - Generate SSL Certificates
- Step 5 - Configure OpenConnect
- Step 6 - Start OpenConnect Server
- Step 7 - Create VPN accounts
- Step 8 - Enable IP Forwarding
- Step 9 - Configure IP Masquerading
- Step 10 - Connect using OpenConnect Client
- Conclusion
OpenConnect VPN aka ocserv is an open-source free VPN solution with enterprise-grade performance and features. It is based on the Cisco AnyConnect VPN protocol which is widely used in the corporate industry. In this tutorial, you will learn how to install the OpenConnect VPN server on a Ubuntu 22.04 machine. You will also learn how to use an OpenConnect client to connect to the server.
Prerequisites
-
A server running Ubuntu 22.04.
-
A non-root user with sudo privileges.
-
A fully qualified domain name (FQDN) like
vpn.example.com
. -
Make sure everything is updated.
$ sudo apt update $ sudo apt upgrade
-
Few packages that your system needs.
$ sudo apt install wget curl nano software-properties-common dirmngr apt-transport-https gnupg2 ca-certificates lsb-release ubuntu-keyring unzip -y
Some of these packages may already be installed on your system.
Step 1 - Configure Firewall
The first step is to configure the firewall. Ubuntu comes with ufw (Uncomplicated Firewall) by default.
Check if the firewall is running.
$ sudo ufw status
You should get the following output.
Status: inactive
Allow SSH port so the firewall doesn't break the current connection on enabling it.
$ sudo ufw allow OpenSSH
Allow HTTP and HTTPS ports as well.
$ sudo ufw allow http $ sudo ufw allow https
Enable the Firewall
$ sudo ufw enable Command may disrupt existing ssh connections. Proceed with operation (y|n)? y Firewall is active and enabled on system startup
Check the status of the firewall again.
$ sudo ufw status
You should see a similar output.
Status: active To Action From -- ------ ---- OpenSSH ALLOW Anywhere 80/tcp ALLOW Anywhere 443 ALLOW Anywhere OpenSSH (v6) ALLOW Anywhere (v6) 80/tcp (v6) ALLOW Anywhere (v6) 443 (v6) ALLOW Anywhere (v6)
Step 2 - Install Git
Step 3 - Install OpenConnect
Ubuntu 22.04 ships with an older version (1.1.3) of OpenConnect. If you are satisfied with that, you can install it using the following command.
$ sudo apt install ocserv
However, for this tutorial, we will install the latest version (1.1.6) of OpenConnect. For this, we will need to build it from the source.
Install the dependencies required for building the source.
$ sudo apt install -y libgnutls28-dev libev-dev libpam0g-dev liblz4-dev libseccomp-dev \ libreadline-dev libnl-route-3-dev libkrb5-dev libradcli-dev \ libcurl4-gnutls-dev libcjose-dev libjansson-dev libprotobuf-c-dev \ libtalloc-dev libhttp-parser-dev protobuf-c-compiler gperf \ nuttcp lcov libuid-wrapper libpam-wrapper libnss-wrapper \ libsocket-wrapper gss-ntlmssp haproxy iputils-ping freeradius \ gawk gnutls-bin iproute2 yajl-tools tcpdump autoconf automake
Clone the ocserv Git repository.
$ git clone https://gitlab.com/openconnect/ocserv.git
Switch to the cloned directory.
$ cd ocserv
Generate configuration scripts.
$ autoreconf -fvi
Compile the source code. Ignore any deprecated warnings.
$ ./configure && make
Install ocserv.
$ sudo make install
The files will be installed to the /usr/local/bin
and /usr/local/sbin
directories. Copy the systemd service file.
$ sudo cp doc/systemd/standalone/ocserv.service /etc/systemd/system/ocserv.service
Open the service file for editing.
$ sudo nano /etc/systemd/system/ocserv.service
Change the path to the ocserv binary in the following line
$ ExecStart=/usr/sbin/ocserv --foreground --pid-file /run/ocserv.pid --config /etc/ocserv/ocserv.conf
to the following.
$ ExecStart=/usr/local/sbin/ocserv --foreground --pid-file /run/ocserv.pid --config /etc/ocserv/ocserv.conf
Save the file by pressing Ctrl + X and entering Y when prompted.
Reload the system daemon.
$ sudo systemctl daemon-reload
Step 4 - Generate SSL Certificates
We need to install Certbot to generate the SSL certificate. You can either install Certbot using Ubuntu's repository or grab the latest version using the Snapd tool. We will be using the Snapd version.
Ubuntu 22.04 comes with Snapd installed by default. Run the following commands to ensure that your version of Snapd is up to date.
$ sudo snap install core && sudo snap refresh core
Install Certbot.
$ sudo snap install --classic certbot
Use the following command to ensure that the Certbot command can be run by creating a symbolic link to the /usr/bin
directory.
$ sudo ln -s /snap/bin/certbot /usr/bin/certbot
There are two possibilities when it comes to generating an SSL certificate. If you don't have a web server running on your system, you can use the standalone method to generate the certificate. Run the following command to create the certificate using the standalone plugin for Certbot.
$ sudo certbot certonly --standalone --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m [email protected] -d vpn.example.com
The above command will download a certificate to the /etc/letsencrypt/live/vpn.example.com
directory on your server.
Next, if you have a server running on your system, you can either use the webroot plugin or the Nginx or Apache plugins if you are using them. For Nginx or Apache servers, you can simply run the command below.
$ sudo certbot certonly --nginx --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m [email protected] -d vpn.example.com
or
$ sudo certbot certonly --apache --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m [email protected] -d vpn.example.com
If you have a different server, then we will need to use the webroot plugin. For that, create the web root directory.
$ sudo mkdir -p /var/www/ocserv
Set the server as the owner of the web root directory. In our case, we are using www-data
as the server user.
$ sudo chown www-data:www-data /var/www/ocserv -R
Next, configure your server to serve the domain vpn.example.com
at the /var/www/ocserv
directory. Restart the server. Next, generate the certificate using the following command.
$ sudo certbot certonly --webroot --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m [email protected] -d vpn.example.com
Check the Certbot renewal scheduler service.
$ sudo systemctl list-timers
You will find snap.certbot.renew.service
as one of the services scheduled to run.
NEXT LEFT LAST PASSED UNIT ACTIVATES Wed 2023-04-19 10:31:47 UTC 2h 55min left Wed 2023-04-19 03:31:58 UTC 4h 3min ago ua-timer.timer ua-timer.service Wed 2023-04-19 12:02:42 UTC 4h 26min left Wed 2023-04-19 03:19:20 UTC 4h 16min ago motd-news.timer motd-news.service Wed 2023-04-19 18:19:56 UTC 10h left Wed 2023-04-19 07:19:52 UTC 16min ago apt-daily.timer apt-daily.service Wed 2023-04-19 22:51:00 UTC 15h left n/a n/a snap.certbot.renew.timer snap.certbot.renew.service
Do a dry run of the process to check whether the SSL renewal is working fine.
$ sudo certbot renew --dry-run
If you see no errors, you are all set. Your certificate will renew automatically.
Step 5 - Configure OpenConnect
If you are installed ocserv using APT, then the configuration file should already be available at the /etc/ocserv/ocserv.conf
location. But if you built the package from the source, we need to copy the configuration file.
Create the directory for the configuration file.
$ sudo mkdir /etc/ocserv
Copy the configuration file.
$ sudo cp /home/username/ocserv/doc/sample.config /etc/ocserv/ocserv.conf
Open the file for editing.
$ sudo nano /etc/ocserv/ocserv.conf
Change the auth
parameter value to the following. This will allow users to use separate VPN accounts.
auth = "plain[passwd=/etc/ocserv/ocpasswd]"
By default, OpenConnect uses the 443 TCP and UDP ports. We will be using only the TCP port for connection, therefore, disable the UDP port by commenting it out.
tcp-port = 443 #udp-port = 443
If you have a web server running on port 443, then change the value of the TCP port by changing the value.
tcp-port = 8443
Next, find the variables server-crt
and server-key
and change their values as follows.
server-cert = /etc/letsencrypt/live/vpn.example.com/fullchain.pem server-key = /etc/letsencrypt/live/vpn.example.com/privkey.pem
Set the maximum number of clients allowed. The default value is 16. Set as 0 for unlimited.
max-clients = 16
Set the number of devices a user can use at the same time. The default value is 2. Set as 0 for unlimited.
max-same-clients = 2
By default, OpenConnect sends keepalive packets every 9 hours (32400 seconds). This is too high of a value. Set it to 60 seconds to reduce the chance of VPN connection dropout.
keepalive = 60
Change the value of the try-mtu-discovery
to true
to enable MTU discovery. It can optimize VPN performance.
try-mtu-discovery = true
Configure the time that a client is allowed to stay idle before being disconnected by uncommenting the following variables. If you want the client to stay connected indefinitely, leave them as it is.
idle-timeout=1200 mobile-idle-timeout=1800
Set the default domain name for the OpenConnect VPN.
default-domain = vpn.example.com
Change the default IPv4 configuration to avoid IP address collision. We will use 10.10.10.0
as the value.
ipv4-network = 10.10.10.0
Uncomment the following line to tunnel all DNS queries via the VPN.
tunnel-all-dns = true
Change the DNS resolver to Google DNS. Add the second entry as well.
dns = 8.8.8.8 dns = 8.8.4.4
Comment out all the route parameters by adding the hash (#) symbol in front of it.
#route = 10.10.10.0/255.255.255.0 #route = 192.168.0.0/255.255.0.0 #route = fef4:db8:1000:1001::/64 #route = default # Subsets of the routes above that will not be routed by # the server. #no-route = 192.168.5.0/255.255.255.0
Save the file by pressing Ctrl + X and entering Y when prompted.
Step 6 - Start OpenConnect Server
Start the OpenConnect VPN server.
$ sudo systemctl start ocserv
Check the status of the service.
$ sudo systemctl status ocserv
You will get a similar output.
? ocserv.service - OpenConnect SSL VPN server Loaded: loaded (/etc/systemd/system/ocserv.service; disabled; vendor preset: enabled) Active: active (running) since Thu 2023-04-20 08:52:18 UTC; 2s ago Docs: man:ocserv(8) Main PID: 19965 (ocserv-main) Tasks: 2 (limit: 1026) Memory: 1.4M CPU: 9ms CGroup: /system.slice/ocserv.service ??19965 ocserv-main ??19966 ocserv-sm Apr 20 08:52:18 openconnect ocserv[19965]: note: skipping 'pid-file' config option Apr 20 08:52:18 openconnect ocserv[19965]: note: vhost:default: setting 'plain' as primary authentication method Apr 20 08:52:18 openconnect ocserv[19965]: error connecting to sec-mod socket '/var/run/ocserv-socket.a4413bc9': No such file or directory Apr 20 08:52:18 openconnect ocserv[19965]: note: setting 'file' as supplemental config option Apr 20 08:52:18 openconnect ocserv[19965]: listening (TCP) on 0.0.0.0:443... Apr 20 08:52:18 openconnect ocserv[19965]: listening (TCP) on [::]:443... Apr 20 08:52:18 openconnect ocserv[19966]: ocserv[19966]: sec-mod: reading supplemental config from files Apr 20 08:52:18 openconnect ocserv[19966]: sec-mod: reading supplemental config from files Apr 20 08:52:18 openconnect ocserv[19966]: ocserv[19966]: sec-mod: sec-mod initialized (socket: /var/run/ocserv-socket.a4413bc9.0) Apr 20 08:52:18 openconnect ocserv[19966]: sec-mod: sec-mod initialized (socket: /var/run/ocserv-socket.a4413bc9.0)
If you see the error regarding connecting to sec-mod socket
, ignore it. It's normal. It will initialize the file if it doesn't find it.
Step 7 - Create VPN accounts
You can create VPN accounts using the ocpasswd
utility. Run the following command to create a new VPN account.
$ sudo ocpasswd -c /etc/ocserv/ocpasswd username Enter password: Re-enter password:
The password will be saved to the /etc/ocserv/ocpasswd
file. To reset the password for the username
, run the above command again. Run the above command with a different user to create another account.
Step 8 - Enable IP Forwarding
For the VPN server to route packets between the client and the Internet, you need to enable IP forwarding by running the following command.
$ echo "net.ipv4.ip_forward = 1" | sudo tee /etc/sysctl.d/60-custom.conf
Run the following commands to enable the 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
Make the changes permanent using the following command.
$ sudo sysctl -p /etc/sysctl.d/60-custom.conf
Step 9 - Configure IP Masquerading
The next step is to set up IP masquerading in the firewall so that the VPN server can work as a virtual router for the clients. Find the name of the server's main network interface.
$ ip addr
You will get a similar output.
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq state UP group default qlen 1000 link/ether 56:00:04:67:7e:79 brd ff:ff:ff:ff:ff:ff inet 95.179.138.135/23 metric 100 brd 95.179.139.255 scope global dynamic enp1s0 valid_lft 66999sec preferred_lft 66999sec inet6 2a05:f480:1400:2381:5400:4ff:fe67:7e79/64 scope global dynamic mngtmpaddr noprefixroute valid_lft 2591657sec preferred_lft 604457sec inet6 fe80::5400:4ff:fe67:7e79/64 scope link valid_lft forever preferred_lft forever
In our case, enp1s0
is the name of the interface. Add the iptables command in a UFW configuration file by opening it for editing.
$ sudo nano /etc/ufw/before.rules
Add the following lines at the end of the file. Replace enp1s0
in the code with your network interface.
# NAT table rules *nat :POSTROUTING ACCEPT [0:0] -A POSTROUTING -s 10.10.10.0/24 -o enp1s0 -j MASQUERADE # End each table with the 'COMMIT' line or these rules won't be processed COMMIT
Find the following lines in the file.
# ok icmp code for FORWARD -A ufw-before-forward -p icmp --icmp-type destination-unreachable -j ACCEPT -A ufw-before-forward -p icmp --icmp-type time-exceeded -j ACCEPT -A ufw-before-forward -p icmp --icmp-type parameter-problem -j ACCEPT -A ufw-before-forward -p icmp --icmp-type echo-request -j ACCEPT
Paste the following lines after it.
# allow forwarding for trusted network -A ufw-before-forward -s 10.10.10.0/24 -j ACCEPT -A ufw-before-forward -d 10.10.10.0/24 -j ACCEPT
Save the file by pressing Ctrl + X and entering Y when prompted.
Restart the firewall.
$ sudo systemctl restart ufw
You can check the Masquerade rule using the following command.
$ sudo iptables -t nat -L POSTROUTING
You will get the following output.
Chain POSTROUTING (policy ACCEPT) target prot opt source destination MASQUERADE all -- 10.10.10.0/24 anywhere
Step 10 - Connect using OpenConnect Client
We will install OpenConnect Client on a Ubuntu 22.04 machine. Run the following command to install the client.
$ sudo apt install openconnect
Next, connect to the VPN server using the following command. The -b
flag makes the client run in the background once the connection is established.
$ sudo openconnect -b vpn.example.com:443
You will be asked to enter the VPN username and password. Enter the credentials created in step 7.
POST https://vpn.example.com/ Connected to 95.179.138.135:443 SSL negotiation with vpn.example.com Connected to HTTPS on vpn.example.com with ciphersuite (TLS1.3)-(ECDHE-SECP256R1)-(ECDSA-SECP256R1-SHA256)-(AES-256-GCM) XML POST enabled Please enter your username. Username:navjot POST https://vpn.example.com/auth Please enter your password. Password: POST https://vpn.example.com/auth
You will see the following output on a successful connection. DTLS is disabled because we disabled the UDP.
Got CONNECT response: HTTP/1.1 200 CONNECTED CSTP connected. DPD 90, Keepalive 60 No DTLS address Set up UDP failed; using SSL instead Configured as 192.168.1.13, with SSL connected and DTLS disabled Continuing in background; pid 1650
Run the following command to stop the connection.
$ sudo pkill openconnect
Let us create some systemd scripts for OpenConnect. The first script is to get the client to auto-connect on system startup.
Create and open the service file for editing.
$ sudo nano /etc/systemd/system/openconnect.service
Paste the following code in it.
[Unit] Description=OpenConnect VPN Client After=network-online.target systemd-resolved.service 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 the file by pressing Ctrl + X and entering Y when prompted.
Enable the service.
$ sudo systemctl enable openconnect.service
Start the service.
$ sudo systemctl start openconnect.service
To restart your VPN connection automatically when your PC resumes from the suspend state, you need to create another systemd script.
Create and open the restart script for editing.
$ sudo nano /etc/systemd/system/openconnect-restart.service
Paste the following code in it.
[Unit] Description=Restart OpenConnect client when resuming from suspend After=suspend.target [Service] Type=simple ExecStart=/bin/systemctl --no-block restart openconnect.service [Install] WantedBy=suspend.target
Save the file by pressing Ctrl + X and entering Y when prompted.
Enable the service.
$ sudo systemctl enable openconnect-restart.service
We can also create a service to restart the VPN connection automatically when it drops. Create and open the VPN check service for editing.
$ sudo nano /etc/systemd/system/openconnect-check.service
Paste the following code in it.
[Unit] Description=OpenConnect VPN Connectivity Checker After=openconnect.service [Service] Type=simple ExecStart=/bin/bash -c 'for ((; ; )) do (ping -c9 10.10.10.1 || systemctl restart openconnect) done' [Install] WantedBy=multi-user.target
Save the file by pressing Ctrl + X and entering Y when prompted.
Enable and start the service.
$ sudo systemctl enable enable openconnect-check.service --now
This will run the ping command forever to check the VPN connection. If it drops, it will automatically restart OpenConnect.
You can download OpenConnect GUI Clients if you want. However, they haven't been updated in quite a while. If you want an updated GUI client, you can visit the OpenConnect GUI GitLab repository and compile it yourself.
Conclusion
That completes our tutorial on installing an OpenConnect VPN server on a Ubuntu 22.04 server and using the command line client to connect to it. If you have any questions, post them in the comments below.