Hlavní navigace

Postavte si VPN pomocí sshuttle, bude vám stačit přístup na SSH

Petr Krčmář

VPN pro chudé. Nebo lépe: VPN pro lidi, kteří vůbec nechtějí řešit nějakou VPN. To je sshuttle – jednoduchý nástroj propojující transparentní proxy s SSH. Výsledkem je uživatelská VPN na jeden jediný příkaz.

Doba čtení: 5 minut

Sdílet

Pokud potřebujete tunelovat provoz třeba přes nedůvěryhodnou síť nebo se potřebujete dostat do oblasti uzavřené za sedmero naty, obvykle je vám doporučeno nasadit VPN. Můžete použít tradiční řešení v podobě OpenVPN nebo zkusit progresivní WireGuard. Řešení je mnoho, dokonce si můžete za pár dolarů zaplatit nějakou službu.

Jenže někdy tohle celé řešit nechcete a rádi byste něco jednoduchého a rychlého, co nevyžaduje konfiguraci dvou stran, generování klíčů a nastavování routovacích tabulek. Jednou z možností jsou SSH tunely, které dovolují na jeden příkaz vytvořit spojení tunelované přes SSH server. To funguje pěkně, ale musíte vždy předem zvolit, kde má váš tunel začínat a kde má končit. Tohle je pro univerzální VPN těžkopádné.

No a pak je tu sshuttle. Což vlastně ale není VPN. Není to ani tunelování portů. Je to od obojího trochu.

VPN pomocí SSH

Sshuttle je transparentní proxy, kterou si jedním příkazem spustíte u sebe na stroji. Provoz je tunelován automaticky přes zvolený SSH server, na kterém ale nejsou potřeba ani rootovská oprávnění. Stačí vám běžný účet, ani nemusíte nic dalšího instalovat. Všechno se krásně zařídí samo. Líbí?

Všechna magie se odehrává na klientské straně, kde je nainstalován samotný nástroj a kde ho taky ovládáte. K tomu ovšem už rootovská oprávnění potřebovat budete, což ovšem bývá menší problém než je získat na nějakém serveru. Výhoda je, že se o serverovou stranu nemusíte vůbec starat a neřešíte třeba nekompatibilitu různých verzí na klientovi či na serveru. Tohle všechno taky odpadá.

Na klientské straně je potřeba: samotný nástroj sshuttle, rootovský přístup (stačí přes sudo) a nainstalovaný Python. Na serveru musíte mít nějaký účet (stačí uživatelský) a taky interpret Pythonu. Autor doporučuje použít Python 3.5 a novější.

Jak to funguje

Nástroj sshuttle vytvoří pomocí jaderného Netfilteru transparentní proxy, do které začne posílat veškerý provoz. Spojení je pak ukončeno hned na místním stroji a nebalí se do tunelu. Původní pakety se tedy vůbec nedostávají do sítě a nepřenášejí se tunelem, podobně jako je to v případě zmíněného tunelování pomocí SSH nebo třeba OpenVPN v režimu TCP.

Místo toho se v Netfilteru založí NAT, který všechny pakety vybaluje, data z něj vyndá a posílá je jedním tunelem simulujícím sériovou linku (podobně jako PPP). Na druhé straně poslouchá serverová strana napsaná v Pythonu, kterou si tam sshuttle při svém spuštění nahrál (velmi šikovné, že?) ta zase data vytahuje, sestavuje z nich pakety a posílá do světa.

Výhodou je, že se sshuttle tímhle chytrým mechanismem vyhýbá přenosu TCP-over-TCP. To je vždy nedoporučovaná varianta, jejíž nevýhody pocítíte především při výpadku paketů. Zatímco vnější spojení požádá o opakování, vnitřní o tom nic neví a protože se mu také ztratila část komunikace, požádá taky. Jenže to udělá zbytečně, protože spojení nad ním je spolehlivé a paket by za chvíli přišel. Kvůli různě nastaveným časovačům se ale začnou obě spojení vzájemně překřikovat a výkon jde k nule. VPN postavená pomocí sshuttle nepoužívá TCP-over-TCP, ale spíše data-over-TCP, což tímto problémem netrpí.

