VPN everywhere: IPsec without L2TP with strongSwan (even in OpenVZ)
yep, pretty strong swan
If you ever looked for VPN which works on desktop, mobile devices and routers without installing additional software or reflashing router, you probably had a choice between PPTP and L2TP+IPsec. With some security and NAT traversal issues, PPTP is not a good choice for today, and L2TP only introduces additional overhead and can transmit L2 packets, which is almost always unnecessary.
Strange that you hardly find any decent IPsec without L2TP in transport mode configuration manual on the internet, taking into account that IPsec is a very flexible and mature protocol stack you can configure as you want. I'm writing this article to remedy this deficiency.
Diving into IPsec
Generally speaking, it's not quite accurate to call IPsec the VPN. IPsec was not developed as a solution for virtual private networks, but to sign and encrypt IP data between two endpoints. It works as a special layer over IP which works different with different configuration. Unlike usual VPN, which creates new network interface (network segment) where all the traffic is routed, IPsec just encrypts data over external server and client network interfaces. It's magic!
Modern IPsec uses the following things:
- Authentication Header (AH). Protocol with sender authentication and data integrity. Not only data is signed, but the packet headers, too, except some mutable fields like ToS or TTL.
- Encapsulating Security Payload (ESP). Protocol with sender authentication, data integrity and confidentiality.
- Security Association (SA). Security attributes of the connection.
- Internet Key Exchange (IKE and IKEv2). IPsec connection configuration protocol.
Both AH and ESP are transport protocols with their own protocol numbers in IP header. In own modern world with NAT over NAT everywhere, we are bound to use something more usual. IPsec supports UDP encapsulation of ESP packets which works good with NAT. AH doesn't work with NAT.
There are two modes of IPsec:
- Transport mode. Signs IP headers and data (for AH) or signs and encrypts data (ESP). Does not hide destination IP. This mode is used for L2TP+IPsec.
- Tunnel mode. Signs (AH) and also encrypts (ESP) the whole packet.
IKE protocol allows you to authenticate roadwarrior with X.509 certificates, Pre-Shared Key or using Extensible Authentication Protocol (EAP). Two factor authentication is also supported.
Every modern desktop OS (Windows VIsta/7/8/8.1, OS X, Linux), mobile devices (Android, iOS, Windows Phone, Blackberry) and some routers support IPsec in tunnel mode with ESP, which is configured using IKE protocol, that's why we will configure this stack.
By the way, it's IPsec but Cisco IPSec.
IPsec in Linux
The IPsec (AH/ESP, SA) works in the kernel mode, we just need to install and setup usespace IKE daemon for client configuration. Although several available, there are only two which are in active development: strongSwan and libreswan. I can't say anything for the second one because I didn't use it, but the first one is awesome. Also, that's the only daemon with it's own userspace IPsec library so you can use it in OpenVZ with old kernel versions (which, by the way, comes with broken IPsec routing).
Some notes on IPsec in OpenVZ
OpenVZ fully supports IPsec and it's suitable for L2TP+IPsec, but there are some general issues with the routing to non-local interfaces. These issues could be resolved by adding firewall rules on the host, but that's the main problem as none of the VPS providers would allow you to do that. You should use strongSwan userspace IPsec library called libipsec. To use it, one should build strongSwan with --enable-kernel-libipsec configuration option.
Bug links: 1, 2, 3, 4
We need strongSwan >= 5.0.0. I would recommend using 5.2.0+ because of new control utility swanctl. It's much more convenient than old ipsec. It is used almost only for information or statistics so it's not a big deal if you use ipsec.
Life with swanctl
Life without swanctl
We should need some modules which could be missing in your repository:
- xauth-noauth. Fake XAUTH authenticator which allows any username and password. Useful for iPhone and iPad which can't use IPsec without XAUTH (so-called Cisco IPSec).
- vici. Internal interface for swanctl.
- libipsec. Userspace IPsec for OpenVZ and other containers.
If your distro doesn't have these modules and you don't need to run strongSwan in OpenVZ containter, you're OK with ipsec utility and don't care about login/password on iPhone and iPad, you can use stock build. It's a shame that Debian doesn't supply these modules so I made a patch you can use to rebuild it with all the needed modules.
It's time to configure everything
We would set up IKEv2 connection for Windows, Linux, Blackberry; IKEv1+XAUTH for iOS, OS X and Android, and IKEv2+EAP-TLS for Windows Phone using X.509 keys only. PSK is for girls!
strongSwan developers offer their own solution for key generation — "ipsec pki". I find it inconvenient and hard to use as it's just a wrapper on openssl with a bit different syntax so I forked OpenVPN's Easy-RSA. You can generate one keychain for both IPsec and OpenVPN with it!
Easy-RSA is very easy to use so maintaining PKI is a pleasure with it.
We should initialize PKI, generate CA and server/client keys. It's important for server key to have a name of servers' FQDN (full domain name)!
$ git clone https://github.com/ValdikSS/easy-rsa-ipsec.git $ cd easy-rsa-ipsec/easyrsa3 $ ./easyrsa init-pki init-pki complete; you may now create a CA or requests. $ ./easyrsa build-ca nopass Generating a 2048 bit RSA private key … Common Name (eg: your user, host, or server name) [Easy-RSA CA]:IPsec CA … $ ./easyrsa build-server-full uk1.pvpn.pw nopass Generating a 2048 bit RSA private key … Write out database with 1 new entries Data Base Updated $ ./easyrsa build-client-full client1 nopass Generating a 2048 bit RSA private key … Write out database with 1 new entries Data Base Updated $ ./easyrsa export-p12 client1 nopass Successful export of p12 file. Your exported file is at the following location…
Now the keys are generated. I've added "nopass" paramter and the keys are generated without password. You can add the password anytime later.
Now we should copy our generated keys to the strongSwan keys directory.
# cp pki/ca.crt /etc/ipsec.d/cacerts/ # cp pki/issued/uk1.pvpn.pw.crt /etc/ipsec.d/certs/ # cp pki/private/uk1.pvpn.pw.key /etc/ipsec.d/private/
Now, we should add our private key to /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. # this file is managed with debconf and will contain the automatically created private key include /var/lib/strongswan/ipsec.secrets.inc : RSA uk1.pvpn.pw.key
This is how strongSwan configuration file should look like
# ipsec.conf - strongSwan IPsec configuration file # basic configuration config setup # strictcrlpolicy=yes # uniqueids = no include /var/lib/strongswan/ipsec.conf.inc conn %default dpdaction=clear dpddelay=35s dpdtimeout=200s fragmentation=yes ike=aes256gcm16-aes256gcm12-aes128gcm16-aes128gcm12-aesxcbc-sha256-sha1-modp4096-modp2048-modp1024,aes256-aes128-sha256-sha1-modp4096-modp2048-modp1024! esp=aes128gcm12-aes128gcm16-aes256gcm12-aes256gcm16-modp4096-modp2048-modp1024,aes128-aes256-sha1-sha256-modp4096-modp2048-modp1024! # left - local (server) side left=%any leftauth=pubkey leftcert=uk1.pvpn.pw.crt leftsendcert=always leftsubnet=0.0.0.0/0,2000::/3 # right - remote (client) side right=%any rightauth=pubkey rightsourceip=192.168.103.0/24,2002:25f7:7489:3::/112 rightdns=126.96.36.199,2001:4860:4860::8888 conn ikev2-pubkey keyexchange=ikev2 auto=add conn ikev1-fakexauth keyexchange=ikev1 rightauth2=xauth-noauth auto=add conn ikev2-eap-tls also="ikev2-pubkey" rightauth=eap-tls eap_identity=%identity
As you can see, configuration is split into different sections.
config setup section has two commented lines:
strictcrlpolicy = yes would require actual certificate revocation list for authentication,
uniqueids = no allows multiple concurrent connections using the same certificate.
Next sections are for connections.
%default section stores default configuration which other connections can inherit. The following parameters are set:
dpdaction=clearturns on Dead Peer Detection feature and configures it to forget client if timeout exceeded.
dpddelay=35s— timeout before DPD
dpdtimeout=200s— timeout for DPD
fragmentation=yesenables fragmentation. Helps with some broken ISPs.
ike— list of IKE ciphersuites (for the control connection)
esp— list of ESP ciphersuites (for the data connection)
right— listen all interfaces and accept all clients
leftauth/rightauth=pubkey— X.509 key authentication
leftsubnet— subnets to route on client side. All the IPv4 and IPv6 internet. Remove IPv6 subnet if you don't use it.
rightsourceip— IP pool for clients. Remove IPv6 subnet if you don't use it.
rightdns— DNS IP address
Let's take a look on IKE and ESP ciphersuites. We should include all the popular algorithms to make sure our VPN would work on all the devices. The first ones are AEAD ciphers (ciphers which don't need additional authentication algorithm) with descending Diffie-Hellman group. That's the fastest ciphers available in IPsec. Then goes AES in CBC mode. It's not allowed to connect with disabled Perfect Forward Secrecy.
If your strongSwan installation missing xauth-noauth module, you can change it to just
xauth and add user
client with password
client1 : XAUTH "clientpass"
Now you have three connections: ikev2-pubkey with IKEv2, ikev1-fakexauth with IKEv1 and fake login/password authentication, and ikev2-eap-tls IKEv2+EAP-TLS for Windows Phone.
swanctl -L should show something like this is for a correctly configured daemon
$ swanctl -L ikev2-pubkey: IKEv2 local: %any remote: %any local public key authentication: id: CN=uk1.pvpn.pw certs: CN=uk1.pvpn.pw remote public key authentication: ikev2-pubkey: TUNNEL local: 0.0.0.0/0 2000::/3 remote: dynamic ikev1-fakexauth: IKEv1 local: %any remote: %any local public key authentication: id: CN=uk1.pvpn.pw certs: CN=uk1.pvpn.pw remote public key authentication: remote XAuth authentication: ikev1-fakexauth: TUNNEL local: 0.0.0.0/0 2000::/3 remote: dynamic ikev2-eap-tls: IKEv2 local: %any remote: %any local public key authentication: id: CN=uk1.pvpn.pw certs: CN=uk1.pvpn.pw remote EAP authentication: ikev2-eap-tls: TUNNEL local: 0.0.0.0/0 2000::/3 remote: dynamic
Due to different IPsec implementations and bugs in it, it's not possible to guess clients' MTU on the server side. For example, Android IPsec client sets MTU to 1500, strongSwan client uses 1400 and Cisco sets it to 1300. To fix this, we could modify TCP MSS value to prevent TCP packets data go over 1360 bytes for IPv4 and 1340 bytes for IPv6. We'll get 1400 bytes packets that way.
# iptables -t mangle -I FORWARD -p tcp -m policy --pol ipsec --dir in --syn -m tcpmss --mss 1361:1536 -j TCPMSS --set-mss 1360 # iptables -t mangle -I FORWARD -p tcp -m policy --pol ipsec --dir out --syn -m tcpmss --mss 1361:1536 -j TCPMSS --set-mss 1360 # ip6tables -t mangle -I FORWARD -p tcp -m policy --pol ipsec --dir in --syn -m tcpmss --mss 1341:1536 -j TCPMSS --set-mss 1340 # ip6tables -t mangle -I FORWARD -p tcp -m policy --pol ipsec --dir out --syn -m tcpmss --mss 1341:1536 -j TCPMSS --set-mss 1340
That's all, we finished with the server side. Don't forget to configure NAT!
Overall, steps are as follows: import p12 certificate to the keychain, create new IPsec PKI / IPsec XAUTH RSA or IKEv2 connection depending on the device, specify client certificate and server address. It is important to use exact domain name which you used for server key. It's not possible to connect to another domain or by IP address.
Windows 7, 8, 8.1
OS X and iOS
You can use either native Android IPsec client (IKE) or strongSwan client (IKEv2). I find strongSwan client more stable and faster.
In my humble opinion, IPsec is a great stack of protocols and could be used as a OpenVPN alternative. I have no idea why lots of VPN services still use L2TP+IPsec as strongSwan provides all the needed providing things (RADIUS authentication, accounting, a bunch of plugins). I use it in my own service and it works great. As i already said, IPsec is very flexible and you can use crazy EAP authenticators like EAP-SIM or EAP-AKA for authentication using your cellphone SIM card.
If you're in fear of NSA, please read Don't stop using IPsec just yet