Cineva cere ca browserul să folosească tunelul, iar răspunsul vine ca o regulă de firewall care se potrivește cu porturile de destinație 80 și 443. Pare precisă și nu este. O potrivire de port selectează pachetele după antetul de transport, nu după programul care a deschis socketul, iar navigarea modernă nu se limitează la acele două porturi pe TCP. Regula va rata o parte din traficul pe care voiați să îl includeți și va prinde trafic pe care nu intenționați niciodată să îl atingeți. Înainte de a o scrie, decideți care dintre trei granițe diferite o vreți de fapt.

Regula descrie o clasă de transport, nu o aplicație

Pe Linux, o potrivire de port de destinație inspectează antetul TCP și nimic deasupra lui. Marcarea acelor pachete și dirijarea lor cu o rută de politică funcționează exact cum este documentat, iar niciuna dintre aceste mecanisme nu știe ce înseamnă încărcătura sau ce proces a trimis-o. Marcajul este un număr atașat unui pachet, nu o identitate atașată unei aplicații.

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

Urmează imediat două consecințe. Un actualizator de software care contactează TCP 443 primește același tratament ca browserul, ceea ce poate fi în regulă sau poate fi o întrerupere care așteaptă următorul ciclu de actualizare. Iar un serviciu web publicat intenționat pe alt port, să zicem 8443, iese complet din regulă deși este încă traficul web de care îi păsa utilizatorului.

Numerele sunt selectori legitimi când cerința este într-adevăr despre acele porturi. Devin ficțiune când în ticket scrie „browser” și în setul de reguli se implementează un interval de porturi. Acel decalaj nu este un detaliu de documentație. Este diferența dintre o regulă pe care o puteți apăra într-o revizuire și una pe care nimeni nu o poate testa.

HTTP/3 părăsește în liniște regula dumneavoastră TCP

HTTP/3 rulează peste QUIC, iar QUIC este transportat în UDP. O regulă care se potrivește doar cu TCP nu îl poate vedea, așa că același browser care trece pagina de test poate trimite o cerere ulterioară prin UDP și ocoli tunelul fără ca cineva să schimbe o setare. RFC 9114 descrie HTTP/3 ca un protocol bazat pe QUIC, iar QUIC folosește UDP cu portul implicit 443 în implementarea obișnuită.

Dacă un anumit browser încearcă HTTP/3 depinde de configurația lui, de site și de dacă o încercare anterioară a reușit. Asta îl face un lucru prost pentru raționament din memorie. Întrebați instrumentul:

curl --http3 -sS -o /dev/null -w '%{http_version} %{time_total}\n' https://example.com
ss -tunp | grep -E ':443\b'

Linia curl afișează versiunea negociată, deci un 3 confirmă că a fost folosită calea UDP. Lista de socketuri arată apoi dacă acea conexiune este legată de interfața tunelului sau de cea fizică. Dacă HTTP/3 nu este disponibil în build-ul dumneavoastră de curl, indicatorul eșuează zgomotos în loc să se retragă în liniște, ceea ce este mica lui îndurare.

DNS este o decizie separată pe care trebuie să o luați

O regulă de port pentru trafic web nu spune nimic despre rezolvarea numelor. Browserul poate folosi resolverul sistemului, un resolver configurat în interiorul browserului sau unul împins de ultima conexiune. Fiecare dintre ele poate trimite interogări pe o cale diferită de cea pe care o selectează regula dumneavoastră, ceea ce produce scindarea clasică: pagina se încarcă, numele se rezolvă într-un loc în care nu vă așteptați, iar site-ul intern se rezolvă la o adresă publică sau deloc.

Decideți explicit. Dacă numele interne trebuie rezolvate prin tunel, resolverul trebuie să fie în interiorul lui, iar setul de reguli trebuie să permită DNS către acel resolver ținând celelalte interogări afară. Dacă browserul folosește DNS over HTTPS către un furnizor public, interogarea ocolește complet resolverul dumneavoastră și regula de port nu poate ajuta. Scrieți alegerea în același registru de modificare ca regula de rutare, pentru că ambele sunt citite împreună de cel care va depana următoarea defecțiune.

Apoi verificați cu resolverul, nu cu pagina:

resolvectl query intranet.example.internal
resolvectl status | grep -A3 'Current DNS Server'

Un răspuns lipsă este o problemă de rezolvare chiar și când mesajul de eroare al browserului dă vina pe rețea. Aceste două defecțiuni arată identic pentru utilizator și sunt tichete complet diferite.

Trei granițe, trei mecanisme diferite

Cea mai mare parte a confuziei dispare de îndată ce numiți granița pe care o vreți. Ele nu sunt interschimbabile, iar fiecare are un mod de eșec diferit în timpul unei întreruperi a tunelului.

What you actually wantMechanism that fitsWhat it does not cover
These transport ports use this exitFirewall mark plus policy routeApplications, HTTP/3 over UDP, DNS
This browsing session stays separateApplication-aware VPN, or a separate network namespace plus a proxyOther applications in the same session
Only these private sites are reachableDestination-based routes with private DNSPublic sites on the same address family

Un profil de browser separat este capcana din rândul din mijloc. El separă cookie-urile și istoricul și nu schimbă nimic în tabela de rutare a hostului, așa că ambele profiluri iau aceeași cale. Izolarea cere ceva ce impune nucleul, adică un spațiu de nume, un container sau o aplicație care are propria interfață de tunel.

Orice rând s-ar aplica, scrieți ce trebuie să se întâmple când tunelul cade. O rută bazată pe marcaj care dispare cu interfața revine de obicei la ruta implicită fizică, ceea ce este comportament fail-open. Asta poate fi acceptabil pentru navigare și inacceptabil pentru orice altceva, iar asta este o decizie, nu un detaliu de implementare.

Testați fluxurile pe care pretindeți că le acoperiți

Testul de acceptare trebuie să urmeze granița pe care ați scris-o, nu numerele de port care erau convenabile. Alegeți un flux care trebuie să treacă prin tunel, unul care nu trebuie și unul care folosește un transport la care nu v-ați gândit:

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'

Interogarea de rută vă spune ce interfață folosește de fapt o destinație, iar acesta este faptul pe care majoritatea rapoartelor îl greșesc. Linia curl confirmă versiunea negociată și familia de adrese. Descărcarea setului de reguli prinde regula pe care ați adăugat-o în timpul testării și ați uitat să o delimitați, și așa un marcaj temporar devine rutare fail-open permanentă.

Înregistrați toate cele trei ieșiri cu un marcaj de timp și păstrați-le împreună cu modificarea. Când mai târziu cineva raportează că „VPN-ul a stricat intranetul”, diferența dintre granița intenționată și cea implementată va fi vizibilă în acel registru, iar remedierea va fi o schimbare de regulă, nu o dezbatere.

Articole similare