Rozbité pakety:
Na rozdíl od veřejné telefonní sítě je internet konstruován jako síť s přepojováním paketů. Ale jak velké tyto pakety mohou být?“
CC BY 2.0 image by ajmexico, inspired by
Tato otázka je stará a RFC IPv4 na ni odpovídají poměrně jasně. Myšlenkou bylo rozdělit problém na dva samostatné problémy:
-
Jaká je maximální velikost paketu, kterou zvládnou operační systémy na obou koncích?
-
Jaká je maximální povolená velikost datagramu, který lze bezpečně protlačit fyzickým spojením mezi hostiteli?
Když je paket příliš velký pro fyzické spojení, může jej zprostředkující směrovač rozřezat na více menších datagramů, aby se do něj vešel. Tento proces se nazývá „dopředná“ fragmentace IP a menší datagramy se nazývají fragmenty IP.
Obrázek Geoffa Hustona, reprodukováno se svolením
Specifikace IPv4 definuje minimální požadavky. Z RFC791:
Every internet destination must be able to receive a datagramof 576 octets either in one piece or in fragments tobe reassembled. Every internet module must be able to forward a datagram of 68octets without further fragmentation.
První hodnota – povolená velikost znovu sestaveného paketu – obvykle není problematická. IPv4 definuje minimum 576 bajtů, ale populární operační systémy si poradí i s velmi velkými pakety, typicky až 65KiB.
Druhá hodnota je problematičtější. Všechna fyzická spojení mají přirozené limity velikosti datagramů v závislosti na konkrétním médiu, které používají. Například Frame Relay může posílat datagramy o velikosti 46 až 4 470 bajtů. ATM používá pevných 53 bajtů, klasický Ethernet zvládne mezi 64 a 1500 bajty.
Specifikace definuje minimální požadavek – každé fyzické spojení musí být schopno přenášet datagramy o velikosti alespoň 68 bajtů. Pro IPv6 byla tato minimální hodnota zvýšena na 1280 bajtů (viz RFC2460).
Naopak maximální velikost datagramu, který lze přenést bez fragmentace, není definována žádnou specifikací a liší se podle typu spoje. Tato hodnota se nazývá MTU (Maximum Transmission Unit).
MTU definuje maximální velikost datagramu na místní fyzické lince. Internet je vytvořen z nehomogenních sítí a na cestě mezi dvěma hostiteli mohou existovat spoje s kratšími hodnotami MTU. Maximální velikost paketu, kterou lze přenést bez fragmentace mezi dvěma vzdálenými hostiteli, se nazývá Path MTU a může být potenciálně pro každé spojení jiná.
Vyhnout se fragmentaci
Někdo by si mohl myslet, že je v pořádku vytvářet aplikace, které přenášejí velmi velké pakety a spoléhat se na směrovače, že provedou fragmentaci IP. To však není dobrý nápad. O problémech s tímto přístupem poprvé hovořili Kent a Mogul v roce 1987. Zde je několik hlavních bodů:
-
Pro úspěšné opětovné sestavení paketu musí být doručeny všechny fragmenty. Žádný fragment se nesmí poškodit nebo ztratit za letu. Jednoduše neexistuje způsob, jak upozornit druhou stranu na chybějící fragmenty!“
-
Poslední fragment téměř nikdy nebude mít optimální velikost. U velkých přenosů to znamená, že značná část provozu bude složena z neoptimálních krátkých datagramů – plýtvání drahocennými prostředky směrovače.
-
Před opětovným sestavením musí hostitel v paměti uchovávat částečné, fragmentované datagramy. To otevírá příležitost k útokům na vyčerpání paměti.
-
Další fragmenty postrádají hlavičku vyšší vrstvy. Záhlaví TCP nebo UDP je přítomno pouze v prvním fragmentu. To znemožňuje firewallům filtrovat fragmentované datagramy na základě kritérií, jako jsou zdrojové nebo cílové porty.
Podrobnější popis problematiky fragmentace protokolu IP naleznete v těchto článcích Geoffa Hustona:
- Vyhodnocení fragmentace paketů IPv4 a IPv6
- Fragmentace IPv6
Nefragmentovat – příliš velký paket ICMP
Obrázek Geoffa Hustona, reprodukováno se svolením
Řešení těchto problémů bylo zahrnuto do protokolu IPv4. Odesílatel může v záhlaví protokolu IP nastavit příznak DF (Don’t Fragment) a požádat tak zprostředkující směrovače, aby nikdy neprováděly fragmentaci paketu. Místo toho směrovač se spojením, které má menší MTU, pošle zprávu ICMP „zpět“ a informuje odesílatele, aby pro toto spojení snížil MTU.
Protokol TCP vždy nastavuje příznak DF. Síťový zásobník pečlivě vyhledává příchozí zprávy ICMP „Packet too big“ a sleduje charakteristiku „path MTU“ pro každé spojení. Tato technika se nazývá „zjišťování MTU cesty“ a nejčastěji se používá pro protokol TCP, i když ji lze použít i pro jiné protokoly založené na protokolu IP. Schopnost doručovat zprávy ICMP „Packet too big“ je rozhodující pro udržení optimálního fungování zásobníku TCP.
Jak vlastně funguje internet
V dokonalém světě by zařízení připojená k internetu spolupracovala a správně zpracovávala fragmentované datagramy a související pakety ICMP. Ve skutečnosti jsou však fragmenty IP a pakety ICMP velmi často filtrovány.
Důvodem je to, že moderní internet je mnohem složitější, než se před 36 lety předpokládalo. Dnes v podstatě nikdo není připojen přímo k veřejnému internetu.
Zařízení zákazníků se připojují přes domácí směrovače, které provádějí NAT (překlad síťových adres) a obvykle vynucují pravidla brány firewall. Stále častěji je na cestě paketů více než jedna instalace NAT (např. NAT na úrovni operátora). Pakety se pak dostanou do infrastruktury poskytovatele internetových služeb, kde se nacházejí „prostřední krabice“ poskytovatele. Ty provádějí s provozem nejrůznější podivnosti: vynucují omezení plánu, omezují připojení, provádějí logování, přebírají požadavky DNS, zavádějí vládou nařízené zákazy webových stránek, vynucují transparentní cache nebo pravděpodobně „optimalizují“ provoz nějakým jiným zázračným způsobem. Prostřední krabičky používají zejména mobilní operátoři.
Podobně je mezi serverem a veřejným internetem často více vrstev. Poskytovatelé služeb někdy používají směrování BGP Anycast. To znamená: zpracovávají stejné rozsahy IP z více fyzických míst po celém světě. V rámci datového centra je naopak stále populárnější používat ECMP Equal Cost Multi Path pro vyrovnávání zátěže.
Každá z těchto vrstev mezi klientem a serverem může způsobit problém s Path MTU. Dovolte mi, abych to ilustroval na čtyřech scénářích.
1. Klient -> Server DF+ / ICMP
V prvním scénáři klient odešle na server nějaká data pomocí protokolu TCP, takže na všech paketech je nastaven příznak DF. Pokud se klientovi nepodaří předpovědět vhodnou MTU, zprostředkující směrovač velké pakety zahodí a pošle klientovi zpět oznámení ICMP „Packet too big“. Tyto pakety ICMP mohou být zahozeny špatně nakonfigurovanými zákaznickými zařízeními NAT nebo prostředními boxy ISP.
Podle článku Maikela de Boera a Jeffreyho Bosmy z roku 2012 blokuje příchozí pakety ICMP přibližně 5 % hostitelů IPv4 a 1 % hostitelů IPv6.
Moje zkušenosti to potvrzují. Zprávy ICMP jsou skutečně často zahazovány kvůli domnělým bezpečnostním výhodám, ale to lze poměrně snadno napravit. Větší problém je u některých mobilních ISP s podivnými prostředníky. Ty často zcela ignorují ICMP a provádějí velmi agresivní přepisování spojení. Například Orange Polska nejenže ignoruje příchozí zprávy ICMP „Packet too big“, ale také přepisuje stav spojení a upíná MSS na neoddiskutovatelných 1344 bajtů.
2. Klient -> Server DF- / fragmentace
V dalším scénáři klient odesílá nějaká data jiným protokolem než TCP, který má vymazaný příznak DF. Může se jednat například o uživatele, který hraje hru pomocí protokolu UDP nebo vede hlasový hovor. Velké odchozí pakety se mohou v určitém bodě cesty fragmentovat.
Tuto situaci můžeme emulovat spuštěním ping
s velkou velikostí užitečného zatížení:
$ ping -s 2048 facebook.com
Tento konkrétní ping
selže s užitečným zatížením větším než 1472 bajtů. Jakákoli větší velikost bude fragmentována a nebude správně doručena. Důvodů, proč mohou servery špatně zpracovávat fragmenty, je více, ale jedním z oblíbených problémů je používání vyrovnávání zátěže ECMP. Kvůli hašování ECMP bude první datagram obsahující hlavičku protokolu pravděpodobně rozložen na jiný server než zbytek fragmentů, což zabrání opětovnému sestavení.
Podrobnější diskusi o tomto problému naleznete v:
- Náš předchozí zápis o ECMP.
- Jak se společnost Google pokouší vyřešit problémy s fragmentací ECMP pomocí vyrovnávače zátěže Maglev L4.
Dalším významným problémem je chybná konfigurace serveru a směrovače. Podle RFC7852 30 až 55 % serverů zahazuje datagramy IPv6 obsahující fragmentační hlavičku.
3. Server -> Klient DF+ / ICMP
Další scénář se týká klienta stahujícího nějaká data přes TCP. Když se serveru nepodaří předpovědět správnou MTU, měl by obdržet zprávu ICMP „Packet too big“. Jednoduché, že?“
Naneštěstí tomu tak není, opět kvůli směrování ECMP. Zpráva ICMP bude s největší pravděpodobností doručena špatnému serveru – hash 5-paketu ICMP se nebude shodovat s hashem 5-paketu problematického spojení. O tomto problému jsme již v minulosti psali a vyvinuli jsme jednoduchého démona v uživatelském prostoru, který jej řeší. Funguje tak, že vysílá příchozí oznámení ICMP „Packet too big“ na všechny servery ECMP a doufá, že ho uvidí ten s problematickým spojením.
Díky směrování Anycast může být navíc ICMP doručen úplně špatnému datacentru! Směrování v internetu je často asymetrické a nejlepší cesta z mezilehlého směrovače může směřovat pakety ICMP na špatné místo.
Chybějící oznámení ICMP „Packet too big“ může mít za následek zaseknutí a časování spojení. Tomuto jevu se často říká černá díra PMTU. Na pomoc tomuto pesimistickému případu Linux implementuje řešení – MTU Probing RFC4821. MTU Probing se snaží automaticky identifikovat pakety zahozené kvůli nesprávné MTU a pomocí heuristiky ji vyladit. Tato funkce se ovládá pomocí sysctl:
$ echo 1 > /proc/sys/net/ipv4/tcp_mtu_probing
Ale MTU probing není bez problémů. Zaprvé má tendenci chybně klasifikovat ztráty paketů související s přetížením jako problémy s MTU. Dlouho běžící spojení mají tendenci skončit se sníženou MTU. Za druhé, systém Linux neimplementuje funkci MTU Probing pro protokol IPv6.
4. Server -> Klient DF- / fragmentace
Nakonec existuje situace, kdy server posílá velké pakety pomocí jiného protokolu než TCP s vymazaným bitem DF. V tomto scénáři se velké pakety na cestě ke klientovi fragmentují. Tuto situaci lze nejlépe ilustrovat na velkých odpovědích DNS. Zde jsou dva požadavky DNS, které vygenerují velké odpovědi a budou klientovi doručeny jako několik fragmentů IP:
$ dig +notcp +dnssec DNSKEY org @199.19.56.1$ dig +notcp +dnssec DNSKEY org @2001:500:f::1
Tyto požadavky mohou selhat kvůli již zmíněnému špatně nakonfigurovanému domácímu směrovači, nefunkčnímu NAT, nefunkčním instalacím ISP nebo příliš restriktivnímu nastavení brány firewall.
Podle Boera a Bosmy asi 6 % hostitelů IPv4 a 10 % hostitelů IPv6 blokuje příchozí fragmentované datagramy.
Tady je několik odkazů s dalšími informacemi o konkrétních problémech fragmentace ovlivňujících DNS:
- DNS-OARC Reply Size Test
- IPv6, velké pakety UDP a DNS
A přesto internet stále funguje!
Jak je možné, že internet při všech těchto problémech stále funguje?
CC BY-SA 3.0, zdroj:
To především díky úspěchu sítě Ethernet. Drtivá většina linek ve veřejném internetu je ethernetová (nebo z ní odvozená) a podporuje MTU 1500 bajtů.
Pokud slepě předpokládáte MTU 1500, budete překvapeni, jak často to bude fungovat bez problémů. Internet funguje dál hlavně proto, že všichni používáme MTU 1500 a zřídkakdy potřebujeme provádět fragmentaci IP a posílat zprávy ICMP.
To přestane fungovat při neobvyklém nastavení s linkami, které mají nestandardní MTU. VPN a další software pro síťové tunely musí dbát na to, aby fragmentace a zprávy ICMP fungovaly správně.
To se projevuje zejména ve světě IPv6, kde se mnoho uživatelů připojuje prostřednictvím tunelů. Mít zdravý průchod ICMP oběma směry je velmi důležité, zejména proto, že fragmentace v IPv6 v podstatě nefunguje (citovali jsme dva zdroje, které tvrdí, že 10 až 50 % hostitelů IPv6 blokuje hlavičku IPv6 Fragment).
Protože problémy s Path MTU v IPv6 jsou tak časté, mnoho serverů IPv6 omezuje Path MTU na protokolem předepsané minimum 1280 bajtů. Tento přístup vyměňuje trochu výkonu za nejlepší spolehlivost.
Online kontrola černých děr ICMP
Pro pomoc při zkoumání a ladění těchto problémů jsme vytvořili online kontrolu. Najdete zde dvě verze testu:
- Verze IPv4: http://icmpcheck.popcount.org
- Verze IPv6: http://icmpcheckv6.popcount.org
Tyto stránky spouštějí dva testy:
- První test doručí vašemu počítači zprávy ICMP s cílem snížit MTU cesty na směšně malou hodnotu.
- Druhý test vám pošle zpět fragmentované datagramy.
Přijetí „pass“ v obou těchto testech by vám mělo poskytnout rozumnou jistotu, že se internet na vaší straně kabelu chová dobře.
Testy lze také snadno spustit z příkazového řádku pro případ, že byste je chtěli spustit na serveru:
perl -e "print 'packettoolongyaithuji6reeNab4XahChaeRah1diej4' x 180" > payload.bincurl -v -s http://icmpcheck.popcount.org/icmp --data @payload.bincurl -v -s http://icmpcheckv6.popcount.org/icmp --data @payload.bin
To by mělo snížit MTU cesty na náš server na 905 bajtů. To si můžete ověřit nahlédnutím do tabulky směrovací mezipaměti. V Linuxu to provedete pomocí:
ip route get `dig +short icmpcheck.popcount.org`
V Linuxu je možné vymazat směrovací cache:
ip route flush cache to `dig +short icmpcheck.popcount.org`
Druhý test ověřuje, zda jsou fragmenty správně doručeny klientovi:
curl -v -s http://icmpcheck.popcount.org/frag -o /dev/nullcurl -v -s http://icmpcheckv6.popcount.org/frag -o /dev/null
Souhrn
V tomto příspěvku jsme popsali problémy se zjišťováním hodnot Path MTU v internetu. Datagramy ICMP a fragmentované datagramy jsou často blokovány na obou stranách spojení. Klienti mohou narazit na špatně nakonfigurované brány firewall, zařízení NAT nebo používat poskytovatele internetových služeb, kteří agresivně zachycují spojení. Klienti také často používají sítě VPN nebo tunely IPv6, které mohou při špatné konfiguraci způsobit problémy s MTU cesty.
Servery na druhé straně stále častěji spoléhají na Anycast nebo ECMP. Obě tyto věci, stejně jako chybná konfigurace směrovače a brány firewall, jsou často příčinou zahazování datagramů ICMP a fragmentů.
Nakonec doufáme, že online test je užitečný a umožní vám lépe nahlédnout do vnitřního fungování vašich sítí. Test obsahuje užitečné příklady syntaxe tcpdump, užitečné pro získání většího přehledu. Šťastné ladění sítě!
Je oprava problémů s fragmentací pro 10 % internetu vzrušující? Přijímáme systémové inženýry všeho druhu, programátory Golangu, krotitele jazyka C a stážisty na více místech! Přidejte se k nám v San Franciscu, Londýně, Austinu, Champaignu a Varšavě.
-
V IPv6 funguje fragmentace „dopředu“ trochu jinak než v IPv4. Mezilehlé směrovače mají fragmentaci paketů zakázanou, ale zdroj ji stále může provádět. To je často matoucí – hostitel může být požádán, aby fragmentoval paket, který v minulosti přenesl. Pro bezstavové protokoly, jako je DNS, to nedává příliš smysl. ︎
-
Na okraj: existuje také „minimální přenosová jednotka“! V běžně používaném ethernetovém rámování musí mít každý přenášený datagram na 2. vrstvě alespoň 64 bajtů. To znamená 22 bajtů na vrstvě UDP a 10 bajtů na vrstvě TCP. U kratších paketů docházelo u více implementací k úniku neinicializované paměti! ︎
-
Striktně řečeno v IPv4 se paket ICMP jmenuje „Destination Unreachable, Fragmentation Needed and Don’t Fragment was Set“. Ale popis chyby IPv6 ICMP „Packet too big“ mi přijde mnohem srozumitelnější. ︎
-
Jako nápovědu uvádí zásobník TCP v paketech SYN také maximální povolenou hodnotu „MSS“ (MSS je v podstatě hodnota MTU snížená o velikost hlaviček IP a TCP). To umožňuje hostitelům zjistit, jaká je MTU na jejich linkách. Všimněte si: to neříká, jaká je MTU na desítkách internetových linek mezi dvěma hostiteli! ︎
-
Chybujme na bezpečné straně. Lepší MTU je 1492, aby se přizpůsobilo připojení DSL a PPPoE. ︎