Ubuntu 22.04 LTE + strongSwan(IKEv2) + Let’s Encrypt

Introduction

In today’s mobile world, securely connecting to the internet from public places like Starbucks or other free Wi-Fi spots is crucial. Hence, I will discuss setting up a personal VPN server. As many are aware, a VPN encrypts your internet traffic, safeguarding it on untrusted networks such as those in coffee shops, conferences, or airports.

First, let’s delve into why I chose IKEv2 over other VPN protocols such as PPTP, L2TP/IPSec, and SSL-VPN. Through extensive testing, I found IKEv2 to be the most stable, fast, and robust option. However, it is slightly more complex to configure compared to its counterparts.

An IKEv2 connection mandates a server certificate. While many tutorials suggest using a self-signed certificate, this requires manual installation on the client, complicating the process. To streamline client connections, I opted for a certificate from Let’s Encrypt.

IKEv2, or Internet Key Exchange version 2, allows for direct IPSec tunneling between the server and client. In IKEv2 VPN implementations, IPSec encrypts the network traffic. IKEv2 is natively supported on most modern platforms (OS X 10.11+, iOS 9.1+, and Windows 10) without additional applications, although Android requires an official VPN client. It also gracefully handles client disconnections.

Today, I will guide you through setting up an IKEv2 VPN server using strongSwan on an Ubuntu 22.04 LTE server and connecting to it from Windows and iOS.

Prerequisites

To complete this set up, you will need:

Step 1: Setting Up Let’s Encrypt

Install certbot to automatically configure HTTPS using Let’s Encrypt:

$ sudo apt-get install certbot
$ sudo certbot certonly
Saving debug log to /var/log/letsencrypt/letsencrypt.log

How would you like to authenticate with the ACME CA?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: Spin up a temporary webserver (standalone)
2: Place files in webroot directory (webroot)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 1
Plugins selected: Authenticator standalone, Installer None
Please enter in your domain name(s) (comma and/or space separated)  (Enter 'c'
to cancel): vpn.yourdomain.com
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for vpn.yourdomain.com
Waiting for verification...
Cleaning up challenges

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/vpn.yourdomain.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/vpn.yourdomain.com/privkey.pem
   Your cert will expire on 2021-09-16. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot
   again. To non-interactively renew *all* of your certificates, run
   "certbot renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

Follow the prompts to select your authentication method and enter your domain name (e.g., vpn.yourdomain.com). Once complete, your certificate and key files will be saved in /etc/letsencrypt/live/vpn.yourdomain.com/.

Ensure your firewall allows HTTPS traffic to enable certbot verification:

$ sudo ufw status
Status: active

To                         Action      From
--                         ------      ----
Anywhere                   ALLOW       my.ip.address            
80/tcp                     ALLOW       Anywhere                  
443/tcp                    ALLOW       Anywhere                   

Option: Verify certbot auto-renewal:

$ sudo systemctl status certbot.timer 
● certbot.timer - Run certbot twice daily
   Loaded: loaded (/lib/systemd/system/certbot.timer; enabled; vendor preset: enabled)
   Active: active (waiting) since Fri 2021-06-18 07:20:58 UTC; 13h ago
  Trigger: Fri 2021-06-18 22:53:11 UTC; 1h 50min left

Jun 18 07:20:58 example systemd[1]: Started Run certbot twice daily.

To test the renewal process, you can do a dry run with certbot:

$ sudo certbot renew --dry-run

Add a cron job to copy the new certificates and reload the IPsec configuration monthly:
cron job will be run on 1st of every month at 00:00 AM.

$ sudo crontab -e
# m h  dom mon dow   command
0 0 1 * * root cp –f /etc/letsencrypt/live/vpn.yourdomain.com/fullchain.pem /etc/ipsec.d/certs/fullchain.pem && cp -f /etc/letsencrypt/live/vpn.yourdomain.com/privkey.pem /etc/ipsec.d/private/privkey.pem && cp -f /etc/letsencrypt/live/vpn.yourdomain.com/chain.pem /etc/ipsec.d/cacerts/chain.pem && ipsec rereadall

Step 2: Setting Up strongSwan

Install strongSwan:

$ sudo apt-get update
$ sudo apt-get install strongSwan

Configure strongSwan by editing the ipsec.conf file:

# ipsec.conf - strongSwan IPsec configuration file

# basic configuration

config setup
        # strictcrlpolicy=yes
        charondebug="all"
        uniqueids=no

