Author: Michael Ibanes - 03 Feb 2023
Do you need a Client-to-site VPN solution? are you often on the move and might need to borrow a computer to quickly access your site and fix something? You might prefer to use IKEv2 EAP over solutions such as WireGuard or OpenVPN. No client download is required, no key is required, just memorised access details.
In this tutorial, I will be using a strongSwan which is open-source and offers support for IKEv2 key exchange protocol. strongSwan can provide authentication based on X.509 certificates or secure IKEv2 EAP user authentication. We will be using client-to-site setup with a User/Password authentication method. Windows®, macOS and iOS can connect to a strongSwan server with their built-in IPSec IKEv2 VPN client. Android and Linux require a strongSwan client to be installed.
Before starting you will need:
When following this guide, you should replace the domain name vpn.mydomain.example with your server's fully-qualified domain name. I will also assume that you are using a non-root sudo user. If you are using the root user directly, just remove the 'sudo's.
You will need to open your firewall ports 500/udp and 4500/udp for IPSec as well as port 80/tcp for Certbot to accept the Let's Encrypt SSL challenges for the SSL certificate registration and renewals.
1. Update OS
$ sudo dnf update
2. Set SELINUX to 'permissive' to start. Once everything is setup and working as it should, feel free to revert this setting to 'enforced'.
$ sudo nano /etc/selinux/config
SELINUX=permissive
3. Reboot
1. Enable IP packet forwarding in the kernel options.
$ echo "net.ipv4.ip_forward=1" | sudo tee /etc/sysctl.conf $ sudo sysctl -p
2. Add service ipsec to firewalld(500/udp, 4500/udp and protocols AH & ESP)
$ sudo firewall-cmd --permanent --add-service="ipsec"
3. Add service HTTP(80/tcp) to firewalld, this will be used by Certbot to obtain(and renew) the Let's Encrypt SSL certificate.
$ sudo firewall-cmd --permanent --add-service="http"
4. Allow NAT packet forwarding, also known as IP masquerade
$ sudo firewall-cmd --permanent --add-masquerade
5. Reload firewalld to apply all changes
$ sudo firewall-cmd --reload
This will require the installation of 'Certbot' and 'Apache' and the creation of a small cronjob for the automatic renewal of the certificate. Let's Encrypt certificates must be renewed every 90 days. Each day, Apache will be started just long enough for 'Certbot' to renew the SSL certificate if required.
1. Enable the CRP repository
$ sudo /usr/bin/crb enable
2. Install the EPEL repository
$ sudo dnf install -y epel-release
3. Install the Let's Encrypt Certbot utility
$ sudo dnf install certbot
4. Install and start Apache (The service does not need to be enabled)
$ sudo dnf install httpd $ sudo systemctl start httpd
5. Register an SSL certificate for the pointed domain/A record which will be used to connect to the VPN service.
$ sudo certbot --key-type rsa certonly --webroot -w /var/www/html -d vpn.mydomain.example
6. Stop apache as it only needs to be enabled for the registration and renewal of the SSL Certificate
$ sudo systemctl stop httpd
7. Create a Cron job for the auto-renewal of the SSL Certificate
$ sudo tee -a /etc/cron.daily/certbot > /dev/null <<EOT #!/usr/bin/sh systemctl start httpd certbot renew sleep 2 systemctl stop httpd EOT
8. Restart Crond
$ sudo systemctl restart crond
1. Install strongSwan
$ sudo dnf install strongswan
2. Link the certificate for use with strongSwan. Replace vpn.mydomain.example with your domain name
$ sudo ln -s /etc/letsencrypt/live/vpn.mydomain.example/fullchain.pem /etc/strongswan/swanctl/x509 $ sudo ln -s /etc/letsencrypt/live/vpn.mydomain.example/privkey.pem /etc/strongswan/swanctl/private $ sudo ln -s /etc/letsencrypt/live/vpn.mydomain.example/chain.pem /etc/strongswan/swanctl/x509ca
3. Create a strongSwan configuration file
$ sudo nano /etc/strongswan/swanctl/conf.d/my_vpn.conf
Paste the following in the file, replace vpn.mydomain.example with your domain name and replace 'username1' and 'password1' with real access details. You can add more 'eap-UserX' blocks for extra users.
NOTE 1: By default, the VPN client will send all your traffic to the VPN Server. If you only want to use your VPN as a split tunnel to your remote private network, you need to:
NOTE 2: If you wish to tunnel both IPv4 and IPv6 through your VPN, you will also need to assign an IPv6 pool, DNS and local subnet. Use settings such as:
local_ts = 0.0.0.0/0,::/0
addrs = 10.1.1.0/24,2a00:1450:400c:c05::/112
dns = 8.8.8.8,2001:4860:4860::8888
connections { ikev2-eap-mschapv2 { version = 2 proposals = aes256-sha256-modp4096,aes256-sha256-modp2048,aes256gcm16-sha256-modp1024 rekey_time = 0s pools = pool-ipv4 fragmentation = yes dpd_delay = 30s send_cert=always unique = never local { id = vpn.mydomain.example certs = fullchain.pem } remote { auth = eap-mschapv2 eap_id = %any } children { ikev2-eap-mschapv2 { local_ts = 0.0.0.0/0 rekey_time = 0s dpd_action = clear esp_proposals = aes256-sha256-sha1 } } } } pools { pool-ipv4 { addrs = 10.1.1.0/24 dns = 1.1.1.1, 8.8.8.8 } } secrets { eap-User1 { id = username1 secret = "password1" } }
4. Disable the Openssl plugin (Openssl 3 on Rocky9 does not allow RSA signatures with SHA-1 which causes authentication failures)
$ sudo sed -i "s/load = yes/load = no/" /etc/strongswan/strongswan.d/charon/openssl.conf
5. Enable and start the strongSwan service
$ sudo systemctl enable strongswan $ sudo systemctl start strongswan
To connect to your VPN server, choose the instructions for your client operating system.