Die Maximum Transmission Unit (MTU) beschreibt die maximale Paketgröße eines Protokolls auf Layer 3 (IP). Diese in der MTU angegebene Paketgröße passt also genau in die Payload eines Layer 2 Protokolls (Beispielsweise Ethernet).

MTU bei Tunneln

Da das Tunnelprotokoll in ein anderes IP bzw. UDP Paket eingefügt wird, verringert sich die maximale Paketgröße innerhalb des Tunnels. Hierbei muss darauf geachtet werden, dass eine passende MTU gewählt wird, damit die äußeren Pakete nicht fragmentiert werden müssen, weil sie zu groß sind. Weiterhin kann der Linux-Kernel Wireguard aktuell überhaupt nicht fragmentieren, daher geht Wireguard mit zu großer MTU innerhalb des Tunnels ganz kaputt.

Generell sollte die MTU immer auf beiden Seiten gleich sein. Auch wenn es erstmal kein Problem ist, wenn sie unterschiedlich ist, solange an beiden Seite klein genug für die Leitung.

Das ganze kann man sich leicht ausrechnen. Zuerst braucht man die MTU des Transportweges. Die kann man entweder ausmessen, oder man weiß sie schon. Bei einem typischen DSL ist das normalerweise 1492, bei Cable (DOCSIS) 1500 Bytes.

Dann muss man den Overhead von allem, was zwischen Transportweg und den "inneren" Paketen liegt abziehen. Beispiel Wireguard: - IPv4 (20 Bytes) oder IPv6 (40 Bytes) - UDP (8 Bytes) - Wireguard Overhead (32 Bytes)

Somit kommt man bei "normaler" MTU (1500) auf dem Transportweg und IPv6 als Transportprotokoll (als das _worüber_ der Tunnel aufgebaut wird) auf die "magischen" 1420 Bytes, die ja auch Standard sind.

MTU Probleme bei Tunneln

MTU innerhalb des Tunnels zu groß

Wie oben bereits erwähnt, kann es problematisch sein, die MTU innerhalb des Tunnels zu groß zu wählen.

Normalerweise sollten zu große Pakete von der Tunnelsoftware fragmentiert werden. Allerdings kann das nicht jede Software. GRE und Wireguard können dies nicht, daher gehen Verbindungen mit großen Paketen innerhalb des Tunnel dann häufig kaputt und Seiten laden (teilweise) nicht.

PMTUD funktioniert nicht

Damit Clients überhaupt wissen können, dass die MTU auf dem Weg plötzlich kleiner wird, müssen Router passende Fehlerpakete (ICMP) senden können. Diese teilen dann dem Client mit, dass er seine Pakete kleiner machen muss. Das betroffene Paket wird vom Router verworfen.

