Outils pour utilisateurs

Outils du site


vpn:vpn-mtu

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentesRévision précédente
vpn:vpn-mtu [2022/01/03 17:01] – modification externe 127.0.0.1vpn:vpn-mtu [2022/01/16 21:41] (Version actuelle) – [Trop long, je me fous des détails] pizzacoca
Ligne 1: Ligne 1:
 +====== 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.).
 +
 +{{:travel-wifi-vpn-packet.png?400|}}
 +
 +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:
 +
 +<code>1500 - headers IP (GRE) - Headers GRE - headers IP (wireguard) - headers wireguard</code>
 +
 +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:
 +
 +<code>1500 - 20 - 4 - 20 - 40 = 1416</code>
 +
 +Pour un dual stack IPv6, on va prendre la taille des headers v6: 40
 +octets, on aura une MTU de:
 +
 +<code>1500 - 20 - 4 - 40 - 40 = 1396</code>
 +
 +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:__
 +<code>iptables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -o wg0 -j TCPMSS --set-mss 1376</code>
 +
 +__syntaxe nftables:__
 +
 +Dans votre chaîne forward:
 +<code>oinfname wg0 tcp flags syn tcp option maxseg size set 1376</code>
 +
 +  * **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.