Outils pour utilisateurs

Outils du site


vpn:vpn-mtu

Sombres Histoires de MTU

Trop long, je me fout des détails

Sur le réseau Baionet, derrière le VPN, utilisez une MTU de 1416 en IPv4-only, une MTU de 1396 en IPv6 ou dual stack.

Vous avez dit MTU?

Vu de haut, c'est très simple: la MTU est la taille maximale que peut atteindre un paquet. Si un paquet dépasse cette taille maximale, il sera rejeté par le routeur au lieu d'être transféré.

De base, pour Ethernet v2, la MTU d'un paquet sera de 1500 octets, c'est plus ou moins standard. Jusque ici, tout va bien. Les problèmes commencent à apparaître lorsque, comme dans le cas d'un VPN, on tunnelle une connexion.

Tout d'un coup, on va s'amuser à mettre un paquet entier dans le corps d'un autre paquet. Dès lors, on comprend que si l'on s'amuse à mettre un paquet de 1500 octets dans un autre paquet, le tout dépassera la taille de 1500 octets à cause des headers du paquet + headers divers (wireguard, etc.).

C'est pourquoi, la plupart du temps, on va mettre une MTU inférieure à 1500 sur l'interface qui va se charger de tunneler les paquets. L'interface wireguard dans notre cas

Comment calculer la MTU?

Pour cette section, on va prendre le cas du VPN Baionet pour exemple.

Nous avons un premier tunnel GRE qui relie le serveur VPN a son transit, suivi d'un second tunnel wireguard qui relie le VPN au client.

La MTU du client sera donc de:

1500 - headers IP (GRE) - Headers GRE - headers IP (wireguard) - headers wireguard

Les headers wireguard prendront toujours 40 octets. Cf. https://lists.zx2c4.com/pipermail/wireguard/2017-December/002201.html

Les headers GRE 4 octets.

Si vous ne faites que de l'IPv4, on peut partir du principe que les headers IP prennent 20 octets, on aura une MTU de:

1500 - 20 - 4 - 20 - 40 = 1416

Pour un dual stack IPv6, on va prendre la taille des headers v6: 40 octets, on aura une MTU de:

1500 - 20 - 4 - 40 - 40 = 1396

Il va donc falloir utiliser une MTU de 1396 sur votre interface wireguard.

Plot Twist du Routeur

Vous mettez le tunnel en place sur votre ordinateur, tout va bien.

Puis, vous montez le même tunnel sur un routeur, vous redirigez tout le monde dessus, et là, tout à coup, rien ne va plus ! La connexion est très lente, certains sites ne chargent pas.

W-T-F?

Votre routeur connaît bien la MTU et fait bien attention à la taille maximale des paquets, mais ce n'est pas le cas des clients! Eux, ne savent même pas qu'ils passent par un tunnel wireguard.

Comment communiquer la MTU aux clients du coup?

Il y a trois façons de faire ça.

Via la découverte PMTU

https://fr.wikipedia.org/wiki/Path_MTU_discovery

L'idée ici, c'est que le client va envoyer des paquets de test de taille décroissante jusqu'à ce que ça passe. Il va ensuite sauver la taille maximale pour laquelle “ça passe” et va ré-utiliser ça comme MTU.

C'est la solution la plus propre et efficace, mais elle a le malheur de se baser sur le protocole ICMP, qui est souvent bloqué par des firewalls peu scrupuleux pour des raisons de sécurité.

Ce qu'il faut malheureusement retenir de cette solution, c'est que ça ne marche pas.

Via DHCP/RA

Le routeur peut envoyer une MTU à utiliser sur le lien lors de la négociation de l'adresse IPv4 en DHCP et de l'adresse IPv6 en Router Advertisement. Vous allez donc configurer votre daemon DHCP/RA pour partager une MTU de 1396 octets.

Ça marche très bien sur la majorité des clients linux/mac/android, en revanche, ça ne marche pas avec les machines windows.

Ça peut être la solution parfaite pour vous si vous n'avez pas de windows derrière le routeur.

Le dirty hack

J’imagine que vous le voyez venir: les solutions propres existantes ne marchent pas dans la pratique, les ingés télécom ont donc trouvé une solution qui marche a peu près partout mais qui est bien dégueulasse: ré-écrire les paquets SYN TCP.

L'idée est de parasiter le handshake TCP pour y ré-écrire un Max Segment Size (MSS) bidon.

  • Q: C'est quoi le MSS?
  • R: C'est la taille de données maximale que peut supporter un paquet TCP. En gros c'est MTU - taille header TCP. En pratique, MTU - 20.

Dans le cas de Baionet, il faudra donc MSS clamper à 1376.

On va donc intercepter tous les messages TCP Syn (demande de connexion) et ré-écrire le MSS avec la valeur 1376.

Dans la pratique, ça va se faire avec votre firewall.

sytaxe iptables:

iptables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -o wg0 -j TCPMSS --set-mss 1376

syntaxe nftables:

Dans votre chaîne forward:

oinfname wg0 tcp flags syn tcp option maxseg size set 1376
  • Q: on fait quoi pour UDP du coup?
  • R: aucune idée. Je n'ai pas eu de problèmes avec UDP jusque là…

Une fois cette opération faite sur votre routeur, vous devriez être bon.

vpn/vpn-mtu.txt · Dernière modification : 2022/01/16 22:41 de pizzacoca