Le routeur qui ne doit jamais transporter un paquet
Trois protocoles à état de liens, trois façons différentes de rejoindre un réseau et de lui être inutile exprès
Michel Wijnberg
L’article deux soutenait qu’Osprey ne touche pas à votre réseau. Cette série est le niveau en dessous de cette affirmation : comment on rejoint réellement chaque protocole, ce que chacun refuse de livrer, et où être un invité bien élevé se révèle plus difficile qu’il n’y paraît.
Commençons par l’exigence la plus dure, car tout le reste en découle.
Pour lire une base de données à état de liens, il faut être dedans. Pas à côté, pas en interrogeant : une vraie adjacence, échangeant de vrais LSA, apparaissant dans la base de tous les autres comme un routeur. Il n’existe pas de mode observateur en OSPF ni en IS-IS. Vous rejoignez, ou vous n’obtenez rien.
Et à l’instant où vous rejoignez, chaque routeur de la zone exécute un plus court chemin sur un graphe qui vous contient désormais. Personne n’a demandé si vous vouliez le trafic.
L’exigence est donc :
Soyez un routeur parfaitement conforme. Ne soyez jamais sélectionné comme chemin.
Les deux sont en tension par construction, et les trois protocoles la résolvent différemment.
OSPFv2 : le coût maximal
Le RFC 2328 impose à un routeur OSPFv2 d’originer un Router-LSA pour chaque zone à laquelle il participe. Pas d’adjacence observateur de repli : participer, c’est être décrit. L’enregistreur en origine donc un, annonçant son unique lien point à point au coût 65535, le maximum que contient une métrique 16 bits.
Tous les autres routeurs de la zone exécutent dûment Dijkstra en incluant ce lien, et n’importe quel chemin alternatif l’emporte. L’enregistreur est dans le graphe, visible, conforme, et jamais sur un plus court chemin sauf si le réseau n’a véritablement rien d’autre, auquel cas vous avez de plus gros problèmes que votre supervision.
C’est tout le mécanisme en OSPFv2, et il vaut la peine de noter ce qu’il n’est pas. Ce n’est pas un drapeau disant « ne m’utilisez pas ». C’est une métrique ordinaire réglée assez haut pour que la réponse tombe d’elle-même de l’algorithme normal. Les routeurs conformes n’ont besoin d’aucun traitement particulier, parce qu’il ne se passe rien de particulier.
Il y a une seconde moitié dont l’apprentissage a coûté une panne, et c’est la plus intéressante. L’enregistreur annonce le lien point à point et rien d’autre, en particulier pas le réseau stub du sous-réseau interne du tunnel GRE. Annoncer cela, même au coût maximal, amène tous les autres routeurs à installer une route pour le préfixe du tunnel. Cette route peut alors orienter les paquets externes du tunnel lui-même, ce qui tue l’adjacence qui portait l’observation. La supervision casse ce dont elle a besoin pour superviser. L’article sept raconte la version de cette histoire où je l’ai découvert à la dure.
Le coût maximal vous tient hors du plus court chemin. Il ne vous tient pas hors de la table de routage, et ce sont des problèmes différents.
OSPFv3 : la même chose, plus un bit qui le dit franchement
OSPFv3 hérite de l’astuce de la métrique, puis ajoute quelque chose dont OSPFv2 n’a aucun équivalent.
OSPFv3 porte un bit R dans les options du Router-LSA (RFC 5340). Lorsque le bit est à zéro, le routeur annonceur n’est pas considéré comme capable d’acheminer du trafic de transit. Il continue de participer à la distribution de topologie ; il n’est simplement pas éligible comme nœud de transit.
Ce n’est pas une métrique. C’est une déclaration, l’enregistreur laisse donc le bit R à zéro, et un routeur OSPFv3 conforme l’exclut entièrement du calcul de transit au lieu de simplement le classer dernier.
La différence compte plus qu’elle n’en a l’air. Une métrique maximale est une affirmation sur une préférence qui se trouve être décisive. Un bit R à zéro est une affirmation sur une capacité, et elle ne peut pas être renversée par une topologie où tous les autres chemins sont pires.
Cela referme aussi une boucle du côté lecture. Le SPF d’Osprey honore ce même bit via un drapeau de non-transit par zone, de sorte qu’un enregistreur est exclu du transit par les routeurs conformes et par le calcul de chemin d’Osprey, pour la même raison déclarée. Deux implémentations, un bit, aucun cas particulier dans l’une ni dans l’autre.
OSPFv2 n’a tout simplement nulle part où mettre cette phrase. Le champ d’options n’a pas d’équivalent, donc v2 n’a que la métrique, et l’asymétrie est une propriété des protocoles et non de l’effort qu’on y a mis.
IS-IS : deux portes et un verrou
IS-IS possède le mécanisme individuel le plus fort et, dans cette implémentation, le plus de ceinture et bretelles autour.
Le LSP auto-originé positionne le bit de surcharge. ISO 10589 est sans ambiguïté sur ce que cela signifie : les autres routeurs peuvent atteindre ce système, mais ne doivent pas calculer de chemins à travers lui. C’est la même classe d’affirmation que le bit R d’OSPFv3, et il le précède largement.
Puis deux autres, et ce ne sont pas la même chose :
| Champ | Valeur | Ce qu’il empêche |
|---|---|---|
| Bit OL | positionné | d’être calculé comme nœud de transit |
| Bits ATT | 0000 | d’être installé comme passerelle par défaut |
| Métrique TLV 22 | 0xFFFFFF | tout ce qui traiterait le bit de surcharge comme indicatif |
La ligne ATT mérite sa place parce qu’elle ferme une autre porte. Le bit de surcharge concerne le calcul de chemins. Le bit attached concerne le routage par défaut : un routeur L1L2 le positionne pour dire aux routeurs de niveau 1 qu’il peut atteindre l’extérieur de la zone, et ces routeurs pointent alors une route par défaut vers lui. Ce n’est pas un chemin calculé à travers l’enregistreur, c’est chaque paquet sans meilleure correspondance qui lui est envoyé, ce qui est pire et arrive par une voie que le premier mécanisme ne couvre pas.
La ligne de la métrique est de la pure défense. Une métrique 24 bits de 16 777 215 fait l’astuce d’OSPFv2 sous un mécanisme qui devrait déjà la rendre inutile, en supposant qu’il existe quelque part une implémentation traitant le bit de surcharge comme indicatif.
(Le LSP met aussi à zéro le bit de réparation de partition, ce qui est vraiment mineur et mentionné seulement pour que personne n’ait à se demander pourquoi il est là.)
C’est tout l’argument en un tableau. Les enregistreurs sont dans la base, avec leurs propres LSA et leurs propres numéros de séquence, exactement comme n’importe quel autre routeur. Un lien chacun, aucun indicateur, rien à redistribuer. Le modèle de sûreté n’est pas ce qui les tient dehors ; c’est ce qui rend le fait d’être dedans inoffensif.
Ce que le titre ne prétend pas
À séparer avant d’aller plus loin, car le titre exagère si on le lit comme une affirmation sur la machine.
Rien de ce qui précède ne rend l’hôte physiquement incapable d’acheminer. Sur
l’enregistreur du laboratoire il se trouve qu’il en est incapable, parce que
net.ipv4.ip_forward vaut 0 et l’équivalent IPv6 aussi. Mais c’est un réglage
d’hôte. Quelqu’un peut le changer en une commande, et rien dans la couche protocole ne
s’en apercevrait.
L’exigence n’est donc pas « cette machine ne peut pas acheminer un paquet ». Elle est :
Aucun calcul de routage, nulle part dans le réseau, ne peut sélectionner cette machine comme nœud de transit.
La différence tient à l’endroit où réside la garantie. Si l’innocuité de l’enregistreur
dépendait d’un sysctl, alors tout exploitant qui en déploie un serait à un sysctl -w de
placer un hôte de supervision dans le chemin d’acheminement, et le réseau n’en saurait
rien. Parce qu’elle dépend de la topologie, le calcul de plus court chemin du réseau
refuse de router par l’enregistreur, que le noyau ait acheminé ou non.
Le sysctl est une bonne ceinture. C’est juste la chose la plus faible de cet article, et la section suivante porte précisément sur ce gradient.
Celui qui est une valeur par défaut plutôt qu’un invariant
Les trois enregistreurs tournent aussi avec une priorité d’élection de DR à zéro, et ne peuvent donc jamais devenir routeur désigné d’un segment. Un enregistreur qui gagnerait une élection de DR deviendrait ce dont tous les autres routeurs du segment dépendent pour l’inondation, ce qui est l’opposé de toute la prémisse.
La priorité zéro est la valeur par défaut, et je veux être précis sur le type de protection que c’est : c’est un champ de configuration. Rien dans le code ne refuse une valeur supérieure. Réglez-la et l’enregistreur disputera l’élection comme n’importe quel routeur.
Cela mérite d’être séparé du reste de cet article, car tout ce qui précède est une constante
dans le code. Le bit de surcharge est OLBit: true au point d’origination, sans moyen de le
désactiver. La métrique OSPFv2 est 65535 dans le constructeur de LSA. Le bit R n’est
jamais positionné. Ce sont des invariants. La priorité DR est une valeur par défaut, et les
valeurs par défaut sont la classe de sûreté qui survit exactement tant que personne
n’édite un fichier YAML.
Rendre l’erreur indisponible
Ce qui m’amène à la partie qui m’intéresse vraiment.
Empêcher le transit est un problème de préférence. Empêcher l’injection est un problème de correction, et c’est bien pire, car le mode de défaillance n’est pas un chemin sous-optimal. C’est une route dans la table de quelqu’un d’autre qui ne correspond à rien.
Le LSP IS-IS auto-originé ne porte donc aucune accessibilité IP. Pas de TLV 128, 130, 135 ni 236. Pas de TLV 134 d’identifiant de routeur d’ingénierie de trafic, qui placerait l’enregistreur dans la base TE. Pas de TLV 222, pas de TLV 242.
La façon dont c’est imposé est le point clé. La routine d’origination prend son entrée dans une petite structure de configuration contenant un niveau, un identifiant de système, une adresse de zone, un identifiant de système du pair, un numéro de séquence, une adresse d’interface et un authentificateur optionnel. Il n’y a dessus aucun champ pouvant contenir un préfixe. Un appelant ne peut pas passer une route, parce qu’il n’y a nulle part où en passer une.
Je veux être exact sur la limite de cela, car il est tentant d’en revendiquer davantage. Le LSP en construction contient une liste générique de TLV, et la routine y ajoute. Quelqu’un éditant cette routine pourrait y ajouter un TLV d’accessibilité ; le système de types ne s’y opposerait pas. Ce que la conception supprime, ce n’est pas la possibilité, c’est l’accident : aucune configuration, aucun appelant et aucune combinaison de réglages ne peut introduire une route. En injecter une exige d’éditer une fonction dont le bloc de documentation énumère les invariants pour lesquels elle existe.
Cette distinction est toute la différence entre les deux moitiés de cet article, et il y a désormais quatre échelons en jeu. Un réglage d’hôte est quelque chose qu’un exploitant peut changer sans jamais savoir ce qu’il protégeait. Une vérification à l’exécution est quelque chose qu’on peut oublier d’écrire. Une valeur par défaut est quelque chose qu’on peut surcharger sans s’en rendre compte. Une surface d’entrée sans nulle part où mettre l’erreur est quelque chose qu’il faut se donner du mal pour contourner, et ce mal se voit dans un diff.
Aucun de ces échelons n’est absolu. Ce sont seulement des quantités très différentes d’accidentel, et l’ingénierie qui vaut la peine consiste à faire descendre une garantie dans cette liste plutôt qu’à ajouter une vérification de plus en haut.
L’essentiel
Trois protocoles, trois mécanismes, une exigence, et les mécanismes ne sont pas interchangeables. OSPFv2 ne peut exprimer que « coûteux ». OSPFv3 et IS-IS peuvent exprimer « pas un routeur de transit », ce qui est plus fort et plus honnête, et ils l’expriment dans des bits qui précèdent tout cela de plusieurs décennies.
L’ingénierie intéressante n’a pas été d’écrire le drainage. Ç’a été de remarquer qu’un coût maximal ne vous tient pas hors d’une table de routage, qu’une valeur par défaut n’est pas un invariant, et que l’endroit le plus sûr pour une règle est là où la règle ne peut pas être exprimée de travers.
Ensuite : partir. Un enregistreur qui redémarre trouve le réseau tenant encore son ancien lui-même à un numéro de séquence plus élevé, et le message qui corrige cela est celui qu’il envoie en s’éteignant. Le LSA qu’on ne peut pas reprendre.