Configuriamo un server VPN IKEv2 con StrongSwan e Let’s Encrypt su Debian

In questo articolo vedremo come configurare un Server VPN con IKEv2 e strongSwan. La scelta di questo tipo di protocollo è dovuta al fatto che con la corretta configurazione è automaticamente supportata da praticamente ogni client integrato su smartphone (sia Android che iOS) e sui client di default di MacOS e Windows (e ovviamente Debian).

Considerando il precedente articolo Ma una VPN ci serve davvero? vi potreste chiedere come mai abbia avuto la necessità di utilizzare una VPN dopo averne decantato i motivi per cui fosse completamente inutile per la maggior parte delle persone. Vi spiego brevemente:

  • la mia rete aziendale filtra il traffico TCP, ma non quello UDP (cosa fondamentale visto che la VPN necessita delle porte 500 e delle porte 4500 UDP aperte per poter funzionare) e volevo aggirare le limitazioni sui dispositivi personali (tra cui è rallentato il traffico di WhatsApp);
  • ho la necessità di utilizzare un dispositivo Windows da casa tramite il protocollo RDP. Non mi fido assolutamente a mostrare il servizio RDP sulla rete esterna e quindi ho utilizzato una VPN come compromesso. Questa non è una scelta moderna, anzi, fa molto anni ’90 e va contro il principio zero trust network. Diciamo che essendo la mia rete locale ho trovato un compromesso che ho deciso di accettare.

In ogni caso se per qualunque motivo tu volessi configurare una VPN personale vediamo insieme come fare.

Questa configurazione prevede l’avere un dominio associato alla VPN per il quale chiederemo un certificato con certbot (ma va bene anche se già lo avete configurato). Questa guida non tratterà la richiesta di dominio, ma nel caso ne abbiate necessità potete consultare il post Configuriamo un dominio dinamico con Google domains.

Installazione software necessario

Se non avete già per qualche motivo configurato certbot (per gestire i certificati SSL) dovete installarlo con

apt-get install certbot

Procediamo anche con l’installazione di strong-swan (il software della VPN).

apt install --install-suggests strongswan

Configurazione dei certificati

Se non avete mai richiesto il certificato per il vostro server dovrete lanciare

certbot certonly –standalone –pre-hook “echo -n” –post-hook “echo -n”

è importante che il dominio scelto punti già al server e che sia accessibile la porta 80 da esterno (va aperta sul router).

Il --pre-hook "echo -n" e --post-hook "echo -n" li abbiamo inseriti per fare da segnaposto e poi configurare manualmente il file di configurazione di certbot.

I certificati li troverete in ls /etc/letsencrypt/live/tuodominio.net/. Dal momento che la versione di Strong-Swarn attualmente presente in Debian 11 imposta di default una configurazione di AppArmor i certificati in questa directory di default non sarebbero accessibili.

Per comodità, invece di andare a modificare i profili di AppArmor, andiamo a creare un nuovo script che copia i certificati nella directory di StrongSwarn e riavvia il servizio. Quindi diamo nano /usr/local/bin/ipsec-cert-renew e inseriamo:

#!/bin/bash

certSource="/etc/letsencrypt/live/tuodominio.net"

cp -f "$certSource/privkey.pem" "/etc/ipsec.d/private/key.pem"
cp -f "$certSource/cert.pem" "/etc/ipsec.d/certs/certificate.pem"
cp -f "$certSource/chain.pem" "/etc/ipsec.d/cacerts/ca.pem"

systemctl restart strongswan-starter.service

Avendo cura di modificare tuodominio.net nel dominio che si è realmente configurato. Diamo i permessi corretti

chmod 750 /usr/local/bin/ipsec-cert-renew

e testiamo la correttezza dello script lanciando ipsec-cert-renew. Verifichiamo che in /etc/ipsec.d/private, in /etc/ipsec.d/certs/ e in /etc/ipsec.d/cacerts/ siano presenti rispettivamente key.pem, certificate.pem e ca.pem.

Dobbiamo ora dire a certbot di aggiornare i certificati e riavviare StrongSwan ogni volta che viene effettuato il rinnovo. Quindi diamo

nano /etc/letsencrypt/renewal/tuodominio.net.conf

Al parametro post_hook = echo -n sostituiamo con post_hook = ipsec-cert-renew e salviamo.

Perché abbiamo fatto questa scelta di configurare un dominio come standalone con certbot e mettere un post_hook e un pre_hook con un segnaposto come il comando “echo -n“? Perché nel caso in cui dovessi avere anche un server apache da riavviare per gestire i certificati potremo dare nel pre_hook il comando systemctrl apache2 stop e nel post_hook systemctrl apache2 start && ipsec-cert-renew in modo da avere una gestione più flessibile.

~ Digressione

Configurazione di StrongSwan

Configuriamo StrongSwan per la nostra connessione. Dobbiamo editare il file /etc/ipsec.conf come segue (ricordiamo di commentare la prima riga del config setup e aggiungiamo dopo)

