Self-host your very own strongSwan IKEv2/IPsec state-of-the-art VPN server for iOS and macOS

surveilance

If you configured strongSwan using a tutorial, chances are you are using weak cryptography. I was. Here’s how you can check before upgrading your setup.

If you are conscious about internet privacy, chances are you are concerned about how public Wi-Fi networks are vulnerable to spoofing and man-in-the-middle attacks. How your ISP (short for internet service provider) is probably logging your every move online. How some DNS providers are logging which apps you use and your browsing habits. Put simply, how many companies are working very hard at (and succeeding to) track you online.

Many recommend using Tor or a VPN (short for virtual private network) to reduce how much of what you do online is shared with these companies and, guess what, they are absolutely right. That being said, using a VPN by itself is not a silver bullet and this guide explains (in perhaps too much detail) why.

DISCLAIMER 1: if you use a VPN to be anonymous. You aren’t! VPNs are not anonymity tools. Tor is a much better alternative but, even using Tor, your identity may be leaked.

DISCLAIMER 2: if you use a VPN to pirate apps, movies or music that you can afford and care about privacy, please don’t. The internet is messed up in part because of how companies are forced to monetize through advertising and data mining which is why we are so heavily tracked in the first place. Nation-state policies is another reason, but that’s another story.

In this guide, I will bring you along in my quest to privacy and explain why I recommend always using a VPN (even at home). Why using a VPN by itself doesn’t solve all privacy problems. Why using third-party VPN providers might not be our best shot at privacy. Finally, I will explain why I recommend strongSwan and how you can self-host your very own VPN server using state-of-the-art cryptography: 256 bit AES-GCM with a 128 bit ICV, SHA2_384 PRF and Diffie Hellman with a 3072 bit modulus.

Know your way around VPNs, skip to the guide.

Always use a VPN (even at home)

Take my word for it, connecting to free Wi-Fi is tempting. That being said, connecting to free Wi-Fi (even when secured by WPA2) compromises your privacy and security. I will put together a video shortly to illustrate why but, for the time being, close your eyes (metaphorically) and picture all these bytes of data flowing between the access point (or Wi-Fi router) and your computer. Each and every one of them is easy to intercept using Wireshark. In a perfect world, all the bytes sent and received by your computer would be encrypted using TLS, but they aren’t. Then again, even if they were, what if someone could stand in the middle and hack these bytes. This is called a man-in-the-middle attack. Beware of "Your connection is not secure" errors. If you get one, close the window immediately! You might be victim of one.

your-connection-is-not-secure

Now, at home, you can trust the network right? Wrong. Your ISP is probably logging your every move online. Short story, I recommend always using a VPN, even at home.

A VPN by itself doesn’t solve all privacy problems

Say you are an avid VPN user. You are probably guessing that your privacy is covered. Unfortunately it isn’t and here’s why. VPNs are only effective when they are well configured and connected. In order to connect, your computer needs access to the internet. See how conflicting this is? How can you be protected online using a VPN when to be protected online by a VPN you need to be online in the first place. WOW. Well, on iOS you simply can’t and that’s why the tracking device that is your smart phone (at so many levels, guide to come) can never be considered "safe" from a privacy perspective. Now on macOS, thankfully, there is a lot we can do and this is the subject of another guide. Put simply, as soon as your Mac (or iPhone) connects to the internet (before the device has time to connect to a VPN), it immediately sends a ton of data to the internet potentially leaking your identity and, at times, making you vulnerable to attacks.

Avoid third-party VPN providers

Although some third-party VPN providers are presumably well-intentioned, not all have your privacy at heart. Many are focused on turning a quick profit. They advertise great crypto but do not enforce it letting weak clients connect (convenience over privacy). More alarming, others, such as HolaVPN, are poorly secured botnets.

strongSwan

