Czarna dziura MTU: dlaczego małe żądania działają, a wysyłki się zawieszają
Małe żądania kończą się, podczas gdy duża wysyłka wisi wiecznie, a nadawca nigdy nie dowiaduje się, że ścieżka jest węższa. Zmierz dokładny rozmiar, przy którym to pęka.
Strona się ładuje, małe wywołanie API wraca, a potem wysyłka pliku wisi, aż klient się podda. Nic w logu serwera tego nie wyjaśnia, bo pakiety zostały odrzucone w środku ścieżki bez wysłania z powrotem użytecznej odpowiedzi. Ten wzorzec to czarna dziura MTU: łącze węższe, niż zakłada nadawca, plus ciche odmówienie powiedzenia tego. Rozmiar, przy którym to zawodzi, jest powtarzalny, i właśnie to czyni go diagnostycznym.
Co czyni dziurę czarną
Każde łącze ma maksymalną jednostkę transmisji, a pakiet większy od limitu następnego skoku musi zostać albo rozfragmentowany, albo odrzucony komunikatem ICMP, który to mówi. Wykrywanie MTU ścieżki zależy od tego, czy ten komunikat dotrze i zostanie uszanowany. Filtrowanie go lub ignorowanie pozostawia nadawcę przy powtarzaniu pakietu, który nigdy się nie zmieści.
Enkapsulacja czyni to częstym wokół VPN, bo tunel dodaje zewnętrzny nagłówek do pakietu, który był już zwymiarowany dla łącza fizycznego. Pakiet wewnętrzny jest legalny przy 1500 bajtach, a enkapsulowany nie, więc ginie na granicy, podczas gdy małe pakiety przechodzą. Zakończony handshake i działająca strona logowania dowodzą tylko, że małe pakiety działają. Największy pakiet, który aplikacja próbuje wysłać, jest tym, który się liczy.
Znajdź rozmiar, przy którym to pęka
Wyszukaj binarnie rozmiar ładunku testem bez fragmentacji, z hosta po jednej stronie tunelu do hosta po drugiej. Największy ładunek, który przechodzi, to twoje użyteczne MTU ścieżki minus narzut nagłówka.
ping -M do -s 1400 -c 2 192.0.2.20
ping -M do -s 1200 -c 2 192.0.2.20
ping -f -l 1372 192.0.2.20
Ładunek 1472 bajtów przechodzi na czystej ścieżce Ethernet 1500 bajtów, gdy doda się 28 bajtów nagłówków IPv4 i ICMP. Gdy ten sam test udaje się dopiero przy mniejszym ładunku po podniesieniu tunelu, różnicą jest narzut enkapsulacji, a granica tunelu to miejsce, w którym powinien powstać komunikat odrzucenia. Zapisz obie liczby, przed i po połączeniu, bo ta para jest dowodem. Powtórz test dla IPv6, gdy aplikacja go używa, bo nagłówek jest większy i próg awarii się przesuwa.
Przeczytaj dowody, zanim obwinisz tunel
Błędy zdalnych aplikacji, przeciążenie i zwykła utrata również zatrzymują wysyłki, więc jedna nieudana transmisja nie identyfikuje czarnej dziury. Różni je relacja rozmiarów: powtarzalny sukces przy 1200 bajtach i powtarzalne zatrzymanie przy 1400 bajtach, w tym samym kierunku, przez ten sam punkt końcowy.
Zapis na obu końcach pokazuje duże pakiety wychodzące i nigdy nieprzychodzące, bez odrzucenia pomiędzy. To moment, by spojrzeć na urządzenie graniczne zamiast na serwer, który odpowiada na każde żądanie, jakie rzeczywiście otrzymuje. Przeciążenie też zatrzymuje, ale zatrzymuje różne rozmiary w różnych momentach, a to inna sygnatura.
Sprawdź naprawę na obu transportach
Wspierana naprawa to pozwolenie granicy na zgłoszenie prawdziwego limitu albo ściśnięcie tam maksymalnego rozmiaru segmentu TCP, aby nie próbowano zbyt dużego segmentu. Obniżanie każdego MTU w sieci lub wyłączanie zapory ukrywa objaw i zostawia konfigurację, nad którą nikt później nie zdoła rozumować.
ip link show dev tun0
sudo nft list ruleset | grep -i -E 'mtu|mss'
sysctl net.ipv4.tcp_mtu_probing
ping -M do -s 1400 -c 2 192.0.2.20
Zweryfikuj tym samym testem rozmiaru, potem aplikacją, która zawiodła, i sprawdź drugi protokół, bo aplikacje UDP nigdy nie otrzymują korekty rozmiaru segmentu TCP. Zachowaj pierwotne wartości w zgłoszeniu, bo naprawa, której nie da się cofnąć, jest drugim problemem czekającym na wystąpienie. Jeśli test rozmiaru przechodzi, a wysyłka nadal się zawiesza, czarna dziura nie była przyczyną i dochodzenie powinno iść dalej, zamiast rozszerzać zmianę.