Strongswan
Strongswan est une implémentation libre du protocole IPSec sous Linux. Nous utilisons ce type de tunnel pour la réplication des bases de données entre nos deux Wiki: https://doc.ycharbi.fr et https://doc.lesmorin.fr.
Nous documenterons la mise en place de ce type de VPN et en bonus, la mise en place d'un tunnel GRE avec Open vSwitch pour y faire passer un lien trunk. Dans chacune des explications, nous partons du principe que deux serveurs derrière un NAT (le cas concret d'Internet avec IPv4) veulent se connecter ensemble (IKEv2 gère automatiquement le NAT).
Il est possible de s'authentifier via un mot de passe (PSK) ou via un certificat (PKI).
Connexion par PKI
Dans cette section, nous allons voir comment utiliser une paire de clés publique/privée pour la connexion au VPN.
Installation des paquets
À effectuer sur les deux serveurs:
apt install strongswan strongswan-pki
Sur le serveur 1
Configuration des noms
Pour la clarté du tuto, nous utiliserons les noms appliqués dans cette section.
Changement du nom d'hôte
vim /etc/hostname
ipsec1
Résolution des paires
vim /etc/hosts
192.168.180.96 ipsec1 192.168.181.18 ipsec2
Configuration IPSec
Création des clés
ipsec pki --gen --type ecdsa --outform pem --size 521 > /etc/ipsec.d/private/YC-NM_ycharbi_key.pem
ipsec pki --self -t ecdsa --in /etc/ipsec.d/private/YC-NM_ycharbi_key.pem --outform pem --lifetime 3650 --dn "CN=YC-NM_ycharbi_crt" > /etc/ipsec.d/certs/YC-NM_ycharbi_crt.pem
Configuration de la connexion
vim /etc/ipsec.conf
conn %default
ikelifetime=60m
keylife=20m
rekeymargin=3m
keyingtries=%forever
keyexchange=ikev2
mobike=no
conn YC-NM
ike=aes256gcm128-sha512-ecp521!
esp=aes256gcm128-sha512-ecp521!
left=ipsec1
leftsubnet=10.254.254.254/32
leftid=@ycharbi
leftcert=YC-NM_ycharbi_crt.pem
leftfirewall=yes
right=ipsec2
rightsubnet=10.254.254.253/32
rightid=@lesmorin
rightcert=YC-NM_lesmorin_crt.pem
auto=route
Ajout d'une ACL pour la connexion
vim /etc/ipsec.secrets @lesmorin @ycharbi : ECDSA /etc/ipsec.d/private/YC-NM_ycharbi_key.pem
Configuration de l'interface réseau
allow-hotplug eth0
iface eth0 inet static
address 192.168.180.96
netmask 255.255.255.0
gateway 192.168.180.254
up ip addr add 10.254.254.254 dev eth0
up ip route add 10.254.254.253/32 dev eth0 src 10.254.254.254 || true
down ip route del 10.254.254.253/32 dev eth0 src 10.254.254.254 || true
down ip addr del 10.254.254.254 dev eth0
Donner le certificat à ipsec2
scp /etc/ipsec.d/certs/YC-NM_ycharbi_crt.pem root@ipsec2:/etc/ipsec.d/certs/
Sur le serveur 2
Configuration des noms
Changement du nom d'hôte
vim /etc/hostname
ipsec2
Résolution des paires
vim /etc/hosts
192.168.180.96 ipsec1 192.168.181.18 ipsec2
Configuration IPSec
Création des clés
ipsec pki --gen --type ecdsa --outform pem --size 521 > /etc/ipsec.d/private/YC-NM_lesmorin_key.pem
ipsec pki --self -t ecdsa --in /etc/ipsec.d/private/YC-NM_lesmorin_key.pem --outform pem --lifetime 3650 --dn "CN=YC-NM_lesmorin_crt" > /etc/ipsec.d/certs/YC-NM_lesmorin_crt.pem
Configuration de la connexion
vim /etc/ipsec.conf
conn %default
ikelifetime=60m
keylife=20m
rekeymargin=3m
keyingtries=%forever
keyexchange=ikev2
mobike=no
conn YC-NM
ike=aes256gcm128-sha512-ecp521!
esp=aes256gcm128-sha512-ecp521!
left=ipsec2
leftsubnet=10.254.254.253/32
leftid=@lesmorin
leftcert=YC-NM_lesmorin_crt.pem
leftfirewall=yes
right=ipsec1
rightsubnet=10.254.254.254/32
rightid=@ycharbi
rightcert=YC-NM_ycharbi_crt.pem
auto=route
Ajout d'une ACL pour la connexion
vim /etc/ipsec.secrets @lesmorin @ycharbi : ECDSA /etc/ipsec.d/private/YC-NM_lesmorin_key.pem
Configuration de l'interface réseau
allow-hotplug eth0
iface eth0 inet static
address 192.168.181.18
netmask 255.255.255.0
gateway 192.168.181.254
up ip addr add 10.254.254.253 dev eth0
up ip route add 10.254.254.254/32 dev eth0 src 10.254.254.253 || true
down ip route del 10.254.254.254/32 dev eth0 src 10.254.254.253 || true
down ip addr del 10.254.254.253 dev eth0
Donner le certificat à ipsec1
scp /etc/ipsec.d/certs/YC-NM_lesmorin_crt.pem root@ipsec1:/etc/ipsec.d/certs/
Connexion
À faire sur l'un des deux serveurs. Si vous avez utilisé l'option auto=start
, la connexion s'est initialisée d'elle même au redémarrage du démon. Dans le cas d'une option à auto=add
, la commande suivante permet d'initier la connexion.
Initier la connexion bilatérale
ipsec up YC-NM
initiating IKE_SA YC-NM[1] to 192.168.180.96
generating IKE_SA_INIT request 0 [ SA KE No N(NATD_S_IP) N(NATD_D_IP) N(FRAG_SUP) N(HASH_ALG) N(REDIR_SUP) ]
sending packet: from 192.168.181.18[500] to 192.168.180.96[500] (332 bytes)
received packet: from 192.168.180.96[500] to 192.168.181.18[500] (332 bytes)
parsed IKE_SA_INIT response 0 [ SA KE No N(NATD_S_IP) N(NATD_D_IP) N(FRAG_SUP) N(HASH_ALG) N(MULT_AUTH) ]
authentication of 'CN=YC-NM_lesmorin_crt' (myself) with ECDSA_WITH_SHA512_DER successful
establishing CHILD_SA YC-NM
generating IKE_AUTH request 1 [ IDi N(INIT_CONTACT) IDr AUTH SA TSi TSr N(MULT_AUTH) N(EAP_ONLY) ]
sending packet: from 192.168.181.18[500] to 192.168.180.96[500] (401 bytes)
received packet: from 192.168.180.96[500] to 192.168.181.18[500] (350 bytes)
parsed IKE_AUTH response 1 [ IDr AUTH SA TSi TSr N(AUTH_LFT) ]
using trusted certificate "CN=YC-NM_ycharbi_crt"
authentication of 'CN=YC-NM_ycharbi_crt' with ECDSA_WITH_SHA512_DER successful
IKE_SA YC-NM[1] established between 192.168.181.18[CN=YC-NM_lesmorin_crt]...192.168.180.96[CN=YC-NM_ycharbi_crt]
scheduling reauthentication in 3314s
maximum IKE_SA lifetime 3494s
CHILD_SA YC-NM{1} established with SPIs c3c1c23c_i cd8f8267_o and TS 10.254.254.253/32 === 10.254.254.254/32
connection 'YC-NM' established successfully
Afficher l'état du tunnel
ipsec status
Security Associations (1 up, 0 connecting):
YC-NM[1]: ESTABLISHED 2 minutes ago, 192.168.181.18[CN=YC-NM_lesmorin_crt]...192.168.180.96[CN=YC-NM_ycharbi_crt]
YC-NM{1}: INSTALLED, TUNNEL, reqid 1, ESP SPIs: c3c1c23c_i cd8f8267_o
YC-NM{1}: 10.254.254.253/32 === 10.254.254.254/32
Tests de fonctionnement
Sur ipsec1
ping 10.254.254.253
Sur ipsec2
ping 10.254.254.254
À ce stade, c'est terminé. La partie suivante n'est que bonus.
Correction de problèmes
Retenter la connexion lors d'un échec de résolution de nom DNS
Lors du démarrage d'une machine avec l'option auto=start
, le service strongwan fait appel au démon charon (IKE) pour initier la connexion. Le problème est que cet imbécile le fait avant que la partie réseau ne soit pleinement opérationnelle. On se tape donc une jolie erreur de résolution DNS et comme ce couillon s’arrête à la première erreur, rien ne se passe. Il faut donc lui dire de réessayer (toute les 30 secondes dans notre cas).
vim /etc/strongswan.d/charon.conf
À la ligne 208 au moment ou j’écris ceci
retry_initiate_interval = 30
Relancer le service
systemctl restart strongswan.service
Configuration d'un tunnel GRE
Petit bonus, nous allons utiliser Open vSwitch pour monter un tunnel GRE entre nos deux serveurs, et ceux, dans le but d'y faire passer un lien trunk 802.1Q pour transporter nos VLAN.
Cette partie peut vous être utile si vous voulez utiliser nos documentations sur LXC et QEMU dans des VLAN.
Sur les deux serveurs
apt install openvswitch-switch
Sur ipsec1
ovs-vsctl --may-exist add-br br0 ovs-vsctl add-port br0 gre0 trunks=10,20,1000,1001,1002,1003,1004,1005,1006,1007,1008,1009 -- set interface gre0 type=gre options:remote_ip=10.254.254.253
Sur ipsec2
ovs-vsctl add-br br0 ovs-vsctl add-port br0 gre0 trunks=10,20,1000,1001,1002,1003,1004,1005,1006,1007,1008,1009 -- set interface gre0 type=gre options:remote_ip=10.254.254.254
Sur les clients
Dé lors, vos machines virtuelles et vos conteneurs appartenant à l'un des VLAN du trunk GRE pourrons communiqué sur le même réseau sans passerelle à leurs paires via le tunnel IPSec. Un seul bémol au tableau, il faut modifier le MTU des interfaces réseau de ces éléments pour qu'ils puissent communiquer (sinon seul le ping passe - c'est un peu limitant je dois dire).
Dans chaque MV ou conteneur
vim /etc/network/interfaces
auto eth0
iface eth0 inet static
address 10.10.0.1
netmask 255.255.255.248
gateway 10.10.0.6
up ip link set $IFACE mtu 1368
Bien que ce caractéristique soit censé être géré par le protocole PMTUD, je n'ai pas réussi à le faire fonctionner dans cette installation. On est donc obligé de ce faire chier de la sorte (bon courage avec l'IOT...). À améliorer donc...
Sources
- https://wiki.strongswan.org/projects/strongswan/wiki/ConnSection
- https://wiki.strongswan.org/projects/strongswan/wiki/ConnSection
- https://wiki.strongswan.org/projects/strongswan/wiki/VirtualIp
- https://wiki.strongswan.org/projects/strongswan/wiki/IKEv2CipherSuites
- https://strongswan.org/testresults4.html