When I first considered self-hosting my own VPN server, I had a few requirements in mind. I was looking for an open source solution, I didn’t want to install third-party iOS or macOS clients and I wanted strong crypto. I initially followed this tutorial and, before I knew it, I was self-hosting my very own VPN server! Blessed, I went on with my life until I discovered I was using weak broken crypto (3DES, SHA-1 and MODP1024). God Damn It!

The problem, as I later found out, wasn’t with strongSwan. I had followed a poorly written tutorial (which has been updated since, but still isn’t that good). See, if you care about privacy and security, you have to RTFM and that’s what I have been doing for the past week. Yes, a full week. I spent over 60 hours doing research. My girlfriend is quite mad at strongSwan right now and can’t blame her. The good news is that I am going to break it down for you so you can spend time with your loved ones, not reading the ******* manual.

Credits: I would like to thank Tobias (one of strongSwan’s core team members) who was instrumental in writing the following guide. His patience (I was quite a newbie at this), generosity and dedication towards the strongSwan community is remarkable.

This is a good time to take a break and make yourself a double-shot espresso.

Guide

This guide is designed for people who know their way around Linux and command line. If you don’t, there are tons of tutorials on YouTube that can help you get up to speed.

The following steps refer to DigitalOcean as our virtual private server provider. Feel free to choose another provider as long as the Debian Stretch operating system is supported.

For increased privacy, consider choosing a provider that is headquartered in a country that has good privacy legislation in place.

At the time of this writing, Iceland, Switzerland and Sweeden are good options.

If you choose DigitalOcean, please use my referral link.

Step 1: sign up at https://www.digitalocean.com/

Step 2: choose a hostname for your Droplet

For the following steps, I will be using server as the hostname but it can be what ever you like.

Step 3: create a SSH key pair for server

When asked for a file in which to save the key, type server and press enter.

cd ~/.ssh
ssh-keygen -t rsa -C "server"

Step 4: add SSH key to your DigitalOcean account

This is done here. Click Add SSH Key. Then, paste the output of cat server.pub in the SSH key content input. Name is server.

Step 5: create a Debian Droplet (choose the datacenter region closest to you).

create-droplet

Step 6: log in using SSH

Replace 159.203.26.109 with the IP of your Droplet.

ssh root@159.203.26.109 -i ~/.ssh/vpn-server

Step 7: create admin user

When asked for a password, paste the output of openssl rand -base64 24 (and store that password in your password manager). For all other fields, press enter. Then press y.

adduser vpn-server-admin

Step 8: copy root’s authorized_keys file over to vpn-server-admin’s home folder.

mkdir /home/vpn-server-admin/.ssh
cp /root/.ssh/authorized_keys /home/vpn-server-admin/.ssh/authorized_keys
chown -R vpn-server-admin:vpn-server-admin /home/vpn-server-admin/.ssh

Step 9: set root password

When asked for a password, paste the output of openssl rand -base64 24 (and store that password in your password manager).

passwd

Step 10: log out

Step 11: log in as vpn-server-admin (don’t forget to replace 159.203.26.109 with the IP of your Droplet)

ssh vpn-server-admin@159.203.26.109 -i .ssh/vpn-server

Step 12: switch to root

When asked, enter root password.

su -

Step 13: update SSH config to prevent root log-ins and restart SSH daemon

Security tip 1: it is bad practice to allow root to log in via SSH or allow password log-ins as they are vulnerable to brute-force attacks

sed -i -E 's/(#)?PermitRootLogin (prohibit-password|yes)/PermitRootLogin no/' /etc/ssh/sshd_config
sed -i -E 's/(#)?PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
/etc/init.d/ssh restart

Step 14: install and configure vim

Pro tip 1: when copy/pasting commands that start with cat << "EOF", select all lines (from cat << "EOF" to EOF) at once as they are part of the same (single) command

apt install -y vim

cat << "EOF" > ~/.vimrc
set encoding=UTF-8
set termencoding=UTF-8
set nocompatible
set backspace=indent,eol,start
set autoindent
set tabstop=2
set shiftwidth=2
set expandtab
set smarttab
set ruler
set paste
syntax on
EOF

