StrongSwan VPN setup
This is a guide for setting up strongSwan, a VPN solution that allows you to securely connect to your home network from a remote location. The guide is based on this excellent blog post by Atomstar.
While strongSwan can work with a wide range of scenarios, the setup presented here is a typical home network where the VPN server acts as a gateway allowing you to connect to your home devices from outside the network.
I used a Raspberry Pi in my setup, but the instructions can be easily applied to any Debian-based Linux distribution.
Why strongSwan
I personally chose strongSwan because it uses IKEv2/IPSec under the hood, a protocol stack natively supported by macOS and iOS without the need of a separate app. After struggling to configure an OpenVPN client on macOS (via the Tunnelblick app) I decided to look for an alternative solution, and was surprised to see how smooth strongSwan's configuration went.
Another reason would be that StrongSwan is already present in the official Debian apt repository, making installation easier and more secure.
There are other IPSec solutions for Linux, such as Openswan or Libreswan. The differences between all the "Swans" are highlighted in this serverfault question, but ultimately StrongSwan seems to be the more mature project and better suited for Debian/Ubuntu/RaspberryPi.
The setup
Installing required packages
strongSwan is part of the official apt repository for RaspberryPi OS, Debian and Ubuntu, so installation involves just running an apt install
:
sudo apt install strongswan strongswan-pki libcharon-extra-plugins libstrongswan-extra-plugins
Certificates and keys
Let's generate the required certificate and keys.
We will do this within a directory that nobody else can access:
mkdir ~/vpn-certs/
cd ~/vpn-certs/
chmod 700 .
Let's set some environment variables to help us with the commands. Adjust these to match your setup:
export SERVER_FQDN="mihai.fm"
export SERVER_COUNTRY="RO"
An IKEv2 server requires a certificate to identify itself to clients. This needs to be signed by a certificate authority root certificate and key.
We first need to generate the key for our certificate authority.
ipsec pki --gen --type rsa --size 4096 --outform pem > server-root-key.pem
chmod 600 server-root-key.pem
Then we generate the root certificate for our certificate authority.
ipsec pki --self --ca --lifetime 3650 \
--in server-root-key.pem \
--type rsa --dn "C=${SERVER_COUNTRY}, O=VPN Server, CN=VPN Server Root CA" \
--outform pem > server-root-ca.pem
Next, let's generate a key for our VPN server:
ipsec pki --gen --type rsa --size 4096 --outform pem > vpn-server-key.pem
Finally, generate the certificate for our VPN server and sign it with the certificate authority key/certificate.
ipsec pki --pub --in vpn-server-key.pem \
--type rsa | ipsec pki --issue --lifetime 1825 \
--cacert server-root-ca.pem \
--cakey server-root-key.pem \
--dn "C=${SERVER_COUNTRY}, O=VPN Server, CN=${SERVER_FQDN}" \
--san ${SERVER_FQDN} \
--flag serverAuth --flag ikeIntermediate \
--outform pem > vpn-server-cert.pem
Copy the output files to the necessary locations and set permissions:
sudo cp ./vpn-server-cert.pem /etc/ipsec.d/certs/vpn-server-cert.pem
sudo cp ./vpn-server-key.pem /etc/ipsec.d/private/vpn-server-key.pem
sudo chown root /etc/ipsec.d/private/vpn-server-key.pem
sudo chgrp root /etc/ipsec.d/private/vpn-server-key.pem
sudo chmod 600 /etc/ipsec.d/private/vpn-server-key.pem
All these commands are better explained in this digitalocean guide.
Configuration file
The main configuration file for strongSwan is /etc/ipsec.conf
. All the configuration options for this file are well documented in the strongSwan wiki.
Let's make a backup of the original file first:
sudo cp /etc/ipsec.conf /etc/ipsec.conf.original
Below is the actual /etc/ipsec.conf
I used in my setup:
conn ikev2-vpn
auto=add
forceencaps=yes
mobike=yes
ikelifetime=22h
lifetime=23h
# manually choosing the ciphers
ike=aes192gcm16-aes128gcm16-prfsha256-ecp256-ecp521,aes192-sha256-modp3072
esp=aes192gcm16-aes128gcm16-ecp256-modp3072,aes192-sha256-ecp256-modp3072
dpdaction=clear
dpddelay=300s
left=%any
leftid=@mihai.fm
leftcert=/etc/ipsec.d/certs/vpn-server-cert.pem
leftsendcert=always
leftsubnet=0.0.0.0/0
right=%any
rightid=%any
rightauth=eap-mschapv2
rightdns=10.10.10.10
rightsourceip=%dhcp
rightsendcert=never
eap_identity=%identity
The only things that need to be changed are:
leftid
- needs to be the domain name of your serverrightdns
- address of a DNS server to be used by the clients.
I'm also running Pi-hole on my Raspberry-Pi, so I've set this value to the local IP address of the Pi.
Regarding the ciphers, there is more information on Atomstar's blog post, including some performance results for the various ciphers.
Adding login info
Login credentials for connecting clients can be created by editing /etc/ipsec.secrets
:
mihai.fm : RSA "/etc/ipsec.d/private/vpn-server-key.pem"
YOUR_USERNAME %any% : EAP "YOUR_PASSWORD"
The file format is documented on the strongSwan wiki.
Starting ipsec
After editing /etc/ipsec.conf
and /etc/ipsec.secrets
, we need to start the IKE daemon used by strongSwan:
sudo ipsec start
If we make any changes to the configuration, we can reload the files with:
sudo ipsec reload
IP packet forwarding
One critical configuration item without which this setup wouldn't work, is to enable IPv4 packet forwarding in Linux. This is done by uncommenting a line in /etc/sysctl.conf
# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1
Enable and start the service
Finally we can enable and start strongSwan:
sudo systemctl enable strongswan
sudo systemctl start strongswan
Port forwarding
Going into our router settings, we need to make sure the following ports are open and forwarded to our VPN server:
- UDP 500
- UDP 4500
Connecting clients
In order to connect our clients to the VPN server, we need to install server-root-ca.pem
on any of the clients.
In macOS, we can simply copy the file to our device and double click on it. This will add the certificate to the keychain, after which we need to explicitly Trust it. To create the VPN connection, we can go to System Preferences -> Network -> click the + button -> set Interface to VPN
.
For iOS, we can email the certificate to our self and click on the attachment in the Mail app. This will install the certificate on the phone. We can then go to Settings -> VPN -> Add VPN Configuration...
and enter the credentials we configured in /etc/ipsec.secrets
.
More detailed instructions on how to connect clients (including a Windows client) can be found on the digitalocean guide.
Troubleshooting
strongSwan adds log entries to the system log, which is /var/log/syslog
on the Raspberry Pi, so basic troubleshooting can be done by checking this file.
There was only one weird problem that I encountered during my setup, that might be worth mentioning. I detailed the problem in this serverfault question, but basically I could not connect to the VPN if my router happened to have the same private IP address (or same network) as the Wi-Fi gateway I was connecting from (typically 192.168.0.1
).
The easiest way to fix this was to configure my router with a different private IP, less likely to be encountered in the wild.