Technickou řečí: sshuttle si v tabulce nat založí vlastní řetězec sshuttle-12300 a v tabulkách PREROUTING a OUTPUT  si pošle veškerý provoz na lokální port 12300. Musí samozřejmě druhým pravidel zajistit, aby se na takto přesměrovaný provoz už nesahalo a ten skončil ve správném portu. Pravidla vypadají takto:

-t nat -N sshuttle-12300
-j RETURN --dest 127.0.0.1/32 -p tcp
-j REDIRECT --dest 0.0.0.0/0 -p tcp --to-ports 12300 -m ttl ! --ttl 42

To je vlastně všechno, na co jsou potřeba práva roota. Zbytek se už děje pod běžným uživatelským účtem, kde začne na správném portu nástroj poslouchat a přijímat veškerý síťový provoz. Ve výchozím stavu se port otevře jen na loopbacku, ale můžete jej otevřít i do sítě a nabídnout službu dalším počítačům okolo sebe.

Použití v praxi

Další dobrou zprávou je, že sshuttle je běžně zabalený v distribucích, takže jednoduše stačí nainstalovat příslušný balíček. Bude tedy stačit něco jako:

# apt install sshuttle

Samotné použití je velmi snadné, stačí utilitě předat informace o tom, na jaký server se má připojit a jakou podsíť má tunelovat. Pokud potřebujete vše, můžete buď uvést 0.0.0.0/0 nebo zkrácenou verzi 0/0. Pokud vás naopak zajímají podsítě, můžete sshuttle spustit víckrát a nechat se takto propojit do různých sítí.

$ sshuttle -r uzivatel@server.example.com 0/0

Pomocí parametru -x můžete vyjmenovat cíle, pro které si nepřejete komunikaci posílat tunelem. To se hodí, pokud potřebujete komunikovat zároveň s některým strojem v místní síti. Užitečný může být také parametr -H, který umožní automaticky doplňovat místní /etc/hosts podle cílů v sítích za tunelem. 

Pokud takto chcete tunelovat i UDP provoz pro DNS, přidejte parametr --dns. V takovém případě bude do filtru přidáno ještě jedno pravidlo, které DNS požadavky (UDP/53) opět pošle do místního portu sshuttle a dotazy pak vyřizuje DNS resolver nastavený na serveru. Místní síť vám pak nemůže zasahovat ani do DNS.

Kde je IPv6?

Pokud jste četli pozorně a prohlédli jste si také nastavení Netfilteru, asi si teď kladete otázku z mezinadpisu: kde je IPv6? Ve výchozím stavu sshuttle tuneluje jen TCP po IPv4 a DNS. Pokud potřebujete tunelovat IPv6 nebo veškerý UDP provoz, budete muset použít režim TPROXY.

Pozor ovšem na to, že sshuttle nemá mechanismus překladu mezi IPv4 a IPv6. Oba protokoly tedy můžete tunelovat, ale nikoliv mezi nimi překládat. V praxi se to projevuje tak, že klient musí mít nakonfigurovanou konektivitu pro IPv6, aby byl ochoten vytvářet šestkové pakety. Teprve ty pak může sshuttle zachytit a protlačit tunelem.

Dále je potřeba si dát pozor na to, že musíte při spouštění příkazu ručně vyjmout z tunelovaného rozsahu adresu či adresy, na které se budete ve skutečnosti připojovat. Pokud to neuděláte, utilita se k serveru nebude schopná připojit.

$ sshuttle --method tproxy -r uzivatel@server.example.com -x 2001:DB8::/32 ::/0

Užitečný pomocník

Přestože je článek poměrně dlouhý, popisuje obšírně vlastně velmi jednoduchý nástroj, který od uživatele nevyžaduje prakticky žádné znalosti. Pokud máte po ruce SSH server, můžete se pomocí něj připojit do jiné sítě. Je to univerzálnější a rychlejší než klasické SSH tunely, které musí mít pevně stanovený konec. Tohle víc připomíná VPN a jedním příkazem se připojíte do celé sítě za serverem.

Užitečné je to například ve chvíli, kdy máte vzdálený SSH server vystavený do internetu a ten slouží jako brána pro síť, která je jinak schovaná za natem. Pokud se potřebujete připojovat k různým strojům v ní, je jednou z možností použití právě sshuttle. Řekl bych, že je to možnost nejjednodušší, protože nemusíte nikde nic konfigurovat ani vymýšlet. Prostě si pustíte SSH.