weidner/archives/2021/11/

Wie gehe ich mit kaputter Path-MTU-Discovery um?

Path-MTU (PMTU) ist ein Maß dafür, wie groß Datagramme einer Verbindung sein dürfen, um unfragmentiert vom Sender zum Empfänger zu gelangen. PMTU-Discovery ist ein Mechanismus, den zum Beispiel TCP verwendet, um die PMTU jeder einzelnen Verbindung zu ermitteln. Auf manchen Verbindungen ist PMTU-Discovery gestört, was sich in merkwürdigem Verhalten der betroffenen Verbindung äußert. Es gibt verschiedene Workarounds bei gestörter Path-MTU. Besser ist jedoch, das Problem abzustellen.

Wie funktioniert PMTU-Discovery?

Die Maximum Transmission Unit (MTU) gibt die maximale Größe eines Datagramms an, dass in einem Netzsegment in einem Stück gesendet werden kann. Bei Ethernet sind das üblicherweise 1500 Bytes. Weil bei verbundenen Netzen die Daten über verschiedene Netzsegmente übertragen werden, ist es möglich, das sie ein Netzsegment passieren, dessen MTU kleiner ist als beim Sender. Die Path-MTU ist die kleinste MTU aller Netzsegmente, die ein Datagramm vom Sender zum Empfänger passiert.

Weil die PMTU vom Weg der Datagramme zwischen Sender und Empfänger abhängt, kann sie für verschiedene Empfänger unterschiedlich sein. Der TCP-Stack verwaltet daher die PMTU als Attribut jeder einzelnen Verbindung, das sich ändern kann während die Verbindung offen ist. Dabei kann der Mechanismus der PMTU-Discovery von jedem einzelnen gesendeten Datagramm ausgelöst werden, wenn dieses zu groß für den aktuellen Pfad ist.

Bei IPv4 gibt es hierfür das Don't-Fragment-Flag im IP-Header, das die Router unterwegs anweist, Datagramme zu verwerfen, wenn diese zu groß für das nächste Segment auf dem Weg sind. In diesem Fall sendet der Router eine ICMP-Nachricht vom Typ 3 Subtyp 4 an den Sender und fügt an den ICMP-Header die ersten Bytes des verworfenen Datagramms an, damit der Sender die Verbindung identifizieren kann.

IPv6-Datagramme dürfen grundsätzlich nicht fragmentiert werden. Hier sendet der Router eine ICMPv6-Nachricht vom Typ 2 zusammen mit den ersten Bytes des verworfenen Datagramms an den Sender.

Kommt eine dieser ICMP-Nachrichten beim Sender an, identifiziert dieser die Verbindung, passt die PMTU an und sendet die verworfenen Daten erneut, dieses Mal in kleineren Datagrammen.

Was sind die Symptome einer defekten PMTU-Discovery?

Bekomme ich eine nicht funktionierende Verbindung gemeldet, die sich bei einem Verbindungstest problemlos aufbaut, könnte defekte PMTU-Discovery die Ursache des Problems sein.

Manchmal kann ich mich per SSH an einem Server anmelden und arbeiten, plötzlich jedoch hängt die Verbindung, vorzugsweise wenn ich einen Befehl aufgerufen habe, der viele Daten zur Anzeige bringt.

Oder ich teste die Erreichbarkeit eines Webservers mit netcat oder openssl s_client und bekomme in beiden Fällen eine Antwort, Beim Aufruf mit dem Webbrowser kommen jedoch keine Bilder und der Seitenaufbau hängt.

Manche modernen TCP-Stacks schalten automatisch auf eine geringere Datagramm-Größe herunter, wenn große Datagramme nicht bestätigt werden. Das nimmt der Benutzer nur als kurzen Aussetzer in der Verbindung wahr, was dazu führen kann, das eine Verbindung mit einem Rechner/Betriebssystem funktioniert und mit einem anderen nicht.

Ein gleichzeitiger Paketmitschnitt auf beiden Seiten zeigt große Datagramme nur auf der sendenden Seite und nicht beim Empfänger.

Wie kann ich kaputte PMTU-Discovery genauer diagnostizieren?

Zur genaueren Diagnose einer kaputten PMTU-Discovery kann ich die Programme ping und traceroute verwenden.

Bei den meisten ping-Programmen, die ich kenne, kann ich mit der Option -s die Größe des Datagramms vorgeben und mich damit an den exakten Wert der Path-MTU einer Verbindung herantasten. Allerdings benötige ich noch eine zweite Option, um das Don't-Fragment-Bit der Datagramme zu setzen. Bei ping von iputils Version s20190709, welches gerade auf meinem Testrechner installiert ist, muss ich die Option -M do verwenden.

