Vnořený WireGuard: prostřední přeskok neumí odpovědět na svůj vlastní port
Když prostřední přeskok posílá všechno do jednoho tunelu, odpovědi na jeho příchozí službu odcházejí špatnou cestou. Pravidlo zdrojového portu na rozhraní to opraví.
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ý.
| Approach | What it costs | Where it breaks |
|---|---|---|
| Source-port policy rule | One rule per exposed port | Anything B forwards rather than originates |
| Destination exception route | A route pinned to specific client addresses | Clients whose address changes |
| Stop full-tunnelling on B | Loses the catch-all path toward C | Designs that depend on it |
| Split into two tunnels | More interfaces and more policy | Nothing, 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.