Ce billet détaille comment monter un tunnel IPSec sous Linux. C’est à mon sens un must have, principalement parce qu’IPSec est une merde ignoble sous Linux.
Mais avant de procéder plus avant, une question se pose.
Pourquoi IPSec ?
Actuellement je souhaite relier :
- plusieurs serveurs sur Internet
- plusieurs réseau locaux (celui du bureau et ceux des machines virtuelles derrières le routeur qui détient l’IP publique)
Voici mes possibilités pour réaliser ce « gros » réseau :
- créer plein de règles nat sur chaque routeurs.
- c’est pénible à maintenir
- oblige à reconfigurer les services pour n’utiliser que certaines plages de ports, et sans chevauchement d’une machine/vm à l’autre
- oblige à avoir une feuille avec la table de mapping et utiliser des ports non standards
Pas géniale comme solution, et les tuyaux ne sont pas sécurisés.
On peut alors reconfigurer tous les services pour protéger chaque flux, mais la manière de faire et la possibilité dépendent du service. Désormais on a la plupart des tuyaux qui sont sécurisés et encore plus de maintenance.
- mettre en place OpenVPN qui répond entièrement à la problématique, mais :
- il est architecturé en étoile (1 serveur, plusieurs clients). On peut aussi installer OpenVPN sur chaque routeur en mode serveur, mais c’est pas mal de configuration.
- il fonctionne en faisant le transport sur la couche applicative du modèle OSI (les paquets sont encapsulé dans un flux SSL sur du TCP ou UDP), cela induit un peu d’overhead
C’est la solution qui est actuellement en place chez moi.
Par rapport à OpenVPN, voici les avantages d’IPSec :
- c’est du P2P, il n’y a pas de notion « serveur », les routeurs se connectent donc en direct
- comme OpenVPN, la communication entre les 2 pairs est chiffrée
- il est kernel-space sous Linux et Windows, il est donc moins lourd qu’OpenVPN et ne nécessite aucune installation sous Windows
- son intégration aux protocoles IPs lui permet d’avoir un overhead plus faible qu’avec OpenVPN, donc une bande passante plus large
- les tunnels d’OpenVPN semblent saturer vite vers 10Mbps chez moi
Quelle implémentation d’IPSec ?
C’est une question qui ne se pose que pour le monde Unix. Avoir le choix c’est bien, mais dans le cas d’IPSec, c’est un peu compliqué. Côté logiciel, il y a eu FreeSwan, puis OpenSwan, puis StrongSwan ; côté noyau également, il a existé plusieurs implémentations : klips et netkey.
Aujourd’hui, j’ai jeté mon dévolu sur strongswan. Klips n’existe plus et les autres logiciels ne sont plus maintenus depuis plusieurs années, c’est donc quasiment un choix par défaut, mais également pour la négociation par certificats que strongswan est le seul à proposer (et que je trouve beaucoup plus simple à configurer que le Pre-Shared Key).
La conf !
Elle est très simple. Voici un exemple fonctionnel ci-dessous qui utilise l’authentification mutuelle par certificat, pour le détail: RTFM, ce dernier est plutôt à jour et bien réalisé.
Je ne détaille pas comment générer les certificats, ce n’est pas le but du billet, et puis j’ai déjà traité ça ici.
config setup cachecrls=yes # uniqueids = no # Add connections here. conn %default auto=start compress=no # ne fonctionne pas dpdaction=restart esp=aes128-sha1! ike=aes128-sha1-modp2048,aes128-sha1-modp1024! rightallowany=yes left=2001:41d0:fe1c:1300:20c:29ff:fe99:fbf #left=%any leftauth=pubkey rightauth=pubkey leftid="C=FR, O=Kveer, OU=Kveer IPSec Services, CN=Tefnout" leftca="C=FR, O=Kveer, OU=Kveer IPSec Services, CN=Kveer IPSec CA" rightca=%same leftcert=tefnout.crt leftfirewall=no mobike=no keyexchange=ikev2 conn illidan right=illidan.kveer.fr rightid="C=FR, O=Kveer, OU=Kveer IPSec Services, CN=Illidan" leftsubnet=192.168.3.0/24 rightsubnet=192.168.14.128/27
# les règles iptables à ajouter. iptables -A INPUT -p udp -m multiport --dport isakmp,ipsec-nat-t -m comment --comment ipsec -j ACCEPT iptables -A INPUT -p esp -j ACCEPT iptables -t nat -I POSTROUTING 1 -m policy --dir out --pol ipsec -j ACCEPT
La dernière règle iptables est à ne pas oublier si l’on souhaite faire fonctionner le tunnel pour les routeurs eux-mêmes. Dans le cas d’un tunnel IPv4, ça ne marchera pas, dans le cas d’un tunnel IPv6, le kernel va générer un Oops (la règle est obligatoire sous peine de non-sens, mais cela n’autorise pas le kernel à planter, c’est bien un bug, en attente de correction)