Eine einzige Zeile auf einer PPP-Schnittstelle entscheidet den größten Teil der Routing-Diskussion auf einer VPN-Box: die innere Adresse und der daneben ausgegebene Peer. Liest man dieses Paar als winziges Subnetz, sucht man nach einem Gateway, das es nicht gibt. Liest man es als die beiden Enden einer einzigen Strecke, wird der Next Hop offensichtlich. Der Vergleich hier gilt diesen beiden Lesarten, denn jede Tabelle, die man danach baut, erbt die einmal gewählte. Über den äußeren VPN-Endpunkt entscheidet keine von beiden etwas.

Zwei Lesarten einer Schnittstellenzeile

Nehmen wir eine Sitzung, in der die Schnittstelle inet 10.64.3.9 peer 10.64.3.1/32 meldet. Die Subnetz-Lesart behandelt 10.64.3.9 als einzelnen Host auf einer /32-Insel und sucht dann einen Router, um irgendetwas außerhalb davon zu erreichen. Da die einzige andere Adresse auf der Strecke der Peer ist, schlägt diese Lesart am Ende 10.64.3.9 selbst als Gateway vor, was zirkulär ist.

Die Endpunkt-Lesart ist die dokumentierte. Auf einer Punkt-zu-Punkt-Schnittstelle benennt peer das entfernte Ende dieser einen Strecke, sodass 10.64.3.1 der brauchbare Next Hop ist und 10.64.3.9 stets nur eine Quelladresse.

Dieser Unterschied bestimmt, was in via stehen darf. Trägt man dort die lokale Adresse ein, entsteht eine Route, die der Kernel keinem Nachbarn zuordnen kann; der Eintrag scheitert dann an der Validierung oder schluckt den Verkehr, während er in einer Auflistung vollkommen gesund aussieht. Der Peer funktioniert, weil er ein echtes Ziel auf der Strecke ist. Beide Lesarten stimmen beim äußeren VPN-Endpunkt überein, der eine völlig eigene Identität ist: Er wird über das Underlay erreicht, nicht über den Tunnel, den er beendet.

Was die Sitzung bereits installiert hat

Bevor man eine eigene Tabelle schreibt, sollte man ausgeben, was mit der Strecke gekommen ist. Eine unterstützte PPP-Integration installiert beim Sitzungsaufbau üblicherweise eine Geräte-Route und eine Peer-Route, und diese beiden Einträge kodieren bereits die richtige Lesart.

ip -4 addr show dev ppp0
ip route show dev ppp0
ip route show table main | head -n 5

Eine Geräte-Route wie 10.64.3.1 dev ppp0 proto kernel scope link src 10.64.3.9 trägt kein Gateway, weil die Schnittstelle selbst der Pfad ist. Eine Route, die den Peer mit via benennt, ist ein anderes Objekt mit anderer Lebensdauer, und sie verschwindet, wenn die Sitzung abbricht. Eine der beiden Formen in eine persistente Tabelle zu kopieren, ohne zu prüfen, wie sie neu installiert wird, ist der übliche Grund, warum ein funktionierender Tunnel nach einer Wiederverbindung seine Route verliert.

Vergleicht man die beiden Auflistungen, statt dem Gedächtnis zu vertrauen. Existiert die Peer-Route in main, während die eigene Zusatztabelle leer ist, hat man etwas gelernt, was die Adresszeile nie gesagt hat.

Regel und Tabelle sind getrennte Entscheidungen

Eine Tabelle auszuwählen und sie zu füllen sind unabhängige Schritte, und der Vergleich zählt hier, weil beide beim Debuggen oft verwechselt werden. Eine Regel, die markierten Verkehr in Tabelle 100 schickt, bewirkt nichts, wenn Tabelle 100 keine passende Route hat, und eine gut gefüllte Tabelle ist unerreichbar, wenn keine Regel auf sie zeigt.

Ein halber Default ist kein Default. Ein einzelnes 0.0.0.0/1 deckt die untere Hälfte des IPv4-Raums ab, also braucht eine Policy, die alles einfangen will, zusätzlich das passende 128.0.0.0/1 oder ein echtes default. Eine funktionierende Konfiguration zu lesen und eine der beiden Hälften zu kopieren, ist der Weg, auf dem Leute eine Routingschleife bekommen, die nur bei bestimmten Zielen bricht.

Für Adressen, die im LAN bleiben müssen, lässt man bewusst Ausnahmen stehen und entscheidet, was passiert, wenn die Suche in der gewählten Tabelle nichts findet. Eine ausdrückliche Fallback-Route ist leichter nachzuvollziehen als eine leere Tabelle, die ein Unreachable-Ergebnis liefert und die Anwendung eher kaputt als falsch geroutet aussehen lässt.

Die Suche so stellen, wie die Anwendung sie stellt

ip route get löst einen Pfad auf; ip route show listet gespeicherte Einträge, und beide können sich widersprechen, ohne dass einer falsch ist. Den Quellkontext mitgeben, denn quellbasierte Regeln greifen nur, wenn die Suche eine Quelle mitführt.

ip route get 198.51.100.23 from 10.64.3.9
ip route get 198.51.100.23 from 10.64.3.9 iif ppp0
ip -4 rule show

Der erste Befehl stellt die vom Host ausgehende Frage. Der zweite fügt eine Eingangsschnittstelle hinzu, was dem näher kommt, was weitergeleiteter Verkehr erlebt, und die Antwort zeigt oft auf eine andere Tabelle. Keines der Ziele ist ein Live-Testdienst; 198.51.100.23 ist eine Dokumentationsadresse, also ersetzt man sie durch einen Host, den man prüfen darf.

Selbst eine korrekte Suche beweist nur, dass ein Pfad gewählt wurde. Sie sagt nichts darüber, ob die Gegenseite den Verkehr annimmt oder ob die Antwort über dieselbe Überlegung zurückkommen kann.

Wo der Vergleich kippt

Host-Verkehr und weitergeleiteter Verkehr nehmen nicht nur unterschiedliche Suchen; sie treffen auf dem Rückweg auch auf unterschiedliche Filter. Linux wendet Reverse-Path-Validierung mit der strengeren der Einstellungen für alle Schnittstellen und für die empfangende Schnittstelle an, sodass eine Änderung an einer Schnittstelle womöglich keine sichtbare Wirkung hat. Mark-basiertes Routing fügt die Beziehung src_valid_mark hinzu, bei der die Marke übereinstimmen muss, damit eine Quelle als gültig gilt.

Wenn Antworten verschwinden, während das ausgehende Routing richtig aussieht, liest man die effektiven Werte, bevor man sie anfasst, und ändert sie nur mit einem genannten Policy-Grund.

sysctl net.ipv4.conf.all.rp_filter
sysctl net.ipv4.conf.ppp0.rp_filter
sysctl net.ipv4.conf.all.src_valid_mark

Zwischen den beiden Entwürfen entscheidet man auf Basis von Belegen: Bindet sich die Anwendung an die PPP-Adresse, genügen eine Quellregel und eine Tabelle mit der Peer-Route. Leitet die Box für ein LAN dahinter weiter, müssen zusätzlich der Eingangskontext und der Rückweg übereinstimmen. Widersprechen sie sich, korrigiert man die Eigentümerschaft der Route, statt die Validierung für die ganze Maschine zu lockern.

Ähnliche Artikel