lalahop
Categorie: BGP & RPKI+ROA

L'article « Quelques pistes sur le renforcement de la sécurité autour du protocole de routage BGP » a été publié aux pages 60-65 du numéro 70 (novembre/décembre 2013) de MISC. Ayant un peu étudié la sécurité de BGP, je souhaite donner mon avis qui tiendra compte du format (revue papier) qui oblige les auteurs à fortement résumer leurs propos.

Je réagis maintenant car j'achète, éventuellement (si une thématique abordée m'intéresse), la version PDF de ce magazine à l'unité et qu'il faut attendre la publication du numéro suivant pour que le numéro précédent devienne disponible au téléchargement. Je ne trollerai pas sur cette pratique ni sur celle qui consiste à faire payer le même prix pour la version numérique (pixellisée, mauvaise qualité) que pour la version papier alors que les coûts de production ne sont pas identiques (dupliquer un fichier, PDF ou pas, on frôle le zéro en coût de production). Oui, j'imagine bien qu'il faut rémunérer la production initiale (le contenu, la mise en page) et le fait que la version numérique n'est pas dominante sur la version papier, ce qui oblige à imprimer des exemplaires avec un risque d'invendus à provisionner mais quand même ...

Je mets une copie de cet article à votre disposition.

Mon premier regret sera que l'article ne met pas directement en évidence les deux catégories d'attaques existantes : celles qui visent la communication entre deux pairs BGP et celles qui visent à injecter de fausses informations qui se propageront de pair en pair. Une mention de la différence sera néanmoins faite dans la première conclusion (section 2.6).

De même, l'article ne met pas suffisamment en évidence la solution bien actuelle pour garantir l'origine d'une annonce BGP, RPKI+ROA, au profit des solutions historiques dont on sait qu'elles ne seront ni normalisées en l'état ni déployées. C'est dommage car on a l'impression que l'article est tourné vers le passé plutôt que vers le présent/futur et incite à l'immobilisme ("aucune vraie solution pour sécuriser BGP").

La section 2.2 (« Le contrôle par les secrets partagés ») traite uniquement de MD5, ce qui est assez dommage de nos jours ... Alors oui, IPsec et TCP AO ne sont pas encore suffisamment déployés pour justifier de faire la une des journaux TV mais je m'attendais à ce qu'ils soient cités dans cet article publié dans une revue spécialisée sur la sécurité informatique.

Les exemples de configuration sont mal formulés. Exemple : « neighbor «destination_adresse» password «mot» ». Ne serait-il pas plus exact de parler de « adresse_pair » au lieu de « destination_adresse » ?

Section 2.3 - « Le contrôle par les TTLs » :

En effet, partant du principe que les sessions de routage BGP entre deux routeurs sont généralement directes, les paquets IP contenant des informations de routage BGP émis par un routeur doivent arriver à l’autre routeur avec un TTL = TTL -1.

Le TTL est décrémenté uniquement en cas de forward. Un routeur reçoit un paquet, se rend compte qu'il ne lui est pas destiné, cherche une entrée dans sa FIB, décrémente le TTL. Si TTL = 0, il détruit le paquet et envoie un message ICMP « Time to Live exceeded in Transit » (type 11, code 0 😉 ) à celui qui prétend en être l'expéditeur. Si TTL > 0, le routeur forward le paquet.

Le RFC 5082 - The Generalized TTL Security Mechanism (GTSM) explique clairement que le paquet doit avoir un TTL fixé à 255 à l'émission et qu'il doit être inchangé à la réception. On lit souvent, y compris dans la CLI Cisco[1], que l'on doit avoir un TTL supérieur ou égal 254 à la réception : c'est une erreur ou plutôt, d'après mes recherches, un sacrifice de la sécurité sur l'autel de la compatibilité avec de vieilles architectures qui ne devaient pas gérer correctement la décrémentation du TTL (source : le plus loin que j'ai pu remonter, la présentation de cette proposition de TTL à 255 lors de la 27e rencontre NANOG : The BGP TTL Security Hack (BTSH)).

GTSM (Generalized TTL Security Mechanism) permet de généraliser cette approche à plusieurs sauts possibles et autres protocoles [RFC3682].

Le RFC 5082 a rendu obsolète le RFC 3682.

Sections 3.2 et 3.3 - « sBGP (secure BGP) » et « soBGP (secure origin BGP) » :

La première initiative a été le protocole sBGP (secure-BGP)

Ni S-BGP ni soBGP ne sont des protocoles.

Section 3.2 - « sBGP (secure BGP) » :

La validation de l’origine d’une route repose sur de la cryptographie à clé asymétrique nécessitant la mise en œuvre d’un système à clé publique où chaque système autonome possède alors un certificat électronique. La structure de gestion de clés proposée permet de traiter les extensions pour les blocs d’adresses certifiant l’appartenance d’une adresse à un AS.

Heu ... je ne comprends pas la dernière phrase ... En plus clair : les certificats x509 seront étendus avec de nouveaux types qui permettront de lier le titulaire de la clé privée du certificat à un préfixe IP/ASN. Ces extensions sont normalisées dans le RFC 3779 et doivent être présentes dans les certificats utilisés dans RPKI+ROA.

Un certificat est donc délivré à chaque organisme propriétaire d’un bloc d’adresse IP par l’entité responsable del’attribution des adresses IP. En partant du haut, on trouve l’IANA (Internet Assigned Numbers Autority) qui gère l’espace d’adressage d’Internet et l’assignation des blocs de numéros d’AS.

L'IANA gère, au plus haut niveau, toutes les ressources numériques uniques d'Internet, que ça soit les numéros d'AS, l'adressage IP ou bien encore les nombres dans les protocoles (exemple : les valeurs possibles pour les champs « Protocol »/« Next header » de la couche IP).

La validation du chemin pris par une annonce de route repose aussi sur de la cryptographie à clé asymétrique permettant de signer à chaque saut d’AS le chemin émis (avec sa clé privée) vers un autre système autonome comme l’illustre la figure 2 (les signatures s’empilent alors comme les couches d’un oignon).

Ce n'est pas ce que j'ai retenu de S-BGP. Pour moi, il y a autant de Route Attestation que d'AS traversés et elles ne sont pas empaquetées en oignon, chacune est indépendante. La présentation d'un des auteurs nous dit :

To validate a route received from ASn, ASn+1 requires:
[...]
- An RA corresponding to each AS along the path (ASn to AS1), where the RA generated and signed by the router in ASn encompasses the Network Layer Reachability Information (NLRI) and the path from ASn+1 through AS1

- A certified public key for each S-BGP router that signed an RA along the path (ASn to AS1), to check the signatures on the corresponding RAs

[...] The router verifies the signature on each RA and verifies the correspondence between the signer of the RA and the authorization to represent the AS in question. There also must be a correspondence between each AS in the path and an appropriate RA. If all of these checks pass, the UPDATE is valid.

On arrive à la section consacrée à RPKI+ROA, la plus floue de toute, ce qui est dommage compte tenu que RPKI+ROA est la solution normalisée à l'IETF pour initier la définition d'un routage inter-AS sécurisé.

Cette nouvelle initiative de l’IANA (groupe de travail sur la sécurité du routage inter-domaine (SIDR)) [...]

SIDR est le nom d'un groupe de travail de l'IETF. RPKI+ROA n'a rien à voir avec l'IANA. C'est assez comique de lire ça quand on sait que personne n'a voulu de l'IANA comme racine unique de la RPKI.

La solution repose sur :
- Une infrastructure de distribution de certificats numériques dont l’objectif est de prouver qu’un AS a le droit d’annoncer un préfixe. Elle s’appelle la RPKI (Resource Public Key Infrastructure)

Non, les certificats certifient que le détenteur de la clé privée associée à la clé publique contenue dans ce certificat est le titulaire des ressources (préfixes IP) mentionnées dans le certificat et qu'il peut en distribuer tout ou partie.

- Le ROA (Route Origin Authorization) est un objet signé par une autorité indiquant que « le préfixe y peut être originé par un AS donné x ». Plus spécifiquement, il s’agit d’un fichier signé avec la clé du certificat de l’autorité donnant les AS qui peuvent être à l’origine d’un ou plusieurs préfixes.

Non, un ROA ne peut contenir qu'un seul ASN. Il peut en revanche contenir plusieurs préfixes. L'"autorité" qui signe un ROA est un opérateur réseau qui détient un certificat lui procurant droit sur un préfixe IP.

L’autorité peut donc publier son certificat et ses ROAs dans des bases de données publiques (RIPE, etc.).

Ce n'est pas faux dans la pratique mais attention : la base de données publique, la RPKI, est un ensemble de dépôts dont tout un chacun peut obtenir une copie en utilisant le protocole rsync (ce que font les logiciels cités plus bas dans l'article RPKI Validator, rcynic ou bien encore RPSTIR). Ce système de dépôts est distribué et hiérarchique. Seul l'usage fait que, pour l'instant, il ne semble pas exister d'autres instances de publication que celles des 5 RIR.

