Pravidla pro porty 80 a 443 nepošlou prohlížeč přes VPN
Shoda portu vybírá TCP toky, ne prohlížeč. HTTP/3 běží po UDP, DNS může jít jinou cestou a aktualizátor odpovídá stejnému pravidlu, které jste napsali.
Někdo požádá, aby prohlížeč používal tunel, a zpět přijde pravidlo firewallu odpovídající cílovým portům 80 a 443. Vypadá přesně a přesné není. Shoda portu vybírá pakety podle jejich transportní hlavičky, ne podle toho, který program otevřel socket, a moderní prohlížení se na TCP neomezuje na tyto dva porty. Pravidlo mine část provozu, který jste chtěli zahrnout, a zachytí provoz, který jste nikdy nechtěli zasáhnout. Než ho napíšete, rozhodněte, kterou ze tří různých hranic vlastně chcete.
Pravidlo popisuje třídu transportu, ne aplikaci
V Linuxu shoda cílového portu zkoumá TCP hlavičku a nic nad ní. Označení těchto paketů a jejich přesměrování pomocí politické trasy funguje přesně tak, jak je dokumentováno, a žádný z těchto mechanismů neví, co užitečné zatížení znamená ani který proces ho odeslal. Značka je číslo připojené k paketu, ne identita připojená k aplikaci.
nft add rule inet mangle output tcp dport { 80, 443 } meta mark set 0x1
ip rule add fwmark 0x1 table 100
ip route add default dev wg0 table 100
Okamžitě plynou dva důsledky. Aktualizátor softwaru, který kontaktuje TCP 443, dostane stejné zacházení jako prohlížeč, což může být v pořádku nebo to může být výpadek čekající na další cyklus aktualizace. A webová služba záměrně publikovaná na jiném portu, řekněme 8443, zcela vypadává z pravidla, i když je to stále webový provoz, na kterém uživateli záleželo.
Čísla jsou legitimní selektory, když se požadavek skutečně týká těchto portů. Stanou se fikcí, když je v tiketu napsán „prohlížeč“ a v sadě pravidel je implementován rozsah portů. Ta mezera není dokumentační drobnost. Je to rozdíl mezi pravidlem, které obhájíte při revizi, a takovým, které nikdo nedokáže otestovat.
HTTP/3 tiše opouští vaše TCP pravidlo
HTTP/3 běží nad QUIC a QUIC se přenáší v UDP. Pravidlo, které odpovídá jen TCP, ho nevidí, takže stejný prohlížeč, který projde vaší testovací stránkou, může pozdější požadavek odeslat přes UDP a obejít tunel, aniž by kdokoli změnil nastavení. RFC 9114 popisuje HTTP/3 jako protokol založený na QUIC a QUIC používá UDP s výchozím portem 443 v obvyklém nasazení.
Zda daný prohlížeč zkusí HTTP/3, závisí na jeho konfiguraci, na webu a na tom, zda předchozí pokus uspěl. Proto je špatné o tom uvažovat po paměti. Zeptejte se raději nástroje:
curl --http3 -sS -o /dev/null -w '%{http_version} %{time_total}\n' https://example.com
ss -tunp | grep -E ':443\b'
Řádek curl vypíše vyjednanou verzi, takže 3 potvrzuje, že byla použita cesta přes UDP. Výpis socketů pak ukáže, zda je toto spojení vázáno na rozhraní tunelu, nebo na fyzické. Pokud HTTP/3 ve vašem sestavení curl není, přepínač hlasitě selže místo tichého návratu, což je jeho vlastní malé milosrdenství.
DNS je samostatné rozhodnutí, které musíte udělat
Pravidlo portu pro webový provoz neříká nic o překladu jmen. Prohlížeč může použít systémový resolver, resolver nakonfigurovaný uvnitř prohlížeče nebo ten, který protlačilo poslední připojení. Každý z nich může posílat dotazy jinou cestou, než kterou vybírá vaše pravidlo, což vytváří klasické rozdvojení: stránka se načte, jméno se přeloží někde, kde jste to nečekali, a interní web se přeloží na veřejnou adresu, nebo vůbec.
Rozhodněte to výslovně. Pokud se interní jména musí překládat přes tunel, resolver musí být uvnitř něj a sada pravidel musí povolit DNS k tomuto resolveru a ostatní dotazy držet venku. Pokud prohlížeč používá DNS over HTTPS k veřejnému poskytovateli, dotaz zcela obchází váš resolver a pravidlo portu nemůže pomoci. Zapište volbu do stejného záznamu o změně jako pravidlo směrování, protože obojí čte společně ten, kdo bude ladit příští selhání.
Poté ověřte resolverem, ne stránkou:
resolvectl query intranet.example.internal
resolvectl status | grep -A3 'Current DNS Server'
Chybějící odpověď je problém překladu, i když chybová zpráva prohlížeče viní síť. Tato dvě selhání vypadají pro uživatele stejně a jsou to zcela různé tikety.
Tři hranice, tři různé mechanismy
Většina zmatku zmizí, jakmile pojmenujete hranici, kterou chcete. Nejsou zaměnitelné a každá má jiný způsob selhání při výpadku tunelu.
| What you actually want | Mechanism that fits | What it does not cover |
|---|---|---|
| These transport ports use this exit | Firewall mark plus policy route | Applications, HTTP/3 over UDP, DNS |
| This browsing session stays separate | Application-aware VPN, or a separate network namespace plus a proxy | Other applications in the same session |
| Only these private sites are reachable | Destination-based routes with private DNS | Public sites on the same address family |
Samostatný profil prohlížeče je pastí prostředního řádku. Odděluje cookies a historii a nic nemění na směrovací tabulce hostitele, takže oba profily jdou stejnou cestou. Izolace vyžaduje něco, co vynutí jádro, tedy jmenný prostor, kontejner nebo aplikaci, která vlastní vlastní rozhraní tunelu.
Ať platí kterýkoli řádek, zapište, co se má stát, když tunel spadne. Trasa založená na značce, která zmizí s rozhraním, obvykle spadne zpět na fyzickou výchozí trasu, což je chování fail-open. To může být přijatelné pro prohlížení a nepřijatelné pro cokoli jiného, a je to rozhodnutí, ne detail implementace.
Otestujte toky, o kterých tvrdíte, že je pokrýváte
Přejímací test musí sledovat hranici, kterou jste zapsali, ne čísla portů, která byla pohodlná. Vyberte jeden tok, který musí jít tunelem, jeden, který nesmí, a jeden, který používá transport, na který jste nemysleli:
ip route get 203.0.113.40
curl -sS -o /dev/null -w 'v4 %{http_version} %{remote_ip}\n' https://example.com
nft list ruleset | grep -A2 'dport'
Vyhledání trasy vám řekne, které rozhraní cíl skutečně používá, a to je fakt, který většina zpráv plete. Řádek curl potvrdí vyjednanou verzi a rodinu adres. Výpis sady pravidel zachytí pravidlo, které jste přidali při testování a zapomněli omezit, a tak se z dočasné značky stane trvalé fail-open směrování.
Zaznamenejte všechny tři výstupy s časovým razítkem a uchovejte je u změny. Když někdo později nahlásí, že „VPN rozbila intranet“, rozdíl mezi zamýšlenou a implementovanou hranicí bude v tom záznamu vidět a oprava bude změnou pravidla, ne hádkou.