Linux mini-howto? Krátce o nástrojích ze života sysadmina.
Tunelování TCP skrz TCP
Tunelování spojení, TCP over …. , z praxe dnes běžně známe tunelování TCP spojení např. protokolem PPP což je protokol druhé vrstvy pro navázaní spojení mezi dvěma body, do PPP zapouzdříme na straně odesílatele naše TCP spojení (hlavičku + data) a odešleme, na druhé straně odebereme PPP informace a naše TCP pokračuje v sítí cestou dále k požadovanému cíli, zní to jednoduše a ve většině případů to funguje “par excellence”.
Jenže “neštěstí” nechodí po horách, ale po lidech a stejně je tomu i v telekomunikacích, když honíte duchy v sítí není dobré se obrnit myšlenkou, že tohle se mi nemůže stát aneb jak jsem tunelovali přes VPN tunel (tcp) další TCP tunel a jak to “blblo”.
Něco málo k teorii, TCP ve své podstatě reprezentuje proud dat rozdělený do tzv. segmentů (narozdíl od UDP, které představuje samostatné na sobě nezávisle datagramy, nezaručuje doručení ani pořadí), segmenty jsou opatřeny tzv. sequence number, což je číslo ukazující pořadí segmentu ve streamu a segmenty odesílány jako IP packety k cíli s velikosti MTU.
Cíl (na obrázku server) přijme packet a odpovída zpět pomocí příznaku ACK (acknowledge, odpověd), kde jako acknowledge number uvede přijmuté sequence number ze segmentu + 1, popis mechanismu je pro náš účel zjednodušen, ale to podstatné je zachováno, odesílatel (client) se tímto způsobem může dozvědět, že segment (data) byla ztracena a dojde k opětovnému zaslání (resend).
Dobře, co s tím dále ? Internet je “pěkně” divoké prostředí, data procházejí přes uzly které nemáte šanci kontrolovat, různá kvalita linek, zpoždění, ztrátovost, tvůrci TCP s tím počítali, proto je v návrhu TCP vlastnost timeoutu (odesílatel čeká na potvrzení ACK po určitý čas), round-trip-time (RTT), problém je ovšem v tom jak určit kolik RTT má být, pevná hodnota je nevyhovující a proto máme v TCP adaptivní timeout, který korigován “automacticky” během spojení, tak aby vyhověl i nejpomalejším linkám na trase, hodnota se může pohybovat od řádů sekund až po minuty (RFC2001), což je opravdu velký rozptyl.
TCP “meltdown” problém
V předchozích řádkách bylo nastíněno zjednodušené pozadí fungování TCP, představme si situaci, mějme TCP spojení (např. VPN) a uvnitř další TCP spojení, uvažujme problém na trase (pktloss/ztrátovost), nižší vrstva TCP (VPN) začne žádat o znovu zaslání dat (retransmission) a prodlužovat svůj timeout (RTT), spojení je blokováno, vyšší vrstva TCP (zapouzdřené TCP) začne timeoutovat a opět žádat o resend a prodlužovat svůj RTT, hodnota RTT zapouzdřeného TCP je nižší než hodnota skutečného TCP, vyšší vrstva tedy generuje více požadavků na znovu zaslání dat než může nižší vrstva TCP (skutečné) obsloužit, této situaci se říka TCP meltdown (utavení, roztavení, zhroucení).
TCP meltdown má vliv na výkon sítě, či může véct k úplnému rozpadu spojení, v našem případě jsme měli problém s OpenVPN a PPTP, na použití TCP bylo trváno zákazníkem kvůli politice jeho firewallu, nakonec přechod k UDP a vhodná úprava konfigurace firewall ukázalo průchodné řešení.
Na každý pád to znamená zajímavou zkušenost, není úplně snadné tento problém hledat, klon konfigurace do vašeho prostředí většinou nevede k cíli protože vše funguje, co je dobré vědět a velmi pomohlo k porozumění problému, je možnost simulovat zpoždění i ztrátovost přímo Linux routerem (nástroj tc, iptables), odkazy přiloženy a pochopitelně tcpdump/wireshark.
simulate-delayed-and-dropped-packets-on-linux
dropping-packets-in-ubuntu-linux-using-tc-and-iptables
Děkuji za pozornost.
František Havel, MOJEservery.cz