Le handshake WireGuard fonctionne mais pas l’internet : suivre le paquet
Le handshake ne prouve que les clés et l’accessibilité. Suivez un paquet depuis AllowedIPs à travers le transfert, le NAT et la route de retour pour voir où il s’arrête.
Le tunnel est monté, wg show signale un handshake récent, vous pouvez pinguer l’adresse du tunnel du serveur, et rien au-delà ne répond. Le réflexe est de régénérer les clés ou de repartager la configuration. Cela modifie précisément la partie du chemin dont le fonctionnement est déjà prouvé.
Un handshake terminé dit que les deux pairs s’accordent sur les clés, qu’UDP atteint le point de terminaison et que le routage cryptographique accepte le paquet. Il ne dit rien sur la capacité du paquet à quitter le serveur ensuite.
Suivez donc un seul paquet au lieu de deviner. Il y a quatre endroits où il peut mourir, et chacun laisse une trace différente.
Ce que le handshake prouve réellement
WireGuard est un protocole UDP qui établit une session avec un handshake Noise puis chiffre les paquets pour un pair. Quand wg show affiche un handshake de quelques secondes et un compteur de transfert croissant, le point de terminaison, les clés et la clé publique du pair sont tous corrects.
Ce qu’il ne prouve pas, c’est que votre client envoie bien du trafic vers l’internet dans l’interface, que le serveur accepte de le transférer ou qu’une réponse trouve le chemin du retour. Ce sont des décisions de routage du noyau et du pare-feu, et elles se prennent hors du tunnel.
C’est pourquoi pinguer l’adresse du tunnel du serveur est un test si trompeur. Ce paquet est adressé au serveur lui-même, il se termine donc localement. Il n’a jamais besoin de transfert, jamais de traduction et jamais d’une route de retour depuis l’internet.
AllowedIPs est une décision de routage
Sur le client, AllowedIPs fait deux choses. C’est la table de routage par clé cryptographique qui décide quelles adresses de destination entrent dans le tunnel de ce pair, et c’est la liste des adresses sources que le pair acceptera de vous. Si la configuration du client ne liste que 10.8.0.0/24, les destinations publiques n’entrent jamais dans l’interface et votre route par défaut habituelle les emporte hors du tunnel. Le tunnel fonctionne alors parfaitement et ne fait rien de ce que vous vouliez.
Regardez ce que le client a réellement installé plutôt que ce que dit le fichier de configuration :
wg show wg0 allowed-ipsip route get 1.1.1.1
La seconde commande est la décisive. Si la réponse nomme votre interface physique et la passerelle habituelle, le paquet n’est pas tunnelisé et aucun changement côté serveur n’y remédiera. Ajoutez 0.0.0.0/0 pour IPv4 et ::/0 pour IPv6 séparément ; une règle qui attrape tout pour une famille laisse l’autre sur son chemin d’origine, et c’est une cause fréquente d’un tunnel IPv4 qui fonctionne et d’une résolution IPv6 bloquée.
Où le paquet meurt sur la passerelle
Si la route est correcte et que le paquet ne va toujours nulle part, il arrive au serveur et s’y arrête. Quatre vérifications couvrent la plupart des passerelles.
Le transfert. sysctl net.ipv4.ip_forward qui renvoie 0 est la réponse classique, et beaucoup de distributions restent à 0 par défaut. Il doit valoir 1, et être réglé durablement dans un fichier sysctl plutôt que par une commande qui disparaît au redémarrage. Le transfert IPv6 est un commutateur distinct.
La politique de filtrage. Une chaîne FORWARD avec une politique d’abandon par défaut rejettera le trafic du tunnel tout en autorisant le trafic vers l’hôte lui-même, ce qui correspond exactement au symptôme. Lisez le jeu de règles actif, pas un fichier enregistré : nft list ruleset ou iptables -S.
Traduction ou routage. Les clients utilisant des adresses de tunnel privées ont besoin soit d’un NAT source sur l’interface de sortie du serveur, soit d’un préfixe routé que le réseau amont sait renvoyer. Le choix entre les deux suit le plan d’adressage. Ajouter MASQUERADE à un réseau qui route déjà votre préfixe en retour est inoffensif mais inutile, et l’omettre là où aucune route n’existe laisse les réponses adressées à une plage privée non routable.
Le chemin de retour. Dans les conceptions routées, le routeur amont a besoin d’une route pointant vers votre serveur. Le réseau du fournisseur peut aussi le bloquer : plusieurs clouds activent une vérification de source et de destination sur l’instance, qui abandonne silencieusement les paquets dont la source n’est pas l’adresse propre de l’instance jusqu’à ce que cette vérification soit désactivée.
Le DNS échoue autrement que le routage
Un paquet vers une adresse connue et une résolution de nom sont deux échecs distincts, et les messages d’erreur induisent en erreur dans des directions opposées. Si ping 1.1.1.1 fonctionne et qu’un navigateur ne charge rien, la route est bonne et la résolution de noms ne l’est pas. Si le ping lui-même échoue, le DNS est hors sujet et vous êtes revenu à la section précédente.
wg-quick peut définir un résolveur à partir de la ligne DNS = de la configuration, et systemd-resolved a son propre comportement par lien. Un VPN qui remplace le résolveur par une adresse joignable seulement à l’intérieur du tunnel fera échouer chaque résolution à l’instant où le tunnel tombe, ce qui donne l’impression que le tunnel casse l’internet.
| Symptom | Layer to inspect |
|---|---|
| Tunnel address pings, nothing else does | Client route, then gateway forwarding |
| Public IP pings, hostnames fail | Resolver selection and reachability |
| Handshake completes, no reply ever | FORWARD policy or missing NAT on the server |
| Small requests work, large transfers stall | MTU and TCP MSS clamping |
Un ordre qui produit des preuves
Exécutez d’abord la vérification côté client, car c’est une seule commande et elle élimine la moitié des possibilités. Confirmez ensuite si le serveur est censé être une sortie vers l’internet ; une passerelle conçue pour l’accès privé n’est pas cassée quand les destinations publiques échouent.
Sur le serveur, surveillez l’interface pendant que vous envoyez un ping depuis le client : tcpdump -ni wg0 icmp devrait montrer la requête, et tcpdump -ni eth0 icmp devrait montrer qu’elle sort, traduite ou non. Si elle apparaît sur la première et jamais sur la seconde, l’arrêt est local au serveur. Si elle sort et qu’aucune réponse ne revient, le problème est en amont, et c’est une autre conversation.
Enfin, faites en sorte que le correctif survive à un redémarrage. Le transfert appartient à un fichier sysctl, les règles du pare-feu au service qui les charge, et les routes du client à la configuration qui monte l’interface plutôt qu’à un shell que vous oublierez. Reconnectez-vous, répétez les deux mêmes tests et confirmez que les compteurs bougent.