Bei IPv4 wurde hier (ohne extra Flags) vom Router fragmentiert. Nur wenn der Client explizit danach fragte (Don't Fragment Flag), wurden Pakete verworfen und ICMP Fehler gesendet. Heute wird aber so gut wie alles mit DF-Flag gesendet, daher gilt für IPv4 mittlerweile das gleiche, wie für IPv6 (dort gibt es ein solches Flag nicht, Pakete werden NIE von Routern fragmentiert)

Testen kann man das ganze leicht mit einem Traceroute. Dort muss (in beide Richtungen!) jeder Router ICMP Pakete (traceroute forciert das Senden von Fehlerpaketen durch eine stark limitierte TTL) antworten können, bei dem ein Übergang von einem MTU-technisch größeren zu einem kleineren Link stattfindet. Es dürfen bei solchen Routern also keine * * * auftauchen.

Beispiel: Internet <-> dezentraler Freifunk Router

fbl@ns2:~$ tracepath 2a0b:f4c0:c8:6d::1
 1?: [LOCALHOST]                        0.025ms pmtu 1500
 1:  2a03:4000:24::2                                       0.244ms 
 1:  2a03:4000:24::2                                       0.600ms 
 2:  2a03:4000:ff00:1::                                    0.336ms 
 3:  ae3-1337.bbr02.anx25.fra.de.anexia-it.net             3.820ms 
 4:  2a00:11c0:47:1:47::140                                3.835ms 
 5:  2a00:11c0:47:1:47::138                                3.681ms 
 6:  ext.zbau.f3netze.de                                   4.007ms 
 7:  2a0b:f4c0:100:1::2                                    4.314ms 
 8:  2a0b:f4c0:100:1::2                                    4.194ms pmtu 1448
 8:  aquarius.sgstbr.de                                    6.899ms 
 9:  aquarius.sgstbr.de                                    6.822ms pmtu 1420
 9:  2a0b:f4c0:c8:6d::1                                   38.009ms reached
  • Bei Hop 7 wird der Link zum ersten mal kleiner, weil das Paket dort durch einen GRE-Tunnel geht. (Daher steht bei Hopt 8 F=1448)
  • Bei Hop 8 wird der Link erneut kleiner, da das Paket dann durch einen Wireguard zu mir nach Hause geht und Wireguard mehr Overhead hat als GRE. Daher muss auch Hop 8 passende ICMP Nachrichten senden können. (F=1420)

Anders herum genauso:

fbl@fbl-desktop:~$ tracepath ns2.sgstbr.de
 1?: [LOCALHOST]                        0.013ms pmtu 1500
 1:  2a0b:f4c0:c8:6d::1                                    0.582ms 
 1:  2a0b:f4c0:c8:6d::1                                    0.568ms 
 2:  2a0b:f4c0:c8:6d::1                                    0.558ms pmtu 1420
 2:  aquarius.sgstbr.de                                   20.390ms 
 3:  zeus.sgstbr.de                                       19.559ms 
 4:  ext.zbau.f3netze.de                                  25.557ms 
 5:  2a00:11c0:47:3::9a                                   30.151ms 
 6:  2a00:11c0:47:3::33                                   27.023ms 
 7:  2a03:4000:24:14a::                                   31.355ms reached
  • Bei Hop 1 wird der Link kleiner, weil Übergang von Ethernet (1500) -> Wireguard (1420).
  • Bei Hop 2 wird der Link nicht mehr kleiner, obwohl getunnelt wird, da GRE weniger Overhead hat als Wireguard.

Genauso kann auch traceroute --mtu verwendet werden.

NAT

In einem ICMP Fehlerpaket ist ein Ausschnitt des Pakets, das zum Fehler geführt hat, enthalten. Das ist nötig, damit der Client weißt, welche Verbindung betroffen ist.

Bei NAT wird ein IP Paket verändert. Passiert hinter dem NAT ein Fehler, der zu einem ICMP Fehlerpaket führt, hängt im ICMP das durch NAT veränderte Paket an.

Findet das ICMP Paket nun einen anderen Weg zum Client, der am NAT vorbei führt, kann das NAT dieses ICMP Paket nicht berichtigen, daher kann der Client das Paket nicht zuordnen.

Bei uns tritt dieses Problem leider sehr häufig auf, da die Tunnel meist erst hinter dem NAT kommen, häufig aber eine eigene unabhängige Verbindung ins Internet haben (um die Tunnel aufbauen zu können).

Eine mögliche Lösung kann die Option net.ipv4.icmp_errors_use_inbound_ifaddr = 1 sein. Diese sorgt dafür, dass ICMP Fehlerpakete auf dem Interface gesendet werden, auf dem das zum Fehler führende Paket eingetroffen ist.

Siehe auch Freifunk-Gateway_aufsetzen#ICMP_Fehlerpakete_f.C3.BCr_IPv4

Maximale PMTU einer Strecke messen

TODO

MTU Probleme erkennen

IPv4

Diese Webseiten können nur IPv4 und laden bei verringerter MTU nur, wenn PMTUD korrekt funktioniert:

  • github.com
  • twitter.com

Diese Webseiten können nur IPv4 und laden bei verringerter MTU auch bei korrekt funktionierender PMTUD nicht:

  • telekom.de
  • ui.com

Das liegt daran, dass die Server die ICMP Fehlerpakete ignorieren, vermutlich weil diese dort gefirewalled werden. Hier müssen die Netzwerkadmins dieser Seiten nochmal ihre Hausaufgaben machen.. ;-)