Zapnutí klienta OpenVPN s plným tunelem na stroji, ke kterému se dostáváte přes SSH, může relaci přerušit během sekundy, a stroj přitom nedělá nic špatně. Tunel nemění, jak pakety dorazí na server; mění, jak odcházejí odpovědi. Jakmile výchozí trasa ukazuje na tun0, odpověď vašemu SSH klientovi jde do sítě poskytovatele, která nemá trasu zpět na vaši adresu. Spojení zamrzne, další pokus vyprší a démon celou dobu poslouchá na portu 22.

Přečtěte si směrovací tabulku dřív, než přečtete log VPN. Log řekne, že tunel vstal, a bude mít pravdu. Otázka je, kterému rozhraní se každá odpověď předá, a to je vyhledání pro každý paket v tabulce, kterou tunel právě přepsal.

Proč odpověď vychází špatnými dveřmi

Příchozí pakety stále dorazí na fyzické rozhraní, protože klient VPN nemůže změnit, jak se internet dostane na veřejnou adresu vašeho serveru. Odpovědi jsou samostatné rozhodnutí: pro každý paket jádro hledá cíl a po --redirect-gateway výchozí záznam říká tunel. Výstup poskytovatele vidí cíl, kterému neposkytuje službu, a paket zahodí.

Vlastní ochrana OpenVPN pokrývá přesně jeden cíl. Manuál k 2.6 popisuje --redirect-gateway jako posloupnost: přidá hostitelskou trasu pro peer VPN přes bránu používanou před tunelem, aby se šifrovaný provoz nemohl zacyklit sám do sebe, a pak nahradí výchozí trasu. Tato hostitelská trasa je jen pro peer. Váš SSH klient je jen další internetová adresa a žádnou výjimku nedostane.

Jednu chybu s prefixem stojí za to vyloučit brzy. ip route add -net 0.0.0.0 gw 10.8.0.1 dev tun0 bez délky odpovídá jediné adrese 0.0.0.0, ne internetu; musí to být 0.0.0.0/0. A pokud převzetí výchozí trasy rozbije vlastní transport tunelu, přidejte koncový bod jako hostitelskou trasu přes fyzické rozhraní s použitím skutečné adresy poskytovatele.

Připněte adresu svého SSH klienta pro okamžitou opravu

Nejrychlejší oprava je hostitelská trasa pro adresu vašeho klienta přes bránu, kterou server používal před tunelem. Ze své strany najděte adresu, kterou server uvidí, a pak si přečtěte tabulku serveru, abyste znali starou bránu:

curl -s https://ifconfig.co
ip route

Na serveru přidejte výjimku dřív, než klient nastartuje. Adresy jsou tu zástupné; důležitý je tvar:

sudo ip route add 80.128.240.55 via 192.168.178.1

Toto je oprava použitá v hlášeném případě a funguje okamžitě. Je také křehká ve dvou předvídatelných ohledech: trasa zmizí při restartu a bude špatná ve chvíli, kdy vám ISP přidělí jinou adresu. Berte ji jako nouzové opatření a záměrně ji udělejte trvalou, přes síťovou jednotku nebo háček dispečeru, nebo přijměte, že je dočasná, a zapište cestu obnovy.

Zabráníte klientovi převzít výchozí trasu

Čistější možností je zabránit tunelu, aby vůbec nahradil výchozí trasu. route-nopull, použitý s --client nebo --pull, přijímá posílané volby kromě tras, block-outside-dns a voleb ve stylu DHCP, jako jsou servery DNS, takže přidáte jen prefixy, které potřebujete. Užší nástroj je filtr stahování, který zahodí jednu problematickou direktivu a zbytek ponechá:

route-nopull
pull-filter ignore "redirect-gateway"

Použijte jedno nebo druhé, ne obojí, a mějte jasno, co se změní. Bez výchozí trasy přes tunel server už neprochází internet přes poskytovatele; dosáhne jen na to, co jste výslovně nasměrovali. Pokud byl plný tunel celým smyslem nastavení, tohle je špatné kolečko a hostitelská trasa výše je ta správná.

Rozdělte zpáteční cestu podle zdroje nebo podle spojení

Když je příchozí adresa stabilní, pravidlo zdroje udrží odpovědi lokálně, aniž by se dotklo vlastních tras tunelu. Dejte adrese fyzického rozhraní vlastní tabulku s prefixem LAN a fyzickou výchozí trasou a pak tuto tabulku vybírejte pro provoz, který z ní pochází:

ip rule add from 192.168.1.11 table 128
ip route add table 128 to 192.168.1.0/24 dev eth0
ip route add table 128 default via 192.168.1.1

Funguje to proto, že odpovědi na příchozí SSH spojení pocházejí z adresy, na kterou se klient připojil. Hlášený případ, kde každá příchozí služba musela dál fungovat, použil přesně tento tvar. Když příchozí adresa plave nebo je cesta dynamická, označte místo toho spojení: nastavte značku conntrack na první paket přicházející z fyzického rozhraní, zkopírujte ji na odpovědní pakety v OUTPUT a směrujte označené pakety tabulkou, která ukazuje na fyzickou bránu.

iptables -t mangle -A PREROUTING -i eth0 -m conntrack --ctstate NEW -j CONNMARK --set-mark 1234
iptables -t mangle -A OUTPUT -m connmark --mark 1234 -j MARK --set-mark 4321
ip route add default via 192.168.1.1 dev eth0 table 3412
ip rule add fwmark 4321 table 3412

Během testování držte značku spojení, značku firewallu a číslo tabulky oddělené. Opětovné použití jednoho čísla pro dvě role vytvoří pravidlo, které vypadá správně a trefí špatné pakety. Výchozí záznam tabulky také potřebuje via s bránou LAN na běžném Ethernet spoji; holý dev eth0 funguje jen tehdy, když je rozhraní bod-bod nebo se další skok vyřeší jinak. Hlášený hostitel Jessie náhodou seděl na spoji, kde holý tvar fungoval, což není distribuční pravidlo ke kopírování.

Ověřte, aniž byste se uzamkli venku

Netestujte odpojením. Nechte první relaci otevřenou, zvedněte tunel a zeptejte se jádra, kterou cestou by šla vaše vlastní adresa:

ip route get 80.128.240.55

Odpověď by měla jmenovat fyzické rozhraní a starou bránu, ne tunel. Pak otevřete druhé SSH spojení; to je skutečný test, protože stará relace může přežít na stavu, který nové spojení nedokáže reprodukovat. Pokud druhé zamrzne, zatímco první ještě odpovídá, pravidlo nikdy netrefilo provoz, na kterém záleží, a hledat je třeba ve značkách nebo ve zdrojové adrese.

Po celou dobu mějte po ruce konzoli mimo pásmo. Server, jehož jediná cesta přístupu je tunel, který jste právě rozbili, nelze opravit přes ten tunel, a návrat je snazší, když máte zapsaná čísla tabulek a prefixy, které jste přidali.

Související články