Routage d'un client VPN

Routage d'un client VPN : full tunnel, split tunnel, AllowedIPs

Une fois le tunnel établi, la question suivante est : quels paquets y entrent ? Comme le rappelle la page d'accueil sur le fonctionnement d'un VPN, l'interface virtuelle n'agit que sur le trafic que la table de routage lui envoie. Comprendre comment un client manipule cette table éclaire à la fois le tunnel complet, le tunnel divisé et les fuites de routage.

Rappel : la table de routage

Pour chaque paquet, le système choisit la route la plus spécifique qui correspond à l'adresse de destination. La route par défaut, notée 0.0.0.0/0, s'applique quand aucune autre ne correspond ; elle pointe normalement vers la passerelle du réseau local. Établir un tunnel complet consiste à faire en sorte que, pour toutes les destinations Internet, la route retenue soit celle qui passe par l'interface du tunnel.

Le tunnel complet et l'astuce des deux demi-routes

La méthode naïve serait de remplacer la route par défaut existante. C'est risqué : si le client plante sans nettoyer, la machine se retrouve sans route par défaut. OpenVPN emploie donc une astuce élégante : il ajoute deux routes, 0.0.0.0/1 et 128.0.0.0/1, qui couvrent à elles deux tout l'espace d'adressage mais sont plus spécifiques que le 0.0.0.0/0 d'origine. Elles l'emportent donc sans le supprimer. Il ajoute en parallèle une route très précise vers l'adresse du serveur VPN, via la passerelle physique, pour que les paquets du tunnel eux-mêmes ne rebouclent pas dans le tunnel. Au débranchement, il suffit de retirer les deux demi-routes et la route du serveur : la vraie route par défaut, jamais touchée, reprend la main.

WireGuard : AllowedIPs, fwmark et règles de politique

WireGuard n'a pas de table de routage propre : le champ AllowedIPs associé à un pair fait double emploi. En réception, il filtre : un paquet déchiffré dont l'adresse source n'appartient pas aux AllowedIPs du pair est rejeté. En émission, il indique quelles destinations passent par ce pair. Déclarer AllowedIPs = 0.0.0.0/0, ::/0 revient donc à un tunnel complet.

Le problème du rebouclage est résolu autrement : le client marque les paquets qu'il émet lui-même vers le serveur avec une étiquette (fwmark), puis installe une règle de politique de routage qui dit « les paquets portant cette étiquette utilisent la table de routage principale, tous les autres utilisent la table du tunnel ». C'est plus propre que les demi-routes, mais cela suppose que le système gère les règles de politique — ce qui est le cas de Linux et d'Android, moins systématiquement ailleurs, où le client WireGuard retombe alors sur une approche proche de celle d'OpenVPN.

Le tunnel divisé

Le tunnel divisé n'envoie dans le VPN qu'une partie du trafic. Trois granularités existent. Par adresse ou par plage : on ne route que certains blocs — utile pour n'atteindre qu'un réseau d'entreprise, ou au contraire pour tout envoyer sauf quelques services. Par application : le client lie chaque socket d'une application donnée à l'interface du tunnel — via SO_BINDTODEVICE sous Linux, la plateforme de filtrage sous Windows, un mécanisme par application sur mobile. Par domaine : le client résout le nom, puis ajoute dynamiquement une route vers les adresses obtenues ; c'est la méthode la plus fragile, car un domaine peut renvoyer des adresses changeantes ou multiples, et la résolution elle-même doit être maîtrisée.

Le tunnel divisé a un intérêt réel — garder l'accès à une imprimante locale, à un site bancaire qui bloque les adresses de VPN, à un service de streaming national — mais chaque exclusion est un chemin en clair, avec l'adresse réelle, qu'il faut assumer.

Le cas IPv6

L'oubli le plus fréquent. Un client qui route 0.0.0.0/0 mais pas ::/0 laisse tout le trafic IPv6 sortir en clair. Sur un réseau et un système en double pile, cela suffit à révéler l'adresse IPv6 réelle à tout site joignable en IPv6. Un client correct route les deux familles, ou désactive l'IPv6 pendant la session. Ce point recoupe directement la page fuites DNS, IPv6 et WebRTC.

Le réseau local

Par défaut, un tunnel complet capture aussi le trafic vers le réseau local, ce qui coupe l'accès à une imprimante, un NAS ou une passerelle domestique. La plupart des clients proposent une option « autoriser l'accès au réseau local » qui ajoute une route plus spécifique vers le /24 local via la passerelle physique. C'est pratique, mais cela crée une exception : un site malveillant qui connaît votre plage locale pourrait tenter de la sonder. À activer en connaissance de cause.

Le rebouclage : le piège de la route hôte

La route très précise vers l'adresse du serveur VPN, via la passerelle physique, est indispensable : sans elle, les paquets chiffrés destinés au serveur seraient eux-mêmes routés dans le tunnel, qu'ils sont censés constituer, et rien ne partirait. C'est aussi une petite faiblesse de confidentialité : cette route reste visible dans la table de routage et trahit l'adresse du serveur à qui inspecte la machine. Elle doit par ailleurs être recalculée à chaque changement de passerelle, faute de quoi le tunnel se retrouve établi mais muet.

Conteneurs, machines virtuelles et sous-réseaux

Un VPN configuré sur l'hôte ne couvre pas automatiquement les environnements isolés qui tournent dessus. Un conteneur avec son propre espace réseau, une machine virtuelle en mode ponté, un sous-réseau derrière la machine : chacun a sa propre table de routage et peut sortir directement. Pour les protéger, il faut soit établir le tunnel à l'intérieur de l'environnement, soit router explicitement son sous-réseau vers l'interface du tunnel de l'hôte et le déclarer côté serveur. C'est une source fréquente de fuite dans les usages techniques.

Vérifier sa table de routage

Le contrôle se fait en une commande. Sous Linux, ip route et ip -6 route listent les routes actives ; les deux demi-routes ou l'entrée pointant vers l'interface du tunnel doivent apparaître, ainsi que la route hôte vers le serveur. Sous Windows, route print donne l'équivalent, et Get-NetRoute en PowerShell. On vérifie ensuite par où sort réellement un paquet avec un traceroute — le premier saut doit être l'adresse interne du serveur VPN, pas la passerelle locale.

Le changement de réseau

Quand la machine change de réseau — Wi-Fi vers cellulaire, changement de point d'accès —, l'adresse de la passerelle physique change, et la route précise vers le serveur VPN doit être recalculée. WireGuard et IKEv2 avec MOBIKE gèrent cette transition sans réétablir tout le tunnel ; OpenVPN la gère avec l'option de déplacement de session. Un client qui ne suit pas ce changement laisse le tunnel « mort » : établi en apparence, mais sans aucun trafic qui passe, ce qui, sans interrupteur d'arrêt, fait repartir les applications en clair dès qu'elles réessaient.

Ce qu'il faut retenir

Un tunnel complet bien fait n'écrase pas la route par défaut : il la contourne avec des routes plus spécifiques, faciles à retirer. WireGuard formalise ce comportement avec AllowedIPs et le marquage de paquets. Le tunnel divisé est utile mais chaque exclusion est un chemin en clair, et l'IPv6 comme le réseau local sont les oublis classiques. La forme du tunnel dépend du protocole ; ce qui s'échappe malgré un routage correct est traité sur la page fuites.