Aller au contenu
Sylvain Joffraud l4w
Retour

WireGuard full-tunnel : le ping passe, le débit meurt

Un routeur OpenWrt qui monte un full-tunnel WireGuard vers mon VPS, pour faire sortir tout un LAN par l’IP du serveur. Sur le papier, propre. À l’usage : « la connexion rame ». Sauf que le diagnostic est contre-intuitif.

Le symptôme qui trompe

Depuis un poste derrière le tunnel :

$ ping -c5 1.1.1.1
5 packets transmitted, 5 received, 0% packet loss
rtt min/avg/max = 12.2/17.5/27.1 ms      ← parfait

$ curl -o /dev/null https://speed.cloudflare.com/__down?bytes=100000000
  débit : 584 B/s                          ← mort

Le ping est nickel, le débit s’effondre à quelques centaines d’octets par seconde. En coupant le VPN : 21 Mo/s, instantané. On accuse spontanément la bande passante, le routeur, le disque… tout sauf le vrai coupable.

Ce que ça veut dire

Petits paquets → OK. Gros transferts → morts. C’est exactement la signature d’un trou noir MTU/MSS.

WireGuard ajoute ~60 octets d’en-tête au paquet encapsulé. Le tunnel a donc un MTU effectif d’environ 1420 octets. Or les clients du LAN, eux, croient être sur du 1500 : ils annoncent un MSS de 1460. Le serveur distant leur renvoie donc des paquets de 1500 octets… qui ne rentrent pas dans le tunnel de 1420. Avec le bit Don’t Fragment et un PMTUD cassé, ces paquets sont jetés en silence. La connexion TCP s’établit (petits paquets), puis se fige dès qu’il faut transférer des données.

Le diagnostic côté serveur

$ ip link show wg0 | grep -o 'mtu [0-9]*'
mtu 1420                                   ← bon

$ sudo iptables -t mangle -S | grep -i mss
                                           ← RIEN. C'est ça le problème.

Le MTU du tunnel est correct, mais aucun MSS clamping n’est configuré. Le noyau ne rabote donc jamais le MSS, et les grosses trames se perdent.

Le correctif : MSS clamping

Le MSS clamping intercepte les SYN TCP et abaisse le MSS annoncé à la taille du tunnel (~1380). Les deux bouts négocient alors d’emblée des segments qui rentrent.

Sur OpenWrt (le bon endroit — il possède les clients du LAN) :

En iptables (filet côté serveur, couvre tous les clients du tunnel) :

$ sudo iptables -t mangle -A FORWARD -o wg0 \
    -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

Et on vérifie que l’interface WireGuard est bien à MTU 1420 des deux côtés.

Lessons learned

Questions fréquentes

Le ping passe mais les téléchargements sont bloqués sur mon VPN, pourquoi ?
C’est la signature d’un trou noir MTU. Les petits paquets (ping, poignée de main TCP) passent, mais les gros paquets de données dépassent le MTU du tunnel et sont jetés silencieusement. Le PMTUD (découverte de MTU) est cassé quand les ICMP « fragmentation needed » n’arrivent pas jusqu’à l’émetteur : le transfert TCP stalle indéfiniment.
Quel MTU utiliser pour une interface WireGuard ?
1420 est la valeur sûre par défaut. WireGuard ajoute ~60 octets d’en-tête (80 en IPv6) au paquet encapsulé. Sur un lien à MTU 1500, il reste donc ~1420 pour la charge utile. C’est la valeur que wg-quick pose automatiquement, mais un montage manuel ou un routeur mal configuré peut l’oublier.
Qu’est-ce que le MSS clamping et où l’activer ?
Le MSS clamping fait diminuer le MSS annoncé dans les paquets SYN TCP à la taille réelle du tunnel (~1380), de sorte que les deux extrémités n’envoient jamais de segment trop gros. Sur OpenWrt : cochez « MSS clamping » sur la zone firewall qui contient l’interface WireGuard (option mtu_fix '1'). En iptables : iptables -t mangle -A FORWARD -o wg0 -p tcp --syn -j TCPMSS --clamp-mss-to-pmtu.

Partager cet article :

Article précédent
WiFi plus lent que la 4G ? Votre IPv6 est cassé
Article suivant
NAS headless figé au boot : il attend un appui sur F1