Skrytá hrozba jménem MTU
Wednesday, 23. July 2008, 00:23 Linux
Po dlouhé době opět jedna drobnost, která mě stála spousty přemýšlení. Jednoduchá modelová situace: Počítač s linuxem, sloužící jako firewall-NAT-router zakončuje PPPoE spojení od ADSL modemu (v režimu bridge) a prostřednictvím maškarády, potažmo SNATu (víte vůbec někdo, jaký je v tom rozdíl?) sdílí internetové připojení ostatním zařízením v lokální síti.
Jenže teď to nějak nefungovalo. Ne, že by to nefungovalo vůbec. Spíše šlo o typickou skrytou závadu - při pokusu cíleně odhalit její příčinu se neprojevila. Šlo o to, že určité www stránky se nenačítaly, či se jim pouze načetl titulek a pak bylo spojení ukončeno. Jiné stránky šly v pohodě. Pokud se ale použil http proxy server, běžící přímo na firewallu, šlo vše v pohodě.
Příčina těchto záhad se skrývala, jak již titulek napovídá, v nastavení MTU. Jak známo, ethernet umí přenést nejvýše 1500 B na paket, což vychází na hodnotu MTU 1460 B. Jenže díky 8 B záhlaví PPPoE je nejvyšší hodnota MTU na PPPoE spoji jen 1452 B. Zatímco počítač, na kterém byl PPP spoj přímo zakončen tuto informaci měl, ostatní počítače v síti o žádném PPP spojení nevěděly. Proto v záhlaví TCP segmentů s příznakem SYN nesprávně signalizovaly, že jsou schopni zpracovat větší množství dat, než odpovídalo realitě. Jak jsem zjistil zachycením komunikace na PPP rozhraní Wiresharkem, došlo k tomu, že příliš dlouhý paket byl na vzdálené straně PPP spojení zahozen. Protokol TCP sice zajistil opakování vysílání, ale i opakovaný segment byl zahozen. Za nějakou chvíli vypršel časový limit a spojení bylo zrušeno.
Nabízí se ovšem otázka, proč to tedy občas fungovalo? Zdůvodnění je dvojí - buď (1) nedošlo k naplnění celé velikosti paketu (například u telnetu, čí ssh) a/nebo (2) při zahození segmentu z důvodu překročení délky by měl prvek, který zahození provede, vygenerovat zdroji ICMP zprávu, ve které žádá o rozdělení segmentu na menší části. Takovouto zprávu pak server správně zpracuje a data rozdělí na menší kousky. Bohužel, někteří síťoví administrátoři mají takovou hrůzu ze zpráv protokolu ICMP, že je pro jistotu filtrují firewallem, někdy i včetně požadavku na odezvu (ping).
No a na závěr: Jak to spravit?
Takto:
# iptables -t mangle -I FORWARD 1 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
ještě jsem vygooglil toto a to by přesně mohlo být ono, vyzkoušíme uvidíme