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.
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.
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 126.96.36.199 --dport 500 -j DNAT --to-destination 10.0.122.7 -A PREROUTING -i eno1 -p udp -d 188.8.131.52 --dport 4500 -j DNAT --to-destination 10.0.122.7
Note that in this example "184.108.40.206" is the public IP address of the KVM host and "10.0.122.7" 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.
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 "
<VirtualHost *:80> ServerName vpn.tqdev.com # Proxy all requests ProxyPreserveHost On ProxyPass / http://10.0.122.7:80/ </VirtualHost>
Replace "10.0.122.7" with the internal IP address of your VPN server and "vpn.tqdev.com" with the hostname you use for your VPN server.
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.
We configure Strongswan by editing the file "
/etc/ipsec.conf" so that it has the following content:
config setup strictcrlpolicy=yes uniqueids=no conn roadwarrior auto=add type=tunnel keyexchange=ikev2 fragmentation=yes forceencaps=yes ike=aes256-aes128-sha256-sha1-modp3072-modp2048-modp1024 dpdaction=clear dpddelay=180s rekey=no left=%any firstname.lastname@example.org leftcert=fullchain.pem leftsendcert=always leftsubnet=10.0.122.0/24 right=%any rightid=%any rightauth=eap-mschapv2 eap_identity=%identity rightsendcert=never rightsourceip=10.0.122.50-10.0.122.100
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.
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.
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.
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.