Tři přeskoky WireGuardu dosáhnou sítě bez veřejné adresy a potom prostřední stroj přestane odpovídat na portu, na kterém měl poslouchat. Tunel dál funguje, vzdálený hostitel stále odpovídá a jen prostřední server sám zvenčí ztichl. Tahle kombinace mate právě proto, že je sama sobě způsobena: prostřední přeskok poslouchá svou vlastní routovací tabulku a tabulka posílá jeho odpovědi špatným směrem.

Řetěz, který funguje, dokud nepromluvíte s prostřední krabicí

Vezměte ilustrativní řetěz: klient A dosáhne serveru B přes UDP 500 a B pokračuje dál na server C přes UDP 500. C přijímá provoz jen z adresy svého jediného protějšku, což z něj dělá list a udržuje jeho chování jednoduché. B není list a všechno zajímavé na téhle poruše se děje právě tam.

Rozdíl je důležitý, protože role listu a prostředku táhnou opačnými směry. List může poslat všechno do jednoho tunelu bez následků, protože na něm nic dalšího nezávisí. Prostřední přeskok je zároveň koncovým bodem pro klienty a klientem směrem k vzdálené straně a ty dvě práce chtějí jiné routování.

Proč odpověď odchází tunelem

Na B nese rozhraní obrácené k C AllowedIPs = 0.0.0.0/0 spolu s odpovídající výchozí trasou. Každý paket, který B vytvoří, proto jde do toho tunelu, pokud nepřeváží něco konkrétnějšího.

Paket z A adresovaný B dorazí a je přijat, protože B je cílem a místní doručení probíhá první. Odpověď je zbrusu nový lokálně vytvořený paket namířený na veřejnou adresu A a tento cíl odpovídá výchozí trase do tunelu. C ho obdrží, nevlastní tu adresu a zahodí ho.

Příznak vypadá jako problém firewallu nebo neshoda klíčů, a tady není pravda ani jedno. Zachycení na tunelu směrem k C ukazuje, že odpovědi míří špatným směrem. To jediné pozorování ušetří víc času než jakékoli čtení konfigurace, tak si ho zapište, než začnete měnit klíče. Kdokoli zachycení neviděl, bude předpokládat, že je rozbitý samotný tunel.

Úzká oprava: pravidla politiky, která odpovídají zdrojovému portu

Odpovědi z naslouchajícího socketu B odcházejí se zdrojovým portem 500. Pravidlo politiky na to může zareagovat a poslat ty pakety zpět do běžné tabulky:

ip rule add sport 500 table main priority 100
ip rule add sport 8080 table main priority 101

Pravidla politiky se procházejí v pořadí priority a hlavní tabulka je na 32766, takže pravidlo na 100 se ptá dřív, než se výchozí trasa tunelu dostane ke slovu. Přidejte jeden záznam pro každý port, který musí zůstat dostupný zvenčí, a nic víc, aby přeposílaný provoz dál používal tunel, pro který byl postaven.

Znejte hranici tohoto triku. Selektor sport odpovídá lokálně vytvořeným paketům, což pokrývá přesně případ odpovědi a záměrně nepokrývá provoz, který B jen přeposílá za někoho jiného. Služba hostovaná za B stále potřebuje svou vlastní odpověď a předstírání opaku dává opravu, která funguje pro první službu a selhává pro druhou.

Dejte pravidlu vlastníka

Pravidlo napsané do promptu zmizí při příštím přestavění rozhraní. V nastavení WireGuardu ho umístěte tam, kde se rozhraní vytváří a odstraňuje:

PostUp = ip rule add sport 500 table main priority 100
PostDown = ip rule del sport 500 table main priority 100

Jestliže rozhraní vlastní NetworkManager, distribuční hook nebo vstupní bod kontejneru, patří dvojice tomu vlastníkovi, a ne ručně upravovanému souboru. Zkontrolujte platná pravidla po opětovném připojení, ne jen po prvním startu, protože první start je případ, který funguje vždycky.

Porovnejte alternativy poctivě

Pravidlo zdrojového portu je jedna ze čtyř cest ven a je ta nejužší. Má výhodu, že se tunelové politiky vůbec nedotýká, a proto obvykle přežije pozdější změny. Úzké opravy také hlasitě selhávají, když přestanou platit, zatímco široká výjimka dál tiše funguje dlouho poté, co důvod zmizel. Ten rozdíl je důležitější než elegance, když krabici za dva roky vlastní někdo jiný.

ApproachWhat it costsWhere it breaks
Source-port policy ruleOne rule per exposed portAnything B forwards rather than originates
Destination exception routeA route pinned to specific client addressesClients whose address changes
Stop full-tunnelling on BLoses the catch-all path toward CDesigns that depend on it
Split into two tunnelsMore interfaces and more policyNothing, at the cost of complexity

Po volbě ověřte z obou konců. Z A zahajte spojení na port B a chvíli ho držte zaneprázdněné. Na B přinuťte jádro, aby odůvodnilo cestu odpovědi něčím jako ip route get <address-of-A> sport 500, a potvrďte, že uvádí rozhraní WAN, a ne tunel. Poté zkontrolujte, že něco za C stále odpovídá přes řetěz, což dokazuje, že výjimka zůstala úzká, místo aby se proměnila v obchvat. Nakonec zapište porty do návrhových poznámek, jinak to příští operátor znovu objeví u jiné služby.

Související články