Technologie internetu (10.): Óda na TCP

15. 10. 2007

Sdílet

Kdybych měl vybrat jediný protokol, který se rozhodující měrou zasloužil o historický úspěch internetu, pak by jedním z nejvážnějších kandidátů byl Transmission Control Protocol (TCP). Jde o protokol transportní vrstvy, který nad nespolehlivou a nespojovanou internetovou vrstvou realizuje to, co většina komunikačních aplikací potřebuje – spolehlivé obousměrné spojení mezi libovolnými dvěma body v internetu.

Kdybych měl vybrat jediný protokol, který se rozhodující měrou zasloužil o historický úspěch internetu, pak by jedním z nejvážnějších kandidátů byl Transmission Control Protocol (TCP). Jde o protokol transportní vrstvy, který nad nespolehlivou a nespojovanou internetovou vrstvou realizuje to, co většina komunikačních aplikací potřebuje – spolehlivé obousměrné spojení mezi libovolnými dvěma body v internetu.

První specifikace (RFC 793) pochází ze září 1981, TCP má tedy za sebou právě čtvrt století existence. Během této doby se internet samozřejmě změnil k nepoznání, od malé experimentální sítě s rychlostmi okruhů v řádu stovek bitů za sekundu až k dnešní globální síti se stovkami milionů účastníků a desetigigabitovými okruhy. Protokol TCP tyto kardinální změny ustál se ctí, byť s určitými drobnými změnami. Stojí na něm všechny hlavní aplikace dnešního internetu, tedy například WWW, e-mail, instant messaging a SSH, celkem přenáší TCP zhruba 95 % veškerého provozu.

TCP vytváří pro aplikace užitečnou abstrakci souvislého datového proudu. Znamená to, že aplikace se nemusí starat o to, jakým způsobem bude datový tok rozdělen do IP datagramů, pouze posílá svá data do „virtuální roury“, na jejímž druhém konci vyjdou zaručeně nepoškozena a v tom pořadí, jak byla poslána. Zdůrazněme, že implementace TCP plně respektuje princip periferní inteligence, o němž jsme mluvili v prvním dílu seriálu: vše se odehrává v operačních systémech hostitelů na obou koncích spojení, mezilehlé směrovače nemají za normálních okolností o TCP spojeních ani tušení.

TCP segmenty

Datový proud generovaný určitou aplikací rozděluje subsystém TCP na úseky vhodné velikosti, které se nazývají segmenty. Při odesílání většího objemu dat je to obvykle zařízeno tak, aby se výsledný paket vešel do maximální velikosti rámce (Maximum Transmission Unit, MTU) síťových rozhraní na obou koncích TCP spojení, která například pro Ethernet činí 1 500 bajtů. Pokud by některý spoj po cestě měl MTU menší, zařídí směrovače na koncích tohoto spoje fragmentaci datagramů. Jiné je to ovšem v případě IPv6, protože tam tato automatická fragmentace není vůbec povolena. Hostitel má pak dvě možnosti: buď se uchýlí k MTU=1280, která musí být podle specifikace IPv6 garantována na všech spojích, anebo použije speciální proceduru, s jejíž pomocí zjistí skutečnou MTU podél celé trasy (Path MTU Discovery).

Každý segment je opatřen hlavičkou TCP a předán internetové vrstvě k odeslání. Standardní hlavička TCP má délku 20 bajtů a obsahuje několik datových položek a příznaků (flags), které TCP pro svou činnost potřebuje. Především jsou zde čísla zdrojového a cílového portu, jimiž se rozlišují jednotlivá TCP spojení. Díky tomu může stejný hostitel zároveň obsluhovat různé TCP aplikace, popřípadě více instancí jedné aplikace.

Další důležitou položkou v hlavičce je sekvenční číslo, které v datovém segmentu udává pořadí prvního bajtu dat v rámci datového proudu. Jinými slovy: za každý odeslaný bajt se musí sekvenční číslo o jedničku zvětšit. Porovnáním sekvenčních čísel může přijímající strana zjistit, že se některé segmenty ztratily anebo dorazily v přeházeném pořadí – viz níže. V hlavičce TCP je také zapsán kontrolní součet zahrnující jak hlavičku, tak i data. Přijímající strana je povinna tento součet přepočítat, a tím odhalit případné poškození dat, pokud by k němu cestou došlo.

V hlavičce některých segmentů mohou být také některé volitelné záznamy (TCP options), které slouží pro různé doplňkové funkce. V současné době je jich definováno celkem 26, nejběžnější z nich najdete ve vloženém textu. Pokud se použijí, je hlavička TCP delší než 20 bajtů, a proto jedna z povinných položek také udává celkovou délku TCP hlavičky.

Potvrzování a retransmise

Přijímající strana musí průběžně potvrzovat, že řádně přijala všechna data. K tomuto účelu slouží segment s nastaveným příznakem ACK (acknowledge), v němž je zároveň vyplněna další položka v hlavičce TCP – potvrzovací číslo (acknowledgement number). Ta udává sekvenční číslo prvního bajtu příchozího datového proudu, který přijímající strana dosud neviděla. Odesílatel si po obdržení takového potvrzení může být jist, že datový proud byl na druhé straně řádně přijat až do sekvenčního čísla, které je o jedničku nižší než dotyčné potvrzovací číslo. Přijetí dat je možné potvrdit a zároveň s tím ve stejném segmentu odeslat opačným směrem vlastní data.

Pokud se při přenosu některý segment ztratí, přijímající strana nemůže zvýšit potvrzovací číslo. Odesílatel proto po uplynutí určitého času zahájí retransmisi, při níž odešle znovu všechna data počínaje nejnižším sekvenčním číslem, pro něž dosud nemá potvrzení.

Otevření a uzavření spojení

Aplikace používající TCP pracují v režimu klient-server. Na straně serveru se nejdříve musí realizovat pasivní otevření TCP spojení, které vede k tomu, že server očekává na stanoveném portu příchozí žádosti o spojení. Vlastní komunikaci pak zahajuje klient takzvaným aktivním otevřením spojení: odešle segment s nastaveným příznakem SYN (synchronize), v němž zároveň uvede počáteční sekvenční číslo pro svůj datový proud. Server odpoví segmentem s nastavenými příznaky SYN a ACK a svým počátečním sekvenčním číslem. Klient potvrdí přijetí tohoto segmentu svým druhým segmentem, tentokrát s příznakem ACK, čímž je spojení otevřeno a může začít výměna dat. Tato tzv. trojcestná výměna (three-way handshake) je základním charakteristickým znakem TCP.

Je důležité, aby počáteční sekvenční číslo bylo pro každé spojení zvoleno (pseudo)náhodně. Proč? Hlavním důvodem je bezpečnost. Pokud by sekvenční čísla začínala vždy třeba od nuly anebo se dala snadno uhodnout, mohl by se případný útočník vetřít do aktivního spojení a předstírat, že je jedním z účastníků. Takové útoky se skutečně děly, stačilo k tomu, když některý operační systém nevolil svá počáteční sekvenční čísla dostatečně náhodně.

Spojení se ukončuje podobným postupem jako při otevření. Popud k tomu může tentokrát dát jak klient, tak server tím, že odešle segment s nastaveným příznakem FIN (finish). Protější strana obvykle odpoví svým segmentem s příznaky FIN a ACK, načež iniciátor ukončení spojení definitivně uzavře potvrzujícím segmentem s příznakem ACK.

Příště se budeme věnovat nejkomplikovanější části protokolu TCP, jíž je obrana proti zahlcení.

TCP Options

K běžně používaným volitelným položkám v hlavičce TCP patří tyto:

Maximum Segment Size – stanovuje explicitně maximální velikost TCP segmentu.

Window Scale – umožňuje použít větší klouzavé okno pro řízení toku dat (viz příští díl). Tuto volbu smí každá strana použít jen v úvodním SYN segmentu.

Selective Acknowledgement – slouží k podrobnějšímu informování odesílatele o tom, které segmenty byly v pořádku přijaty. Standardně se musí s potvrzováním skončit v místě, kde chybí první bajt datového proudu.

MD5 Signature – umožňuje připojit k segmentu kryptografický podpis založený na rozptylovací funkci MD5. Využívá se nejčastěji k ochraně relací BGP.

 

Autor článku