#config setup
        # strictcrlpolicy=yes
        # uniqueids = no

config setup
#        charondebug="cfg 2"  # log proposals
        uniqueids=never  # allow multiple connections from a given user

conn myvpn
        keyexchange=ikev2
        auto=add
        left=%any
        leftid=@tuodominio.net
        leftsubnet=0.0.0.0/0
        leftauth=pubkey
        leftcert=certificate.pem
        leftsendcert=always
        right=%any
        rightsourceip=10.10.10.10/24
        rightauth=eap-mschapv2
        rightsendcert=never
        rightdns=192.168.1.254
        eap_identity=%any
        dpdaction=clear
        dpddelay=2400s
        rekey=no
        fragmentation=yes
        forceencaps=yes
        ike=aes256-aes192-aes128-sha384-sha256-sha1-modp3072-modp2048-modp1536-modp1024!
        esp=aes256-aes192-aes128-sha384-sha256-sha1!

# Add connections here.

La riga charondebug="cfg 2" è di default disabilitata, nel caso in cui ci siano dei malfunzionamenti possiamo abilitarla per aggiungere verbosità nel debug. Inoltre ricordiamo di cambiare leftid=@tuodominio.net con il dominio che state utilizzando e rightdns=192.168.1.254 con il DNS che volete utilizzare. Io ho utilizzato il mio router, magari il vostro router ha un indirizzo IP differente (potete vederlo dalla configurazione dhcp del vostro sistema con . Se non sapete quale indirizzo mettere scegliete rightdns=8.8.8.8,8.8.4.4 che sono i google DNS.

Configuriamo ora gli utenti con dando nano /etc/ipsec.secrets facendo diventare il file come segue

#  GNU nano 5.4                   /etc/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.

### SSL private key
: RSA key.pem

### Clients' credentials (plaintext)
nomeutente1 : EAP "password1"
nomeutente2 : EAP "password2"
# ...etc.  Note that the presence of whitespace either side of the ':' is significant.

# You could also tell strongSwan to include secrets from elsewhere,
# for example an auto-generated file:
#include /etc/ipsec.d/secrets/myvpn

Andiamo quindi a modificare nomeutente1 e password1 (così come i 2) con gli utenti che vogliamo andare a configurare. Le password devono essere messe in chiaro.

Configurazione del sistema

Dobbiamo configurare il kernel per permettere il redirict dei pacchetti. Diamo

sudo nano /etc/sysctl.conf

e aggiungiamo

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

Con questa configurazione ammettiamo il forward dei pacchetti ipv4, al tempo stesso blocchiamo la redirezione di pacchetti ICMP per motivi di sicurezza.

Configurazione del firewall

È necessario configurare il firewall per effettuare il redirict della connessione. Lanciamo da root, ricordandoci di sostituire enp3s0 con il nome della nostra interfaccia di rete che stiamo utilizzando (che possiamo trovare dando il comando ip link).

iptables -A FORWARD --match policy --pol ipsec --dir in  --proto esp -s 10.10.10.10/24 -j ACCEPT
iptables -A FORWARD --match policy --pol ipsec --dir out --proto esp -d 10.10.10.10/24 -j ACCEPT
iptables -t nat -A POSTROUTING -s 10.10.10.10/24 -o enp3s0 -m policy --pol ipsec --dir out -j ACCEPT
iptables -t nat -A POSTROUTING -s 10.10.10.10/24 -o enp3s0 -j MASQUERADE
iptables -t mangle -A FORWARD --match policy --pol ipsec --dir in -s 10.10.10.10/24 -o enp3s0 -p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1361:1536 -j TCPMSS --set-mss 1360

Una volta fatto ciò è necessario rendere permanenti le modifiche al firewall (altrimenti non sopravvivono al riavvio). Se non abbiamo già installato iptables-persistent diamo

apt install iptables-persistent

e facciamo configurare automaticamente le regole per IPv4. Possiamo non far configurare le regole per IPv6 a meno che non lo utilizziamo.

Se abbiamo aggiornato la configurazione di iptables o abbiamo sbagliato durante la configurazione automatica basta dare

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

al fine di aggiornarla.

Configurazione dei client

Configurare i client è semplicissimo, basta inserire come indirizzo della VPN l’indirizzo associato al server, inserire lo stesso valore anche come ID remoto e il proprio username e password.

Configurazione su MacOS Ventura

Configurazione su iOS 16

Per configurare una VPN su iPhone è sufficiente andare in Impostazioni → Generali → VPN e gestione dispositivi → Aggiungi configurazione VPN e poi inserire in Server e ID remoto l’indirizzo del proprio server e in Nome utente e Password il nome utente e la password configurata

Fonti

[1] https://www.cl.cam.ac.uk/~mas90/resources/strongswan/
[2] https://www.digitalocean.com/community/tutorials/how-to-set-up-an-ikev2-vpn-server-with-strongswan-on-ubuntu-22-04
[3] https://molchanoff.me/post/ikev2-vpn-server-with-strongswan-and-lets-encrypt/