← Tous les articles

Empreinte nulle

Comment Osprey voit un réseau sans en faire partie

Michel Wijnberg

Tous les produits de supervision de la planète se disent « sans agent ». La plupart veulent dire qu’ils se connectent en SSH et raclent la sortie des commandes show, ce qui est sans agent au même titre qu’un cambrioleur est un invité.

Osprey prend une autre route, et je veux être précis là-dessus, y compris sur la partie où la phrase marketing n’est pas tout à fait vraie.

Osprey obtient ses données de trois façons. Les trois sont visibles pour un exploitant qui regarde (ce n’est pas un produit furtif), mais une seule place Osprey à l’intérieur de la base de données d’un protocole de routage, et c’est celle qui mérite l’examen.


1. L’enregistreur GRE : une vraie adjacence qui ne peut jamais porter de trafic

La plus intéressante. Osprey peut former une véritable adjacence IGP au-dessus d’un tunnel GRE : une vraie relation de voisinage OSPFv2, OSPFv3 ou IS-IS, avec de vrais Hellos, un vrai échange DBD, une vraie inondation. Il apprend la LSDB comme un routeur l’apprend : parce qu’on la lui dit.

C’est strictement mieux que de parcourir une MIB, parce que vous obtenez la base telle que le protocole la distribue réellement, avec les numéros de séquence, les âges et les sommes de contrôle intacts, et vous voyez les changements à l’instant où ils sont inondés plutôt qu’au prochain intervalle d’interrogation.

Cela veut aussi dire que les routeurs voient bel et bien un voisin. Disons-le franchement : Osprey apparaît dans la LSDB. Il le faut. La RFC 2328 §12.4.1 exige que tout routeur d’une area émette un Router-LSA de type 1, et un routeur qui forme une adjacence sans en émettre un est un routeur cassé.

La question n’est donc pas « peut-on être invisible », puisque non, mais « peut-on être incapable d’influencer l’acheminement ». Celle-là a une vraie réponse :

// originateRouterLSA creates and installs our Router-LSA in the LSDB.
// RFC 2328 Section 12.4.1 requires every router to originate a Type 1 LSA.
// We use cost 65535 (maximum) so no router will ever route traffic through
// Osprey. Only the P2P link is advertised. NO stub network for the tunnel
// inner subnet. Advertising the tunnel subnet (even at max cost) causes SPF
// on other routers to install a route for the tunnel prefix, which can
// disrupt the GRE outer path and kill the adjacency.

Deux décisions volontaires là-dedans, et la seconde m’a coûté une panne de laboratoire pour être bien comprise.

Métrique maximale. L’enregistreur annonce son unique lien point à point au coût 65535, et c’est la plus faible des deux garanties. Une métrique ne fait que rendre un chemin peu attirant, et un chemin peu attirant l’emporte quand même s’il est le seul. La vraie garantie est la forme : l’enregistreur n’a qu’une seule adjacence, c’est donc une feuille dans le graphe, et il n’existe aucun chemin à travers une feuille qu’un SPF puisse trouver. Ajoutez qu’il n’annonce aucun préfixe à lui et il n’y a rien vers quoi router non plus. La métrique maximale est une ceinture par dessus des bretelles, sur une topologie qui ne peut déjà pas porter de transit.

Pas de réseau stub. L’enregistreur annonce le lien P2P et rien d’autre. En particulier, il n’annonce pas le sous-réseau interne du tunnel comme réseau stub. C’est le point subtil. S’il le faisait, chaque routeur de l’area installerait une route vers le préfixe du tunnel. Cette route peut alors supplanter le chemin de transport sur lequel le tunnel GRE lui-même circule, ce qui casse le transport externe, ce qui tue l’adjacence, ce qui fait tomber l’enregistreur : un battement magnifiquement auto-infligé. N’annoncer rien de joignable évite toute cette classe de problème, et satisfait quand même la RFC 2328.

La version IS-IS est plus stricte

IS-IS fournit un mécanisme conçu exactement pour cela, alors l’enregistreur IS-IS l’utilise. Le LSP qu’il émet lui-même porte un jeu d’invariants stricts :

