Kill-Switch blockiert nur IPv4: Warum IPv6 trotzdem entweicht
Ein Firewall-Regelsatz für IPv4 sagt nichts über IPv6 aus. Auf einem Dual-Stack-Gerät kann der Tunnel ausfallen, während eine App einen funktionierenden Weg daran vorbei behält.
Der Tunnel fällt aus, der Kill-Switch meldet, dass er gegriffen hat, und ein Download läuft weiter. An den IPv4-Regeln ist nichts kaputt. Die Anwendung ist einfach auf einen Weg ausgewichen, für den diese Regeln nie geschrieben wurden.
Dual-Stack-Geräte haben zwei unabhängige Wege nach draußen. Eine Sperre für einen davon ist eine halbe Sperre.
Zwei Regelsätze, zwei Voreinstellungen
Unter Linux sind iptables und ip6tables getrennte Tabellen mit getrennten Richtlinien. Die Ketten INPUT und OUTPUT der IPv4-Tabelle auf DROP zu setzen, ändert nichts an der IPv6-Tabelle, in der die Voreinstellung normalerweise ACCEPT ist. Dieselbe Aufteilung gibt es in nftables, wo man eine Familie prüfen und feststellen kann, dass nur eine von ihnen die eigenen Regeln trägt. Diese Asymmetrie ist normal, und sie ist das ganze Problem.
Deshalb kann ein Kill-Switch gründlich aussehen und sich nur teilweise verhalten. Das Skript, das die IPv4-Regeln geschrieben hat, lief, die Zähler steigen, die Logzeile erscheint, und ein IPv6-Paket verlässt die physische Schnittstelle völlig unberührt.
Lies, was dein Client tatsächlich installiert, statt was die Marketeseite verspricht. Manche Clients leiten IPv6 in den Tunnel, manche blockieren es bewusst, und manche lassen es in Ruhe, während eine Sperre auf Plattformebene eine andere Regel durchsetzt. Die Herstellerdokumentation ist hier die einzige Quelle, der man trauen sollte.
Was die Schnittstellenkonfiguration dir verrät
Die Handbuchseite von wg-quick enthält IPv6-Regeln in ihrer Beispielkonfiguration, und der Grund ist genau diese Lücke. Das Beispiel ist keine Dekoration. Es existiert, weil die IPv4-Regeln allein die zweite Familie offen lassen würden.
Die Hälfte eines Beispiels zu kopieren, ergibt die Hälfte einer Richtlinie. Das ist der häufigste Ursprung dieses Lecks. Ein Blogbeitrag kürzte das Beispiel der Länge wegen. Die gekürzte Fassung wurde dann zur Vorlage, die alle wiederverwendeten.
# what is actually installed, per family?
sudo iptables -S OUTPUT | head -20
sudo ip6tables -S OUTPUT | head -20
# nftables: inspect each family separately
sudo nft list ruleset inet | head -40
# does this host even have a usable IPv6 path?
ip -6 route show default
Wenn der zweite Befehl eine erlaubende Richtlinie ausgibt, während der erste DROP ausgibt, hast du die Antwort gefunden, ohne den Client anzufassen. Diese Asymmetrie ist der Fehler.
Warum eine einzelne Abfrage nicht die ganze Geschichte ist
Ein einzelner Name kann sowohl einen A-Record als auch einen AAAA-Record zurückgeben, und Anwendungen wählen nicht alle gleich. Ein Browser kann IPv6 bevorzugen, wenn das Netz es anbietet, und bei einem Fehler zurückfallen, während eine Hintergrundsynchronisierung oder ein Updater seinen eigenen Resolver und seine eigene Präferenz verwendet. Ein erfolgreicher Test über IPv4 beweist daher einen Weg, nicht die Richtlinie.
Netzwerkwechsel ändern die Antwort ebenfalls. Der Beitritt zu einem anderen Wi-Fi-Netz, das Aufwachen aus dem Ruhezustand oder der Wechsel zu Mobilfunk kann dem Gerät ein neues IPv6-Präfix geben, und die Richtlinie, die im Büro-LAN ausreichend aussah, deckt es möglicherweise nicht ab.
Teste den Zustand, in dem der Tunnel aus ist
Ein Test im verbundenen Zustand sagt dir, dass der Tunnel funktioniert. Der interessante Test ist der nicht verfügbare Zustand, denn dann soll der Kill-Switch halten. Stoppe den Tunnel absichtlich und probiere dann die Ziele, auf die es ankommt, aus der App heraus, die du schützt.
# with the tunnel stopped, does anything still leave?
ip -6 route get 2606:4700:4700::1111
curl -6 -sS -o /dev/null -w '%{http_code}\n' --max-time 5 https://ipv6.example.net/
curl -4 -sS -o /dev/null -w '%{http_code}\n' --max-time 5 https://ipv4.example.net/
Beide Familien sollten geschlossen scheitern. Wenn die IPv4-Anfrage abläuft und die IPv6-Anfrage einen Statuscode zurückgibt, ist die Richtlinie unvollständig, und kein noch so häufiges erneutes Testen des Tunnels ändert das.
Behalte auch die dokumentierten Ausnahmen in diesem Test. Die lokale Netzwerkerkennung, eine DHCP-Erneuerung oder der Bootstrap-Pfad zum VPN-Endpunkt müssen möglicherweise erreichbar bleiben, und diese Ausnahmen sollten in der Richtlinie benannt werden, statt während eines Ausfalls entdeckt zu werden. Ein Leck-Test, der scheitert, weil der Tunnel nicht wieder hochkommt, ist kein Sicherheitsbefund, sondern ein Konnektivitätsbefund.