Blog about software development


Install an IPsec IKEv2 VPN server on KVM

03 Feb 2020 - by 'Maurits van der Schee'

In a previous post I have shown how to set up port forwarding to KVM virtual machines. In this post I will show you how to add an IPsec IKEv2 VPN to your (Ubuntu 18.04) KVM setup. I will show how to install the VPN endpoint on a virtual machine and make it available using port forwards. This allows for a simple networking setup and easy replacement of VPN technology.

Install Strongswan

You need to setup a new Ubuntu virtual machine using "virt-install" (as described here). On this newly created machine you need to install the strongswan IPsec software:

sudo apt-get install strongswan libstrongswan-standard-plugins strongswan-libcharon libcharon-standard-plugins libcharon-extra-plugins

There are relevant config file in:

In this tutorial we will be only modifying the first two files.

Configure forwarding on the gateway

In this tutorial I assume that you are running the VPN server as a guest on your Ubuntu KVM host machine and that the KVM host machine is running UFW.

Add the following to "/etc/ufw/before.rules" in the "nat" chain (as explained in the previous post) on the KVM host:

-A PREROUTING -i eno1 -p udp -d --dport 500 -j DNAT --to-destination
-A PREROUTING -i eno1 -p udp -d --dport 4500 -j DNAT --to-destination

Note that in this example "" is the public IP address of the KVM host and "" is the static IP address (see this earlier post) of the VPN server.

This port forward is not enough, as we also need to allow forwarding of IKEv2 VPN traffic (IPsec passthrough) on the KVM host, by running:

sudo ufw route allow in on any out on any proto esp 

With this command we tell UFW to allow IPsec passthrough on our KVM host towards our VPN server.

Forward port 80 on the webserver

If you run a webserver as one of your KVM guests, then you have probably forwarded port 80 to this webserver. Since we want to use "certbot" over HTTP we need to configure a proxy forward for the specific hostname of your VPN server. We use "mod_proxy_http" for this.

sudo a2enmod proxy_http

Then add the following in "/etc/apache2/sites-available/100-vpncertbot.conf"

<VirtualHost *:80>
    ServerName vpn.tqdev.com
    # Proxy all requests
    ProxyPreserveHost On
    ProxyPass /

Replace "" with the internal IP address of your VPN server and "vpn.tqdev.com" with the hostname you use for your VPN server.

Configure Lets Encrypt automatic certificate renewal

To install the latest "certbot" you may run:

sudo add-apt-repository ppa:certbot/certbot
sudo apt update
sudo apt install certbot
sudo certbot certonly --standalone --preferred-challenges http -d vpn.tqdev.com
sudo nano /etc/letsencrypt/renewal/vpn.tqdev.com.conf

A text file will open with some configuration options. Add your hook on the last line:

renew_hook = cp /etc/letsencrypt/live/vpn.tqdev.com/fullchain.pem /etc/ipsec.d/certs/ && cp /etc/letsencrypt/live/vpn.tqdev.com/chain.pem /etc/ipsec.d/cacerts/ && cp /etc/letsencrypt/live/vpn.tqdev.com/privkey.pem /etc/ipsec.d/private/ && ipsec reload 

Save and close the file, then run a "certbot dry run" to make sure the syntax is ok:

sudo certbot renew --dry-run

This command should give a warning:

Dry run: skipping deploy hook command

And otherwise run correct, printing:

Congratulations, all renewals succeeded.

Showing that certbot configuration is correct.

Strongswan roadwarrior configuration

We configure Strongswan by editing the file "/etc/ipsec.conf" so that it has the following content:

config setup

conn roadwarrior

Make sure the "leftid" matches your hostname prefixed with an "at" sign (which means: don't resolve). Adjust the "leftsubnet" to match with your private network and the "rightsourceip" with the (virtual) ip addresses you want to give to clients connecting to your VPN server.

If you want to capture all traffic and set the default route over the VPN tunnel, you need to set:


If you want to suggest a DNS server (such as Cloudflare DNS), you may add:


Note that Windows 10 may only set a default route for IPv4 traffic (and use the suggested DNS server) if you disable IPv6 on your LAN adapter.

In the file "/etc/ipsec.secrets" you should put the following to create 3 users:

vpn.tqdev.com : RSA "privkey.pem"
username1 : EAP "SomeVeryLongAndSecretPasswordForUser1"
username2 : EAP "SomeVeryLongAndSecretPasswordForUser2"
username3 : EAP "SomeVeryLongAndSecretPasswordForUser3"

The first line identifies the server using the private key. The next 3 lines define 3 users. Make sure that there are spaces around the colon (":") as shown above.

Set up forwarding

Add the following lines to the end of the file "/etc/sysctl.conf" to make your Linux machine act as an IPv4 router:

# enable ipv4 routing
net.ipv4.ip_forward = 1

Now you need to run:

sudo sysctl -p

This command reloads sysctl config file and makes the settings effective.

Installing the client on Ubuntu

If you are connecting from Windows 10, then you don't need to install client software for this VPN connection. If you use Ubuntu, then you need to install a client. You can do so by running:

sudo apt install network-manager-strongswan libcharon-standard-plugins libcharon-extra-plugins

If you don't see the VPN option marked "strongswan" in the network manager applet, then you may have to log out and in for it to appear.

Next: Installing OpenConnect VPN

In the next post I will show you how to add an OpenConnect VPN to your KVM setup. I will show how to install the VPN endpoint on a virtual machine, as a replacement for the IPsec VPN server that we installed in this post. OpenConnect may be easier to setup and maintain, but it does require VPN client software on Windows 10.

Click here to read the next article (on how to add OpenConnect VPN to your KVM setup).

PS: Liked this article? Please share it on Facebook, Twitter or LinkedIn.