InvariantPourquoi
Bit OL = 1Le bit Overload. L’ISO 10589 impose que tout autre routeur traite un routeur en surcharge comme non transitaire. C’est la garantie principale, pas une astuce de métrique.
Bits ATT = 0000Ne jamais attirer de route par défaut L1. Un routeur L1 seul ne doit pas pointer sa route par défaut vers Osprey.
Bit P = 0Pas de réparation de partition.
TLV 22 métrique = 0xFFFFFFMétrique large maximale, ceinture et bretelles à côté du bit OL.
Aucun TLV 128 / 130 / 135 / 236Ce sont les TLV de joignabilité IP. En émettre un reviendrait à injecter des routes.
Aucun TLV 134Pas de TE Router ID. Cela insérerait Osprey dans la base d’ingénierie de trafic.
Aucun TLV 222 / 242Pas de multi-topologie, pas de router capability ni de segment routing.

Lisez ce tableau comme une liste de choses que le code ne sait pas faire plutôt que comme une liste de réglages. Il n’existe aucune option de configuration qui désactive le bit Overload et aucun chemin de code qui sérialise un TLV de joignabilité IP, parce que la façon la plus sûre de garantir qu’on n’annonce jamais un préfixe est de ne pas implémenter l’annonce.

Donc : visible, participant, et structurellement incapable d’attirer le moindre paquet. C’est une affirmation bien plus forte que « invisible », et contrairement à « invisible », elle est vraie.


2. SNMP : la LSDB par la voie ennuyeuse, plus tout ce que la LSDB ne porte pas

Tous les équipements ne vous accordent pas une adjacence, et certaines choses ne figurent simplement dans aucune base à état de liens. Osprey interroge donc aussi.

Cibles SNMP : 192 équipements, tous actifs, intervalle de 300 secondes, identifiants masqués
Cibles SNMP : 192 équipements, tous actifs, intervalle de 300 secondes, identifiants masqués

192 cibles dans ce laboratoire, toutes au vert, interrogées sur un cycle de 300 secondes, dernier relevé mesuré en secondes.

La colonne des identifiants affiche ***, et il vaut la peine d’être précis sur l’endroit où ce masquage a lieu : dans le gestionnaire d’API, pas dans le navigateur. Les identifiants sont stockés chiffrés en AES-256-GCM, et tout chemin de lecture fait passer la réponse par un masque avant de la sérialiser. L’interface ne reçoit donc jamais la chaîne de communauté ni les mots de passe v3 auth/priv, et il n’y a par conséquent aucun bouton « révéler », et il ne pourrait pas y en avoir un sans modifier le serveur.

Masquer dans le client, c’est du théâtre. Masquer dans le gestionnaire, c’est un contrôle.

SNMP fait ici quatre métiers :

  • Reconstruction de la LSDB là où aucun enregistreur n’est branché (c’est ce qui a produit les 13 382 LSA du billet précédent, avec les champs d’en-tête manquants honnêtement déclarés)
  • Compteurs d’interface pour le trafic, les erreurs et l’utilisation
  • EIGRP, qui n’a aucune base à rejoindre et est lu entièrement depuis CISCO-EIGRP-MIB
  • Voisins L2 via LLDP et CDP

Ce dernier point compte plus qu’il n’en a l’air :

Voisins CDP/LLDP : 303 adjacences, 66 équipements distants uniques
Voisins CDP/LLDP : 303 adjacences, 66 équipements distants uniques

303 adjacences L2, 66 équipements distants uniques. C’est la couche qui permet à Osprey de dire quel port physique une session BGP inter-AS traverse réellement, au lieu d’agiter la main vers « un lien quelconque entre ces deux routeurs », et vous voyez l’un de ces liens inter-AS directement dans le tableau : l’entrée CDP de ams1-gw1 Et1/1 vers e-ams1-gw1, c’est-à-dire la frontière AS 200 ↔ AS 100.


3. BMP : laisser parler les routeurs

Pour BGP, la voie préférée n’est pas de demander. C’est d’écouter.

BMP (RFC 7854) est un protocole où le routeur pousse sa Adj-RIB-In, les chemins que ses voisins lui ont annoncés, vers une station de supervision, sur une simple session TCP. Il n’y a pas de boucle d’interrogation, pas d’analyse de show ip bgp, et aucune charge de requêtes sur le plan de contrôle au-delà de la session elle-même. Le routeur décide quoi envoyer et quand.

Voisins BGP : 378 sessions sur 57 pairs, 374 up, 4 down
Voisins BGP : 378 sessions sur 57 pairs, 374 up, 4 down

