Die Einstellung sieht wie ein Schalter pro Anwendung aus, also binden Leute den Client an das WireGuard-Interface und erwarten, dass nur dieser Client den Tunnel nutzt. Tatsächlich wählt das Binden eine Quelladresse. Der Kernel sucht dann eine Route zum Ziel, findet die gewöhnliche Standardroute und schickt das Paket mit angehängter Tunneladresse über den physischen Link hinaus. Nur eine für diese Quelladresse gewählte Route erfüllt die Absicht.

Der Mechanismus hat zwei Hälften: eine Routing-Tabelle, die nur der Tunnelverkehr nutzen soll, und eine Regel, die die passende Quelle dorthin schickt.

Binden setzt eine Quelladresse, mehr nicht

Linux wählt ein Ausgangs-Interface, indem es das Ziel in einer Routing-Tabelle nachschlägt, nachdem Policy-Regeln die Gelegenheit hatten, dieses Nachschlagen umzuleiten. Regeln können nach Quelladresse, Firewall-Mark, eingehendem Interface, einer UID oder sogar einem Port auswählen; jede ist eine andere Art zu sagen: dieser Verkehr statt aller. Die Konfiguration des VPN-Clients wählt die Tabelle, die die Tunnelrouten hält; die Regel wählt, welcher Verkehr sie konsultieren darf. Das Binden allein liefert keins von beidem.

Deshalb sieht der Fehler so seltsam aus. Die Anwendung nutzt definitiv die Tunneladresse, der Tunnel ist definitiv oben, und der Verkehr verlässt definitiv das falsche Interface. Jede Aussage ist wahr, und zusammen beschreiben sie ein System, in dem nichts die Adresse mit der Route verband.

Gib dem Tunnel seine eigene Tabelle

wg-quick legt Routen dort an, wo das Profil es sagt. Table = 40 unter [Interface] verschiebt sie in Tabelle 40 statt in die Haupttabelle. Bringe das Interface hoch und prüfe, ob sie angekommen sind: ip -4 route ls table 40 sollte die Routen des Tunnels zeigen, und ip -4 route get 10.66.127.142 zeigt, wie der Kernel derzeit eine davon auflöst. Mit den Routen in ihrer eigenen Tabelle funktioniert die Haupttabelle für alles andere weiter.

Mach dasselbe für IPv6, statt ein breites Präfix zu matchen. ip -6 rule add from fd00::2/128 lookup 40 legt eine Adresse fest; fc00::/8 kann mit anderen Interfaces auf dem Host kollidieren und eine Regel erzeugen, die mehr trifft als beabsichtigt.

Füge die Quellregel hinzu und beobachte die Zähler

Dann verbinde die Hälften: ip -4 rule add from 10.66.127.142/32 lookup 40, mit derselben Adresse am WireGuard-Interface. Lege beide Regeln in PostUp ab, damit ein Wiederverbinden sie wiederherstellt. Prüfe mit einer echten Anfrage statt mit einer Einstellung: ip route get 1.1.1.1 from 10.66.127.142 sollte das Tunnelgerät nennen, und curl --interface wg0 ifconfig.me sollte die Tunneladresse melden statt der heimischen.

Wenn es weiter scheitert, lies ip -s rule. Eine Regel, die existiert, aber nie getroffen hat, zeigt Null-Zähler, und das unterscheidet eine falsche Regel von gar keiner Regel. Dieser eine Befehl spart viel Raten darüber, ob die Anwendung ihre Interface-Einstellung ignoriert hat.

Der umgekehrte Fall: SSH aus dem Tunnel heraushalten

Das gegenteilige Problem ist genauso häufig: wg-quick besitzt die Standardroute, und die SSH-Sitzung zum Server stirbt mitten in der Sitzung. Seine Regeln stehen auf einer niedrigen Prioritätsnummer, also muss eine Ausnahme früher ausgewertet werden als sie. ip rule add dport 22 ipproto tcp table main priority 123 erledigt das auf einem neueren iproute2; wo der Selektor fehlt, markiere den Fluss in nftables und triff stattdessen die Markierung.

Prüfe auch den Rückweg. Eine SSH-Sitzung, die sich aufbaut und dann verstummt, hat meist asymmetrisches Routing: eine Richtung geht durch den Tunnel, die andere durch das physische Interface. ip route get für die Serveradresse sagt dir, wohin die Antwort ginge.

Notiere Tabellennummer, Quellregel und Ausnahme im Profil selbst. Alle drei gehören zu einem Entwurf und werden zusammen bearbeitet.

Ähnliche Artikel