Step 15: set timezone (the following command is for Montreal time)

timedatectl set-timezone America/Montreal

Step 16: configure and enable iptables and make rules persistent

First, let’s install iptables-persistent. When asked if you wish to save current IPv4 or IPv6 rules, answer Yes.

apt update
apt install -y iptables-persistent

Then, run the following commands to only allow SSH, DNS and HTTP(S) traffic. DNS and HTTP(S) is required by apt, which will later be use to download and install packages.

iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
iptables -A OUTPUT -p tcp --dport 53 -m state --state NEW -j ACCEPT
iptables -A OUTPUT -p udp --dport 53 -m state --state NEW -j ACCEPT
iptables -A OUTPUT -p tcp --dport 80 -m state --state NEW -j ACCEPT
iptables -A OUTPUT -p tcp --dport 443 -m state --state NEW -j ACCEPT
iptables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -P FORWARD DROP
iptables -P INPUT DROP
iptables -P OUTPUT DROP

Make sure the rules are enforced by running iptables -L.

Chain INPUT (policy DROP)
target     prot opt source               destination
ACCEPT     all  --  anywhere             anywhere
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:ssh
ACCEPT     all  --  anywhere             anywhere             state RELATED,ESTABLISHED

Chain FORWARD (policy DROP)
target     prot opt source               destination

Chain OUTPUT (policy DROP)
target     prot opt source               destination
ACCEPT     all  --  anywhere             anywhere
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:domain state NEW
ACCEPT     udp  --  anywhere             anywhere             udp dpt:domain state NEW
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:http state NEW
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:https state NEW
ACCEPT     all  --  anywhere             anywhere             state RELATED,ESTABLISHED

👍

I recommend logging out using command exit twice (once for root and once for vpn-server-admin) and logging-in again to make sure the above rules didn’t lock you out. If somehow you got locked out, use the DigitalOcean dashboard to power cycle your Droplet and start over.

Finally, make rules persistent using the following command.

iptables-save > /etc/iptables/rules.v4

By default, DigitalOcean does not enable IPv6, but, to be extra safe, we will drop all IPv6 packets using the following commands.

ip6tables -P FORWARD DROP
ip6tables -P INPUT DROP
ip6tables -P OUTPUT DROP
ip6tables-save > /etc/iptables/rules.v6

Step 17: switch DNS nameservers over to privacy first 1.1.1.1

cat << "EOF" > /etc/resolv.conf
nameserver 1.1.1.1
nameserver 1.0.0.1
EOF

You now have a secure server. Good job!

Step 18: install strongSwan

If you are shown a "old runlevel management superseded" warning, answer Ok.

apt install -y strongswan libcharon-extra-plugins

Step 19: configure strongSwan

# Backup and override /etc/ipsec.conf
cp /etc/ipsec.conf /etc/ipsec.conf.backup
cat << "EOF" > /etc/ipsec.conf
config setup
  charondebug="ike 1, knl 1, cfg 0"
  uniqueids=never

conn ikev2
  auto=add
  compress=no
  type=tunnel
  keyexchange=ikev2
  fragmentation=yes
  forceencaps=yes
  ike=aes256gcm16-sha384-modp3072!
  esp=aes256gcm16-sha384-modp3072!
  dpdaction=clear
  dpddelay=300s
  rekey=no
  left=%any
  leftid=my-vpn.com
  leftcert=vpn-server.crt
  leftsendcert=always
  leftsubnet=0.0.0.0/0
  right=%any
  rightid=%any
  rightauth=eap-tls
  rightdns=1.1.1.1,1.0.0.1
  rightsourceip=10.0.2.0/24
  rightsendcert=never
  eap_identity=%identity
EOF

# Backup and override /etc/ipsec.secrets
cp /etc/ipsec.secrets /etc/ipsec.secrets.backup
cat << "EOF" > /etc/ipsec.secrets
: RSA vpn-server.key
EOF

