Update 04/20/2014: Adjusted to take into account the modular configuration layout introduced in strongSwan 5.1.2. Tweaked cipher settings to provide perfect forward secrecy if supported by the client.
This article is a step by step guide on how to prepare strongSwan 5 to run your own private VPN, allowing you to stop snoopers from spying on your online activities, to bypass geo-restrictions, and to circumvent overzealous firewalls.
strongSwan is a modern and complete IPsec implementation with full support for IKEv1 and IKEv2. It’s natively supported by most modern clients, including Linux, Windows 7, Apple iOS, Mac OSX, FreeBSD and BlackBerry OS.
If you wonder why I chose strongSwan over Openswan, check out this post from strongSwan maintainer Prof. Andreas Steffen (yes, it’s biased and dated, but I find it convincing nonetheless).
Throughout this post I assume that you’re using Debian Wheezy. If you don’t – don’t worry. It should be easy to follow the guide even if you favor another Linux distribution.
Debian Wheezy ships with strongSwan 4.5.2. I prefer strongSwan 5, the new mainline branch, which got rid of Pluto in favor of a single daemon, charon, to handle both IKEv1 and IKEv2. Instead of installing from source, let’s get a copy from wheezy-backports, which includes strongSwan 5.1.2 from Debian testing recompiled for Wheezy.
Add wheezy-backports to your APT repository
$ echo "deb http://ftp.debian.org/debian wheezy-backports main" \ > /etc/apt/sources.list.d/wheezy-backports.list $ apt-get update
$ apt-get -t wheezy-backports install strongswan libcharon-extra-plugins
This installs the strongSwan package along with its dependencies (there are only a few). To determine that you’re running the right version, do:
$ ipsec version
Linux strongSwan U5.1.2/K3.2.0-4-amd64 Institute for Internet Technologies and Applications University of Applied Sciences Rapperswil, Switzerland See 'ipsec --copyright' for copyright information.
Excellent – you’re now running strongSwan 5.1.2 on Linux kernel 3.2.0.
Create your certification authority (CA)
The first step is to generate the X.509 certificates, including a certificate authority (CA), a server certificate, and at least one client certificate.
Let’s start by creating a self-signed root CA certificate.
$ cd /etc/ipsec.d/ $ ipsec pki --gen --type rsa --size 4096 \ --outform pem \ > private/strongswanKey.pem $ chmod 600 private/strongswanKey.pem $ ipsec pki --self --ca --lifetime 3650 \ --in private/strongswanKey.pem --type rsa \ --dn "C=CH, O=strongSwan, CN=strongSwan Root CA" \ --outform pem \ > cacerts/strongswanCert.pem
The result is a 4096 bit RSA private key
strongswanKey.pem (line 4) and a self-signed CA certificate
strongswanCert.pem (line 10) with a validity of 10 years (3650 days). The files are stored in PEM encoded format (I prefer working with PEM over binary DER, the strongSwan default).
You can change the Distinguished Name (DN) to more relevant values for country (C), organization (O), and common name (CN), but you don’t have to.
To list the properties of your newly generated certificate, type in the following command:
$ ipsec pki --print --in cacerts/strongswanCert.pem
cert: X509 subject: "C=CH, O=strongSwan, CN=strongSwan Root CA" issuer: "C=CH, O=strongSwan, CN=strongSwan Root CA" validity: not before Nov 22 11:55:41 2013, ok not after Nov 20 11:55:41 2023, ok (expires in 3649 days) serial: 65:39:93:df:a0:f8:40:03 flags: CA CRLSign self-signed authkeyId: 45:30:11:da:a4:0e:0b:0a:a3:41:a5:81:41:ab:d8:04:7a:40:6c:c0 subjkeyId: 45:30:11:da:a4:0e:0b:0a:a3:41:a5:81:41:ab:d8:04:7a:40:6c:c0 pubkey: RSA 4096 bits keyid: dc:15:91:95:04:07:a5:13:69:5f:77:65:26:d7:02:3f:60:ec:73:c8 subjkey: 45:30:11:da:a4:0e:0b:0a:a3:41:a5:81:41:ab:d8:04:7a:40:6c:c0
Create your VPN host certificate
$ cd /etc/ipsec.d/ $ ipsec pki --gen --type rsa --size 2048 \ --outform pem \ > private/vpnHostKey.pem $ chmod 600 private/vpnHostKey.pem $ ipsec pki --pub --in private/vpnHostKey.pem --type rsa | \ ipsec pki --issue --lifetime 730 \ --cacert cacerts/strongswanCert.pem \ --cakey private/strongswanKey.pem \ --dn "C=CH, O=strongSwan, CN=vpn.zeitgeist.se" \ --san vpn.zeitgeist.se \ --flag serverAuth --flag ikeIntermediate \ --outform pem > certs/vpnHostCert.pem
The result is a 2048 bit RSA private key
vpnHostKey.pem (line 4). In line 6 we extract its public key and pipe it over to issue
vpnHostCert.pem (line 13), a host certificate signed by your CA. The certificate has a validity of two years (730 days). It identifies the VPN host by its Fully Qualified Domain Name (FQDN) (here: vpn.zeitgeist.se).
Important: The domain name or IP address of your VPN server, which is later entered in the client’s connection properties, MUST be contained either in the subject Distinguished Name (here in CN, line 10) and/or in a subject Alternative Name (line11). I prefer to include it in both. Make sure both times to replace vpn.zeitgeist.se with your VPN’s hostname – or else the connection between client and server will fail!
Important: If you’re going to use the built-in VPN client of Windows 7, you MUST add the serverAuth extended key usage flag to your host certificate as shown above, or the client will refuse to connect. In addition, OS X 10.7.3 or older requires the ikeIntermediate flag, which we also added here. Since the addition of these two flags probably won’t hurt anyone (as far as I know), you should make sure you keep them there.
Let’s take a look at the properties of our newly generated certificate.
$ ipsec pki --print --in certs/vpnHostCert.pem
cert: X509 subject: "C=CH, O=strongSwan, CN=vpn.zeitgeist.se" issuer: "C=CH, O=strongSwan, CN=strongSwan Root CA" validity: not before Nov 22 21:16:51 2013, ok not after Nov 22 21:16:51 2015, ok (expires in 729 days) serial: 0c:05:d7:d5:57:0e:d9:48 altNames: vpn.zeitgeist.se flags: serverAuth iKEIntermediate authkeyId: 9b:57:35:fb:cd:9e:2d:20:37:1d:61:4c:e7:c4:5b:5e:dc:64:ad:fc subjkeyId: 5f:12:c2:06:ee:2b:1e:cc:5f:78:54:ff:f0:f3:7b:a0:2b:c0:b4:d6 pubkey: RSA 2048 bits keyid: 6f:a7:99:60:27:27:09:96:02:c1:b9:d9:7d:c1:b0:10:e3:e1:d5:45 subjkey: 5f:12:c2:06:ee:2b:1e:cc:5f:78:54:ff:f0:f3:7b:a0:2b:c0:b4:d6
Create a client certificate
Any client will require a personal certificate in order to use the VPN. The process is analogous to generating a host certificate, except that we identify a client certificate by the client’s e-mail address rather than a hostname.
$ cd /etc/ipsec.d/ $ ipsec pki --gen --type rsa --size 2048 \ --outform pem \ > private/AlexanderKey.pem $ chmod 600 private/AlexanderKey.pem $ ipsec pki --pub --in private/AlexanderKey.pem --type rsa | \ ipsec pki --issue --lifetime 730 \ --cacert cacerts/strongswanCert.pem \ --cakey private/strongswanKey.pem \ --dn "C=CH, O=strongSwan, CNemail@example.com" \ --san firstname.lastname@example.org \ --outform pem > certs/AlexanderCert.pem
The result is a 2048 bit RSA private key
AlexanderKey.pem (line 4). In line 6 we extract its public key and pipe it over to issue
AlexanderCert.pem (line 12), the first client certificate signed by your CA. The certificate has a validity of two years (730 days) and identifies the client by his e-mail address (here: email@example.com).
Export client certificate as a PKCS#12 file
A VPN client needs a client certificate, its private key, and the signing CA certificate. The most convenient way is to put everything in a single signed PKCS#12 file and export it with a paraphrase.
$ cd /etc/ipsec.d/ $ openssl pkcs12 -export -inkey private/AlexanderKey.pem \ -in certs/AlexanderCert.pem -name "Alexander's VPN Certificate" \ -certfile cacerts/strongswanCert.pem \ -caname "strongSwan Root CA" \ -out Alexander.p12
Now you can send Alexander.p12 and its export paraphrase to the person who’s going to install it onto the client. In some cases (iOS for example) you have to separately include the CA certificate
Revoke a certificate (if necessary)
If a certificate is lost or stolen, it must be revoked so nobody can use it to connect to your VPN server. Assuming the certificate from the previous step got stolen, we revoke it with:
$ cd /etc/ipsec.d/ $ ipsec pki --signcrl --reason key-compromise \ --cacert cacerts/strongswanCert.pem \ --cakey private/strongswanKey.pem \ --cert certs/AlexanderCert.pem \ --outform pem > crls/crl.pem
This generates the new certificate revocation list (CRL) crls/crl.pem. When someone tries to authenticate with the stolen certificate, he’ll receive an authentication credentials error message, and your log file will contain something like:
charon: 13[CFG] certificate was revoked on Nov 24 17:34:40 UTC 2013, reason: key compromise
To add another revoked certificate to the same list, we need to copy the existing list into a temporary file:
$ cd /etc/ipsec.d/ $ cp crls/crl.pem crl.pem.tmp $ ipsec pki --signcrl --reason key-compromise \ --cacert cacerts/strongswanCert.pem \ --cakey private/strongswanKey.pem \ --cert certs/AnotherStolenCert.pem \ --lastcrl crl.pem.tmp \ --outform pem > crls/crl.pem $ rm crl.pem.tmp
Certificates – Recap
So far you’ve created the following files:
/etc/ipsec.d/private/strongswanKey.pem # CA private key /etc/ipsec.d/cacerts/strongswanCert.pem # CA certificate /etc/ipsec.d/private/vpnHostKey.pem # VPN host private key /etc/ipsec.d/certs/vpnHostCert.pem # VPN host certificate /etc/ipsec.d/private/AlexanderKey.pem # Client "Alexander" private key /etc/ipsec.d/certs/AlexanderCert.pem # Client "Alexander" certificate /etc/ipsec.d/Alexander.p12 # Client "Alexander" PKCS#12 file
The private key
/etc/ipsec.d/private/strongswanKey.pem of the CA should be moved somewhere safe, possibly to a special signing host without access to the Internet. Theft of this master signing key would completely compromise your public key infrastructure.
Only three files are required for your strongSwan configuration:
/etc/strongswan.conf, which may point to a directory containing further configuration snippets
Fortunately, the default strongSwan application configuration works just fine for us. For the purpose of this article there is nothing you need to do here. I invite you though to take a look at the strongSwan Wiki for a full list of configuration options of strongswan.conf.
Let’s do the fun stuff. Here is my
# ipsec.conf - strongSwan IPsec configuration file config setup # uniqueids=never charondebug="cfg 2, dmn 2, ike 2, net 2" conn %default keyexchange=ikev2 ike=aes128-sha256-ecp256,aes256-sha384-ecp384,aes128-sha256-modp2048,aes128-sha1-modp2048,aes256-sha384-modp4096,aes256-sha256-modp4096,aes256-sha1-modp4096,aes128-sha256-modp1536,aes128-sha1-modp1536,aes256-sha384-modp2048,aes256-sha256-modp2048,aes256-sha1-modp2048,aes128-sha256-modp1024,aes128-sha1-modp1024,aes256-sha384-modp1536,aes256-sha256-modp1536,aes256-sha1-modp1536,aes256-sha384-modp1024,aes256-sha256-modp1024,aes256-sha1-modp1024! esp=aes128gcm16-ecp256,aes256gcm16-ecp384,aes128-sha256-ecp256,aes256-sha384-ecp384,aes128-sha256-modp2048,aes128-sha1-modp2048,aes256-sha384-modp4096,aes256-sha256-modp4096,aes256-sha1-modp4096,aes128-sha256-modp1536,aes128-sha1-modp1536,aes256-sha384-modp2048,aes256-sha256-modp2048,aes256-sha1-modp2048,aes128-sha256-modp1024,aes128-sha1-modp1024,aes256-sha384-modp1536,aes256-sha256-modp1536,aes256-sha1-modp1536,aes256-sha384-modp1024,aes256-sha256-modp1024,aes256-sha1-modp1024,aes128gcm16,aes256gcm16,aes128-sha256,aes128-sha1,aes256-sha384,aes256-sha256,aes256-sha1! dpdaction=clear dpddelay=300s rekey=no left=%any leftsubnet=0.0.0.0/0 leftcert=vpnHostCert.pem right=%any rightdns=22.214.171.124,126.96.36.199 rightsourceip=172.16.16.0/24 conn IPSec-IKEv2 keyexchange=ikev2 auto=add conn IPSec-IKEv2-EAP also="IPSec-IKEv2" rightauth=eap-mschapv2 rightsendcert=never eap_identity=%any conn CiscoIPSec keyexchange=ikev1 # forceencaps=yes rightauth=pubkey rightauth2=xauth auto=add
This configuration has settings for three types of VPN services: IKEv2 + RSA certificate, IKEv2 + EAP, and IKEv1 + Xauth RSA, thus providing compatibility for a wide range of IPsec clients.
Let’s go briefly over the important items:
- line 4: (disabled here) by default only one client can connect at the same time with an identical certificate and/or password combo; the newer connection will always replace the older (in other words, a new connecting client using the same credentials kicks out the older still connected client). If you don’t like this, for instance because you want to use the same client certificates on multiple clients at the same time, enable this option
- line 5: slightly more verbose logging. Very useful for debugging. Check out this link for a full list of options.
- line 7: individual conn sections inherit the settings from the conn %default section. Put everything in here that you would otherwise have to repeat in the other conn sections. Helps to keep your setting file more concise.
- line 21: settings specific to IKEv2 + RSA certificate connections
- line 25: settings specific to IKEv2 + EAP connections
- line 31: settings specific to IKEv1 + Xauth RSA connections
Your best resource for learning more about the available options is the strongSwan Wiki.
For now, if you like to enable your VPN server as quickly as possible, use above configuration as a template; only make sure to modify line 16 leftcert=vpnHostCert.pem to name your host VPN certificate instead.
Lastly, here is my
# This file holds shared secrets or RSA private keys for authentication. # RSA private key for this host, authenticating it to any other host # which knows the public part. Suitable public keys, for ipsec.conf, DNS, # or configuration of other implementations, can be extracted conveniently # with "ipsec showhostkey". : RSA vpnHostKey.pem user1 : EAP "topsecretpassword" user2 : XAUTH "evenmoretopsecretpassword"
- line 8: identifies the private key of the VPN host to allow your host to authenticate itself with its host certificate
- line 9: defines an EAP credential (username / password) that can be used by clients to connect without client certificate
- line 10: defines an XAUTH credential (username / password) that is required in addition to a client certificate for IKEv1 + Xauth RSA connections (as used by Apple iOS clients for example)
Whenever you edit
/etc/ipsec.secrets while strongSwan is running, you must reload the file:
$ ipsec rereadsecrets
Once again, the strongSwan Wiki has all the details if you are interested.
You’re almost done setting up your server. There are a few things left to make your VPN server properly route the VPN tunnel:
$ echo 1 > /proc/sys/net/ipv4/ip_forward $ echo 0 > /proc/sys/net/ipv4/conf/all/accept_redirects $ echo 0 > /proc/sys/net/ipv4/conf/all/send_redirects
Or to make it permanent, add the following to your
# VPN net.ipv4.ip_forward = 1 net.ipv4.conf.all.accept_redirects = 0 net.ipv4.conf.all.send_redirects = 0
Use the following iptables rules (adjust the interface if yours isn’t eth0, and make sure to enter your VPN host IP where indicated):
$ iptables -t nat -A POSTROUTING -o eth0 ! -p esp \ -j SNAT --to-source <your VPN host IP>
Speaking of iptables, if you have a restrictive firewall for incoming traffic, don’t forget to allow IPsec communications. Three rules are required:
$ iptables -A INPUT -p udp --dport 500 --j ACCEPT $ iptables -A INPUT -p udp --dport 4500 --j ACCEPT $ iptables -A INPUT -p esp -j ACCEPT
- line 1: for ISAKMP (handling of security associations)
- line 2: for NAT-T (handling of IPsec between natted devices)
- line 3: for ESP payload (the encrypted data packets)
That’s it! Restart strongSwan and your VPN server is ready.
$ service ipsec restart
Of course you cannot do anything with until you’ve configured your clients. Instead of boring you with dull screenshots, here are the essential strongSwan Wiki articles describing how to configure IPsec clients for popular systems. Of course you can also Google for other howtos since the client configuration is mostly independent from the server software.
Windows 7 with IKEv2 + RSA certificate
- Installing the certificate (client + CA)
- Configuring the built-in client
- Starting the VPN connection