378 sessions sur 57 pairs ici, mais elles ne sont pas toutes arrivées de la même façon, et cette distinction est enregistrée plutôt que gommée.

Six routeurs de ce laboratoire sont exportateurs BMP (ams1-gw1, jfk1-gw1, e-ams1-gw1, e-sin1-gw1, i-jfk1-gw1, i-sin1-gw1), et ils représentent 24 sessions : dont toutes les sessions eBGP du laboratoire. Les 354 restantes viennent de parcours SNMP de la BGP4-MIB sur des routeurs qui n’exportent pas BMP du tout.

Les deux voies vers la donnée sont légitimes et méritent toutes deux d’exister ; elles ne se valent simplement pas. Un flux BMP porte tous les chemins que le voisin a annoncés, plus les Peer Up et Peer Down tels que le routeur les voit. Un parcours SNMP vous donne la table des sessions au moment du relevé et rien entre deux relevés. Quelle RIB compte ici : la RFC 7854 supervise la Adj-RIB-In, ce qui est arrivé avant que ce routeur ne choisisse quoi que ce soit. La table effectivement retenue par le routeur, la Loc-RIB, est une extension distincte et ultérieure (RFC 9069) que ces exportateurs n’envoient pas, si bien que la sélection du meilleur chemin parmi ces candidats est un calcul d’Osprey et est étiquetée comme tel.

Chaque ligne porte donc une colonne source enregistrant d’où elle vient, et cette valeur est porteuse plus haut dans la pile. Quand Osprey assemble plus tard un chemin inter-AS et doit justifier un saut interdomaine, une session eBGP compte comme preuve avec sa provenance attachée (bmp-peer contre snmp-peer), jamais comme un fait anonyme. Même tableau, mais gradué.

Les deux familles d’adresses circulent sur une seule session BMP par exportateur, c’est pourquoi vous voyez des lignes IPv4 et IPv6 partager un routeur déclarant.

Les lignes eBGP de ce tableau sont les plus intéressantes, car ce sont les coutures entre les trois locataires :

DeASVersAS
e-ams1-gw1100ams1-gw1200
i-sin1-gw1300e-sin1-gw1100
i-jfk1-gw1300jfk1-gw1200

Un triangle : AS 200 ↔ AS 100 à Amsterdam, AS 100 ↔ AS 300 à Singapour, AS 200 ↔ AS 300 à New York. Six sessions, douze lignes sur les deux familles. Ce triangle est ce qui rend l’assemblage de chemins interdomaines possible, et c’est le sujet du billet trois.


Ce qu’Osprey ne peut structurellement pas faire

Certaines contraintes méritent d’être énoncées comme des contraintes plutôt que comme des fonctionnalités, parce qu’elles sont la raison pour laquelle le reste est digne de confiance :

  • Aucune injection de route. L’enregistreur émet exactement un Router-LSA décrivant exactement un lien P2P au coût maximal, et rien d’autre. Il n’a aucun chemin de code qui annonce un préfixe.
  • Aucun acheminement de paquet. Osprey n’est pas dans le plan de données. Il n’y a pas de table d’acheminement, pas de FIB, rien à mal programmer.
  • Aucune écriture de configuration. Le terminal SSH de l’interface est un terminal. Les frappes sont les vôtres, la session est enregistrée pour l’audit, et Osprey lui-même n’émet jamais de commande de configuration.
  • Flux de données à sens unique. Les collecteurs et BMP ingèrent et publient vers NATS ; le moteur persiste dans PostgreSQL ; l’API sert l’interface. Aucun service ne rappelle en amont. Il n’existe aucun chemin de l’interface web vers un routeur qui ne soit pas un humain tapant dans un terminal.

Le résumé honnête

Osprey est passif au sens qui compte : il ne peut pas attirer de trafic, ne peut pas injecter de route et ne peut pas acheminer de paquet. Mais il n’est pas invisible, et je préfère vous le dire plutôt que vous le laisser découvrir dans un show ip ospf neighbor qui compte une ligne de plus que prévu.

Si un fournisseur vous dit que son outil rejoint votre IGP et que personne ne peut s’en apercevoir, demandez-lui à quoi ressemble son Router-LSA.


Ensuite : pourquoi votre outil de chemin vous ment probablement, et la mesure sur 4 032 paires qui le prouve : La vérité saut par saut.