# Backup and override /etc/strongswan.conf
cp /etc/strongswan.conf /etc/strongswan.conf.backup
cat << "EOF" > /etc/strongswan.conf
libtls {
  suites = TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
}
EOF

If you wish to better understand these settings, have a look here.

Highlights are uniqueids=never which allows multiple connections using the same credentials (say your iPhone and Mac), keyexchange=ikev2 which enables IKEv2 (vs v1), ike=aes256gcm16-sha384-modp3072! and esp=aes256gcm16-sha384-modp3072! which only allows state-of-the-art crypto and rightauth=eap-tls which enables EAP-TLS (or certificate-based) authentication (significantly harder to brute-force).

Step 20: create certificate authority (or CA), server and client private keys and certificates (this is done on your Mac vs the server)

Security tip 2: it is recommended to create the certificate authority private key on a computer that isn’t connected to the internet

The following commands will create a certificate-authority folder on your desktop, create a CA private key (ca.key) and use it to create a CA root certificate (ca.crt) used to sign server and client certificates. Then, vpn-server and vpn-client private keys and certificates will be created. Some of these commands are interactive so you need to run them one at a time (copy/pasting them all at once will not work). When asked for an export password, paste the output of openssl rand -base64 24 (and store that password in your password manager).

The common name (or CN) of the CA root certificate (ca.crt) and the server certificate (vpn-server.crt) should be fully qualified domain names (or FQDNs) and the common name of the client certificate (vpn-client.crt), an email registered under the servers’ FQDN.

Want to learn more about public-key cryptography, watch this video.

Documentation for the ca, server and client parts of openssl.cnf is found here.

Don’t forget to run the following commands one at a time and remember pro tip 1.

# Create `certificate-authority` folder
mkdir ~/Desktop/certificate-authority
cd ~/Desktop/certificate-authority

# Create OpenSSL config file
cat << "EOF" > openssl.cnf
[ req ]
distinguished_name = req_distinguished_name
attributes = req_attributes
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_min = 2
countryName_max = 2
0.organizationName = Organization Name (eg, company)
commonName = Common Name (eg, fully qualified host name)
commonName_max = 64
countryName_default = CA # Defaults
0.organizationName_default = My VPN # Defaults
[ req_attributes ]
challengePassword = A challenge password
challengePassword_min = 4
challengePassword_max = 20
[ ca ]
subjectKeyIdentifier = hash
basicConstraints = critical, CA:true
keyUsage = critical, cRLSign, keyCertSign
[ server ]
authorityKeyIdentifier = keyid
subjectAltName = DNS:my-vpn.com # Defaults
extendedKeyUsage = serverAuth, 1.3.6.1.5.5.8.2.2
[ client ]
authorityKeyIdentifier = keyid
subjectAltName = email:client@my-vpn.com # Defaults
extendedKeyUsage = serverAuth, 1.3.6.1.5.5.8.2.2
EOF

# Create certificate authority private key
openssl genrsa -out ca.key 4096

# Create certificate authority root certificate (CN: my-vpn.com)
openssl req -x509 -new -nodes -config openssl.cnf -extensions ca -key ca.key -days 3650 -out ca.crt

# Create vpn-server private key and certificate (CN: my-vpn.com)
openssl genrsa -out vpn-server.key 4096
openssl req -new -config openssl.cnf -extensions server -key vpn-server.key -out vpn-server.csr
openssl x509 -req -extfile openssl.cnf -extensions server -in vpn-server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 3650 -out vpn-server.crt

# Create vpn-client private key and certificate (CN: client@my-vpn.com)
openssl genrsa -out vpn-client.key 4096
openssl req -new -config openssl.cnf -extensions client -key vpn-client.key -out vpn-client.csr
openssl x509 -req -extfile openssl.cnf -extensions client -in vpn-client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 3650 -out vpn-client.crt

# Create vpn-client PKCS12 archive
openssl pkcs12 -in vpn-client.crt -inkey vpn-client.key -certfile ca.crt -export -out vpn-client.p12