Ce sont les ROAs qui seront traduits en une liste de filtrage au niveau de l’équipement réseau.

Sémantiquement incorrect. Les ROA contiennent des assertions. Exemple : « l'AS 64501 est autorisé à être à l'origine d'une annonce pour les préfixes 192.0.2.0/24 et 2001:0DB8::/32 ». Cette assertion sera transmise au routeur, qui la stockera en vue de la comparer aux annonces BGP qu'il reçoit. Il réalisera ensuite l'action choisie par l'administrateur en fonction de l'état de sortie de cette comparaison. Si l'état de sortie est « invalid » et que l'administrateur a configuré une politique pour affecter une local pref moindre aux annonces dont l'origine sera marquée invalide, alors la route contenue dans l'annonce recevra une local pref moindre. Il n'y a pas de traduction en ACL ou que sais-je comme la tournure de phrase le laisse supposer.

Cependant et comme l’injection de la liste de filtrage ROAs en mémoire sur un équipement semble dans bien des cas tout simplement impossible (tous les routeurs ne sont pas forcément puissants), une architecture via un cache-validateur semble donc être requise via le protocole RTR (RPKI/Router Protocol).

Aucun rapport. L'injection des assertions contenues dans les ROA consomme de la RAM quelle que soit la manière dont on les transmet au routeur (RTR, manuellement, ...). Les caches-validateurs sont là pour déporter le travail de récupération et de validation cryptographique des objets de la RPKI.

Le cache/validateur ne revoit que les ROAs pour des AS donnés, la décision de routage restant à la décision du routeur via sa configuration

Non. Le cache-validateur envoie au routeur toutes les assertions contenues dans les ROA qu'il a réussi à valider cryptographiquement.

Nous sommes arrivés à la fin de l'article.

[1] La commande « show tcp tcb <tcb> » affiche : « Mininum incoming TTL 254, Outgoing TTL 255 » lors de l'utilisation de la fonctionnalité « ttl-security hops 1 ».

RPKI+ROA et BIRD pour s’amuser

Aujourd'hui, nous allons voir comment utiliser RPKI+ROA avec BIRD et plus précisément comment prendre en compte les autorisations signées que sont les ROA comme éléments supplémentaires pour prendre une décision lors de la construction de la table de routage.

Table des matières

Si vous ne savez pas bien ce qu'est RPKI+ROA : sécuriser le routage sur Internet - RPKI+ROA.

On ne traitera pas de la manière de créer ses objets signés (ROA, Ghostbusters) quand on est opérateur ou LIR. Des pistes sont données dans le travail linké ci-dessus mais ça reste dans le cadre d'une maquette.

On se concentrera uniquement sur BIRD, une mise en pratique avec Quagga ayant déjà était réalisée dans le travail linké ci-dessus.

Pour sortir un peu du monde des maquettes, nous mettrons ça en pratique sur l'infra d'ARN, FAI associatif en Alsace. 🙂

« Pour s'amuser » dans le titre de ce billet signifie que ce que je vais vous présenter n'est pas la bonne manière de faire en production (exemples : programme additionnel, choix du cache-validateur, sécurité du dernier kilomètre, ...) et que ce billet rapporte juste une expérience, un délire, une envie de découvrir et de mettre en pratique, bref, un truc fait "for ze fun". Bref, ne suivez pas ce billet pour faire prendre des décisions de routing à des routeurs en production.

Bout d'essai

