Der Router, der nie ein Paket tragen darf
Drei Link-State-Protokolle, drei verschiedene Arten, einem Netz beizutreten und ihm absichtlich nutzlos zu sein
Michel Wijnberg
Beitrag zwei argumentierte, dass Osprey Ihr Netz nicht anfasst. Diese Reihe ist die Ebene darunter: wie jedes Protokoll tatsächlich betreten wird, was jedes davon nicht herausrückt, und wo sich ein wohlerzogener Gast zu sein als schwerer herausstellt, als es klingt.
Fangen wir mit der härtesten Anforderung an, denn alles andere folgt aus ihr.
Um eine Link-State-Datenbank zu lesen, müssen Sie in ihr sein. Nicht daneben, nicht per Abfrage: eine echte Adjazenz, echte LSAs austauschend, in der Datenbank aller anderen als Router erscheinend. Es gibt in OSPF und IS-IS keinen Beobachtermodus. Sie treten bei oder Sie bekommen nichts.
Und in dem Moment, in dem Sie beitreten, rechnet jeder Router im Bereich Shortest Path über einen Graphen, der jetzt Sie enthält. Niemand hat gefragt, ob Sie den Verkehr wollen.
Die Anforderung lautet also:
Sei ein voll konformer Router. Werde nie als Pfad ausgewählt.
Diese beiden stehen konstruktionsbedingt in Spannung, und alle drei Protokolle lösen sie anders.
OSPFv2: die maximalen Kosten
RFC 2328 verlangt von einem OSPFv2-Router, für jeden Bereich, an dem er teilnimmt, ein Router-LSA zu originieren. Es gibt keine reine Beobachter-Adjazenz als Rückfallebene: Teilnehmen heißt beschrieben werden. Also originiert der Recorder eines und kündigt seinen einzelnen Punkt-zu-Punkt-Link mit Kosten 65535 an, dem Maximum, das eine 16-Bit-Metrik fasst.
Jeder andere Router im Bereich rechnet Dijkstra brav inklusive dieses Links, und jeder alternative Pfad gewinnt. Der Recorder ist im Graphen, sichtbar, konform, und nie auf einem kürzesten Pfad, es sei denn, das Netz hat wirklich nichts anderes, und dann haben Sie größere Probleme als Ihr Monitoring.
Das ist der ganze Mechanismus in OSPFv2, und es lohnt zu bemerken, was er nicht ist. Er ist kein Flag mit der Bedeutung “benutzt mich nicht”. Er ist eine gewöhnliche Metrik, so hoch gesetzt, dass die Antwort aus dem normalen Algorithmus herausfällt. Konforme Router brauchen keine Sonderbehandlung, weil nichts Besonderes passiert.
Es gibt eine zweite Hälfte, die einen Ausfall gekostet hat zu lernen, und die interessanter ist. Der Recorder kündigt den Punkt-zu-Punkt-Link an und sonst nichts, insbesondere nicht das Stub-Netz für das innere Subnetz des GRE-Tunnels. Das anzukündigen, selbst zu maximalen Kosten, bringt jeden anderen Router dazu, eine Route für das Tunnelpräfix zu installieren. Diese Route kann dann die äußeren Pakete des Tunnels selbst lenken, was die Adjazenz tötet, die die Beobachtung trug. Das Monitoring zerstört genau das, was es zum Beobachten braucht. Beitrag sieben erzählt die Version dieser Geschichte, in der ich es auf die harte Tour herausfand.
Maximale Kosten halten Sie vom kürzesten Pfad fern. Sie halten Sie nicht aus der Routing-Tabelle heraus, und das sind verschiedene Probleme.
OSPFv3: dasselbe, plus ein Bit, das es ausspricht
OSPFv3 erbt den Metrik-Trick und fügt dann etwas hinzu, wofür OSPFv2 kein Äquivalent hat.
OSPFv3 trägt ein R-Bit in den Optionen des Router-LSA (RFC 5340). Ist das Bit gelöscht, gilt der ankündigende Router als nicht fähig, Transitverkehr weiterzuleiten. Er nimmt weiterhin an der Topologieverteilung teil; er ist schlicht nicht als Transitknoten geeignet.
Das ist keine Metrik. Das ist eine Erklärung, also lässt der Recorder das R-Bit gelöscht, und ein konformer OSPFv3-Router schließt ihn ganz aus der Transitberechnung aus, statt ihn bloß als letzten zu reihen.
Der Unterschied wiegt mehr, als er aussieht. Eine maximale Metrik ist eine Aussage über Präferenz, die zufällig entscheidend ist. Ein gelöschtes R-Bit ist eine Aussage über Fähigkeit, und sie kann von keiner Topologie überstimmt werden, in der jeder andere Pfad schlechter ist.
Es schließt auch auf der Leseseite einen Kreis. Ospreys eigenes SPF respektiert dasselbe Bit über ein Kein-Transit-Flag pro Bereich, sodass ein Recorder von konformen Routern und von Ospreys eigener Pfadberechnung aus demselben angegebenen Grund vom Transit ausgeschlossen wird. Zwei Implementierungen, ein Bit, kein Sonderfall in keiner von beiden.
OSPFv2 hat schlicht keinen Platz für diesen Satz. Das Optionsfeld hat kein Äquivalent, also bekommt v2 die Metrik und nur die Metrik, und die Asymmetrie ist eine Eigenschaft der Protokolle und nicht des Aufwands, der hineingesteckt wurde.
IS-IS: zwei Türen und ein Riegel
IS-IS hat den stärksten Einzelmechanismus und, in dieser Implementierung, die meiste doppelte Absicherung darum herum.
Das selbst originierte LSP setzt das Overload-Bit. ISO 10589 ist unmissverständlich, was das bedeutet: Andere Router dürfen dieses System erreichen, aber keine Pfade hindurch berechnen. Es ist dieselbe Klasse von Aussage wie das OSPFv3-R-Bit, und es ist weit älter.
Dann noch zwei, und sie sind nicht dasselbe:
| Feld | Wert | Was es verhindert |
|---|---|---|
| OL-Bit | gesetzt | als Transitknoten berechnet zu werden |
| ATT-Bits | 0000 | als Default-Gateway installiert zu werden |
| TLV-22-Metrik | 0xFFFFFF | alles, was das OL-Bit als Empfehlung behandelt |
Die ATT-Zeile verdient ihren Platz, weil sie eine andere Tür schließt. Das Overload-Bit betrifft Pfadberechnung. Das Attached-Bit betrifft Default-Routing: Ein L1L2-Router setzt es, um Level-1-Routern zu sagen, dass er nach außerhalb des Bereichs kommt, und diese Router richten dann eine Default-Route auf ihn. Das ist kein Pfad, der durch den Recorder berechnet wird, das ist jedes Paket ohne besseren Treffer, das zu ihm geschickt wird, was schlimmer ist und auf einem Weg ankommt, den der erste Mechanismus nicht abdeckt.
Die Metrikzeile ist reine Verteidigung. Eine 24-Bit-Metrik von 16.777.215 macht den OSPFv2-Trick unter einem Mechanismus, der ihn eigentlich überflüssig machen sollte, unter der Annahme, dass es irgendwo eine Implementierung gibt, die das Overload-Bit als Empfehlung behandelt.
(Das LSP löscht außerdem das Partition-Repair-Bit, was wirklich nebensächlich ist und nur erwähnt wird, damit sich niemand fragen muss, warum es da ist.)
Das ist das ganze Argument in einer Tabelle. Die Rekorder sind in der Datenbank, mit eigenen LSAs und eigenen Sequenznummern, genau wie jeder andere Router auch. Je eine Verbindung, keine Flags, nichts zu redistribuieren. Das Sicherheitsmodell hält sie nicht draußen; es macht das Drinsein harmlos.
Was der Titel nicht behauptet
Das gehört vorab getrennt, denn der Titel übertreibt, wenn man ihn als Aussage über die Maschine liest.
Nichts von alledem macht den Host physisch unfähig weiterzuleiten. Auf dem Labor-Recorder
ist er zufällig unfähig, weil net.ipv4.ip_forward auf 0 steht und das IPv6-Äquivalent
auch. Aber das ist eine Host-Einstellung. Jemand kann sie mit einem Befehl ändern, und
nichts auf der Protokollebene würde es merken.
Die Anforderung lautet also nicht “diese Kiste kann kein Paket weiterleiten”. Sie lautet:
Keine Routenberechnung irgendwo im Netz darf diese Kiste als Transitknoten auswählen.
Der Unterschied liegt darin, wo die Garantie wohnt. Hinge die Harmlosigkeit des Recorders
an einem Sysctl, dann wäre jede Betreiberin, die einen ausrollt, ein sysctl -w davon
entfernt, einen Monitoring-Host in den Weiterleitungspfad zu setzen, und das Netz hätte
keine Ahnung. Weil sie stattdessen an der Topologie hängt, weigert sich die
Shortest-Path-Berechnung des Netzes, durch den Recorder zu routen, egal ob der Kernel
weitergeleitet hätte oder nicht.
Das Sysctl ist ein guter Gürtel. Es ist nur das Schwächste in diesem Beitrag, und im nächsten Abschnitt geht es genau um dieses Gefälle.
Das eine, das ein Default ist und kein Invariant
Alle drei Recorder laufen außerdem mit einer DR-Wahlpriorität von null, können also nie Designated Router für ein Segment werden. Ein Recorder, der eine DR-Wahl gewänne, würde zu dem, worauf jeder andere Router auf dem Segment beim Fluten angewiesen ist, was das Gegenteil der ganzen Prämisse ist.
Priorität null ist der Default, und ich möchte genau sein, welche Art von Schutz das ist: Es ist ein Konfigurationsfeld. Nichts im Code verweigert einen höheren Wert. Setzen Sie ihn, und der Recorder tritt in der Wahl an wie jeder andere Router.
Das gehört vom Rest dieses Beitrags getrennt, denn alles darüber ist eine Konstante im
Code. Das Overload-Bit ist OLBit: true an der Stelle der Origination, ohne
Möglichkeit, es wegzukonfigurieren. Die OSPFv2-Metrik ist 65535 im LSA-Builder. Das
R-Bit wird nie gesetzt. Das sind Invarianten. Die DR-Priorität ist ein Default, und
Defaults sind die Klasse von Sicherheit, die genau so lange hält, wie niemand eine
YAML-Datei bearbeitet.
Den Fehler unverfügbar machen
Womit ich beim Teil bin, der mich wirklich interessiert.
Transit zu verhindern ist ein Präferenzproblem. Injektion zu verhindern ist ein Korrektheitsproblem, und es ist viel schlimmer, denn der Fehlermodus ist kein suboptimaler Pfad. Er ist eine Route in der Tabelle eines anderen, die nichts entspricht.
Das selbst originierte IS-IS-LSP trägt daher überhaupt keine IP-Erreichbarkeit. Kein TLV 128, 130, 135 oder 236. Kein TLV 134 Traffic-Engineering-Router-ID, das den Recorder in die TE-Datenbank setzen würde. Kein TLV 222, kein TLV 242.
Wie das durchgesetzt wird, ist der Punkt. Die Originationsroutine nimmt ihre Eingabe aus einem kleinen Konfigurations-Struct mit Level, System-ID, Areaadresse, Peer-System-ID, Sequenznummer, Interface-Adresse und optionalem Authenticator. Es gibt darauf kein Feld, das ein Präfix aufnehmen könnte. Ein Aufrufer kann keine Route hineinreichen, weil es nichts gibt, wo man eine hineinreichen könnte.
Ich will die Grenze davon genau benennen, denn es ist verlockend, mehr zu behaupten. Das LSP, das gebaut wird, hält eine generische TLV-Liste, und die Routine hängt daran an. Wer diese Routine bearbeitet, könnte ein Reachability-TLV anhängen; das Typsystem würde nicht widersprechen. Was der Entwurf entfernt, ist nicht die Möglichkeit, es ist der Unfall: Keine Konfiguration, kein Aufrufer und keine Kombination von Einstellungen kann eine Route einbringen. Eine zu injizieren erfordert, eine Funktion zu bearbeiten, deren Dokumentationsblock die Invarianten aufzählt, für die sie existiert.
Diese Unterscheidung ist der ganze Unterschied zwischen den beiden Hälften dieses Beitrags, und inzwischen sind vier Stufen davon im Spiel. Eine Host-Einstellung kann eine Betreiberin ändern, ohne je zu wissen, was sie schützte. Eine Laufzeitprüfung kann man zu schreiben vergessen. Einen Default kann man überschreiben, ohne es zu merken. Eine Eingabefläche ohne Platz für den Fehler ist etwas, wofür man sich anstrengen muss, und diese Anstrengung ist in einem Diff sichtbar.
Keine davon ist absolut. Sie sind nur sehr verschiedene Grade von Versehentlichkeit, und das lohnende Engineering besteht darin, eine Garantie diese Liste hinunterzuschieben, statt oben noch eine Prüfung anzubauen.
Der Punkt
Drei Protokolle, drei Mechanismen, eine Anforderung, und die Mechanismen sind nicht austauschbar. OSPFv2 kann nur “teuer” ausdrücken. OSPFv3 und IS-IS können “kein Transit-Router” ausdrücken, was eine stärkere und ehrlichere Aussage ist, und sie drücken sie in Bits aus, die all das um Jahrzehnte vordatieren.
Das interessante Engineering war nicht, die Drainage zu schreiben. Es war zu bemerken, dass maximale Kosten Sie nicht aus einer Routing-Tabelle heraushalten, dass ein Default kein Invariant ist, und dass der sicherste Ort für eine Regel dort ist, wo die Regel nicht falsch ausgedrückt werden kann.
Als Nächstes: das Gehen. Ein Recorder, der neu startet, findet das Netz noch mit seinem vorigen Selbst und einer höheren Sequenznummer vor, und die Nachricht, die das behebt, ist die, die er beim Herunterfahren sendet. Das LSA, das man nicht zurücknehmen kann.