lalahop

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 ».

Ce billet présente les quelques changements qui surviennent avec la nouvelle version stable d'OpenWRT. Je sais, je suis un peu en retard de plus d'un an m'enfin bon ... 😛

Table des matières

Ce billet est dans la continuité de mes autres billets sur OpenWRT et notamment de ce billet : Créez votre image personnalisée d’OpenWRT : ce qui change avec Backfire 10.03.1. Référez-vous à ces billets si quelque chose ne vous semble pas clair dans ce billet.

Ce qui change / ce que je change

Depuis tout ce temps, il y a eu des mises à jour que ça soit pour la sécurité ou le confort. Passer de Backfire à Attitude Adjustment permet d'en profiter.

Je ne souhaite plus faire de DROP en output sauf ce qui est autorisé. Je souhaite tout autoriser en sortie. D'un point de vue de la sécurité pure, c'est une perte. D'un point de vue du confort des utilisateurs placés derrière ce firewall, c'est un gain. Et comme je ne suis plus le seul utilisateur de ce réseau ... Il suffira de modifier le script /etc/init.d/firewall qui positionne les règles.

J'aurais souhaité remplacer mon récursif-cache DNS actuel, djbdns dnscache, par un autre, comme Unbound. La raison est que dnscache ne supporte pas des types d'enregistrements (exemple : NAPTR) et surtout, il ne fait pas de validation DNSSEC. Malheureusement, en choisissant Unbound et Unbound-anchor, la taille de l'image générée est de 4,5M. En supprimant LuCi, je peux tomber à 4,1M. Dans tous les cas, l'image est trop imposante pour mon WRT54GL. Donc il n'y aura pas encore de récursif-cache validant sur ce réseau puisque je suis contraint de rester avec dnscache.

Je n'ai plus besoin du package ddns-scripts proposé par OpenWRT car je n'utilise plus DynDNS (ou un autre service équivalent) mais ma propre méthode. Il faudra simplement créer le fichier /etc/crontab/root et placer la clé privée dans l'arborescence de Buildroot comme indiqué dans le billet linké.

J'effectuerai la compilation dans un tmpfs. Cela permet un gain important, notamment quand vous utilisez une machine qui est limitée par ses IO disk comme moi. La compilation utilise ccache. Il faudra le configurer car, par défaut, il met ses fichiers dans le home directory de l'utilisateur ... donc le gain du tmpfs dans ce cas-là est quasi-nul ...

Recréer l’image officielle

Presque rien ne change par rapport à mon billet sur Backfire à part l'utilisation d'un tmpfs et quelques URL.

Nous allons d'abord préparer notre Debian Wheezy (qui est devenue stable, depuis 😉 ) pour recevoir Buildroot :

sudo apt-get install asciidoc autoconf bison build-essential fastjar flex gawk gettext git-core intltool libextutils-autoinstall-perl libncurses5-dev libssl-dev libtool subversion zlib1g-dev

Nous allons créer le tmpfs (source : tmpfs : utiliser sa RAM comme répertoire de stockage. - Génération Linux. Personnellement, /tmp utilise déjà tmpfs. J'augmente donc simplement sa taille :

sudo mount -t tmpfs -o remount,size=7G tmpfs /tmp

En dessous de 8G de RAM, oubliez l'idée d'un tmpfs car la compilation du toolchain, du noyau et des packages que je sélectionne occupe facilement 5G/5,5G. Avec 8G de RAM, vous pouvez avoir un tmpfs de 7G qui vous permettra de compiler le cross-compiler, le noyau et les packages que vous voudrez (j'insiste : vous ne pourrez pas compiler tous les packages en "module").

Avec 7G sur 8G attribués au tmpfs, faites attention à ne pas lancer des applications gourmandes en RAM comme Firefox ou Eclipse (au pif hein 😛 ) en parallèle sinon le noyau va s'énerver et vous allez recevoir la visite de l'OOM Killer.

On se positionne dans notre tmpfs, on récupère les sources d'Attitude Adjustment (pour connaître l'adresse des dépôts : GetSource - OpenWrt) puis on se positionne dans le dossier des sources :

cd /tmp
svn co svn://svn.openwrt.org/openwrt/branches/attitude_adjustment
cd attitude_adjustment/

Dans la suite de ce billet, sauf mention contraire, je considérerai que votre répertoire courant est attitude_adjustment, c'est-à-dire la racine du buildroot.

On s'assure que tout le nécessaire est bien présent :

make defconfig && make prereq

On met à jour la liste des packages disponibles :

./scripts/feeds update -a && ./scripts/feeds install -a

Ensuite, on efface les fichiers de configuration de la compilation (créés automatiquement par make menuconfig, par exemple, nous y reviendrons) :

rm .config && rm .config.old

On récupère le fichier de configuration officiel (ici : déclinaison brcm47xx) :

wget http://downloads.openwrt.org/attitude_adjustment/12.09/brcm47xx/generic/config.brcm47xx_generic -O .config

Pour raccourcir le temps de la compilation, on désactive la compilation de l'image builder (« Build the OpenWrt Image Builder ») et du SDK (« Build the OpenWrt SDK ») :

make menuconfig

Par défaut, tous les packages sont compilés (en module) puis exclus de l’image finale. Pour éviter cette perte de temps lors de la compilation, on va demander à ce que les packages qui ne seront pas intégrés à l’image ne soient pas compilés. Pour cela, on commente les lignes qui finissent par “=m” (module) avec la commande suivante :

sed -i 's,^.*=m,# & is not set,g' .config

On configure ccache pour écrire dans le tmpfs au lieu du home directory de l'utilisateur courant :

export CCACHE_DIR=/tmp/.ccache

On lance la compilation :

make -j 9

La compilation va se vautrer :

make[3] -C package/dnsmasq compile
make -r world: build failed. Please re-run make with V=s to see what's going on
make: *** [world] Erreur 1

Je n'ai pas creusé l'origine de cette erreur mais il suffit de relancer la compilation (avec la même commande que ci-dessus) et cette fois, ça se passe sans emcombres.

Ajouter/supprimer des packages

Je garde les mêmes logiciels qu'avant (à l'exception de ddns-scripts, comme expliqué ci-dessus) et je ne supprime plus ppp/ppp-mod-pppoe (ce cela me semble être sans effet mais je n'ai pas creusé la question). Donc ça nous donne :

  • etherwake dans Network.
  • tcpdump-mini dans Network.
  • djbdns-dnscache dans Network -> IP adresses and Names.
  • ntpd dans Network -> Time Synchronization.
  • iptables-mod-conntrack-extra dans Network -> Firewall -> Iptables.
  • luci-i18n-french dans LuCi -> Translations

Je me suis rendu compte que Busybox intègre un serveur NTP minimaliste qui ne fournit pas le support des queries (il ne répond pas aux requêtes d'administration) ni les tools additionnels qui vont bien (ntpq par exemple). Source : NTP client/ NTP server sur le Wiki OpenWRT. Comme je souhaite conserver l'implé ntpd "classique" de l'université du Delaware (pour la possibilité de monitoring / de jouer avec ntpq principalement et aussi car c'est une valeur sûre à mes yeux depuis le temps que je l'utilise), je désactive le support NTP de Busybox dans base system -> busybox -> Networking utilities

On lance la compilation avec la méthode habituelle :

sed -i 's,^.*=m,# & is not set,g' .config
make -j9

La compilation va planter sur OpenSSL (qui est activé et compilé par dépendance pour ntpd, même si vous n'avez pas coché le support ntpd-ssl, mais qui ne sera pas intégré à l'image finale semble-t-il) :

make[6]: Entering directory `/media/montmpfs/attitude_adjustment/build_dir/target-mipsel_uClibc-0.9.33.2/openssl-1.0.1e/crypto/sha'
ccache_cc -I.. -I../.. -I../modes -I../asn1 -I../evp -I../../include  -fPIC -DOPENSSL_PIC -DZLIB_SHARED -DZLIB -DDSO_DLFCN -DHAVE_DLFCN_H -I/media/montmpfs/attitude_adjustment/staging_dir/target-mipsel_uClibc-0.9.33.2/usr/include -I/media/montmpfs/attitude_adjustment/staging_dir/target-mipsel_uClibc-0.9.33.2/include -I/media/montmpfs/attitude_adjustment/staging_dir/toolchain-mipsel_gcc-4.6-linaro_uClibc-0.9.33.2/usr/include -I/media/montmpfs/attitude_adjustment/staging_dir/toolchain-mipsel_gcc-4.6-linaro_uClibc-0.9.33.2/include -DOPENSSL_SMALL_FOOTPRINT -DHAVE_CRYPTODEV -DOPENSSL_NO_ERR -DTERMIO -fhonour-copts -Wno-error=unused-but-set-variable -msoft-float -fpic -fomit-frame-pointer -Wall -DSHA1_ASM -DSHA256_ASM -DAES_ASM -c   -c -o sha256-mips.o sha256-mips.S
sha256-mips.S: Assembler messages:
sha256-mips.S:1960: Error: opcode not supported on this processor: mips1 (mips1) `bnel $5,$23,.Loop'
make[6]: *** [sha256-mips.o] Error 1

La solution est donné sur la ML OpenSSL-dev : sha256-mips.S:1960: Error: opcode not supported on this processor: mips1 (mips1) `bnel $5,$23,.Loop'. La correction se fait comme suit :

sed -i 's/bnel/bne/' ./build_dir/target-mipsel_uClibc-0.9.33.2/openssl-1.0.1e/crypto/sha/asm/sha512-mips.pl

Le reste du billet Créez votre image personnalisée d’OpenWRT : ce qui change avec Backfire 10.03.1 (modifier les options du noyau, modifier les options de busybox, configurer les logiciels, ...) est encore valable donc je ne le reprends pas ici.

On constate que l'image de base occupe 3,2M au lieu de 3M pour une image Backfire 10.03.1 et que mon image personnalisée occupe 3,5M contre 3,2M à l'époque Backfire. Cela signifie que l'on s'approche de plus en plus de la limite de stockage d'un WRT54GL, qui, si la taille de l'image continue à augmenter, ne pourra plus accueillir de logiciels supplémentaires (comme etherwake, dnscache, ...) ...