Mit diesen Optionen bekomme ich bei funktionierender PMTU-Discovery eine Nachricht vom Router mit der kleinsten MTU und bei kaputter PMTU-Discovery einen Timeout.

$ ping -Mdo -c1 -s1465 1.1.1.1
PING 1.1.1.1 (1.1.1.1) 1465(1493) bytes of data.
From 91.60.153.229 icmp_seq=1 Frag needed and DF set (mtu = 1492)

--- 1.1.1.1 ping statistics ---
1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms

$ ping -Mdo -c1 -s1464 1.1.1.1
PING 1.1.1.1 (1.1.1.1) 1464(1492) bytes of data.
1472 bytes from 1.1.1.1: icmp_seq=1 ttl=56 time=37.4 ms

--- 1.1.1.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 37.418/37.418/37.418/0.000 ms

Das Beispiel aus meinem Testnetz zeigt funktionierende PMTU-Discovery für eine Verbindung, die über PPPoE läuft und deren PMTU folglich 1492 Byte beträgt.

Damit habe ich die maximale PMTU der Verbindung ermittelt, nun möchte ich noch die genaue Stelle herausfinden, an der die PMTU begrenzt wird. Zu diesem Zweck greife ich auf das Programm traceroute zurück, das es ebenfalls in verschiedenen Varianten gibt.

Bei traceroute aus dem gleichnamigen Softwarepaket bei Ubuntu 20.04 lautet die Option -F für das Don't-Fragment-Bit, die Größe des Datagramms gebe ich nach der Adresse an. In meinem Testnetz sieht das mit funktionierender PMTU-Discovery so aus:

$ traceroute -n -F 1.1.1.1 1493
traceroute to 1.1.1.1 (1.1.1.1), 30 hops max, 1493 byte packets
 1  192.168.1.254  0.399 ms  0.348 ms  0.284 ms
 2  192.168.178.1  1.243 ms  1.572 ms  2.311 ms
 3  91.60.153.229  6.641 ms !F-1492  6.838 ms !F-1492  6.664 ms !F-1492

Wie repariere ich eine defekte PMTU-Discovery?

Damit PMTU-Discovery funktioniert, müssen die oben genannten ICMP-Nachrichten immer durch Firewalls durchgelassen werden und bei NAT-Boxen unterwegs so modifiziert werden, dass der Sender des zu großen Datagramms die Verbindung identifizieren kann.

Habe ich mit Ping und Traceroute den Router identifiziert, an dem die MTU zu gering ist, muss ich im nächsten Schritt untersuchen, ob ich die ICMP-Nachrichten in meinem Einflussbereich nachweisen kann. Das sehe ich am Border-Gateway, an dem die Datagramme die von mir betreuten Netze verlassen. Finde ich die ICMP-Datagramme hier, gehe ich weiter zurück bis zum Sender.

An der Stelle, an der die ICMP-Nachrichten verschwinden oder so modifiziert werden, dass die ursprüngliche Verbindung nicht mehr identifiziert werden kann, muss ich die Firewall- oder NAT-Regeln korrigieren. Ist das nicht möglich, kann ich vielleicht das Gerät ersetzen.

Kommen die ICMP-Nachrichten gar nicht an meinem Border-Gateway an, sehen die Chancen schlecht aus, insbesondere wenn die Datagramme durch die Netze verschiedener Provider laufen.

In diesem Fall und wenn ich das Gerät bei mir nicht korrigieren oder ersetzen kann, muss ich zu Workarounds greifen. Diese wirken sich negativ auf die Performance aus.

Ein Workaround ist, die MTU am sendenden Host oder, wenn mehrere Hosts betroffen sind, am ersten Router herabzusetzen. Von diesem Workaround sind jedoch alle abgehenden Datagramme des Hosts beziehungsweise alle durch diesen Router laufenden Datagramme betroffen, was die Performanceprobleme auf andere Verbindungen ausweitet. Habe ich noch eine weitere Schnittstelle am Host oder Router zur Verfügung und genügend Adressen frei, kann ich mit selektiven Routen über diese Schnittstelle senden und die MTU nur hier reduzieren.

Ein anderer Workaround funktioniert nur für TCP-Verbindungen, kann dafür mit Firewall-Regeln sehr genau begrenzt werden. Dabei beschränke ich die Datagrammgröße der betroffenen TCP-Verbindungen mit MSS-Clamping.

Alle diesen Workarounds machen die Netzwerkkonfiguration komplizierter und können zu subtilen Fehlern führen. Darum ist es wichtig, dass ich die Workarounds dokumentiere, welches Problem sie umgehen und warum ich sie gewählt habe.

Posted 2021-11-02
Tags: