Přiznám se, že přesnou definici tunelování jsem nikde nenašel, ani se mi ji nepodařilo vymyslet. Pokusím se vám tedy alespoň nastínit, o co jde. K tunelování je potřeba tunel – kanál pro data mezi dvěma počítači v síti. Tento kanál může být tvořen třeba i TCP spojením, ale v praxi se používá spíše specializovaných protokolů na úrovni IP (ipsec, gre).
Tunelování se většinou využívá pro spojení vzdálených sítí do jedné, která je zdánlivě homogenní. Viz obrázek sítě smyšlené firmy:
Tato síť pak zevnitř bude vypadat třeba takto:
Tunelování pomocí GRE
Nejprve se podíváme na jednodušší a (alespoň podle mého mínění) průhlednější způsob – vytváření tunelů pomocí protokolu GRE. GRE znamená General Routing Encapsulation protocol (všeobecný zapouzdřovací protokol :-). Dá se nastavovat buď pomocí příkazů ifconfig a route, nebo pomocí novějšího programu ip z balíku iproute2. Dále je potřeba podpora GRE v kernelu. Pro další příklady budeme předpokládat, že podnik používá privátní adresy ze sítě 192.168.0.0/0. Centrála má adresu 192.168.0.0/24, pobočky 192.168.1.0/24, 192.168.2.0/24 atd. Spojení mezi pobočkami jde přes centrálu. Viz obrázky výše.
GRE tunel se vytvoří pomocí příkazu:
ip tunnel add pobocka1 mode gre remote 123.45.67.80 local 123.45.67.90
Parametry příkazu:
- ip – program z balíku iproute2
- tunnel – budeme pracovat s tunely
- add pobocka1 – přidej tunel tohoto jména
- mode gre – budeme používat protokol gre
- remote 123.45.67.80 – tunel bude s tímto počítačem
- local 123.45.67.90 – odchozí packety budou mít tuto zdrojovou adresu (nepovinný parametr)
Tím jsme vytvořili síťové zařízení pobocka1, stejně tak, jako máme například eth0. Dále zařízení spustíme:
ip link set pobocka1 up
A přiřadíme mu IP adresu:
ip addr add 192.168.0.254 dev pobocka1
Nyní musíme ještě vytvořit druhý konec tunelu (zařízení pojmenujeme centrala, neboť v tomto případě to bude tunel na centrálu):
ip tunnel add centrala mode gre remote 123.45.67.90 local 123.45.67.80
ip link set centrala up
ip addr add 192.168.1.254 dev centrala
Tím ale naše práce nekončí. Máme sice tunel, ale netečou jím žádne packety. Nastavíme tedy routing na pobočce:
ip route add 192.168.0.0/16 dev centrala
A na centrále:
ip route add 192.168.1.0/24 dev pobocka1
A tunel by měl fungovat. Několik tipů, pokud nefunguje:
- Ujistěte se, že packetům nebrání v průchodnosti firewall. Musí mít povolen IP protokol GRE (číslo 47). Stejně tak se ujistěte, že vám lokální firewall nezahazuje packety přicházející z tunelu. Pokud jej máte restriktivně nastavený, bude pravděpodobně potřeba v něm packety z daného rozhraní povolit.
- Ujistěte se, že packety z druhé strany opravdu přicházejí z adresy, kterou máte nastavenou jako druhý konec. Pokud nezadáte parametr local, může si počítač vybrat libovolnou ze svých adres. Stejně tak pokud ho zadáte špatně, budou packety zahazovány.
- Dobrým pomocníky zde jsou tcpdump a/nebo ethereal, které navíc vidí i „dovnitř“ GRE packetů.
GRE je jednoduchý a poměrně rozšířený standard, GRE tunely se dají vytvářet nejen mezi Linuxy, ale i s Cisco routery nebo dokonce Windows.
Další možnosti příkazu ip tunnel
Pokud jste experimentovali a dali jste si vypsat možnosti příkazu ip tunnel, všimli jste si určitě dalších dvou módů tunelu.ipip tuneling je principiálně podobný GRE, umožňuje však pouze přenos IP packetů a není tolik rozšířený. sit potom slouží pro vytváření IPv6 tunelů po IPv4 síti – tedy propojení dvou IPv6 sítí po síti, která umí pouze IPv4.
Tunelu lze nastavovat různé speciální parametry. Buď je jejich použití zjevné z jejich názvu, nebo vás odkáži na manuál. Zastavím se pouze u jedné možnosti – nastavení TTL. Jde o TTL IP packetu, který „obaluje“ GRE (které „obaluje“ původní packet). Pokud necháme standadní nastavení, bude mít tento packet stejné TTL jako packet, který jím je přenášen v okamžiku odchodu ze serveru do tunelu („zdědí TTL“). To ale může přinášet drobné problémy, například při používání příkazu traceroute.
Traceroute dotrasuje až ke vstupu do tunelu bez problémů. V dalším kroku pošle packet, který bude mít na vstupu do tunelu TTL jedna. Jestliže jej zdědí „obalový“ packet, bude tento na dalším počítači v cestě zahozen a zpět se pošle ICMP zpráva. Ta ale půjde na začátek tunelu, ne na počítač, který dělá treaceroute, protože zdrojová adresa „obalového“ packetu samozřejmě obsahuje začátek tunelu. Tak se traceroute o hopu nedozví a při trasování bude tolik nedosažitelných hostů, přes kolik jich jde tunel.
Když při vytváření tunelu uvedeme parametr ttl <číslo>, budou mít „obalové“ packety nastaveno vždy toto TTL a v traceroute výpisu bude tunel figurovat jako jeden skok.
Problémy s velikostí packetů
Při provozování GRE tunelu může docházet k na první pohled záhadným jevům. Například na některé WWW servery se sice dá spojit, ale už z nich nejde stáhnout žádná stránka. Nebo jdou stáhnout jen některé stránky.
Děje se ve zkratce toto: Server posílá hodně dat najednou (WWW stránku). Rozdělí je tedy do packetů o maximální možné velikosti z hlediska jeho rozhraní (vetšinou ethernetu – 1500 bajtů) a packety odešle. Pokud nejdete přes tunel, je vše v pořádku, packet projde. Pokud je v cestě GRE tunel, dojde packet v pořádku na vstup do tunelu. Tam se ale obalí ještě GRE a IP hlavičkou a jeho velikost vzroste nad oněch 1500 bajtů. Takže nepůjde poslat po ethernetu (kterým bývá konec tunelu většinou připojen), neboť je příliš velký.
Za normálních okolností by se takovýto packet měl rozfragmentovat. Ale pro zvýšení efektivity přenosu bývá zapnut mechanismus „Path MTU discovery“ (zjištění minima největší přípustné délky packetů po celé cestě mezi počítači). Ten packetům zakazuje fragmentaci. Spoléhá se na to, že pokud počítač nemůže příliš velký packet poslat, zahodí jej a odešle zpět ICMP hlášení „fragmentation needed“.
Bohužel někteří „administrátoři“ zakazují šmahem celé ICMP, prý z „bezpečnostních důvodů“. Jedním z důsledků je pak nefunkčnost výše popisovaného mechanismu „Path MTU discovery“. Packety se zahazují a informace o tom neprojdou zpět přes firewall. Projdou jen menší packety, které nenesou tolik dat a po obalení GRE a IP hlavičkami nepřesáhnou kritickou velikost.
Můžete sice uhánět administrátory všech firewallů, ale moc nadějí na úspěch vám nedávám. Místo toho zkuste vzdálený počítač donutit, aby posílal packety o něco menší, aby zbylo místo na GRE a další IP hlavičku. Dosáhnete doho pomocí IPTABLES. Na firemním firewallu zadejte například:
iptables -I FORWARD 1 -p tcp -o eth0 --tcp-flags SYN,RST SYN -m tcpmss --mss 1221: -j TCPMSS --set-mss 1220
Rozebrání pravidla:
- iptables – Příkaz pro manipulaci s iptables
- -I FORWARD 1 – Pravidlo vložíme na první pozici (aby se vždy provedlo) chainu FORWARD.
- -p tcp – Bude se týkat TCP packetů…
- -o eth0 – …které odejdou přes vnější zařízení…
- –tcp-flags SYN,RST SYN – …mají nastavené TCP příznaky SYN nebo SYN a RST (začátek spojení)…
- -m tcpmss –mss 1221: – …a mají maximum segment size větší nebo rovný 1221.
- -j TCPMSS –set-mss – Takovým packetům nastav maximum segment size na 1220.
Nastavená maximum segment size způsobí, že druhý počítač nedá do TCP packetu nikdy více než 1220 bajtů dat a zbude dost místa na připojení IP a GRE hlavičky. S uvedeným číslem (1220) budete muset možná trochu laborovat, mohlo by být i vyšší a někde bude možná nutné nižší. Vypočte se jako:
MTU vnějšího rozhraní (1500 u ethernetu) mínusvelikost linkových (ethernetových) hlaviček mínus 2× velikost IP hlavičky mínus velikost GRE hlavičky mínus velikost TCP hlavičky.
To by bylo pro dnešek o tunelování všechno. Příšte se vrhneme na šifrované tunely tvořené pomocí IPSecu.