IPSEC VPN On Ubuntu 16
IPSEC VPN On Ubuntu 16
04 with StrongSwan
Home
Tutorials
IPSEC VPN on Ubuntu 16.04 with StrongSwan
Table of Contents
1. Why a VPN?
2. No L2TP?
3. Overview
4. Install Strongswan
5. Certificates
1. Client certificate
2. Revoking a certificate
6. IPSEC Configuration
7. Firewall & Packet Routing
1. Persistent settings via /etc/rc.local
8. Start the VPN
9. Client Configuration
10. Sources
This is a guide on setting up an IPSEC VPN server on Ubuntu 16.04 using StrongSwan as the
IPsec server and for authentication. It has a detailed explanation with every step. We choose the
IPSEC protocol stack because of vulnerabilities found in pptpd VPNs and because it is supported
on all recent operating systems by default.
Why a VPN?
More than ever, your freedom and privacy when online is under threat. Governments and ISPs
want to control what you can and can't see while keeping a record of everything you do, and
even the shady-looking guy lurking around your coffee shop or the airport gate can grab your
bank details easier than you may think. A self hosted VPN lets you surf the web the way it was
intended: anonymously and without oversight.
A VPN (virtual private network) creates a secure, encrypted tunnel through which all of your
online data passes back and forth. Any application that requires an internet connection works
with this self hosted VPN, including your web browser, email client, and instant messaging
program, keeping everything you do online hidden from prying eyes while masking your
physical location and giving you unfettered access to any website or web service no matter
where you happen to live or travel to.
This tutorial was written and tested on a Digital Ocean VPS. If you like this tutorial and want to
support my website, use this link to order a Digital Ocean VPS:
https://www.digitalocean.com/?refcode=7435ae6b8212. You will get $10 free credit, which is
equal to two months of a free $5 VPS.
IPSEC encrypts your IP packets to provide encryption and authentication, so no one can decrypt
or forge data between your clients and your server. It also provides a tunnel to send data to the
server.
This VPN setup is called a road-warrior setup, because clients can connect from anywhere.
Another much used VPN setup is called site-to-site, where two VPN servers connect two
networks with one another. In a road warrior setup your local network isn't shared, but you do
get access to the server's network.
1 Ubuntu 16.04 server with at least 1 public IP address and root access
1 (or more) clients running an OS that support IPsec IKEv2 vpns (Ubuntu, Mac OS,
Windows 7+, Android 4+).
Ports 4500/UDP, 500/UDP, 51/UDP and 50/UDP opened in the firewall.
I do all the steps as the root user. You should do to, but only via sudo -i or su -.
No L2TP?
A few of the previous tutorials used L2TP to set up the VPN tunnel and use IPSEC only for the
encryption. With the IKEv2 protocol and newer operating systems (like OS X 10.8+, Android
4+, iOS 6+ and Windows 7+) supporting IKEv2 we can also use IPSEC to set up the tunnel,
before we used IPSEC to do that.
This VPN will therefore not work out of the box on older operating systems. See my other
tutorials with L2TP on how to do that.
Overview
Install packages
Generate certificates
Configure IPSEC
Configure Firewall
Android and Windows client configuration is covered at the end of the tutorial.
Install Strongswan
Certificates
The VPN server will identify itself with a certificate to the clients. The clients should use a
certificate to authenticate themself. Previous tutorials also configured usernames and password
and pre-shared keys, this tutorial does not. Certificates are easier to use, can be revoked and are
less hassle than managing usernames and passwords.
On Android with the StrongSwan Application you can just import the .p12 we are going to
create later on. OS X and iOS from 10.10 and 9 upwards also support this authentication method.
You might want to install haveged to speed up the key generation process:
apt-get install haveged
systemctl enable haveged
systemctl start haveged
cd /etc/ipsec.d/
mkdir private
mkdir cacerts
mkdir certs
mkdir p12
ipsec pki --gen --type rsa --size 4096 --outform der >
private/strongswanKey.der
chmod 600 private/strongswanKey.der
You can view the certificate properties with the following command:
Example output:
cert: X509
subject: "C=NL, O=Example Company, CN=strongSwan Root CA"
issuer: "C=NL, O=Example Company, CN=strongSwan Root CA"
validity: not before Dec 20 08:12:27 2015, ok
not after Dec 17 08:12:27 2025, ok (expires in 3649 days)
serial: 1f:8e:0c:08:c4:a2:5b:1f
flags: CA CRLSign self-signed
authkeyId: d1:ad:f7:76:ad:10:02:7f:1d:04:e1:80:46:9d:b2:c7:fb:4d:d3:bb
subjkeyId: d1:ad:f7:76:ad:10:02:7f:1d:04:e1:80:46:9d:b2:c7:fb:4d:d3:bb
pubkey: RSA 4096 bits
keyid: 88:ef:88:13:7f:da:5a:28:13:77:4b:4c:81:df:ee:db:fb:5c:69:54
subjkey: d1:ad:f7:76:ad:10:02:7f:1d:04:e1:80:46:9d:b2:c7:fb:4d:d3:bb
Generate the VPN Host key. This is the keypair the VPN server host will use to authenticate
itself to clients. First the private key:
ipsec pki --gen --type rsa --size 4096 --outform der > private/vpnHostKey.der
chmod 600 private/vpnHostKey.der
Generate the public key and use our earlier created root ca to sign the public key:
ipsec pki --pub --in private/vpnHostKey.der --type rsa | ipsec pki --issue --
lifetime 730 --cacert cacerts/strongswanCert.der --cakey
private/strongswanKey.der --dn "C=NL, O=Example Company, CN=vpn.example.org"
--san vpn.example.com --san vpn.example.net --san 85.222.227.169 --san
@85.222.227.169 --flag serverAuth --flag ikeIntermediate --outform der >
certs/vpnHostCert.der
The domain name or IP address of your VPN server, which is later entered in the clients
connection properties, MUST be contained either in the subject Distinguished Name (CN) and/or
in a subject Alternative Name (--san). If this does not match the clients will fail to connect.
The built in Windows 7 VPN client needs the serverAuth extended key usage flag in 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 add here.
We add the IP address twice, one with an @ in front so that it gets added as an subjectAltName
of the DNSName type and one of the IPAddess type.
Output:
cert: X509
subject: "C=NL, O=Example Company, CN=vpn.example.org"
issuer: "C=NL, O=Example Company, CN=strongSwan Root CA"
validity: not before Dec 20 08:15:22 2015, ok
not after Dec 19 08:15:22 2017, ok (expires in 729 days)
serial: aa:31:ac:fd:4b:fa:41:5d
altNames: vpn.example.com, vpn.example.net, 185.3.211.43, 185.3.211.43
flags: serverAuth iKEIntermediate
authkeyId: d1:ad:f7:76:ad:10:02:7f:1d:04:e1:80:46:9d:b2:c7:fb:4d:d3:bb
subjkeyId: 27:c7:87:de:83:38:6c:f7:56:57:c2:b3:1f:05:11:ca:b9:2f:89:d4
pubkey: RSA 4096 bits
keyid: f8:03:95:ad:eb:a1:76:93:5f:8d:b8:77:5e:60:dc:ce:78:42:3b:dd
subjkey: 27:c7:87:de:83:38:6c:f7:56:57:c2:b3:1f:05:11:ca:b9:2f:89:d4
You can also use OpenSSL to see the contents, here is an excerpt:
Output:
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 12263773464207966557 (0xaa31acfd4bfa415d)
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=NL, O=Example Company, CN=strongSwan Root CA
Validity
Not Before: Dec 20 07:15:22 2015 GMT
Not After : Dec 19 07:15:22 2017 GMT
Subject: C=NL, O=Example Company, CN=vpn.example.org
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (4096 bit)
[...]
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Authority Key Identifier:
keyid:D1:AD:F7:76:AD:10:02:7F:1D:04:E1:80:46:9D:B2:C7:FB:4D:D3:BB
This key needs to be added into /etc/ipsec.secrets, otherwise StrongSwan will not use it.
vim /etc/ipsec.secrets
# 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.
: RSA vpnHostKey.der
The format : RSA keyname is important, don't forget the space. You can check afterwards if
StrongSwan has the private key available with the ipsec listcerts command:
ipsec listcerts
Output:
If it doesn't say has private key on the pubkey line your filename or syntax is wrong.
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 clients e-mail
address rather than a hostname.
Private key:
ipsec pki --gen --type rsa --size 2048 --outform der > private/JohnKey.der
chmod 600 private/JohnKey.der
ipsec pki --pub --in private/JohnKey.der --type rsa | ipsec pki --issue --
lifetime 730 --cacert cacerts/strongswanCert.der --cakey
private/strongswanKey.der --dn "C=NL, O=Example Company, [email protected]"
--san "[email protected]" --san "[email protected]" --san "[email protected]" -
-outform der > certs/JohnCert.der
A VPN client needs a client certificate, its corresponding 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.
Transport this John.p12 file and the password over seperate channels to a client.
If you need any more user certificates, repeat the above steps with other user data. You can also
do this later on.
Revoking a certificate
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.der --cakey private/strongswanKey.der --cert
certs/JohnCert.der --outform der > crls/crl.der
ipsec restart
This generates the new certificate revocation list (CRL) crls/crl.der. 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:
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.der crl.der.tmp
ipsec pki --signcrl --reason key-compromise --cacert
cacerts/strongswanCert.der --cakey private/strongswanKey.der --cert
certs/OtherStolenCert.der --lastcrl crl.der.tmp --outform der > crls/crl.der
rm crl.der.tmp
ipsec restart
IPSEC Configuration
The main ipsec configuration file is located in /etc/. We are going to edit it:
vim /etc/ipsec.conf
config setup
charondebug="ike 2, knl 2, cfg 2, net 2, esp 2, dmn 2, mgr 2"
conn %default
keyexchange=ikev2
ike=aes128-sha1-modp1024,aes128-sha1-modp1536,aes128-sha1-
modp2048,aes128-sha256-ecp256,aes128-sha256-modp1024,aes128-sha256-
modp1536,aes128-sha256-modp2048,aes256-aes128-sha256-sha1-modp2048-modp4096-
modp1024,aes256-sha1-modp1024,aes256-sha256-modp1024,aes256-sha256-
modp1536,aes256-sha256-modp2048,aes256-sha256-modp4096,aes256-sha384-
ecp384,aes256-sha384-modp1024,aes256-sha384-modp1536,aes256-sha384-
modp2048,aes256-sha384-modp4096,aes256gcm16-aes256gcm12-aes128gcm16-
aes128gcm12-sha256-sha1-modp2048-modp4096-modp1024,3des-sha1-modp1024!
esp=aes128-aes256-sha1-sha256-modp2048-modp4096-modp1024,aes128-
sha1,aes128-sha1-modp1024,aes128-sha1-modp1536,aes128-sha1-modp2048,aes128-
sha256,aes128-sha256-ecp256,aes128-sha256-modp1024,aes128-sha256-
modp1536,aes128-sha256-modp2048,aes128gcm12-aes128gcm16-aes256gcm12-
aes256gcm16-modp2048-modp4096-modp1024,aes128gcm16,aes128gcm16-ecp256,aes256-
sha1,aes256-sha256,aes256-sha256-modp1024,aes256-sha256-modp1536,aes256-
sha256-modp2048,aes256-sha256-modp4096,aes256-sha384,aes256-sha384-
ecp384,aes256-sha384-modp1024,aes256-sha384-modp1536,aes256-sha384-
modp2048,aes256-sha384-modp4096,aes256gcm16,aes256gcm16-ecp384,3des-sha1!
dpdaction=clear
dpddelay=300s
authby=pubkey
left=%any
leftid=vpn.example.org
leftsubnet=0.0.0.0/0
leftcert=vpnHostCert.der
leftsendcert=always
right=%any
rightsourceip=10.42.42.0/24,2002:25f7:7489:3::/112
rightdns=8.8.8.8,2001:4860:4860::8888
conn IPSec-IKEv2
keyexchange=ikev2
auto=add
The configuration has settings for IKEv2 + RSA certificates. This is, as stated above, the most
secure method. Older tutorials also set up IKEv1 (xauth) and username-password combo, but
that is considered insecure.
Apple added support for IKEv2 in iOS 8, but it needs to be configured using a custom
configuration profile. OS X 10.9 and lower do not support IKEv2.
Beginning with iOS 9, IKEv2 connections are natively supported. However, iOS9 only supports
the use of certificates or username/password, but not both.
For iOS 9+ and OS X 10.10+ you need to make sure the leftid= is the same as the CN in your
certificate. You also need to enter that on the devices, otherwise you'll get a no matching peer
config found log error.
Clients will get the Google DNS servers and an IP address in the 10.42.42.0/24 range. We use
a strong ciphersuite.
Configure the iptables firewall to allow vpn traffic and to forward packets:
Replace %SERVERIP% with the external IP of the VPN server. If your external interface is not
named ethX (+ is a wildcard) then rename appropriately.
Execute the below commands to enable kernel IP packet forwarding and disable ICP redirects.
Apply them:
sysctl -p
To make sure this keeps working at boot you might want to add the following to /etc/rc.local:
Add it before the exit 0 line and replace %SERVERIP% with the external IP of your server.
All the configuration on the server is now done. Enable the VPN at startup:
If you get a permission denied error, stroke the files with apparmor:
apparmor_parser -R /etc/apparmor.d/usr.lib.ipsec.charon
apparmor_parser -R /etc/apparmor.d/usr.lib.ipsec.stroke
ipsec status
Output:
ipsec statusall
Output:
Client Configuration
See the Strongswan Wiki for guides on configuring Windows and OS X/iOS clients)
On Android, the easiest way is to install the StrongSwan app, copy over the .p12 and connect
with the IP and option IKEv2 Certificate. Nothing more:
Just one tap to Connect and you're good to go: