Obchvat cgroup v nftables potřebuje i opravu zdrojové adresy
Označení jednoho cgroup jej pošle do jiné tabulky a socket si ponechá adresu, kterou už měl. Klasifikace, směrování a překlad jako tři samostatné kroky.
Označit provoz z jednoho cgroup je ta snadná část. Tři samostatná rozhodnutí se musí sejít, než jedna aplikace vyjde přes fyzické rozhraní, zatímco všechno ostatní zůstane v tunelu: který socket patří výjimce, které hledání trasy značka spustí a jakou zdrojovou adresu paket nese, když vychází. Většina neúspěšných pokusů trefí první, napůl trefí druhé a na třetí se nikdy nepodívá.
Tři rozhodnutí, ne jedno
Klasifikace odpovídá, kdo je vyňat. Směrování odpovídá, kam místo toho označený paket jde. Volba zdroje odpovídá, co uvidí vzdálená strana a kam se má odpověď vrátit.
Selhávají nezávisle. Paket může být klasifikován, přesměrován na fyzické rozhraní a přesto nést privátní adresu, kterou žádný nadřazený router nedokáže vrátit, což vytvoří timeout, jenž vypadá přesně jako blokace firewallem. Nic v kroku klasifikace na to neupozorní. Nic ani v kroku směrování.
Záleží i na pořadí. Klasifikace probíhá při vzniku paketu, směrování potom a překlad v místě výstupu.
Pokud nedokážete pojmenovat, která ze tří fází je rozbitá, neladíte, ale přeskládáváte pravidla a doufáte.
Párujte cgroup, které bude existovat i zítra
nftables umí otestovat členství socketu v cgroup v2, což je opravdu užitečné, protože sleduje proces, ne cíl. Háček je identifikátor. Desktopová aplikace spuštěná z nabídky často žije v přechodném scope, jehož název se při dalším spuštění změní.
nft list ruleset
systemctl status session.slice 2>/dev/null
cat /proc/self/cgroupZkopírovat název scope z jedné relace a natvrdo ho zadat vytvoří pravidlo, které dnes funguje a zítra tiše přestane odpovídat. Umístěte aplikaci raději do záměrně stabilního kontextu spouštění, například do vyhrazeného scope nebo unit, který ovládáte, a párujte s ním. Pravidlo pak přežije restarty i aktualizace balíčků. Také se stane něčím, o čem kolega může uvažovat bez vaší historie relací.
Buďte také přesní v tom, který mechanismus používáte. Klasifikace net_cls v cgroup v1 a párování socketu v cgroup v2 jsou rozdílné věci a pole s podobným názvem v dokumentaci je nečiní zaměnitelnými.
Druhé hledání spouští řetěz typu route
U lokálně generovaného provozu typ řetězu rozhoduje, zda se po nastavení značky něco stane. Výstupní řetěz typu filter může paket označit a jádro bude dál používat trasu, kterou už zvolilo. Řetěz typu route je mechanismus, který si vyžádá nové hledání.
table inet bypass {
chain mark {
type route hook output priority mangle; policy accept;
socket cgroupv2 level 2 "app.slice" meta mark set 0x1 comment "app bypass"
}
}
ip rule add fwmark 0x1 lookup 200
ip route add default via 203.0.113.1 dev wlan0 table 200Značka pak potřebuje pravidlo politiky, které ji pošle do tabulky, a ta tabulka musí být úplná: výchozí trasa, všechna lokální cíle, které aplikace ještě potřebuje, a nadřazená brána, která skutečně odpovídá.
Hodnotu značky volíte záměrně. WireGuard používá vlastní fwmark pro vnější transportní provoz a náhodné přistání na stejném čísle může narušit vlastní výjimku směrování tunelu způsoby, které se bolestivě diagnostikují.
Zdrojová adresa trasu nenásleduje
Socket, který už pro cestu tunelem zvolil zdrojovou adresu, si ji po přesměrování ponechá. Nic ve změně směrování ji nepřepisuje, a proto paket opouští fyzické rozhraní s privátním zdrojem, který nadřazená síť nedokáže vrátit.
Viditelným symptomem je aplikace, která vypadá, že posílá data, a nikdy nedostane odpověď, a log firewallu, který nic neukazuje, protože paket se nikdy nevrátil.
Úzká oprava je pravidlo překladu zdroje omezené na značku této aplikace a její skutečné výstupní rozhraní, začleněné do existujícího NAT místo jeho nahrazení:
table inet bypass {
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
meta mark 0x1 oifname "wlan0" masquerade
}
}Překládejte výjimku a nic jiného. Paušální pravidlo masquerade opraví symptom a zničí vaši schopnost říct, který provoz šel kterou cestou. Párujte značku, skutečné výstupní rozhraní a pokud možno vlastní adresu aplikace. Široká pravidla se snadno píšou a téměř nedají později auditovat.
Co stále uniká výjimce
Překlad názvů může přicházet ze samostatného procesu resolveru v jiném cgroup, takže klasifikace socketu prohlížeče neklasifikuje jeho dotazy. Pokud dotazy resolveru zůstanou v tunelu, zatímco spojení vychází mimo něj, odpovědi split-horizon nemusí odpovídat cestě. Tento nesoulad vytváří selhání, která vypadají jako chyby DNS, ale nejsou.
Podřízené procesy dědí cgroup ve většině nastavení, ale pomocník, který se přesune do vlastního scope, ne. Ověřujte místo předpokládání, zejména u všeho, co se znovu spouští.
Nakonec rozhodněte, co se má stát, když je tunel mimo provoz. Výjimka, která se tiše změní v úplný obchvat, je jiný bezpečnostní postoj než ta, která selže zavřená, a jen jedna z nich je to, co jste mysleli.