====== Setting up an IKEv2 IPSec VPN Server on Rocky Linux 9 using strongSwan and Let's Encrypt ====== **Author:** //[[michael@dmtec.com.au|Michael Ibanes]] - 03 Feb 2023// ===== Introduction ===== 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(r), 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:__ * A newly deployed Rocky Linux 9 instance with root access or a non-root sudo user. * Create a fully-qualified DNS "A" record that points to your server's IP address. 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. ===== Main firewall setup ===== 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. ===== Update OS and set SELINUX to Permissive ===== 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 ===== Configure Networking ===== 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 ===== Register an auto-renewable Lets Encrypt SSL certificate ===== 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 < 8. Restart Crond $ sudo systemctl restart crond ===== Install and configure strongSwan ===== 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: * Disable 'Use default gateway on remote network' in the VPN client settings (This will enable split tunnelling). * Replace 0.0.0.0/0 in the below configuration file, with the address of your remote private network(for example 10.130.0.0/20). * Choose in the below configuration file, an address pool 'addrs' that shares the same A-Class as your remote private network. In our example, 10.1.1.0/24 is appropriate as it is a subnet of the A-Class 10.0.0.0/8. On VPN Startup, if you are using a Windows(r) client, it will automatically add a static route to push traffic for 10.0.0.0/8 to the VPN interface. You can also have, automatically added static routes when a VPN connection is established. Search Google for 'Add-VpnConnectionRoute' or check out the links at the bottom of this page. **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 ---- ===== Client Connections ===== To connect to your VPN server, choose the instructions for your client operating system. ==== Windows ==== - Open **Settings**. - Select **Network & internet**. - Select **VPN**. - Select **Add a VPN configuration**. - Configure the following settings: * VPN provider: Windows (built-in) * Connection name: (any string) * Server name or address: (fully-qualified domain name) * VPN type: IKEv2 * Type of sign-in info: User name and password * User name: (username) * Password: (password) - Click **Save**. - Click your VPN configuration. - Click **Connect**. ==== macOS ==== - Open **System Preferences**. - Select **Network**. - Add a new service with the **+** icon. - Configure the following settings: * Interface: VPN * VPN Type: IKEv2 * Service Name (any string) - Click Create. - Configure the following settings: * Server Address: (fully-qualified domain name) * Remote ID: (fully-qualified domain name) * Local ID: (leave blank) - Click **Authentication Settings**. - Enter your username and password. - Click **OK**. - Click Connect. ==== iOS ==== - Open **Settings**. - Select **VPN**. - Select **Add VPN Configuration**. - Configure the following settings: * Type: IKEv2 * Description: (can be any string) * Server: (fully-qualified domain name) * Remote ID: (fully-qualified domain name) * Local ID: (leave blank) * User Authentication: Username * Username: (username) * Password: (password) * Proxy: Off - Select **Done**. - Tap on the switch to connect or disconnect. ==== Android ==== - Open the Play Store. - Search and install "strongSwan VPN Client". - Launch the app. - Select **Add VPN Profile**. - Configure the following settings: * Server: (fully-qualified domain name) * VPN Type: IKEv2 * Username: (username) * Password: (password) * CA certificate: (Select automatically) * Profile name: (any string) * Server identity: (fully-qualified domain name) - Select **Save**. - Select Connect. ------ ===== Additional information ===== * Check out the [[https://strongswan.org/documentation.html| strongSwan Documentation]] * Windows VPN Client, how to [[https://woshub.com/add-routes-after-connect-vpn-windows/|Automatically Add Static Routes After Connecting to VPN]]