Občas se dostaneme do blízkosti bezdrátové sítě, která k nám není přátelská. Buď nás pustí jen k velmi omezenému množství služeb nebo nám rovnou cestu zatarasí captive portálem, ke kterému neznáme heslo. Pokud nás taková síť pustí k DNS, máme napůl vyhráno a můžeme tudy posílat síťový provoz.
Co se dozvíte v článku
Tunelování DNS (anglicky DNS tunneling) je metoda, jak posílat libovolná data skrz protokol DNS, který k tomu původně nebyl navržen. My ale můžeme DNS dotazy zneužít tak, že do nich zabalíme jeden směr komunikace a v odpovědích nám pak poteče druhý směr. Tímto postranním kanálem tak dokážeme přenášet libovolná data. Protože to je neobvyklá metoda, často ji správci sítě přehlížejí.
Poznámka: Pokud vám na síti funguje alespoň web a vy byste chtěli používat další služby, můžete tunelovat provoz pomocí WebSocket a uniknout pomocí standardních webových služeb.
Co je to DNS a jak funguje?
Krátká odbočka pro ty, kteří vůbec netuší, jak funguje DNS a k čemu se běžně používá. V systému DNS rozlišujeme několik různých aktérů: DNS klient klade dotazy, DNS resolver je (obvykle) v místní síti přebírá a hledá odpovědi. Dělá to tak, že oslovuje autoritativní DNS servery v internetu, které hierarchicky drží určitou část odpovědi.
Resolver tedy musí oslovit několik různých autoritativních serverů a postupně získat informace od kořenové zóny, přes národní zónu (třeba .CZ) až po autoritativní server provozovatele služby, kde už dostaneme výslednou odpověď. Jakmile ji resolver získá, může ji předat klientovi, čímž odpoví na jeho dotaz. Všechny postupně získané informace jsou v resolveru kešovány po určitou dobu, takže se na ně nějakou dobu nemusí znovu ptát.
Informace jsou v DNS uloženy v záznamech určitého typu. Těch je celá řada, nás ale budou zajímat záznamy typu NS, A a případně AAAA. Záznam typu NS deleguje tazatele v hierarchii na další server, který by měl mít více podrobností. Když se tedy autoritativních serverů hostujících kořenovou (nejvyšší) zónu zeptáme na nějakou doménu v .CZ, získáme NS záznam, který nás pošle na autoritativní servery provozované organizací CZ.NIC. Ta nás pomocí NS záznamů přesměruje dále a tak postupně až k cíli.
Jako klienta nás ale obvykle zajímají záznamy obsahující IP adresu, ke které se pak budeme chtít připojit. Bývá to adresa serveru, na kterém běží naše služba: web, mail, SSH, cokoliv. Tyto záznamy se jmenují A pro IPv4 a AAAA pro IPv6. Mapují vlastně doménové jméno na konkrétní IP adresu.
Jak funguje DNS tunel
Předpokládejme, že jsme uzavřeni v síti, která nám odmítá směrovat provoz do internetu. Třeba jí musíme nejprve předat na captive portálu heslo nebo číslo platební karty. V síti ale běží DNS resolver, který je ochoten pro nás překládat doménová jména z internetu. Tím máme vyhráno a pokud jsme se připravili předem, můžeme tento kanál použít pro komunikaci s vnějším světem.
Za normálních okolností by nám tento resolver nijak nepomohl, protože bychom si sice mohli přeložit libovolnou doménu na IP adresu, ale síť nás s ní odmítne spojit. Jako bychom měli krásný kompletní telefonní seznam, ale nikam se stejně nedovoláme, protože sluchátko je hluché.
My to ale uděláme fikaně a místnímu DNS resolveru budeme posílat dotazy, do kterých zabalíme naši komunikaci. Tyto dotazy pak resolver předá našemu autoritativnímu DNS serveru, v domnění, že cílem je přeložit doménové jméno na adresu. Náš specializovaný autoritativní server ale ve skutečnosti nebude odpovídat běžným způsobem, ale do odpovědi zabalí data, která nám chce poslat. Jelikož jde o standardizovanou DNS komunikaci, resolver nám informace ochotně předá.
Co budeme potřebovat
V první řadě budeme potřebovat vlastní doménu ve veřejném doménovém stromě. Je úplně jedno, jaká to bude. Pokud žádnou nemáte, můžete si pořídit nějakou s koncovkou .xyz, .store, .space nebo třeba .tech. Její registrace vás bude stát jen pár desetikorun ročně. Doporučuji pořídit si co nejkratší jméno, protože pak bude v paketech více místa na data.
Kromě toho budete potřebovat linuxový server s veřejnou IP adresou. Možná už nějaký máte, můžete ho klidně využít. Bude stačit nějaký levný VPS (Virtuální Privátní Server), přes který pak budete posílat provoz. Takový server se dá seznat řádově za desetikoruny měsíčně.
Můžete samozřejmě použít i nějaké další zařízení, které je dosažitelné z internetu. Pokud vám doma běží třeba Raspberry Pi v roli NAS (Network-Attached Storage), můžete ho klidně použít. Pokud jste někde za firewallem, musíte se ujistit, že na zařízení doputují požadavky na port 53. Na něm totiž standardně běží DNS provoz a resolver se bude snažit tam získat své odpovědi.
Příprava domény
V doméně (řekněme example.com) musíme vytvořit subdoménu s delegací na náš server (řekněme 198.51.100.15). Potřebujeme totiž, aby si resolvery pro odpověď v naší doméně chodili na náš server, který jim bude podstrkávat komunikaci.
Musíme tedy do zóny pro naši doménu přidat následující dva řádky. Můžeme to klidně udělat na autoritativním serveru, který nám poskytuje náš registrátor, u kterého jsme doménu koupili. Pokud provozujeme vlastní servery, uděláme to na nich.
t1 IN NS ns.example.com. ; pozor na tečku! ns IN A 198.51.100.15
První záznam říká: dotazy na t1.example.com
posílej na server ns.example.com
. Druhý záznam pak dodává: ns.example.com
najdeš na téhle IP adrese. NS záznam může obsahovat jakékoliv doménové jméno, tady jsme ale pro jednoduchost zůstali ve stejné zóně. Musí ovšem obsahovat jméno, proto musíme IP adresu zapsat v dalším záznamu.
Spouštíme tunel
Pro využití domény pro posílání dat použijeme démona iodine (IP Over DNS, jód s protonovým číslem 53). Ten je k dispozici pro Linux, macOS, FreeBSD, NetBSD, OpenBSD a dokonce i pro Windows. V mnoha linuxových distribucích je zabalený v běžných repozitářích, stačí ho tedy nainstalovat. Budeme ho potřebovat na obou stranách, tedy na serveru i u klienta.
Utilita si vytvoří virtuální síťové rozhraní typu tun, které se chová jako síťová karta. Má přidělenou IP adresu a je možné do něj posílat provoz. Ten skončí uvnitř utility, která zajistí jeho předání přes DNS. Síťové karty na obou stranách jsou pak vlastně propojené přes protokol DNS, podobně jako je to u obvyklých VPN.
Server
Utilita iodine
přijímá dva povinné parametry: IP adresu a doménu používanou pro přenos dat. IP adresu si můžeme vybrat, nesmí ale kolidovat s žádným rozsahem v některé z dalších sítí. Je rozumné si tedy vybrat nějaký privátní rozsah z RFC 1918, dejme tomu 10.200.0.0/24. Jako doménu použijeme naši nadelegovanou t1.example.com.
Hodí se nám ještě znát parametr -f
, kterým donutíme utilitu zůstat běžet na popředí a můžeme pak lépe sledovat její chování. Na serveru tedy rovnou spustíme:
# iodined -f 10.200.0.1 t1.example.com
Tím máme vlastně vše připraveno a server je schopen přijímat naši komunikaci. Na produkci pak můžeme spustit připravenou službu iodined.service
, která se například v Debianu konfiguruje v /etc/default/iodine
. Tím zajistíme, že služba poběží automaticky po startu.
Klient
U klienta je pak situace ještě jednodušší, protože jemu stačí předat informaci o používané doméně. Na tu se bude dotazovat místního DNS resolveru a tím bude odesílat komunikaci. Pokud bychom chtěli použít jiný než standardní místní resolver, můžeme jeho adresu předat jako další parametr. Obvykle to ale není potřeba, proto bude stačit:
# iodined -f t1.example.com
Utilita se na obou stranách zeptá na heslo. To musí být samozřejmě v obou případech stejné a klient se jím pak na serveru autentizuje. Klientská utilita zkusí po spuštění detekovat, zda se nedomluví se serverem přímo. Pokud ano, přepne se do režimu přímého UDP tunelu a místní DNS resolver pak vůbec nepotřebuje. Pokud to možné není, použije se standardně tunelování přes DNS dotazy.
V každém případě i na klientské straně vznikne síťové rozhraní, které automaticky dostane IP adresu vedle serverové, tedy 10.200.0.2
. Oba stroje na sebe v takto vytvořeném tunelu vidí a je možné mezi nimi vyzkoušet ping
nebo navázat jakékoliv další spojení. Počítačů může být naráz připojených více a každý z nich dostane svou vlastní adresu. Chová se to tedy jako jednoduchá VPN.
Je možné do síťového rozhraní routovat libovolný provoz a na druhé straně ho forwardovat. Můžete si uvnitř spustit libovolnou VPN, třeba WireGuard nebo OpenVPN. Nebo můžete pomocí -D
použít SSH jako SOCK proxy a poté skrz ni projít na web. Máte prostě dvě propojená rozhraní, která vám tvoří cestu mimo uzavřenou síť.
Omezení
Takový tunel má samozřejmě z principu určitá omezení. V první řadě provoz skrz něj není šifrován, takže ho kdokoliv po cestě může zachytit. Pokud potřebujete bezpečnost, musíte si ji zajistit na vyšší vrstvě. Buď v aplikaci (třeba SSH nebo HTTPS) nebo musíte v tunelu postavit další tunel třeba pomocí zmíněných VPN.
Výkon takového spojení není z principu nijak valný, obvykle se vám přes DNS tunel podaří stáhnout stovky kilobitů za sekundu a v opačném směru odeslat dokonce desítky kilobitů za sekundu. To dnes není nijak závratná rychlost, ale na nouzové odeslání pošty, zobrazení základního webu nebo připojení k serveru pomocí SSH to bude stačit.
Použitý protokol se snaží využívat možností DNS na maximum, takže například používá doménová jména o plné délce 255 znaků. Některé resolvery ale tak dlouhá jména nesnesou a komunikace pak není stabilní. Vyřešit se to dá omezením použitelného prostoru pomocí parametru -M
například na 200 znaků. Nejnižší použitelná hodnota se pohybuje okolo stovky, protože protokol je schopen 1200bajtové pakety fragmentovat nejvýše na 16 dotazů, což vyžaduje 75 bajtů použitelných pro data.