Jemand bittet darum, dass der Browser den Tunnel benutzt, und die Antwort kommt als Firewall-Regel zurück, die auf die Zielports 80 und 443 passt. Sie wirkt präzise und ist es nicht. Ein Port-Treffer wählt Pakete anhand ihres Transport-Headers aus, nicht danach, welches Programm den Socket geöffnet hat, und modernes Browsen beschränkt sich nicht auf diese beiden Ports über TCP. Die Regel wird Verkehr verpassen, den Sie einbeziehen wollten, und Verkehr einfangen, den Sie nie anfassen wollten. Entscheiden Sie vor dem Schreiben, welche von drei verschiedenen Grenzen Sie eigentlich wollen.

Die Regel beschreibt eine Transportklasse, keine Anwendung

Unter Linux prüft ein Zielport-Treffer den TCP-Header und nichts darüber. Diese Pakete zu markieren und mit einer Policy-Route zu lenken, funktioniert genau wie dokumentiert, und keine dieser Maschinerien weiß, was die Nutzlast bedeutet oder welcher Prozess sie gesendet hat. Die Marke ist eine Nummer am Paket, keine Identität an einer Anwendung.

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

Zwei Folgen sind sofort klar. Ein Software-Updater, der TCP 443 kontaktiert, wird genauso behandelt wie der Browser, was in Ordnung sein kann oder ein Ausfall, der auf den nächsten Update-Zyklus wartet. Und ein Webdienst, der bewusst auf einem anderen Port veröffentlicht ist, sagen wir 8443, fällt völlig aus der Regel, obwohl er weiterhin der Webverkehr ist, um den es dem Nutzer ging.

Die Zahlen sind legitime Selektoren, wenn die Anforderung wirklich diese Ports betrifft. Sie werden zur Fiktion, wenn im Ticket „Browser“ steht und im Regelsatz ein Portbereich umgesetzt wird. Diese Lücke ist keine Dokumentationsspitzfindigkeit. Sie ist der Unterschied zwischen einer Regel, die Sie in einem Review verteidigen können, und einer, die niemand testen kann.

HTTP/3 verlässt still Ihre TCP-Regel

HTTP/3 läuft über QUIC, und QUIC wird in UDP übertragen. Eine Regel, die nur TCP trifft, kann es nicht sehen, also kann derselbe Browser, der Ihre Testseite erfüllt, eine spätere Anfrage über UDP senden und den Tunnel umgehen, ohne dass jemand eine Einstellung ändert. RFC 9114 beschreibt HTTP/3 als QUIC-basiertes Protokoll, und QUIC verwendet UDP mit dem Standardport 443 im üblichen Deployment.

Ob ein bestimmter Browser HTTP/3 versucht, hängt von seiner Konfiguration, von der Seite und davon ab, ob ein früherer Versuch erfolgreich war. Das macht es zu einer schlechten Sache, aus dem Gedächtnis darüber zu argumentieren. Fragen Sie stattdessen das Werkzeug:

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

Die curl-Zeile gibt die ausgehandelte Version aus, ein 3 bestätigt also, dass der UDP-Weg benutzt wurde. Die Socket-Auflistung zeigt dann, ob diese Verbindung an die Tunnelschnittstelle oder an die physische gebunden ist. Wenn HTTP/3 in Ihrem curl-Build nicht verfügbar ist, scheitert das Flag laut, statt still zurückzufallen, was seine eigene kleine Gnade ist.

DNS ist eine eigene Entscheidung, die Sie treffen müssen

Eine Portregel für Webverkehr sagt nichts über Namensauflösung. Der Browser kann den System-Resolver nutzen, einen im Browser konfigurierten Resolver oder einen, den die letzte Verbindung hineingeschoben hat. Jeder davon kann Anfragen über einen anderen Weg senden als den, den Ihre Regel auswählt, was die klassische Spaltung erzeugt: Die Seite lädt, der Name wird irgendwo aufgelöst, wo Sie es nicht erwartet haben, und die interne Seite löst auf eine öffentliche Adresse auf oder gar nicht.

Entscheiden Sie es ausdrücklich. Wenn interne Namen durch den Tunnel aufgelöst werden müssen, muss der Resolver darin liegen, und der Regelsatz muss DNS zu diesem Resolver erlauben, während andere Anfragen draußen bleiben. Wenn der Browser DNS over HTTPS zu einem öffentlichen Anbieter nutzt, umgeht die Anfrage Ihren Resolver vollständig, und die Portregel kann nicht helfen. Schreiben Sie die Wahl in denselben Änderungsdatensatz wie die Routingregel, denn beide werden zusammen von dem gelesen, der den nächsten Fehler debuggt.

Prüfen Sie es dann mit dem Resolver statt mit der Seite:

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

Eine fehlende Antwort ist ein Auflösungsproblem, auch wenn die Fehlermeldung des Browsers das Netzwerk beschuldigt. Diese beiden Fehler sehen für einen Nutzer identisch aus und sind völlig verschiedene Tickets.

Drei Grenzen, drei verschiedene Mechanismen

Der meiste Wirrwarr verschwindet, sobald Sie die Grenze benennen, die Sie wollen. Sie sind nicht austauschbar, und jede hat während eines Tunnelausfalls einen anderen Fehlermodus.

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

Ein separates Browserprofil ist die Falle in der mittleren Zeile. Es trennt Cookies und Verlauf und ändert nichts an der Routing-Tabelle des Hosts, also nehmen beide Profile denselben Weg. Isolation erfordert etwas, das der Kernel durchsetzt, also einen Namespace, einen Container oder eine Anwendung, die ihre eigene Tunnelschnittstelle besitzt.

Welche Zeile auch zutrifft, schreiben Sie auf, was passieren soll, wenn der Tunnel wegfällt. Eine markenbasierte Route, die mit der Schnittstelle verschwindet, fällt meist auf die physische Standardroute zurück, was Fail-open-Verhalten ist. Das mag fürs Browsen akzeptabel und für alles andere unakzeptabel sein, und es ist eine Entscheidung, kein Implementierungsdetail.

Testen Sie die Ströme, die Sie abzudecken behaupten

Der Abnahmetest muss der Grenze folgen, die Sie aufgeschrieben haben, nicht den Portnummern, die bequem waren. Wählen Sie einen Strom, der durch den Tunnel muss, einen, der nicht darf, und einen, der einen Transport nutzt, an den Sie nicht gedacht haben:

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'

Die Routenabfrage sagt Ihnen, welche Schnittstelle ein Ziel tatsächlich nutzt, und das ist die Tatsache, die die meisten Berichte falsch angeben. Die curl-Zeile bestätigt die ausgehandelte Version und die Adressfamilie. Der Regelsatz-Dump fängt die Regel, die Sie beim Testen hinzugefügt und nicht eingegrenzt haben, und so wird aus einer temporären Marke dauerhaftes Fail-open-Routing.

Halten Sie alle drei Ausgaben mit einem Zeitstempel fest und bewahren Sie sie mit der Änderung auf. Wenn später jemand meldet, „das VPN hat das Intranet kaputt gemacht“, wird der Unterschied zwischen der beabsichtigten und der umgesetzten Grenze in diesem Datensatz sichtbar, und die Lösung wird eine Regeländerung sein statt einer Diskussion.

Ähnliche Artikel