conn ikev2-vpn
        auto=add
        compress=no
        type=tunnel
        keyexchange=ikev2
        fragmentation=yes
        forceencaps=yes
        ike=aes256-sha1-modp1024,3des-sha1-modp1024!
        esp=aes256-sha1,3des-sha1!
        dpdaction=clear
        dpddelay=300s
        rekey=no
        left=%any
        leftid=@vpn.yourdomain.com
        leftcert=fullchain.pem
        leftsendcert=always
        leftsubnet=0.0.0.0/0
        right=%any
        rightid=%any
        rightauth=eap-mschapv2
        rightsourceip=192.168.1.0/24
        rightdns=8.8.8.8,8.8.4.4
        rightsendcert=never
        eap_identity=%identity
        mobike=yes

Configure VPN authentication in 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 privkey.pem
username : EAP "password"

Restart the strongSwan service:

$ sudo systemctl restart strongSwan

Step 3: Configuring the Firewall & Kernel IP Forwarding

Allow VPN traffic through the firewall:

$ sudo ufw allow 500/udp
$ sudo ufw allow 4500/udp

Add the following rules to /etc/ufw/before.rules:

$ ip route | grep default
default via my.server.ip.address dev ens3 proto static
# For IPSecVPN
*nat
-A POSTROUTING -s 192.168.1.0/24 -o ens3 -m policy --pol ipsec --dir out -j ACCEPT
-A POSTROUTING -s 192.168.1.0/24 -o ens3 -j MASQUERADE
COMMIT
*mangle
-A FORWARD --match policy --pol ipsec --dir in -s 192.168.1.0/24 -o ens3 -p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1361:1536 -j TCPMSS --set-mss 1360
COMMIT
# End

# Don't delete these required lines, otherwise there will be errors
*filter
:ufw-before-input - [0:0]
# Don't delete these required lines, otherwise there will be errors
*filter
:ufw-before-input - [0:0]
:ufw-before-output - [0:0]
:ufw-before-forward - [0:0]
:ufw-not-local - [0:0]
# End required lines

# For IPSecVPN
-A ufw-before-forward --match policy --pol ipsec --dir in --proto esp -s 192.168.1.0/24 -j ACCEPT
-A ufw-before-forward --match policy --pol ipsec --dir out --proto esp -d 192.168.1.0/24 -j ACCEPT
# End

Ensure kernel parameters in /etc/ufw/sysctl.conf are configured to allow IP forwarding:

net/ipv4/ip_forward=1
net/ipv4/conf/all/accept_redirects=0
net/ipv4/conf/all/send_redirects=0
net/ipv4/ip_no_pmtu_disc=1

Restart the firewall to apply changes:

$ sudo ufw disable
$ sudo ufw enable

Step 4: Deploying Certificate Files

Copy the Let’s Encrypt certificate files to the IPSec directory:

$ sudo cp -f /etc/letsencrypt/live/vpn.mydomain.com/fullchain.pem /etc/ipsec.d/certs/fullchain.pem
$ sudo cp -f /etc/letsencrypt/live/vpn.mydomain.com/chain.pem /etc/ipsec.d/cacerts/chain.pem
$ sudo cp -f /etc/letsencrypt/live/vpn.mydomain.com/privkey.pem /etc/ipsec.d/private/privkey.pem

Step 5: Client Configuration

Windows

  1. Add the VPN connection in “Settings” > “Network and Internet” > “VPN”.
  2. Edit the VPN connection: Right-click the VPN connection in “Change adapter options” and select “Properties”.
  3. On the Security tab, set “Data Encryption” to “Maximum strength encryption (disconnect if server declines)”.
  4. On the Networking tab, uncheck “Internet Protocol Version 6 (TCP/IPv6)” and check “Use default gateway on remote network” in IPv4 properties.

iOS and macOS

  1. Create a new VPN connection and set the required items.
  2. Follow similar steps as for Windows to configure the connection.

Android

  1. Download the strongSwan VPN client from the Play Store.
  2. Follow the instructions within the app.

Conclusion

Setting up an IKEv2 VPN server can be complex, particularly with IPSec configurations. However, the security and stability benefits make it worthwhile. By using Let’s Encrypt certificates, the process is simplified, eliminating the need for additional client-side certificate installations. Additionally, the setup allows for secure and unrestricted internet access, even in geographically restricted scenarios. Use this guide to ensure your online activities remain secure wherever you go!

Index