Nous allons créer une table destinée à stocker les VRP (les assertions « tel AS est autorisé à être à l'origine de tels préfixes » qui sont les contenus des ROA (VRP = Validated ROA Payload)) dans BIRD puis nous ferons prendre à BIRD une décision en fonction de la validité (ou non) d'une annonce BGP conformément à une assertion.

Dans bird6.conf (c'est pareil avec bird.conf, juste que c'est v4), on ajoute :

roa table testroa {
        roa 2001:660::/32 max 32 as 64501; # RENATER
}

On déclare donc une table des VRP nommée « testroa ». On la remplit avec une assertion : l'allocation v6 de RENATER doit être originée par l'AS 64501 (ASN faisant partie des ASN réservés à l'IANA pour faire des tests). On est d'accord que c'est faux (ASN de RENATER = 2200) mais, dans RPKI+ROA, les assertions font foi : pour BIRD, ça sera l'annonce BGP qu'il recevra qui sera incorrecte et non l'inverse.

Dans BIRD, l'opérateur « roa_check() » permet d'examiner la conformité d'une annonce BGP vis-à-vis d'une table de VRP (source : documentation BIRD - opérateurs). Il sort selon les 3 états normalisés (RFC 6811) :

  • ROA_UNKNOWN : aucun VRP ne couvre le préfixe annoncé.
  • ROA_VALID : au moins un VRP couvre le préfixe annoncé et l'AS d'un VRP correspond à l'AS "d'origine" indiqué dans l'annonce BGP.
  • ROA_INVALID : au moins un VRP couvre le préfixe annoncé mais aucun n'indique l'AS "d'origine" indiqué dans l'annonce BGP.

On peut donc utiliser roa_check() dans un filtre. Chez ARN, on a déjà un filtre en entrée de nos transitaires qui appelle plusieurs fonctions (une pour filtrer les martians, une pour forcer l'IP de sortie, ...). Voici le montage approximatif que l'on aura :

function verif_roa_test()
{
#       Nos manipulations avec les ROA.
}
 
filter cleaner 
{
        if avoid_martians() then
                accept;
 
        [...]
 
        if verif_roa_test() then
                accept;
 
        reject;
}
 
protocol bgp transitaire1 {
        debug all;
        description "transitaire1";
 
        local as 60630;
        neighbor 2001:db8::1 as 64502;
 
        import filter cleaner; 
        export filter arn_subnet;
}

Alors oui, on n'est pas obligé de faire une fonction mais on tient à laisser le filtre le plus clair possible.

Dans verif_roa_test(), nous pouvons mettre ce que nous voulons. Exemple :

if roa_check(testroa) = ROA_INVALID then return false;
 
return true;

Ici, si la vérification sort avec un état « invalide », l'annonce correspondante sera ignorée.

Pour vérifier, il suffit de demander à BIRD de relire la configuration et de créer la table des VRP (configure soft) puis de re-analyser chaque annonce (restart <nom_protocol>) :

# bird6c 
bird> configure soft
Reading configuration from /etc/bird6.conf
Reconfigured.
bird> restart transitaire1

On patiente un peu et on demande :

bird> show route 2001:660::/32
Network not in table
bird>

L'annonce concernant l'allocation v6 de RENATER a bien été ignorée car l'AS qui prétend en être à l'origine (2200) ne correspondait pas à celui indiquée dans l'assertion présente dans la table (AS 64501). Si vous n'obtenez pas ce comportement, alors vous recevez certainement une annonce pour cette alloc' via une autre session BGP (peering, autre transitaire).

Évidement, cet exemple est mauvais : un opérateur préférera toujours la connectivité à la sécurité car c'est son rôle : fournir de la connectivité. Donc, il ne faut pas rejeter les annonces dans le cas d'une vérification qui sort avec l'état « ROA_INVALID ». Je doute que ces annonces soient rejetées un jour sur des routeurs de production. Le fait de rejeter ces annonces ne permet aucune tolérance aux erreurs (erreur humaine dans la RPKI, erreur matérielle dans la RPKI, erreur humaine dans la création des ROA, ROA qui ne correspondent plus à la topologie, ...).

Le mieux est de leur attribuer une préférence locale différente permettant d'établir une hiérarchie : VALID > UNKNOWN > INVALID. Ainsi, si seulement une annonce invalide parvient au routeur, le préfixe de celle-ci sera quand même ajouté à la table de routage. Si des annonces valide et invalide cohabitent (ce qui est le cas lors d'une attaque par détournement de préfixe), alors l'annonce valide sera privilégiée.

Exemple de mise en pratique :

function verif_roa_test()
{
        if roa_check(testroa) = ROA_INVALID then bgp_local_pref = 90;
 
        if roa_check(testroa) = ROA_UNKNOWN then bgp_local_pref = 100;
 
        if roa_check(testroa) = ROA_VALID then bgp_local_pref = 110;
 
        return true;
}

Demandez à BIRD de recharger sa configuration et de re-analyser toutes les annonces et vous verrez que l'allocation v6 de RENATER se voit affecter une local-pref de 90 :

show route all 2001:660::/32
2001:660::/32      via 2001:db8::1 on eth0 [transitaire1 Oct03] * (100) [AS2200i]
	Type: BGP unicast univ
	BGP.origin: IGP
        [...]
	BGP.local_pref: 90 
        [...]

Soyez plus dynamique svp !

Bon, la vérification de la conformité des annonces vis-à-vis des VRP fonctionne mais si l'on doit ajouter toutes les assertions à la main ... Les routeurs doivent récupérer automatiquement ces assertions depuis un cache-validateur. Le protocole utilisé est RTR (RPKI To Router). Les routeurs doivent implémenter ce protocole. Ce n'est pas encore le cas de BIRD.

Néanmoins, BIRD permet de mettre à jour dynamiquement une table de VRP grâce à des commandes dans birdc(6) :

  • flush roa table <nom_table> : vider une table de toutes les assertions ajoutées dynamiquement (donc pas celles ajoutées depuis le fichier de configuration).
  • add roa <prefixe> max <int_max> as <ASN> table <nom_table> : ajouter une assertion dans une table.
  • del roa <prefixe> max <int_max> as <ASN> table <nom_table> : supprimer une assertion dans une table.

Il nous faut donc écrire un petit programme qui se connecte à un cache-validateur et, en fonction de ce qu'il reçoit, ajoute ou supprime des assertions dans notre table dans BIRD en utilisant birdc(6).

La RTRlib permet de se simplifier le travail puisqu'elle prend en charge la connexion à un cache-validateur et la réception des VRP. Je ne vous explique pas comment installer cette lib, c'est déjà très bien expliqué sur le wiki officiel : installation - RTRlib.

rtrclient est un petit logiciel fourni avec la RTRlib qui permet de la tester. Il se contente d'afficher les VRP qu'il récupère depuis un cache-validateur. Il suffit donc de modifier ce programme pour notre usage. En réalité, je me suis contenté :

  • D'ajouter un « flush roa table testroa » lors de l'initialisation pour éviter tout problème (programme qui plante, état incomplet, ...).
  • De commenter l'affichage « Prefix Prefix Length ASN ».
  • De modifier la fonction de callback « update_cb » pour changer l'action à exécuter pour chaque ajout ou suppression d'une assertion.

ÉDIT du 20/12/2016 à 20h30 : Sinon, de nos jours, on utilise bird-rtrlib-cli qui fait pile poil le même travail mais avec du code plus robuste et en lequel avoir confiance. Fin de l'édit.

Ce n'est pas du grand art mais ça fait le job :

#include <stdlib.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include "rtrlib/rtrlib.h"
 
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
 
static void print_usage(char** argv){
    printf("Usage:\n");
    printf(" %s tcp <host> <port>\n", argv[0]);
 
    printf("\nExamples:\n");
    printf(" %s tcp rpki.realmv6.org 42420\n", argv[0]);
}
 
 
static void update_cb(struct pfx_table* p __attribute__((unused)), const pfx_record rec, const bool added){
    char ip[INET6_ADDRSTRLEN];
    ip_addr_to_str(&(rec.prefix), ip, sizeof(ip));
 
    char buff[100];
 
    if(added)
        sprintf(buff, "add roa %s/%u max %u as %u table testroa", ip, rec.min_len, rec.max_len, rec.asn);
    else
        sprintf(buff, "delete roa %s/%u max %u as %u table testroa", ip, rec.min_len, rec.max_len, rec.asn);
 
    if (fork() > 0)
    {
        /* On ne veut pas d'affichage informatif donc on redirige stdout vers /dev/null */
        int fd = open("/dev/null", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
        dup2(fd, 1);
        close(fd);
 
        if (rec.prefix.ver == IPV6)
	    execl("/usr/sbin/birdc6", "/usr/sbin/birdc6", buff, (char *) NULL);
	else
	    execl("/usr/sbin/birdc", "/usr/sbin/birdc", buff, (char *) NULL);
    }
}
 
 
 
int main(int argc, char** argv){
    enum mode_t { TCP, SSH } mode;
    char* host;
    char* port;
    char* user;
    char* privkey;
    char* pubkey;
    if(argc == 1){
        print_usage(argv);
        return(EXIT_FAILURE);
    }
 
    if(strncasecmp(argv[1], "tcp", strlen(argv[1])) == 0){
        if(argc != 4){
            print_usage(argv);
            return(EXIT_FAILURE);
        }
        mode = TCP;
        host = argv[2];
        port = argv[3];
 
    }
    else if(strncasecmp(argv[1], "ssh", strlen(argv[1])) == 0){
        if(argc != 7){
            print_usage(argv);
            return(EXIT_FAILURE);
        }
 
        mode = SSH;
        host = argv[2];
        port = argv[3];
        user = argv[4];
        privkey = argv[5];
        pubkey = argv[6];
    }
    else{
        print_usage(argv);
        return(EXIT_FAILURE);
    }
 
    tr_socket tr_sock;
    if(mode == TCP){
        tr_tcp_config config = {
            host,
            port,
        };
        tr_tcp_init(&config, &tr_sock);
    }
 
 
    rtr_socket rtr;
    rtr.tr_socket = &tr_sock;
 
    rtr_mgr_group groups[1];
    groups[0].sockets_len = 1;
    groups[0].sockets = malloc(1 * sizeof(rtr_socket*));
    groups[0].sockets[0] = &rtr;
    groups[0].preference = 1;
 
    rtr_mgr_config conf;
    conf.groups = groups;
    conf.len = 1;
 
 
    /* On vide la table pour éviter tout problème */
    if (fork() > 0)
        execl("/usr/sbin/birdc", "/usr/sbin/birdc", "flush roa table testroa", (char *) NULL);
    if (fork() > 0)
        execl("/usr/sbin/birdc6", "/usr/sbin/birdc6", "flush roa table testroa", (char *) NULL);
 
 
    rtr_mgr_init(&conf, 1, 520, &update_cb);
    rtr_mgr_start(&conf);
    //printf("%-40s %3s %3s %3s\n", "Prefix", "Prefix Length", "", "ASN");
    pause();
    rtr_mgr_stop(&conf);
    rtr_mgr_free(&conf);
    free(groups[0].sockets);
 
    return(EXIT_SUCCESS);
}

Je ne suis pas satisfait de l'absence de contrôle des valeurs de retour des appels systèmes, du traitement du buffer et des optimisations restantes. Mais je relativise : c'est juste un PoC et je m'en remets au formalisme et à la rigueur de la RTRlib.

Pour le compiler :

gcc rtrclient-bird.c -o rtrclient-bird -lrtr

Pour l'exécuter (exemple) :

./rtrclient-bird tcp rpki.realmv6.org 42420

Dans cet exemple, j'utilise le cache-validateur mis à disposition par les devs de la RTRlib. Je le fais sans sécurité ce qui est très mal dans un contexte de production surtout quand le cache-validateur n'est pas sur le même réseau L2 que le routeur ! Je signale que le cache-validateur rpki.realmv6.org peut aussi être utilisé over SSH. Voir : RTRlib - Usage.

Ce programme est un peu violent à son lancement : environ 6800 ROA à l'heure actuelle donc 6800 « birdc(6) roa add » donc 6800 fork() + exec() ... Mais en vitesse de croisière, avec +/- 1 ROA par-ci, par-là, ça se passe gentiment.

Pensez à supprimer/commenter le préfixe v6 de RENATER de votre table de VRP et à demander un « configure soft » à BIRD.

Voilà : la table des assertions dans BIRD se remplit toute seule et se maintient à jour toute seule (aussi longtemps que vit le programme rtrclient-bird). À partir de maintenant, BIRD prendra en compte ces assertions en fonction de votre filtre. Pour que ça soit rétroactif, il faut « restart <nom_protocol> ».

Faire des stats

Ce qu'on a vu plus haut, c'est du bonus, pour découvrir. Ce n'est clairement pas une bonne idée de faire tourner l'assemblage présenté ci-dessus (un logiciel maison mal-codé non-revu et qui ne sera pas suivi, une librairie installée en dehors d'un système de paquets, ...) sur une machine en production et surtout de baser une partie du processus de choix des routes sur cet assemblage.

Ce que je voulais obtenir, en vrai, c'est des statistiques comme celles de LACNIC ou celles du RIPE (exemple). Parce que c'est sympa d'avoir ses stats personnelles, que c'est formateur de chercher à les obtenir et aussi parce que l'outil de LACNIC est souvent en rade. ÉDIT du 20/12/2016 à 20h30 : Depuis son apparition en 2013, l'observatoire de la résilience de l'Internet français mesure aussi le déploiement de RPKI+ROA. Fin de l'édit.

Et faire des stats, ça ne nécessite pas d'utiliser les VRP comme une donnée supplémentaire dans le processus de sélection des routes. Vous pouvez donc commenter la fonction verif_roa_test() ou supprimer son appel par le filtre (et « reconfigure » BIRD, of course).

Afficher le nombre d'assertions

birdc "show roa table testroa" | wc -l
birdc6 "show roa table testroa" | wc -l

Afficher le nombre de préfixes par état

birdc show route where roa_check(testroa) = ROA_VALID protocol transitaire1 count
birdc6 show route where roa_check(testroa) = ROA_VALID protocol transitaire1 count
 
birdc show route where roa_check(testroa) = ROA_INVALID protocol transitaire1 count
birdc6 show route where roa_check(testroa) = ROA_INVALID protocol transitaire1 count
 
birdc show route where roa_check(testroa) = ROA_UNKNOWN protocol transitaire1 count
birdc6 show route where roa_check(testroa) = ROA_UNKNOWN protocol transitaire1 count

Il n'est pas obligatoire de spécifier un protocole, c'est juste pour éviter les doublons si vous avez plusieurs transitaires, du peering, ...

Résultats

Voilà ce que l'on obtient, en v4, sur le routeur d'ARN :

birdc "show roa table testroa" | wc -l
5881
 
bird> show route protocol transitaire1 count 
463627 of 927572 routes for 463629 networks
 
bird> show route where roa_check(testroa) = ROA_VALID protocol transitaire1 count 
17167 of 927571 routes for 463628 networks
 
bird> show route where roa_check(testroa) = ROA_INVALID protocol transitaire1 count 
1609 of 927567 routes for 463626 networks
 
bird> show route where roa_check(testroa) = ROA_UNKNOWN protocol transitaire1 count 
444851 of 927571 routes for 463628 networks

Voilà, ce que l'on obtient, en v6, sur le routeur d'ARN :

birdc6 "show roa table testroa" | wc -l
949
 
bird> show route protocol transitaire1 count
14375 of 28809 routes for 14376 networks
 
bird> show route where roa_check(testroa) = ROA_VALID protocol transitaire1 count 
879 of 28809 routes for 14376 networks
 
bird> show route where roa_check(testroa) = ROA_INVALID protocol transitaire1 count 
59 of 28807 routes for 14375 networks
 
bird> show route where roa_check(testroa) = ROA_UNKNOWN protocol transitaire1 count 
13437 of 28809 routes for 14376 networks

On constate qu'environ 8% des routes v4 dont au moins un ROA leur est associé sont invalides. On est a 6% en v6.

On obtient des chiffres assez proches de ceux de LACNIC (attention à additionner v4 et v6 si vous voulez comparer) :

Route counts for the last 24 hours
 
Current INVALID route count for all repositories: 2000
 
Bad MaxLen: 1655
 
Wrong BGP Origin AS: 345
 
Current VALID route count for all repositories: 18277

On constate qu'environ 10% des routes dont au moins un ROA leur est associé sont invalides.

ÉDIT du 26/01/2014 à 20h45 : Voici les stats récoltées aujourd'hui sur le routeur d'ARN :
En v4 :

birdc-arn "show roa table testroa" | wc -l
7005
 
bird> show route protocol transitaire1 count 
474565 of 949513 routes for 474566 networks
 
bird> show route where roa_check(testroa) = ROA_VALID protocol transitaire1 count
18640 of 949510 routes for 474567 networks
 
bird> show route where roa_check(testroa) = ROA_INVALID protocol transitaire1 count
2102 of 949498 routes for 474559 networks
 
bird> show route where roa_check(testroa) = ROA_UNKNOWN protocol transitaire1 count
453815 of 949497 routes for 474558 networks

En v6 :

birdc6-arn "show roa table testroa" | wc -l
1094
 
bird> show route protocol transitaire1 count
15978 of 32033 routes for 15979 networks
 
bird> show route where roa_check(testroa) = ROA_VALID protocol transitaire1 count
999 of 32030 routes for 15978 networks
 
bird> show route where roa_check(testroa) = ROA_INVALID protocol transitaire1 count
60 of 32031 routes for 15978 networks
 
bird> show route where roa_check(testroa) = ROA_UNKNOWN protocol transitaire1 count
14917 of 32031 routes for 15978 networks

On constate qu'environ 10% (augmentation) des routes v4 dont au moins un ROA leur est associé sont invalides. On est a 6% en v6 (stagnation).

Le site web de LACNIC est down depuis plusieurs heures et depuis plusieurs points du réseau donc impossible de comparer.
Fin de l'édit

ÉDIT du 01/03/2014 à 14h30 : Voici les stats récoltées aujourd'hui sur le routeur d'ARN :
En v4 :

birdc "show roa table testroa" | wc -l
7654
 
bird> show route protocol transitaire1 count 
478065 of 956517 routes for 478066 networks
 
bird> show route where roa_check(testroa) = ROA_VALID protocol transitaire1 count 
19182 of 956497 routes for 478056 networks
 
bird> show route where roa_check(testroa) = ROA_INVALID protocol transitaire1 count 
2045 of 956463 routes for 478040 networks
 
bird> show route where roa_check(testroa) = ROA_UNKNOWN protocol transitaire1 count 
456811 of 956463 routes for 478039 networks

En v6 :

birdc6 "show roa table testroa" | wc -l
1202
 
bird> show route protocol transitaire1 count
16413 of 32905 routes for 16414 networks
 
bird> show route where roa_check(testroa) = ROA_VALID protocol transitaire1 count 
1078 of 32905 routes for 16414 networks
 
bird> show route where roa_check(testroa) = ROA_INVALID protocol transitaire1 count 
57 of 32905 routes for 16414 networks
 
bird> show route where roa_check(testroa) = ROA_UNKNOWN protocol transitaire1 count 
15276 of 32902 routes for 16413 networks

On constate qu'environ 10% (stagnation) des routes v4 dont au moins un ROA leur est associé sont invalides. On est a 5% en v6 (diminution). v4 et v6 cumulés : 9%

En comparaison, les chiffres obtenus par LACNIC :

Route counts for the last 24 hours
 
Current INVALID route count for all repositories: 2596
 
Bad MaxLen: 2065
 
Wrong BGP Origin AS: 531
 
Current VALID route count for all repositories: 20765
 
Dataset processed on: March 1, 2014

Fin de l'édit

ÉDIT du 20/12/2016 à 20h30 : Voici les stats récoltées aujourd'hui sur le routeur d'ARN :

En v4 :

birdc "show roa table testroa" | wc -l
25822
 
bird> show route protocol transitaire1 count 
616508 of 616508 routes for 616508 networks
 
bird> show route where roa_check(testroa) = ROA_VALID protocol transitaire1 count 
40657 of 616500 routes for 616500 networks
 
bird> show route where roa_check(testroa) = ROA_INVALID protocol transitaire1 count 
3985 of 616492 routes for 616492 networks
 
bird> show route where roa_check(testroa) = ROA_UNKNOWN protocol transitaire1 count 
571869 of 616517 routes for 616517 networks

En v6 :

birdc6 "show roa table testroa" | wc -l
3650
 
bird> show route protocol transitaire1 count
34642 of 34642 routes for 34642 networks
 
bird> show route where roa_check(testroa) = ROA_VALID protocol transitaire1 count 
3745 of 34651 routes for 34651 networks
 
bird> show route where roa_check(testroa) = ROA_INVALID protocol transitaire1 count 
214 of 34652 routes for 34652 networks
 
bird> show route where roa_check(testroa) = ROA_UNKNOWN protocol transitaire1 count 
30692 of 34651 routes for 34651 networks

En comparaison, les chiffres obtenus par LACNIC :

Route counts for the last 24 hours
 
Current INVALID route count for all repositories: 4848
 
Bad MaxLen: 3575
 
Wrong BGP Origin AS: 1273
 
Current VALID route count for all repositories: 45581
 
Dataset processed on: Dec. 20, 2016

Fin de l'édit du 20/12/2016 à 20h30

Progression

En février 2012, le RIPE dénombrait environ 1800 ROA qui couvraient environ 8200 routes. Environ 40 % des routes dont au moins un ROA leur est associé étaient invalides.

En avril dernier, je dénombrais environ 3000 ROA.

Aujourd'hui, je dénombre environ 6800 ROA qui couvrent environ 19700 routes. Environ 8 % à 10 % des routes dont au moins un ROA leur est associé sont invalides.

ÉDIT du 26/01/2014 à 20h45 : Aujourd'hui, je dénombre environ 8100 ROA qui couvrent environ 21800 routes. Environ 8 % des routes dont au moins un ROA leur est associé sont invalides. Fin de l'édit.

ÉDIT du 01/03/2014 à 14h30 : Aujourd'hui, je dénombre environ 8800 ROA qui couvrent environ 22300 routes. Environ 9 % des routes dont au moins un ROA leur est associé sont invalides. Fin de l'édit.

ÉDIT du 20/12/2016 à 20h30 : Aujourd'hui, je dénombre environ 29500 ROA qui couvrent environ 48600 préfixes. Environ 8,6 % des préfixes dont au moins un ROA leur est associé sont invalides. Fin de l'édit.

Sécuriser le routage sur Internet

Aujourd'hui, je vous propose un long billet sur le routage inter-domaine, sa sécurité actuelle et RPKI+ROA.

Attention : RPKI+ROA est encore un mécanisme tout jeune. Cela signifie que, bien que les concepts de base ne changeront pas et que ce travail date de mai 2013, certaines informations contenues dans ce travail vont devenir obsolètes à plus ou moins long terme.

Pour lire la version HTML, il suffit de cliquer sur le lien "Lire la suite" (et/ou de poursuivre ci-dessous). Pour ceux qui préfèrent lire un si gros pavé en PDF, c'est par là : Sécuriser le routage sur Internet.

Je mets également les sources LaTeX à votre disposition. Ces sources LaTeX peuvent servir de base à d'autres documents. Sources.

Vous pouvez également récupérer la maquette (vous comprendrez la raison de son existence en lisant le pavé). Elle peut servir pour mieux visualiser le fonctionnement de RPKI+ROA ou pour simplement tester ses différents composants. Elle repose sur LXC. Le tar contient la maquette compressée avec LZMA ainsi que les instructions d'utilisation au format texte. Maquette RPKI-ROA. Les fichiers de configurations principaux pour refaire une maquette from scratch sont disponibles ici : Fichiers de configuration principaux de ma maquette RPKI-ROA.

Et pour terminer, vous pouvez également récupérer le visuel projeté durant ma soutenance et ses sources. Support visuel soutenance | Sources LaTeX support visuel soutenance.

Si vous voulez tout récupérer (maquette, sources, pdf) en un seul coup, c'est par là : Sécuriser le routage sur Internet - Pack all-in-one.

Le tout (les sources LaTeX, les pdf, les images, la maquette, ...) est diffusé sous la licence habituelle de ce blog, à savoir : CC-BY-SA 3.0 France.

Lire la suite >>

Mettre en place un Route Reflector BGP avec Quagga pour s’amuser

Un court billet sur comment monter un Route Reflector avec Quagga sur une maquette.

Les termes Route Reflector (RR) et Route Server (RS) sont souvent confondus et on lit de tout sur le web, même sur les sites web qui disposent d'un bon crédit de fiabilité (univ-*.fr, *.edu) : « RR c'est pour monter un looking glass derrière, de la pure collecte passive, RS c'est pour redistribuer les routes », « RR c'est au contraire collecte + redistribution intelligente », « un RR fait du traitement, un RS redistribue "as-is", dans l'état ». Bref, personne ne semble être d'accord.

Pour y voir plus clair, je vous propose les deux ressources suivantes :

Personnellement, je retiens ce qui suit :

  • Les deux sont une solution (plus ou moins complexe, plus ou moins convenable en fonction de la topologie d'un réseau) au problème du full-mesh : que ce soit en interne d'un AS ou sur un GIX, établir des sessions iBGP (ou eBGP sur un GIX) entre tous les routeurs qui causent BGP en présence, c'est juste impossible, ça ne passe pas à l'échelle.
  • Un Route Reflector fait de la redistribution "as-is", dans l'état. Le choix des meilleures routes est donc centralisé, ce qui n'est pas toujours convenable selon l'emplacement du RR dans le cluster et dans l'AS (meilleure route pour un préfixe du point de vue du RR ne veut pas dire que ce soit forcement la meilleure route pour un client, possibilité de boucle, ...).
  • Un Route Server fait aussi de la redistribution mais effectue un traitement des annonces qu'il reçoit pour chacun de ses clients. On a donc plusieurs RIB, une par client du RS. Chacune contient les meilleures routes pour un client donné. Le client participe au choix de la meilleure route pour chaque préfixe connu grâce à ses filtres (route-map, ...) en entrée. La décision n'est donc pas centralisée.
  • Un RS est plus approprié pour un GIX, un RR est plus approprié pour de la redistribution interne à un AS.

Donc nous voulons bien mettre en place un Route Reflector : un truc qui redistribue bêtement (sans traitement) toutes les routes entre tous les routeurs d'un même AS, avec des sessions iBGP. On veut une topologie avec deux RR. Les deux RR sont reliés directement entre eux. Chaque autre routeur de cette topologie monte une session iBGP avec chacun des RR, pour la redondance.

Pour l'instant, nous n'avons pas de sessions eBGP entre nos RR et l'extérieur.

Pour ceux qui ont le cœur à creuser le paramètre « cluster-id » : Understanding BGP Originator-ID and Cluster-ID. Nous ne l'utiliserons pas ici.

Informations utiles pour s'y retrouver et comprendre les fichiers de config' :

  • IP du premier RR (loopback) : 198.18.3.1/32
  • IP du premier RR (loopback) : 198.18.3.15/32
  • Clients (loopbacks) : 198.18.3.2-30/32
  • Chaque client annonce un /30 subnetté dans 198.19.0.0/16
  • Les adresses des loopback sont prises dans 198.18.3/24. 198.18.0.0/16 est annoncé via un IGP. Mais ce n'est pas ce qui nous intéresse ici.

Voici les directives de configuration qu'il faut utiliser pour monter un Route Reflector avec Quagga. Source : Virtual Laboratory Networking Exercises – BGP Route Reflector Configuration.

Fichier « bgpd.conf » du premier RR :

hostname RR1
 
line vty
	no login
 
log syslog warnings
 
 
router bgp 64500
        # Qui suis-je ?
	bgp router-id 198.18.3.1
 
 
	## RR2
	neighbor 198.18.3.15 remote-as 64500
	neighbor 198.18.3.15 description RR2
	neighbor 198.18.3.15 update-source 198.18.3.1
 
 
	## Clients
	neighbor 198.18.3.2 remote-as 64500
	neighbor 198.18.3.2 description Client-1
	neighbor 198.18.3.2 route-reflector-client
	neighbor 198.18.3.2 update-source 198.18.3.1
 
        neighbor 198.18.3.3 remote-as 64500
	neighbor 198.18.3.3 description Client-2
	neighbor 198.18.3.3 route-reflector-client
	neighbor 198.18.3.3 update-source 198.18.3.1
 
        [...]

Fichier « bgpd.conf » du second RR :

hostname RR2
 
line vty
	no login
 
log syslog warnings
 
 
router bgp 64500
        # Qui suis-je ?
	bgp router-id 198.18.3.15
 
 
	## RR1
	neighbor 198.18.3.1 remote-as 64500
	neighbor 198.18.3.1 description RR1
	neighbor 198.18.3.1 update-source 198.18.3.15
 
 
	## Clients
	neighbor 198.18.3.2 remote-as 64500
	neighbor 198.18.3.2 description Client-1
	neighbor 198.18.3.2 route-reflector-client
	neighbor 198.18.3.2 update-source 198.18.3.15
 
	neighbor 198.18.3.3 remote-as 64500
	neighbor 198.18.3.3 description Client-2
	neighbor 198.18.3.3 route-reflector-client
	neighbor 198.18.3.3 update-source 198.18.3.15
 
        [...]

Fichier « bgpd.conf » d'un client (c'est pareil pour tous les autres clients) :

hostname C1
 
line vty
	no login
 
log syslog warnings
 
 
router bgp 64500
        # Qui suis-je ?
	bgp router-id 198.18.3.2
	network 198.19.0.0/30
 
 
        ## RR
	neighbor 198.18.3.1 remote-as 64500
	neighbor 198.18.3.1 description RR1
	neighbor 198.18.3.1 update-source 198.18.3.2
 
	neighbor 198.18.3.15 remote-as 64500
	neighbor 198.18.3.15 description RR2
	neighbor 198.18.3.15 update-source 198.18.3.2

Mesurer la propagation d’une annonce BGP pour s’amuser

Les copains d'Alsace Réseau Neutre, FAI associatif neutre en Alsace ont racké leurs machines en début de semaine et ils ont monté leur première session BGPoIPv4 hier soir. L'idée m'est venue de constater le temps de propagation de leur préfixe à travers les Internets.

Table des matières

Que mesure-t-on ?

Je précise d'abord, pour les mesures-nazi qui passeraient par là, que je ne cherche pas à faire une mesure précise et fiable. L'idée n'est pas de démontrer quelque chose ni d'argumenter une publication scientifique. On est plus dans le domaine du "for ze fun" parce que, oui, voir son préfixe apparaître dans les tables de routage de routeurs à l'autre bout du monde, c'est beau. :')

Et puis avoir une idée et voir les outils disponibles pour la réaliser, c'est formateur.

L'idée est donc de voir comment/à quelle vitesse se propage la première annonce BGP d'ARN de routeur de bordure en routeur de bordure, à travers les Internets.

Nous chercherons à obtenir une chronologie de la propagation. Exemple fictif :
21h00m00 : ARN lance la session BGP.
21h00m49 : Le préfixe apparaît chez notre transitaire
.... : le préfixe apparaît dans tel point d'échange européen
.... : le préfixe apparaît la table d'un routeur à Sydney
Etc, etc.

Comment mesure-t-on ?

On sent, de manière assez intuitive, que la mesure doit être faite depuis d'autres réseaux.

Plusieurs idées peuvent venir en tête :

  • On peut utiliser des looking glasses ou des traceroute mis à la disposition par des opérateurs. Exemples : le préfixe v4 d'ARN dans le looking glass du FAI associatif toulousain Tetaneutral.net, traceroute.org. Inconvénient : à part un mass-F5-autoreload, ça me semble difficilement automatisable.
  • On peut utiliser le service Routing Information Service (RIS) du RIPE. Exemple : le préfixe v4 d'ARN dans RIS (on remarquera au passage qu'il y a une annonce large invalide dans la nature : 88.0.0.0/6 par 3303 depuis le 20/04/2013 ). C'est simple mais ça ne permet pas d'obtenir la chronologie que nous voulons. ÉDIT du 19/07/2013 à 10h30 : En revanche, l'outil BGPlay permet une visualisation très sympathique de la timeline. Exemple : le préfixe v4 d'ARN dans BGPlay. Fin de l'édit
  • On peut utiliser les routeurs en accès libre du projet Route Views. Avec l'outil ctel (du package cssh dont je vous ai déjà parlé), il est possible d'exécuter la même commande en parallèle sur plusieurs collecteurs du projet Route-Views. Le projet permet même de récupérer les archives des annonces BGP vues par les différents collecteurs du projet. Les archives sont disponibles par tranches de 15 minutes.
  • Utiliser les sondes du projet Atlas du RIPE pour lancer un traceroute depuis plusieurs points des Internets. Le résultat doit être intéressant mais je n'ai ni sonde, ni crédit.

Déroulement

RIS

Rien de spécial à faire : à partir du lancement du démon de routing (BIRD dans le cas d'ARN), il suffit de recharger la page à une fréquence donnée.

Route-Views

Avant l'instant I, il suffit de préparer ctel en ajoutant les routeurs que l'on souhaite interroger dans .clusterssh/clusters. Exemple :

ARN-test route-views.sydney.routeviews.org route-views.saopaulo.routeviews.org route-views2.routeviews.org rpki-rtr.ripe.net

Les lecteurs attentifs remarqueront rpki-rtr.ripe.net qui n'est pas un collecteur du projet Route-Views mais un routeur Cisco mis à disposition par le RIPE pour jouer avec RPKI+ROA. L'username est ripe, sans mot de passe.

Peu avant le lancement du démon de routing, il suffira de se connecter aux machines :

ctel ARN-test

et de saisir :

show bgp ipv4 unicast 89.234.141.0/24

ou

show bgp ipv6 [unicast] 2a00:5881:8100::/40

Il faudra maintenir les connexions avec une activité car il y a des timeout. 😉

Suite au lancement de BIRD, il suffit normalement de relancer la commande plusieurs fois (fleche haut-entrée, classique) pour voir les différences.

Archives Route-Views

Les archives sont au format MRT. Il nous faut donc un outil pour les lire. J'ai choisi arbitrairement bgpparser. Attention : la version 0.3b2 distribuée sur le site officiel ne compile pas.

On installe les dépendances nécessaires :

sudo apt-get update && sudo apt-get install libxml2 libxml2-dev liblog4cxx10 liblog4cxx10-dev libboost-all-dev git

On récupère le dépôt git :

git clone https://github.com/cawka/bgpparser.git

Les commandes classiques :

./bootstrap.sh
./configure

make
sudo make install

Il faut penser à ajouter /usr/local/lib en tant que dossier où chercher des bibliothèques (/usr/local/lib est déjà indiqué dans /etc/ld.so.conf.d/libc.conf sinon, il faudrait le faire nous même avant de lancer la commande) :

ldconfig

Ensuite, il suffit de récupérer une archive. Comme écrit sur la page web du projet Route-Views : de nos jours, les fichiers sont nommés en fonction de l'heure UTC (bon, il y a une exception mais ce n'est pas important ici 😛 ). Donc pour un événement qui s'est produit vers 20h31/20h32 UTC+2 le 17 juillet 2013, il faut récupérer un fichier de la forme : updates.20130717.1830.bz2. Ce fichier couvre donc de 20h30 à 20h44m59s UTC+2 du 17 juillet 2013 pour un collecteur donné.

Pour le collecteur de Sydney, on aura donc :

wget http://archive.routeviews.org/route-views.sydney/bgpdata/2013.07/UPDATES/updates.20130717.1830.bz2

Il ne reste plus qu'à lire ce fichier :

bgpparser2 --file updates.20130717.1830.bz2 --ipv4 | grep 89.234.141.0/24

BGP4MP|1374085909|A|202.167.228.20|4739|89.234.141.0/24|4739 3356 1299 42456 60630|IGP|202.167.228.20|0|0|4739:0|NAG||

BGP4MP|1374085922|A|202.167.228.74|4826|89.234.141.0/24|4826 6939 42456 60630|IGP|202.167.228.74|0|0|4826:5901 4826:6150|NAG||

BGP4MP|1374085924|A|202.167.228.37|38809|89.234.141.0/24|38809 2914 1299 42456 60630|IGP|202.167.228.37|0|0|2914:420 2914:1005 2914:2000 2914:3000 65504:1299|NAG||

BGP4MP|1374085930|A|202.167.228.44|10026|89.234.141.0/24|10026 1299 42456 60630|IGP|202.167.228.44|0|10051|10026:3050 10026:31840 10026:40903|NAG||

BGP4MP|1374085936|A|202.167.228.20|4739|89.234.141.0/24|4739 1239 1299 42456 60630|IGP|202.167.228.20|0|0|4739:0|NAG||

BGP4MP|1374086082|A|202.167.228.44|10026|89.234.141.0/24|10026 1299 42456 60630|IGP|202.167.228.44|0|10052|10026:3050 10026:31840 10026:40912|NAG||

ÉDIT du 19/07/2013 à 12h30 :
ou

bgpparser2 --file updates.20130719.0915.bz2 --ipv6 | grep 2a00:5881:8100::/40

BGP4MP|1374226150|A|2001:12f8::20|28571|2a00:5881:8100::/40|28571 1251 20080 6939 42456 60630|IGP|2001:12f8::20|0|0||NAG||

BGP4MP|1374226150|A|2001:12f8::218:21|52888|2a00:5881:8100::/40|52888 1251 20080 6939 42456 60630|IGP|2001:12f8::218:21|0|0||NAG||

BGP4MP|1374226150|A|2001:12f8::20|28571|2a00:5881:8100::/40|28571 1251 20080 6939 1299 42456 60630|IGP|2001:12f8::20|0|0||NAG||

BGP4MP|1374226150|A|2001:12f8::20|28571|2a00:5881:8100::/40|28571 22548 3549 1299 42456 60630|IGP|2001:12f8::20|0|0|3549:2471 3549:30840|NAG||

BGP4MP|1374226150|A|2001:12f8::218:21|52888|2a00:5881:8100::/40|52888 1251 20080 6939 42456 60630|IGP|2001:12f8::218:21|0|0||NAG||

BGP4MP|1374226150|A|2001:12f8::20|28571|2a00:5881:8100::/40|28571 1916 6939 42456 60630|IGP|2001:12f8::20|0|0|1916:1250|NAG||

[...]

Fin de l'édit

On a : le type de message, le timestamp du message, le sous-type (ajout de route (« A »), suppression (« W »)), l'IP du peer, l'ASN du peer puis le message BGP qui se décompose en préfixe, AS_PATH, origine, next-hop, localpref, MED, communautés, pas d'aggrégation (« NAG »).

Pour convertir le timestamp, utilisez votre langage favori (troll inside) comme :

php -r 'echo date ("d/m/Y H:i:s", "1374085909")."\n";'
17/07/2013 20:31:49

Comme c'est tout bien classé par ordre chronologique, on voit que le collecteur de Sydney a reçu la première annonce d'ARN à 20h31m49s.

Donc, les résultats ?

(Temps en UTC+2)

RIS

20h31m?s : lancement de BIRD (première vue : 2013-07-17 20:31:48)
21h : 76% de visibilité
21h30 : 89% de visibilité
22h : 97% de visibilité

Route-Views

IPv4

LINX : 17/07/2013 à 20:31:48
São Paulo : 17/07/2013 à 20:31:48
Sydney : 17/07/2013 à 20:31:49
Oregon : 17/07/2013 à 20:32:07
Tokyo : 17/07/2013 à 20:32:17

IPv6

(Pour les curieux : non, nous ne considérons pas l'annonce du 19/07/2013 à 00h20 comme étant la première)

LINX : 19/07/2013 à 11:29:09
São Paulo : 19/07/2013 à 11:29:10
Sydney : 19/07/2013 à 11:29:09
Oregon : 19/07/2013 à 11:29:09
Tokyo : 19/07/2013 à 11:29:21

J'avais toujours entendu dire qu'il fallait 3 à 4 minutes pour qu'un préfixe nouvellement annoncé apparaisse dans 90% des réseaux des Internets. Avec cette mise en pratique, je constate que c'est jouable en 1 minute. 🙂 Bon, ok, les sessions BGP avec notre transitaire étaient déjà montées au moment du reload de BIRD qui a provoqué l'annonce. Forcement, on gagne un peu. 😀

Atlas

ÉDIT du 19/07/2013 à 12h30 :
Merci à Stéphane Bortzmeyer.

IPv4 :

Monde :
 
Measurement #1013491 to 89.234.141.1 uses 400 probes
400 probes reported
Test done at 2013-07-19T08:16:35Z
Tests: 398 successful tests (99.5 %), 0 errors (0.0 %), 2 timeouts (0.5 %), average RTT: 71 ms
 
Europe :
 
Measurement #1013493 to 89.234.141.1 uses 399 probes
399 probes reported
Test done at 2013-07-19T08:21:20Z
Tests: 398 successful tests (99.7 %), 0 errors (0.0 %), 1 timeouts (0.3 %), average RTT: 52 ms
 
Asie (toujours moins bien) :
 
Measurement #1013494 to 89.234.141.1 uses 114 probes
113 probes reported
Test done at 2013-07-19T08:24:20Z
Tests: 107 successful tests (94.7 %), 0 errors (0.0 %), 6 timeouts (5.3 %), average RTT: 298 ms
 
Measurement #1013495 to 89.234.141.1 uses 115 probes
115 probes reported
Test done at 2013-07-19T08:43:21Z
Tests: 112 successful tests (97.4 %), 0 errors (0.0 %), 3 timeouts (2.6 %), average RTT: 298 ms

IPv6 :

Monde : 
 
Measurement #1013513 to 2a00:5881:8100::1 uses 396 probes
396 probes reported
Test done at 2013-07-19T13:22:53Z
Tests: 344 successful tests (86.9 %), 17 errors (4.3 %), 35 timeouts (8.8 %), average RTT: 71 ms

Fin de l'édit

ÉDIT du 26/10/2013 à 16h30 :
D'autres stats IPv6 homemade cette fois-ci :

Monde : 
392 probes, 938 successful tests (79.8 %), 144 errors (12.3 %), 93 timeout (7.9 %), average RTT: 75
 
Europe : 
396 probes, 971 successful tests (81.6 %), 114 errors (9.6 %), 105 timeout (8.8 %), average RTT: 51
 
Asie : 
52 probes, 119 successful tests (76.3 %), 27 errors (17.3 %), 10 timeout (6.4 %), average RTT: 314
 
Amérique :
151 probes, 295 successful tests (65.1 %), 93 errors (20.5 %), 65 timeout (14.3 %), average RTT: 146

Fin de l'édit

Conclusion

Je vais être bref : expérience enrichissante.