Step 21: copy/paste the content of ca.crt, vpn-server.key and vpn-server.crt to server and make private key root-only.

On your Mac: run cat ca.crt

On the server: run vi /etc/ipsec.d/cacerts/ca.crt, press i, paste output from previous step in the window and press shift+z+z

On your Mac: run cat vpn-server.key

On the server: run vi /etc/ipsec.d/private/vpn-server.key, press i, paste output from previous step in the window and press shift+z+z

On your Mac: run cat vpn-server.crt

On the server: run vi /etc/ipsec.d/certs/vpn-server.crt, press i, paste output from previous step in the window and press shift+z+z

On the server: run chmod -R 600 /etc/ipsec.d/private

Step 22: start strongSwan

ipsec start

Step 23: forward client traffic (required to send iOS and macOS traffic through the VPN) and disable IPv6

# Forward client traffic
sed -i -E 's/#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/' /etc/sysctl.conf

# Disable IPv6
cat << "EOF" >> /etc/sysctl.conf
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
EOF

# Reload config
sysctl -p

Step 24: update iptables rules to allow VPN traffic and reboot server

iptables -A INPUT -p udp --dport  500 -j ACCEPT
iptables -A INPUT -p udp --dport 4500 -j ACCEPT
iptables -A FORWARD --match policy --pol ipsec --dir in  --proto esp -s 10.0.2.0/24 -j ACCEPT
iptables -A FORWARD --match policy --pol ipsec --dir out --proto esp -d 10.0.2.0/24 -j ACCEPT
iptables -t nat -A POSTROUTING -s 10.0.2.0/24 -o eth0 -m policy --pol ipsec --dir out -j ACCEPT
iptables -t nat -A POSTROUTING -s 10.0.2.0/24 -o eth0 -j MASQUERADE
iptables -t mangle -A FORWARD -m policy --pol ipsec --dir in -p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1361:1536 -j TCPMSS --set-mss 1360
iptables -t mangle -A FORWARD -m policy --pol ipsec --dir out -p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1361:1536 -j TCPMSS --set-mss 1360
iptables-save > /etc/iptables/rules.v4
reboot

This is a good time to take a break and make yourself another double-shot espresso.

Step 25: create VPN profiles for macOS and iOS

For this step, we will be using Apple Configurator 2, a free app designed by Apple to manage macOS and iOS profiles. This is where part of the magic of this guide resides (took me for ever to figure this out). macOS and iOS does not offer state-of-the-art crypto by default when setting up VPNs using the user interface. In order to pull that off, we need profiles.

Open Apple Configurator 2, then click File, then New Profile.

In General, fill out Name and Identifier.

apple-configurator-general

In Certificates, click Configure and select ca.crt. Then click + and select vpn-client.p12.

The password is the one from step 20.

apple-configurator-certificates

In VPN, click Configure and enter the settings from the following screenshot. The Child SA Params are the same as IKE SA Params.

apple-configurator-vpn

Finally, click File, then Save, and save file as My VPN.mobileconfig.

Step 26: add VPN profile to macOS

This step is super simple, simply double-click My VPN.mobileconfig and follow instructions.

Step 27: add VPN profile to iOS

This step uses Apple Configurator 2 to add the VPN profile to your iPhone (much safer than sending it to yourself via email or hosting it).

Unlock your iPhone and connect it to your Mac (using a lightning to USB cable) and open Apple Configurator 2.

In All Devices, double-click on your iPhone, then Add, and finally Profiles.

Select My VPN.mobileconfig and follow instructions on your iPhone.

Step 28: connect to your very own strongSwan IKEv2/IPsec state-of-the-art VPN server for iOS and macOS

Hope you enjoyed this guide.

Contributors:Sun KnudsenSun Knudsen

Wish to contribute? Please submit an issue or a pull request.
This website is not tracking you. PGP public key fingerprint: C4FB DDC1 6A26 2672 920D  0A0F C132 3A37 7DE1 4C8B