Wow this was harder than i thought.
I just wanted to get a modern VPN on all my devices without the hassle to install third-party VPN clients on all of them (hello OpenVPN o/). The protocol of choice seems to be IKEv2 as all devices that I own seem to support this and it is more secure than the old PPTP or L2TP protocols the devices could support natively.
But let's just jump directly into it.
On the server we will be using StrongSWAN. All configuration is for Ubuntu 15.10 but should work on any distribution that has StrongSWAN as the configuration did not really change in the last few years.
At first we need to install StrongSWAN (all steps from here on should be done as the
root user, switch to root by issuing
sudo su - and typing your password):
apt install strongswan strongswan-plugin-af-alg strongswan-plugin-agent strongswan-plugin-certexpire strongswan-plugin-coupling strongswan-plugin-curl strongswan-plugin-dhcp strongswan-plugin-duplicheck strongswan-plugin-eap-aka strongswan-plugin-eap-aka-3gpp2 strongswan-plugin-eap-dynamic strongswan-plugin-eap-gtc strongswan-plugin-eap-mschapv2 strongswan-plugin-eap-peap strongswan-plugin-eap-radius strongswan-plugin-eap-tls strongswan-plugin-eap-ttls strongswan-plugin-error-notify strongswan-plugin-farp strongswan-plugin-fips-prf strongswan-plugin-gcrypt strongswan-plugin-gmp strongswan-plugin-ipseckey strongswan-plugin-kernel-libipsec strongswan-plugin-ldap strongswan-plugin-led strongswan-plugin-load-tester strongswan-plugin-lookip strongswan-plugin-ntru strongswan-plugin-pgp strongswan-plugin-pkcs11 strongswan-plugin-pubkey strongswan-plugin-radattr strongswan-plugin-sshkey strongswan-plugin-systime-fix strongswan-plugin-whitelist strongswan-plugin-xauth-eap strongswan-plugin-xauth-generic strongswan-plugin-xauth-noauth strongswan-plugin-xauth-pam strongswan-pt-tls-client
This one seems a bit excessive but I just installed everything I could find for StrongSWAN as I am lazy.
The next step is to get rid of the default configuration and supply our own:
The best bet here is to just move away the default config in
/etc/ipsec.conf (or delete it as it does not contain anything of any value) and copy and paste the config above into it.
You will have to modify some values:
yourhostname.netshould be the hostname of the box you connect to.
rightsourceipshould be a private IPv4 network and a subnet of the IPv6 subnet of your server (if your server got a
/64probably add another address part and use a
rightdnsis the dns server that will be sent to the client, I just used Google's free DNS servers here.
If you only want to use IPv4 just remove the v6 addresses.
To allow the connected VPN clients to actually talk to each other you'll have to enable packet forwarding, if you don't do that the clients will only be able to speak with the server.
Create a new file in
Reload the settings with
If you want to give the VPN clients Internet access you'll have to enable NAT for the interfaces and routing for IPv6. I just added these lines to
/etc/rc.local, you probably want to use the default facility for iptables rules of your distribution though:
Don't forget to actually run the script afterwards to enable the rules without rebooting. (D'oh!)
To be on the real secure side and to make device provisioning as easy as possible we use X.509 certificates to connect to the VPN. There are 3 sets of certificates:
- The root CA
- The VPN server certificate
- The client certificates
/etc/ipsec.d and run all the following in that directory.
For a CA we need a key first (we pick a 4096 bit long RSA key here):
ipsec pki --gen --type rsa --size 4096 --outform der > private/strongswanKey.der chmod 600 private/strongswanKey.der
So let's create a root CA:
ipsec pki --self --ca --lifetime 3650 --in private/strongswanKey.der --type rsa --dn "C=DE, O=Dunkelstern, CN=Dunkelstern VPN Root CA" --outform der > cacerts/strongswanCert.der
So what's all that stuff?
- First we tell the ipsec tool to create a self signed ca with roughly 10 years of lifetime
- Use the key we generated
- Tell the pki tool some settings: The country (DE), the Organisation (Dunkelstern) and the Common Name (Dunkelstern VPN Root CA)
You should probably move all the root CA private files (the key!) off the machine after you're done with them and put them on a disk into a safe or something.
So we have a CA but we definitely do not want to use that directly for the VPN server, so we create a derivative Certificate that has the root CA as parent. So at first we need a key again:
ipsec pki --gen --type rsa --size 4096 --outform der > private/vpnHostKey.der chmod 600 private/vpnHostKey.der
And now comes the interesing part:
export vpn_host="vpn.example.org" export vpn_ipv4="10.0.0.1" export vpn_ipv6="::1" ipsec pki --pub --in private/vpnHostKey.der --type rsa | ipsec pki --issue --lifetime 730 --cacert cacerts/strongswanCert.der --cakey private/strongswanKey.der --dn "C=DE, O=Dunkelstern, CN=$vpn_host" --san $vpn_ipv4 --san @$vpn_ipv4 --san $vpn_ipv6 --san @$vpn_ipv6 --flag serverAuth --flag ikeIntermediate --outform der > certs/vpnHostCert.der
You'll have to replace some values here:
vpn_hostthe hostname of the VPN server
vpn_ipv4the public IPv4 address
vpn_ipv6the public IPv6 address
Now it is really time to move the CA root private key ;)
To create client certificates I made a small script as you'll probably do this often:
Usage is something like
create_vpn_user.sh kopernikus which will drop a p12 file in
/etc/ipsec.d/p12/ with the name you supplied. The p12 file is encrypted with a pass-phrase you'll have to supply.
To get a working VPN config onto an iOS device you'll have to use a
*.mobileconfig configuration profile as the VPN GUI of the iPhone and iPad has a bug that prevents valid connections as of iOS 9.3.
Create mobile config profile
Fetch the Apple Configurator 2 from the AppStore on a Mac (it's free but sadly there is no configurator for Windows)
After starting the configurator choose
File->New Profile from the menu and fill the generic info field as you want:
For the next step you'll need the
p12 file and the
vpnHostCert.der file to add to the certificate store:
And the last step: Configure the VPN
Make sure you select the certificate auth method and the correct certificate. The Remote Identifier is what's in
leftid in the
ipsec.conf, the Local Identifier is what's in the Certificate's common name (
Attention: Set the Encryption algorithm for IKE SA Params and Child SA Params to something sensible, do not use the
3DES is inherently unsafe!
If you're ready, save the config somewhere. So there's another step to get it running: Another Bug workaround!
Open the generated file in some text-editor and search for
OverridePrimary and set it to zero!
Install on iOS device
The easiest way to install the configuration profile is just sending it to yourself as an email and then tap the attachment and allow it to install the VPN. If your device is enrolled in MDM (Mobile device management) you can send the profile over the air.
To connect to the VPN go into
Settings->General->VPN and turn on the switch. All traffic will now be sent through the VPN. If the switch turns off immediately you either forgot to set
OverridePrimary to zero or you chose an encryption that the server does not understand. Look into the server logfile for more information.
Just create a config file like you do for an iOS device and double click it. It will open in the System Preferences Profiles pane (which is not visible until you import a profile)
I had to click the plus button and add the profile again as the preference pane did open but it did not automatically import the profile.
If you want to have an icon in the menu bar, switch to the Network pref-pane and tick the checkbox to show that icon:
Read the follow up: The right way to setup a VPN on windows