Kill switch VPN : modèle fail-closed et vérification des fuites IP
Une route vers le VPN ne garantit pas que votre IP source reste cachée. Modèle fail-closed, DNS, IPv6 et protocole de test sans perturber une cible.
La route vers une cible passe par le VPN. Puis le Wi-Fi saute, le client reconnecte et la route disparaît quelques secondes. Par où part le prochain paquet ? C’est la question qu’un kill switch doit résoudre. Un bouton « connecté » dans l’application et un site qui affiche l’IP du VPN à un instant donné ne répondent pas à ce qui arrive pendant la transition. Pour une mission offensive, le risque est concret : une requête destinée à une cible autorisée peut sortir par l’interface physique et présenter l’adresse publique de l’équipe au lieu de l’adresse de sortie prévue.
Nous n’avons pas audité ici une configuration rootzero ni observé une fuite réelle. Ce billet propose un critère vérifiable et un test sur environnement contrôlé. Il ne fournit pas une règle de pare-feu à copier : une exception inadaptée peut couper l’accès distant ou ouvrir précisément le chemin qu’elle devait fermer.
Définir le trafic protégé avant d’écrire une règle
« Tout doit passer dans le VPN » est parfois la bonne politique pour un tunnel complet. Dans une mission à split tunnel, elle peut être fausse : seul le réseau de mission doit emprunter le tunnel, tandis que le reste du trafic garde sa sortie normale. Il faut donc commencer par nommer les destinations et domaines de mission, l’adresse de sortie attendue, les interfaces possibles et les exceptions autorisées. Le serveur VPN doit rester joignable depuis l’interface physique pour établir le tunnel ; selon l’environnement, quelques services locaux peuvent aussi être nécessaires. Une exception « tout le DNS » ou « tout le LAN » est rarement assez précise pour mériter le nom de kill switch.
Le critère est fail-closed pour les destinations protégées : tunnel absent au démarrage, en cours de connexion ou après une panne, aucun paquet destiné à ces cibles ne sort en clair par l’interface physique. Une erreur de connexion côté application est attendue dans cet état. Elle ne prouve pas à elle seule qu’aucun paquet n’a quitté la machine. Une règle persistante de pare-feu de sortie, installée avant le client VPN, ou un espace réseau isolé peut imposer cette propriété. La documentation WireGuard sur les espaces de noms réseau montre par exemple un processus qui ne voit que l’interface wg0 ; le socket UDP chiffré du tunnel reste dans son espace d’origine.
Une simple route par défaut vers le VPN ne constitue pas cette barrière. WireGuard explique qu’un gestionnaire DHCP peut modifier les routes, et que certains changements d’interface effacent une route explicite vers le serveur VPN (WireGuard, routes et namespaces). La route dit au noyau où il prévoit d’envoyer un paquet maintenant ; la règle de sortie dit quelles voies lui sont permises quand l’état change.
Le script de déconnexion arrive parfois trop tard
La page de manuel de wg-quick fournit un exemple de kill switch basé sur des règles PostUp et PreDown. Il est utile pour comprendre le mécanisme, mais son PreDown retire le rejet lors de l’arrêt normal. Ce seul exemple ne démontre donc pas le blocage avant le premier démarrage ni après un arrêt propre. La page précise aussi qu’il faut traiter IPv6 séparément lorsqu’il est utilisé et signale le cas particulier de certains paquets DHCP hors du chemin Netfilter. Il faut lire ce que protège la règle, et à quels moments elle existe, avant d’en reprendre le nom.
Le même piège existe avec les hooks d’autres clients. OpenVPN documente des scripts up et down, ainsi que des redémarrages où persist-tun peut maintenir l’interface et éviter de rejouer ces scripts. Une déconnexion déclenchée depuis l’interface graphique, une panne du processus, une reconnexion et un changement de Wi-Fi ne suivent pas nécessairement la même séquence de hooks. Une politique de sortie indépendante de cette séquence est plus facile à raisonner : elle n’attend pas que le tunnel annonce sa propre panne pour interdire un paquet.
DNS et IPv6 peuvent prendre une autre route
Même si les adresses IPv4 de mission sont bien routées, un nom de cible peut être résolu auprès du résolveur fourni par le Wi-Fi. La requête DNS révèle alors le nom interrogé et la source physique au résolveur ; selon l’application, une réponse obtenue hors tunnel peut aussi orienter la connexion suivante. Vérifiez la politique DNS par interface et par domaine. NetworkManager documente ses priorités DNS, dont les valeurs négatives qui peuvent exclure les serveurs d’autres profils. systemd-resolved expose les serveurs, domaines de routage et paramètres par lien via resolvectl status. Un fichier /etc/resolv.conf lu isolément ne raconte pas toujours cette décision.
Testez les deux familles IP. Une destination peut avoir un enregistrement AAAA, et l’interface physique peut posséder une route IPv6 utilisable alors que le tunnel ne couvre que 0.0.0.0/0. Inversement, supprimer IPv6 sans vérifier le besoin de la mission n’est pas une méthode de preuve. Pour les accès par nom, incluez aussi la résolution pendant une reconnexion, avec et sans cache, et identifiez le comportement des applications qui utilisent leur propre résolveur. Les règles de sortie doivent porter sur ce qui est effectivement émis. La table de routage que l’on pensait avoir configurée ne suffit pas.
Observer chaque transition du tunnel
Sur une cible de labo que vous contrôlez, choisissez une adresse IPv4, une IPv6 si pertinente et un nom qui produit une résolution observable. Relevez d’abord les interfaces et les routes avec ip route get <adresse-ipv4> et ip -6 route get <adresse-ipv6> ; la page ip-route(8) décrit cette interrogation. Regardez les choix DNS avec resolvectl status. Ces lectures donnent un état, pas encore la preuve qu’un paquet ne sortira jamais.
Lancez ensuite une tentative répétée vers votre point de test et observez simultanément l’interface physique et le tunnel, par exemple avec tcpdump -ni <interface> sur chaque interface. Le capteur placé sur l’interface physique doit voir le trafic chiffré nécessaire au serveur VPN, mais aucun paquet en clair vers la cible protégée ; surveillez aussi les requêtes DNS correspondantes. Comparez quatre moments : avant tout démarrage du VPN, tunnel établi, reconnexion ou perte de lien, puis arrêt du client. Répétez après un changement de réseau si le poste doit survivre à cette transition. Le service de test doit voir l’adresse de sortie attendue quand le tunnel est établi, et ne recevoir aucune connexion protégée quand il ne l’est plus.
Un contrôle sur un site « quelle est mon IP ? » peut compléter ce test pour un tunnel complet. En split tunnel, ce site peut afficher l’IP physique parce qu’il ne fait pas partie des destinations protégées. Pour vérifier le kill switch, corrélez la destination protégée, le chemin réseau observé et l’adresse source vue par votre serveur de test pendant chaque changement d’état du tunnel.
#rootzero
Une question sur votre exposition ?
Écrivez-nous. Une personne de l’équipe technique vous répond, sources à l’appui.