Je suis Charlie

Autres trucs

Accueil

Seulement les RFC

Seulement les fiches de lecture

Mon livre « Cyberstructure »

Ève

Ce blog n'a d'autre prétention que de me permettre de mettre à la disposition de tous des petits textes que j'écris. On y parle surtout d'informatique mais d'autres sujets apparaissent parfois.


RFC 1323: TCP Extensions for High Performance

Date de publication du RFC : Mai 1992
Auteur(s) du RFC : Van Jacobson (University of California Berkeley, Lawrence Berkeley Laboratory), Bob Braden (University of Southern California, Information Sciences Institute), Dave Borman (Cray Research)
Chemin des normes
Première rédaction de cet article le 20 décembre 2013


L'algorithme originel de TCP rendait ce protocole de transport trop prudent et n'utilisant pas assez les réseaux, notamment ceux à forte latence. Après quelques essais, ce RFC 1323, publié en 1992, a permis à TCP de fonctionner correctement sur une bien plus grande variété de réseaux, et jusqu'à aujourd'hui. Ce RFC est ancien et a été remplacé depuis par le RFC 7323. Mais certaines discussions n'ont pas été reprises dans le nouveau RFC et ce RFC 1323 représente donc toujours une lecture indispensable pour les fans de TCP ou tout simplement pour ceux qui veulent comprendre en détail ce protocole.

Avant ce RFC 1323, TCP (normalisé dans le RFC 793 en 1981) se comportait très bien sur les réseaux locaux, ainsi que sur les réseaux distants à faible débit, comme ce qu'on avait sur un modem. Mais il était beaucoup moins satisfaisant sur les réseaux à forte latence et forte capacité, les réseaux à fort BDP où BDP signifie Bandwitdh-Delay Product. Si la capacité est faible ou la latence faible, pas de problèmes. Si leur produit dépasse une certaine valeur, TCP n'était pas capable de remplir la fenêtre et ses performances restaient en deça du maximum théorique du réseau.

La section 1 décrit ce problème. TCP avait été conçu (et avec succès) pour tourner sur des réseaux très disparates, et pour s'adapter automatiquement à leurs caractéristiques (taux de perte, latence, taux de duplication...) À l'époque du RFC 1323, TCP tournait en production sur des réseaux dont les capacités allaient de 100 b/s à 10 Mb/s et cette plage s'est plutôt élargie depuis. La transmission par fibre optique venait juste d'apparaître, poussant à explorer le comportement de TCP à de plus grands débits. Existe-t-il une limite au débit de TCP, au-delà de laquelle il ne servirait à rien d'accélérer encore les réseaux ? La question n'a pas de réponse simple.

La caractéristique importante du réseau n'est en effet pas la capacité mais le produit de la capacité et de la latence, le BDP cité plus haut. C'est cette caractéristique qui indique la taille du tuyau que TCP doit remplir, la capacité étant le « diamètre » du tuyau et la latence sa « longueur ». Si la capacité croît beaucoup, au rythme des progrès techniques, la latence est bloquée par la finitude de la vitesse de la lumière et la seule façon de l'améliorer est de raccourcir les câbles. Donc, un gros BDP oblige TCP à avoir davantage de données « en transit », envoyées, mais n'ayant pas encore fait l'objet d'un accusé de réception, ce qui implique des tampons d'entrée/sortie de grande taille mais qui implique aussi la possibilité de garder trace de grands nombres (par exemple le nombre d'octets en transit), donc d'avoir des compteurs de taille suffisante. Ces liaisons Internet avec un fort BDP sont parfois surnommées les « éléphants » de l'anglais LFN (Long Fat Network).

Un exemple typique d'éléphant est une liaison satellite, avec sa capacité souvent respectable mais sa latence terrible, due à la nécessite d'un aller-retour avec l'orbite géostationnaire. À l'époque de notre RFC, le BDP de ces liaisons était d'environ 1 Mbit soit 100 segments TCP de 1 200 octets chacun. Si une mise en œuvre de TCP se limitait à 50 segments envoyés avant de recevoir un accusé de réception, elle n'utiliserait que la moitié de la capacité disponible. Et les liaisons terrestres peuvent être des éléphants aussi. Un lien transcontinental aux États-Unis a une latence de 30 ms, ce qui, à 45 Mb/s, fait également un BDP de 1 Mbit.

Qu'est-ce qui empêchait TCP de tirer profit de ces éléphants ? Trois points :

  • La taille de la fenêtre n'est stockée par défaut que sur 16 bits, ne permettant pas de fenêtre plus grande que 65 535 octets. Ce problème est résolu par notre RFC 1323 avec l'introduction du window scaling.
  • TCP n'avait pas une connaissance assez précise du RTT, valeur pourtant essentielle au calcul du délai d'attente maximum avant la réémission d'un segment pour lequel il n'y a pas eu d'accusé de réception. Notre RFC 1323 s'attaque au problème avec une nouvelle option TCP permettant d'estampiller temporellement un segment.
  • La récupération était trop longue en cas de perte de paquets. Les premiers TCP, dès qu'un paquet était perdu, attendaient de vider complètement le pipeline, puis repartaient de zéro, comme pour une connexion TCP neuve. En 1990, l'algorithme de TCP avait été modifié pour permettre un redémarrage plus rapide, tant qu'on ne perdait qu'un seul paquet par fenêtre TCP. Mais, avec des fenêtres plus grandes, cette probabilité de perte augmente. Les accusés de réception de TCP étant cumulatifs, une perte de paquet survenant au début de la fenêtre peut faire tout perdre. La solution a été une option d'accusés de réception sélectifs (SACK pour Selective ACKnowledgment). Contrairement aux deux points précédents, celui-ci n'a pas été traité dans ce RFC 1323 mais dans un RFC ultérieur, le RFC 2018.

Un autre problème à considérer est la fiabilité. Si on utilise TCP, c'est pour avoir certaines garanties : que tous les octets émis seront reçus, dans le même ordre, etc. Est-ce que le passage à de plus hautes performances menace ces garanties ? Par exemple, avec des fenêtres plus grandes, la probabilité qu'un paquet ancien, appartenant à une précédente connexion, lorsqu'il finit par arriver, tombe dans la fenêtre courante, cette probabilité est plus élevée. Dans ces conditions, les données seraient corrompues. La principale protection de TCP contre cet accident est la notion de MSL (Maximum Segment Lifetime), le temps qu'un segment peut traîner sur l'Internet. Il ne faut pas réutiliser des numéros de séquence avant qu'une durée supérieure ou égale à la MSL se soit écoulée. Ce numéro ne faisant que 32 bits, cela peut être délicat, surtout aux débits élevés (même sans fenêtres agrandies). La MSL est généralement prise à deux minutes or, à seulement 1 Gb/s, les numéros de séquence ne durent que dix-sept secondes. Or, aucun mécanisme sur l'Internet ne garantit le respect de la MSL. Un vieux paquet ne sera pas jeté. D'où l'utilisation par notre RFC 1323 de la nouvelle option Timestamps pour détecter les segments trop anciens et se protéger donc contre la réutilisation des numéros de séquence TCP.

Reste que les solutions proposées dans ce RFC dépendent des options TCP. Pour certains protocoles, par exemple IP, certaines options ont du mal à passer à travers le réseau. TCP semble mieux placé de ce point de vue (il est mentionné à la fin de mon article sur les options IP).

La section 2 de notre RFC présente la première option qui avait été normalisée pour améliorer les performances de TCP sur les liens à fort BDP (Bandwidth-Delay Product), le window scaling. L'idée de base est très simple : 16 bits pour indiquer la taille de la fenêtre, c'est trop peu, on va donc appliquer un facteur (indiqué dans une option TCP) au nombre décrit par ces 16 bits. À noter que, comme les options ne sont envoyées qu'au début de la connexion TCP, le facteur est constant (la fenêtre elle-même étant dynamique).

La nouvelle (à l'époque de ce RFC) option Window Scale comprend trois champs : Type, Longueur et Valeur. Le type vaut 3 et est enregistré dans le registre des options, la longueur est forcément de 3 (trois octets en tout) et la valeur est un octet qui indique de combien de bits on va décaler la taille de la fenêtre. Une valeur de 0 indique pas de décalage, donc un facteur de 1 (une telle valeur n'est pas inutile car elle sert à indiquer au pair TCP qu'on sait gérer le window scaling). Une valeur de 1 indique qu'on double la taille de la fenêtre pour connaître la vraie valeur, etc. Voici un exemple vu par Wireshark :

Transmission Control Protocol, Src Port: 51336 (51336), Dst Port: 4332 (4332), Seq: 0, Len: 0
...
   Options: (20 bytes), Maximum segment size, SACK permitted, Timestamps, No-Operation (NOP), Window scale
...
        Window scale: 5 (multiply by 32)
            Kind: Window Scale (3)
            Length: 3
            Shift count: 5

Et, quelques paquets plus loin, on voit bien le facteur d'échelle appliqué (32, soit 2^5). Le champ indiquant la longueur de la fenêtre vaut 728 octets mais il faut en fait lire 23 296 octets :

    Window size value: 728
    [Calculated window size: 23296]
    [Window size scaling factor: 32]

(À noter que je parlais aussi de cette option à la fin de l'article sur le RFC 793.) Sur Linux, cette option peut s'activer ou se désactiver avec le paramètre sysctl net.ipv4.tcp_window_scaling (c'est parfois nécessaire de la désactiver dans certains réseaux bogués qui bloquent les paquets TCP contenant des options inconnues d'eux).

Autre option normalisée ici, la meilleure mesure du RTT par l'option Timestamps, en section 3. La mesure du RTT est cruciale pour TCP, pour éviter des accidents comme la congestion brutale décrite dans le RFC 896. Si TCP ne mesure qu'un seul paquet par fenêtre, les résultats seront mauvais pour les grandes fenêtres, par simple problème d'échantillonage (critère de Nyquist).

L'option Timestamps a le type 8, une longueur de 10, et deux champs de quatre octets, l'heure qu'il était au moment de l'envoi et l'heure lue dans le paquet pour lequel on accuse réception (cette valeur n'a donc de sens que si le paquet a le bit ACK). L'« heure » n'est pas forcément celle de l'horloge au mur (puisque, de toute façon, on n'utilisera que des différences), l'important est qu'elle avance à peu près au même rythme. Attention, il n'y a aucune raison qu'on ait le même nombre de paquets dans les deux sens. On peut voir un pair TCP envoyer deux paquets et le récepteur ne faire qu'un seul paquet d'accusé de réception. Dans ce cas, ledit récepteur devra renvoyer le temps du paquet le plus ancien. Toujours avec Wireshark, cela donne :

Transmission Control Protocol, Src Port: 4332 (4332), Dst Port: 51336 (51336), Seq: 0, Ack: 1, Len: 0
...
   Options: (20 bytes), Maximum segment size, SACK permitted, Timestamps, No-Operation (NOP), Window scale
...
        Timestamps: TSval 2830995292, TSecr 27654541
            Kind: Timestamp (8)
            Length: 10
            Timestamp value: 2830995292
            Timestamp echo reply: 27654541

Et, dans le paquet suivant de la même direction, les compteurs ont augmenté :

        Timestamps: TSval 2830995566, TSecr 27654569
            Kind: Timestamp (8)
            Length: 10
            Timestamp value: 2830995566
            Timestamp echo reply: 27654569

Ici, il s'agissait d'une communication entre deux machines Linux. La génération des estampilles temporelles dans les options TCP est contrôlée par la variable sysctl net.ipv4.tcp_timestamps (documentée, comme les autres, dans le fichier Documentation/networking/ip-sysctl.txt des sources du noyau). Par exemple :

% sysctl net.ipv4.tcp_timestamps
net.ipv4.tcp_timestamps = 1

Cela signifie que cette option est activée sur cette machine (0 = désactivée).

La section 4 présente le mécanisme PAWS (Protect Against Wrapped Sequence numbers), qui sert à lutter contre les vieux segments TCP qui arriveraient tard et avec, par malchance, un numéro de séquence qui a été réutilisé depuis et est donc considéré comme valide. Les numéros de séquence étant stockés sur 32 bits seulement, la probabilité d'un tel accident augmente avec la capacité des réseaux. PAWS se sert de la même option Timestamps qui a été présentée plus haut. L'idée est que si un segment TCP arrive avec une estampille temporelle trop ancienne, par rapport à celles reçues récemment, on peut le jeter sans remords. Comme pour tous les usages de l'option Timestamps, il ne nécessite pas de synchronisation d'horloges entre les deux pairs TCP car les comparaisons se font toujours entre les estampilles mises par une même machine.

L'annexe C résume les changements depuis les prédécesseurs, les RFC 1072 et RFC 1185 et ils sont assez profonds. Notamment :

  • L'option SACK (Selective ACKnowledgment), trop contestée à cette époque, a été migrée vers un futur RFC (ce fut le RFC 2018).
  • Les règles précises d'envoi des estampilles temporelles ont été sérieusement refondues.
  • L'ancêtre de l'option Timestamps, les options Echo et Echo reply du RFC 1072 ont été supprimées.

Téléchargez le RFC 1323


L'article seul

RFC 7091: GOST R 34.10-2012: Digital Signature Algorithm

Date de publication du RFC : Décembre 2013
Auteur(s) du RFC : V. Dolmatov (Cryptocom), A. Degtyarev (Cryptocom)
Pour information
Première rédaction de cet article le 17 décembre 2013


L'algorithme de signature GOST est une norme russe de cryptographie. Son utilisation est obligatoire en Russie pour les services publics. L'ancienne version de cet algorithme de signature, GOST R 34.10-2001, était dans le RFC 5832, que ce nouveau RFC met à jour.

Le caractère très étatique de GOST est rappelé dès la section 1.1 du RFC qui note que l'algorithme a été développé par la FAGCI (ou FAPSI), la NSA russe. Il remplace l'ancien GOST R 34.10-2001 (mais ce RFC ne contient malheureusement pas de description des changements entre les deux versions). GOST est obligatoire en Russie pour les services nationaux (section 2 du RFC).

GOST R 34.10-2012, décrit dans ce RFC, est donc un algorithme de pure signature, ne pouvant pas servir au chiffrement. Reposant sur la cryptographie asymétrique, il est donc sur le même créneau que DSA. Mais, contrairement à lui, il repose sur les courbes elliptiques.

Je vous laisse découvrir ledit algorithme dans le RFC, personnellement, mes compétences en cryptographie sont bien trop faibles pour y comprendre quelque chose. Et le code source ? Il ne semble pas être dans OpenSSL qui a apparemment toujours (version 1.0.1e) l'ancienne version de GOST R 34.10. Pour DNSSEC, le numéro d'algorithme 12 est explicitement marqué pour l'ancienne version donc il faudra sans doute un nouveau RFC, succédant au RFC 5933, pour passer à GOST R 34.10-2012.


Téléchargez le RFC 7091


L'article seul

Les places de marché Bitcoin, ça sert à quoi et ça marche comment ?

Première rédaction de cet article le 15 décembre 2013


Il y a plein d'aspects rigolos dans le système Bitcoin et je ne vais pas répéter sur ce blog les très bonnes choses qu'on trouve partout. Cet article se focalise sur un seul aspect, les places de marché. Quel est leur rôle dans le système ? Que font-elles exactement ?

La présentation dans les médias de ces places de marché (bitcoin exchanges dans la langue de Warren Buffett) est souvent trompeuse : elles sont souvent décrites comme un acteur indispensable, nécessaire au fonctionnement du système et, dans ce cas, on en vient forcément à les comparer aux banques traditionnelles, et à se demander si elles sont meilleures ou pires que ces banques et si on a vraiment gagné au change (ah, ah) à remplacer sa banque par une place de marché Bitcoin.

La vérité est que ces places ne sont nullement indispensables. C'est une des beautés de Bitcoin : les intermédiaires ne sont pas indispensables. Vous pouvez parfaitement avoir vos bitcoins dans un ou plusieurs portefeuilles installés sur votre ordinateur et envoyer ou recevoir des bitcoins avec d'autres volontaires, sans passer par une place de marché. Échanger des bitcoins, c'est simplement publier une nouvelle transaction dans la chaîne de transactions publique et cela ne nécessite pas d'intermédiaire entre votre logiciel (comme Electrum ou Multibit) et la chaîne. Les intermédiaires peuvent jouer un rôle utile (j'ai personnellement un compte sur deux de ces places de marché) mais ne sont pas nécessaires. Le rôle d'une de ces places de marché est double : stocker votre argent, qu'il soit en euros ou en bitcoins, et le changer d'euros en bitcoins ou réciproquement.

Le premier rôle est proche de celui d'une banque classique : votre argent n'est pas chez vous, il est dans le cloud. À vous de voir si vous trouvez cela plus sûr ou pas. Des places de marché ont déjà été piratées et les bitcoins volés (les voleurs vont là où est l'argent...) Mais des PC individuels à la maison ont déjà été victimes de logiciels malveillants qui ont volé les bitcoins. Ou de panne ou de destruction.

Si on peut se passer de la première fonction, en gardant les bitcoins chez soi, pour la seconde, c'est plus difficile. Bien sûr, rien n'empêche d'échanger des bitcoins contre des euros avec des copains, ou avec des inconnus rencontrés sur BitcoinMeet ou LocalBitcoins. Pour des petites sommes « pour voir », je ne pense pas que cela cause un problème. Au delà, je ne me prononcerai pas sur la légalité de l'opération. En effet, le bitcoin lui-même n'est pas légal ou illégal. Il est « a-légal » dans la mesure où il n'est pas traité par une loi. Son échange entre acteurs économiques ne me semble pas poser de problème (je ne suis pas juriste, attention, prenez mes appréciations avec des pincettes). En revanche, sa conversion en euros (ou le contraire) fait intervenir la monnaie officielle et c'est là que s'exerce le pouvoir de l'État, à des fins d'imposition ou de lutte contre certains trafics. Donc, l'achat ou la vente de bitcoins avec des euros ne peut probablement pas se faire simplement, d'un commun accord. Vous devez passer par une place de marché (ou par un distributeur automatique), et celles-ci sont fortement régulées. (À noter qu'aussi bien les partisans du Bitcoin, pour s'en féliciter, que ses adversaires, pour le déplorer, affirment souvent que le Bitcoin échappe à toute loi et toute régulation. C'est tout à fait faux, au moins quand on l'échange avec la monnaie officielle.)

Donc, quelles sont les places de marché disponibles, et leurs caractéristiques ? Les médias, qui ne font en général rien d'autre que de se recopier les uns les autres, n'en citent quasiment qu'une seule, Mt.Gox. Enregistrée au Japon, ce n'est pourtant pas forcément la solution la plus naturelle pour quelqu'un qui vit en France, comme moi. Il existe pourtant de nombreuses autres places de marché, et je vais citer les deux où j'ai un compte, Bitcoin Central et Kraken. Elles sont entièrement en ligne (pas de guichets physiques). Dans les deux cas, on se crée un compte en ligne mais, au contraire de tant de services sur le Web, on ne peut pas s'en servir tout de suite, un certain nombre de vérifications sont faites. Ces vérifications dépendent de la politique de la place de marché mais aussi des lois et réglements qui s'appliquent à elles. Si le Bitcoin lui-même peut être décrit comme planant dans un espace virtuel, ces places de marché sont, elles, fermement ancrées dans un espace légal national.

Du point de vue de cet ancrage national, Bitcoin Central est français (et doit donc appliquer la loi française), et Kraken états-unien (avec une adresse d'une banque allemande en Grande-Bretagne pour les virements... On peut noter que leur site Web n'est pas excessivement bavard en informations). Les vérifications demandées sont bien plus détaillées pour Bitcoin Central (il faut donner des détails personnels et envoyer un fichier numérisé d'un certain nombre de papiers officiels) et plus longues (il m'a fallu seize jours pour être validé). Il est difficile de comparer avec les conditions de Kraken, car, alors que Bitcoin Central est binaire (on est validé ou on ne l'est pas), Kraken a un système de niveaux (tiers), cinq au total. Pour passer au niveau supérieur, il faut fournir plus d'informations et se prêter à plus de vérifications. Et les actions qu'on peut faire sont limitées en fonction du niveau. Pour ma part, je suis actuellement au niveau Deux (le troisième, puisque cela part de zéro), ce qui me permet de déposer ou retirer 2 000 $ par jour (avec une limite de 10 000 par mois). La validation à ce niveau a pris deux jours mais il est difficile de dire ce qui a été exactement vérifié (je ne pense pas que quelqu'un soit venu voir en bas de l'immeuble si mon nom était bien sur une des boîtes aux lettres).

Une fois qu'on est validé, que peut-on faire ? L'interface de Bitcoin Central est très simple, n'offrant que peu de possibilités, ce qui est certainement un avantage pour les débutants : bitcoin-central.jpg

Sans vérifier la documentation, on trouve tout de suite comment déposer des euros ou des bitcoins, changer de l'argent, ou retirer des euros ou des bitcoins. Dans mon cas, j'ai alimenté mon compte Bitcoin Central avec des euros par un simple virement bancaire SEPA vers l'IBAN indiqué. Ensuite, j'ai pu changer ces euros en bitcoins et retirer ensuite des bitcoins, en les envoyant à l'adresse Bitcoin indiquée. On voit donc qu'on peut utiliser une place de marché juste pour le change et ne pas laisser son argent ensuite. (Mais attention, avant de retirer des bitcoins, assurez-vous que le portefeuille de destination est sécurisé, à la fois contre le piratage, et contre la perte accidentelle. Vérifiez la sécurité de la machine qui l'héberge, et les sauvegardes. N'oubliez pas que Bitcoin a une sémantique proche de l'argent liquide : si vous envoyez à une mauvaise adresse, l'argent est perdu. Si votre disque dur vous lâche, même chose.) Un autre piège avec Bitcoin Central (documenté mais, comme je l'ai écrit, je n'avais pas lu la documentation) : pour des raisons de sécurité, des tas de choses sont stockées hors-ligne et ne sont extraites du coffre-fort qu'à certains moments. Vous n'aurez donc pas vos bitcoins tout de suite.

L'interface de Kraken est très différente. Par défaut, pour passer un ordre, vous avez la version simple : kraken-simple.jpg

Et il y a une version plus riche :kraken-advanced.jpg

Beaucoup plus riche qu'avec Bitcoin Central, l'interface est même franchement effrayante pour des débutants qui ne connaissent pas le monde de la finance. On vous y propose de faire plein de choses. Suivez un conseil de bon sens : si vous ne connaissez pas ces instruments financiers, tenez-vous à l'écart et contentez-vous, comme dans le paragraphe précédent, d'échanger des bitcoins contre des euros (toujours avec un virement bancaire pour alimenter le compte originalement). L'interface de Kraken étant riche, consulter la documentation, même pour des tâches simples, est recommandée.

Je ne suis pour l'instant qu'un tout petit utilisateur, expérimentant avec des petites sommes. Je ne peux donc pas encore donner d'affirmation solide sur la meilleure place de marché. Je ne peux notamment rien dire sur la qualité du support utilisateurs chez Kraken, je n'ai pas encore eu à l'utiliser. Mais je note que, pendant la grande panne de Kraken du 12 décembre 2013 (apparemment due à une attaque par déni de service), le community manager n'a donné aucune information sur Twitter. En revanche, chez Bitcoin Central, je peux dire que le support est aimable, assez rapide, et répond en général de manière pertinente. Je le sais car j'ai eu souvent besoin de faire appel à eux, chaque opération nécessitant au moins un appel au support, en raison du nombre de choses qui ne fonctionnaient pas encore (virements qui n'arrivent pas, courrier de demande de confirmation qui ne part pas, etc). Leur logiciel semble encore très jeune. Mais, à chaque fois, ça a fini par marcher donc, si vous devenez client de Bitcoin Central, vous profiterez du débogage fait grâce aux premiers utilisateurs :-)

Sur Kraken, un chose est à noter : on peut enregistrer sa clé publique PGP et les messages de Kraken vers vous sont alors en PGP. Excellente idée et j'aimerai bien que les autres banques suivent ! Deux petits bémols toutefois, le sujet du message est en clair et Kraken le fait très informatif, donc cela diminue l'intérêt de chiffrer. Et Kraken met le texte chiffré directement dans le corps du message au lieu d'utiliser le RFC 3156.

Kraken et Bitcoin Central disposent d'autres mécanismes de sécurité rigolos. Par exemple, l'authentification de base est faite par un mot de passe mais on peut demander des mécanismes plus sûrs (mais aussi plus complexes). Pour l'instant, comme je ne manipule que de petites sommes, j'ai juste activé une option astucieuse de Kraken : celle qui bloque toute modification du compte pendant une période qu'on choisit. Ainsi, même si je me fais piquer mon mot de passe, l'attaquant devra attendre quelques jours avant de changer les paramètres d'authentification, ce qui me permettra de détecter le problème et de donner l'alarme.

Ah, et si vous vous demandez ce que veulent dire les termes financiers mystérieux de l'interface de Kraken, Vincent Archer a fait un excellent travail d'explication, que je copie/colle ici avec mes remerciements. Leverage, en économie, c'est le taux d'endettement. Par extension, c'est l'emprunt pour investissement, lorsqu'on emprunte pour investir dans quelque chose qui rapportera plus que le taux d'intérêt à payer, par opposition à l'emprunt de financement (borrowing), pour financer un achat. Utilisé aussi pour indiquer le taux d'endettement ; quand on te demande le niveau de leverage, c'est que tu veux emprunter une partie du montant pour acheter tes bitcoins. Ce n'est pas une distinction absolue, mais plutôt un usage. On utilise beaucoup en adjectif l'expression leveraged buyout qu'on voit dans le rachat d'entreprise. Elle signifie qu'une partie du rachat de la boite est fait avec un emprunt (et pas en trésorerie ou en échange d'actions).

Margin, c'est la partie de ton achat qui est financée par le prêt.

Et la position, dans la bourse, c'est quand tu dois forcément vendre ou acheter quelque chose, en général parce que tu as acheté ou vendu à découvert (ou en margin, comme on vient de dire). Si tu as choisi un pourcentage d'emprunt, tu te places dans une position d'obligation où tu devras revendre la partie que tu as financée via le prêt. Sinon, c'est juste que tu as fait une opération de change et tu peux tout garder.

Et bien sur, closed signifie dérouler l'obligation de revente... Et réaliser (matérialiser en vrai) le bénéfice ou la perte. Fin des explications financières de Vincent.

Les idées sur le caractère a-légal du bitcoin et sur le fait que c'est l'échange en euros qui l'amène sous les projecteurs de la régulation viennent d'une publication de la Banque de France, Focus n° 10, disponible en ligne.

Merci à Vincent Archer et Laurent Penou pour la relecture, mais je garde le copyright sur toutes les fautes et erreurs de cet article.


L'article seul

Article et exposé JRES sur les attaques par déni de service utilisant le DNS

Première rédaction de cet article le 12 décembre 2013


Le 11 décembre, à Montpellier, lors des Journées RÉSeaux (JRES, le plus important rassemblement francophone d'administrateurs système et réseaux), j'ai parlé des attaques par déni de service utilisant le DNS.

Voici l'article complet, son source. Et puis les diapos et leur source.

La page JRES sur cet exposé est https://conf-ng.jres.org/2013/planning.html#article_37. Avec le lien « Voir la présentation en VOD », vous pouvez accéder à la vidéo. Ceci dit, j'ai eu beaucoup de problèmes techniques en streaming. L'URL comprend un nom (video.renater.fr) qui a une adresse IPv6 mais qui ne répond pas en IPv6. vlcne bascule pas tout de suite en IPv4. Quand il le fait, la liaison est mauvaise, on voit des écrans noirs, etc. Peut-être est-ce mieux en téléchargeant.


L'article seul

Sécurité de DANE

Première rédaction de cet article le 9 décembre 2013


Le système DANE (DNS-Based Authentication of Named Entities) permet d'augmenter la sécurité des échanges chiffrés avec TLS en permettant au gérant du serveur de publier lui-même le certificat qu'il utilise, et en permettant au client de vérifier, par une deuxième voie, le DNS, que le certificat est le bon. L'expérience d'autres technologies de sécurité est que DANE, s'il est effectivement déployé dans le futur, sera attaqué par des méchants compétents et que ses faiblesses seront exploitées. C'est donc une bonne idée, avant ce déploiement massif, de se demander quelle est la sécurité de DANE et quelles attaques sont possibles. Plaçons-nous donc dans la peau de l'attaquant. Alice se connecte au serveur de Bob en TLS (par exemple en HTTPS), et Bob utilise DANE. Que peut faire Mallory pour se faire passer pour Bob sans qu'Alice s'en aperçoive ?

Si vous ne connaissez pas DANE, vous pouvez l'apprendre dans l'excellent dossier thématique de l'AFNIC ou (plus anciens) dans mon article à JRES ou encore dans mon article sur le RFC 6698, qui normalise DANE. Avant DANE, les communications en TLS (RFC 5246) étaient sécurisées par X.509 uniquement. Une grosse faiblesse de X.509 est que n'importe quelle autorité de certification peut émettre un certificat pour n'importe quel nom, même s'il n'est pas son client. On voit ainsi régulièrement des faux certificats émis par des AC malhonnêtes, maladroites ou piratées, par exemple pour intercepter le trafic des services de Google.

Donc, plaçons-nous quelques années dans le futur. DANE est largement déployé, des sites Web accessibles en HTTPS publient les enregistrements DANE (nommés TLSA) dans leurs zones DNS signées avec DNSSEC, Alice veut se connecter au serveur de Bob et Mallory, qui peut détourner le trafic, veut être Homme au Milieu sans que le navigateur Web d'Alice ne donne l'alarme.

D'abord, Mallory, en vrai professionnel, étudie les mises en œuvre de DANE dans les navigateurs. Il y a deux façons très différentes d'utiliser DANE, les utilisations 0 et 1 d'un côté, et les 2 et 3 de l'autre. Lorsque l'enregistrement TLSA contient 0 ou 1 dans le champ « Utilisation du certificat » (Certificate usage), l'authentification DANE se fait en plus de l'authentification X.509 classique (plus exactement PKIX, un profil de X.509 décrit dans le RFC 5280). Avec ces utilisations 0 et 1, Mallory doit casser DNSSSEC et X.509. Lorsque l'enregistrement TLSA contient 2 ou 3, l'authentification DNSSEC se fait à la place de l'authentification X.509 classique.

Quelles utilisations seront adoptées ? Les plus prudents, soucieux de ne pas lâcher la proie pour l'ombre, adopteront sans doute 0 et 1, renforçant la sécurité X.509 par celle de DNSSEC (stratégie « ceinture et bretelles »). Les autres, ou simplement ceux qui ne veulent pas passer par les procédures et coûts des AC X.509, adopteront les utilisations 2 et 3 (stratégie « remplacer les bretelles par des ceintures »). Mais il ne faut pas oublier que les choix de sécurité, dans le cas de HTTPS, sont faits essentiellement par les auteurs de navigateurs, pas par les utilisateurs (que ce soit Alice ou Bob). Il est donc possible que certains navigateurs ne mettent en œuvre DANE que pour les usages 0 et 1, jugeant 2 et 3 trop dangereux.

Donc, Mallory regarde l'enregistrement TLSA de Bob (ici, avec le site Web https://dane.rd.nic.fr/) :


% dig TLSA _443._tcp.dane.rd.nic.fr

; <<>> DiG 9.9.3-rpz2+rl.13214.22-P2-Ubuntu-1:9.9.3.dfsg.P2-4ubuntu1 <<>> TLSA _443._tcp.dane.rd.nic.fr
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 40804
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 3, ADDITIONAL: 5

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;_443._tcp.dane.rd.nic.fr. IN TLSA

;; ANSWER SECTION:
_443._tcp.dane.rd.nic.fr. 1 IN TLSA 3 0 1 (
				C68EBCC998FDA83222CABF2C0228ECC413566E709E5D
				C5CF25396A8BF4342DD3 )
...
;; Query time: 117 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Mon Dec 09 10:39:48 CET 2013
;; MSG SIZE  rcvd: 876

OK, il est bien signé (le bit AD pour Authentic Data). Rappelons en effet que DANE dépend de DNSSEC. Le RFC 6698 est très clair là-dessus (après de longs débats à l'IETF) : les enregistrements TLSA non signés sont ignorés. Une conséquence est que la sécurité de DANE dépend d'une bonne politique DNSSEC. Par exemple, pour être vraiment sûre, la validation DNSSEC devrait se faire sur le poste local d'Alice.

Ici, l'utilisation est 3 (les données dans l'enregistrement TLSA sont un certificat auto-signé). Quelles sont les attaques possibles pour Mallory ? Sauf si Mallory connait un moyen de casser cryptographiquement DNSSEC, la seule solution est de s'attaquer à un des intermédiaires dans la chaîne DNSSEC, afin de supprimer ou de remplacer l'enregistrement TLSA. En effet, comme le DNS, DNSSEC fonctionne selon une logique arborescente : la validation de www.example.nl dépend de la racine du DNS et du registre de .nl. On a déjà vu des registres ou des bureaux d'enregistrement être piratés, donc cela n'a rien d'impossible (même si DNSSEC complique sérieusement la tâche de Mallory). Avec l'utilisation 3, pas besoin d'attaquer une AC ou de trouver une faille dans le système X.509. Mais est-ce à dire qu'on a simplement remplacé la confiance dans son AC par la confiance dans son registre de noms de domaine ? Si c'était le cas, DANE ne changerait pas grand'chose. Mais il y a une grosse différence : avec X.509, vous devez faire confiance à toutes les AC, pas seulement celle que vous avez choisi et donc vous êtes clients, car toutes peuvent émettre un certificat pour le site Web de Bob. Avec DNS et DNSSEC, vous choisissez à qui vous faites confiance.

Et si l'enregistrement TLSA avait l'utilisation 2 ? Dans ce cas non plus, il n'y a pas de validation X.509 depuis le magasin de certificats du navigateur Web, et donc pas la peine de détourner une des AC reconnues des auteurs de navigateurs. Avec un enregistrement TLSA d'utilisation 2, le contenu de l'enregistrement TLSA est le certificat d'une AC (qui n'a pas besoin d'être dans le magasin des navigateurs). On a donc deux possibilités d'attaque : contre le système d'enregistrement de noms de domaine, comme dans le cas de l'utilisation 3 précédemment cité, ou bien une attaque contre cette AC particulière, par exemple en la piratant. Notons encore une fois que, contrairement au X.509 classique, Mallory n'a pas le choix de la cible, elle doit réussir à pirater une AC particulière. Conclusion : si l'AC désignée par l'enregistrement TLSA d'utilisation 2 est gérée par une organisation différente de celle de Bob, on a élargi les possibilités de Mallory.

Et si on a le navigateur paranoïaque hypothétique que je citais, celui qui refuse les utilisations 2 et 3 ? Ce cas n'est pas prévu par le RFC. Le plus logique serait qu'il ignore ces enregistrements (les faire correspondre d'autorité aux utilisations 0 et 1 serait une violation de la norme DANE, avec plein de résultats surprenants). On se trouverait donc ramené au cas d'un navigateur qui n'a pas DANE du tout, ce qui est le cas de la totalité de ceux d'aujourd'hui.

Et avec l'utilisation 1 ? Cette fois, les habitué(es) du X.509 classique se retrouveront en terrain connu. Une valeur 1 dans la champ « Utilisation du certificat » de l'enregistrement TLSA signifie que les données de l'enregistrement contiennent le certificat effectivement utilisé par le site et qu'il faut le valider par les mécanismes X.509 habituels. C'est la sécurité maximale : DNSSEC plus X.509. Mallory doit cette fois pirater une AC (pour faire un autre certificat) et modifier l'enregistrement TLSA. Pirater une AC, même celle utilisée par Bob, ne suffirait plus car le certificat est épinglé par Bob : celui-là et pas un autre.

Reste l'utilisation 0, nombre dont la présence dans le champ Utilisation signifie que l'enregistrement TLSA désigne une AC, celle de Bob. Mallory doit donc pirater le DNS pour le changer ou bien pirater cette AC particulière. Notez que, pour les utilisations 0 et 1, cette analyse dépend du fait que le piratage de l'AC et celui du DNS sont des opérations indépendantes. Si, en piratant l'un, Mallory peut pirater l'autre, la double sécurité ne sera en fait qu'une illusion. Or, certaines AC signent des certificats après juste un échange de courrier électronique, qui peut être détourné si on détourne le DNS.

En conclusion, DANE, comme toute technique de sécurité, n'est pas invulnérable. Un attaquant déterminé, patient et compétent peut en venir à bout. Il est donc nécessaire de faire une analyse de la sécurité et de voir ce qu'on risque.

Un autre article en français avec une analyse détaillée de la sécurité de DANE (avec notamment les risques des attaques par rejeu) est celui de Florian Maury. En anglais, curieusement, je n'ai pas encore trouvé grand'chose, à part bien sûr la section 8 du RFC 6698.


L'article seul

Mes opinions sur le bitcoin

Première rédaction de cet article le 9 décembre 2013


Comme j'ai écrit un article sur le bitcoin (et que ce n'est pas terminé), des gens m'ont demandé ce que j'en pensais. Des questions faciles du genre « ça va monter ? », « c'est légal ? », « c'est de gauche ? » ou encore « je peux m'enrichir avec ? » (C'est bien la première fois qu'on me demande un avis sur une question financière : merci, le bitcoin.)

Alors, quelques paragraphes sur mes opinions sur le bitcoin. D'abord, ne me demandez surtout pas de conseil d'investissement, je n'en ai aucune idée. J'ai pour l'instant peu de bitcoins, mais je vais peut-être en acheter plus car je pense que c'est rigolo mais je ne suis pas un gourou des finances qui peut vous aider à vous enrichir (attention : les gourous professionnels n'en savent pas forcément plus que moi). Je note quand même un avantage du bitcoin : sa volatilité est bien connue. Elle est typiquement affichée dès la page d'accueil de la plupart des places de marché (voir par exemple les statistiques sur Bitcoin Central). On aimerait pouvoir en dire autant des mirifiques placements en actions que le commercial de votre banque essaie de vous fourguer à chaque occasion. (Le bitcoin a certes des tas d'inconvénients mais une grande partie de l'intérêt que les gens lui portent est due à la frustration éprouvée avec les banques. Si les banques veulent diminuer l'intérêt pour le bitcoin, elles peuvent déjà commencer par améliorer l'information aux clients. Par exemple, la page d'accueil de l'excellent site http://www.bitcoin.fr/ dit « n'y investissez que le temps et l'argent que vous pouvez vous permettre de perdre ». Quelle banque a des avertissements aussi francs ?)

Deuxième chose, je ne sais pas non plus si le bitcoin est l'avenir de la monnaie et va remplacer les vieux systèmes. Et je m'en fiche, je ne suis pas un commercial cherchant à promouvoir le bitcoin. Ce qui m'intéresse dans ce projet, c'est la réouverture des questions fondamentales, qui avaient été bien verrouillées par les banques et les gouvernements. C'est quoi, la monnaie ? Quelles doivent être ses propriétés essentielles ? Qui doit la contrôler ? En suivant quels principes ? Il n'est donc pas exagéré de dire que le bitcoin est à la finance ce que l'Internet est aux télécommunications : la preuve vivante qu'on peut faire autrement que la « seule méthode », que la pensée unique promue par les experts et les gens sérieux. Qu'un expert dise que le bitcoin ne peut pas marcher, pour telle ou telle raison, cela me laisse froid. Les experts en télécommunications de toutes catégories disaient aussi que l'Internet ne pouvait pas marcher.

Est-ce que la future monnaie générale sera le bitcoin ? Peut-être. Et peut-être pas. Peut-être les forces conservatrices l'emporteront. Peut-être aussi que le bitcoin prouvera, à l'usage, des inconvénients vraiment insupportables et qu'une autre monnaie nouvelle lui succédera (il existe déjà des tas de candidats comme le litecoin). Je l'ai dit, c'est pour l'instant l'exploration de nouvelles possibilités qui m'intéresse.

Enfin, il y a des appréciations sur le bitcoin qui ont l'air techniques mais qui sont en fait morales, voire moralisatrices. Par exemple de dire qu'il est une monnaie virtuelle. Il y a très longtemps que c'est le cas de toutes les monnaies. Pas seulement depuis que les milliards s'échangent de manière dématérialisée avec le HFT et entre paradis fiscaux. Pas seulement depuis l'abandon de l'étalon-or par les États-Unis en 1971. Mais au moins depuis Philippe le Bel qui rognait les pièces d'or en décrétant que la valeur d'une pièce ne provenait pas de son ancrage dans le monde physique, mais uniquement du décret royal.

De la même façon, reprocher aux gens qui achètent du bitcoin et qui le revendent plus cher (sans avoir travaillé pour justifier ce gain) de faire de la spéculation est risible : la majorité des échanges monétaires n'a aucun lien avec une vraie création de richesses. Qu'on critique la finance, OK. Mais qu'on n'oppose pas une vraie économie au méchant bitcoin. La vraie économie (les gens qui, en travaillant, produisent des richesses) est minoritaire en dollars ou en euros depuis bien longtemps.

En conclusion, je ne sais pas encore ce que je vais faire dans l'avenir, question bitcoins. Mais je trouve réjouissantes les critiques qui lui pleuvent dessus : c'est peut-être que le bitcoin pose les bonnes questions.

Cet article a été repris sur l'excellent site d'information sur le Bitcoin http://www.bitcoin.fr/ et a suscité pas mal de commentaires (dont plusieurs négatifs). Même chose sur ContrePoints (site d'information de droite, tendance libertarien).


L'article seul

RFC 7045: Transmission and Processing of IPv6 Extension Headers

Date de publication du RFC : Décembre 2013
Auteur(s) du RFC : B. Carpenter (Univ. of Auckland), Huawei Technologies
Chemin des normes
Première rédaction de cet article le 6 décembre 2013


Encore un RFC de clarification sur IPv6. Le déploiement effectif de ce protocole a en effet suscité des questions qui n'étaient pas évidentes avant. Ce RFC s'occupe des en-têtes d'extension que peut contenir un datagramme IPv6. Les règles de traitement de ces en-têtes dans la section 4 du RFC 2460 n'étaient en effet pas d'une clarté limpide. Ce RFC précise aussi les règles d'enregistrement de nouveaux en-têtes à l'IANA, puisqu'il n'existait malheureusement pas de liste faisant autorité.

Petit rappel, d'abord (section 1 du RFC) : l'en-tête normal d'un datagramme IPv6 est de taille fixe (40 octets) contrairement à ce qui se passe en IPv4. Mais entre cet en-tête et le contenu du paquet (qui peut être du TCP, de l'ICMP, de l'UDP ou même être vide), peuvent se glisser plusieurs en-têtes d'extension. Il y a donc une chaîne d'en-têtes, reliés par le champ Next header qui identifie le type de l'en-tête d'extension ou du contenu qui suit. Par exemple, un Next header à 60 signifie que cet en-tête est suivi par un en-tête Destination options alors qu'un Next header à 6 indique que l'en-tête est suivi par du contenu TCP.

La norme IPv6, le RFC 2460, spécifiait dans sa section 4 un jeu initial d'en-têtes d'extension, ainsi que la façon de les traiter. À l'exception de l'en-tête Hop-by-Hop Options, les en-têtes d'extension devaient être ignorés par les routeurs intermédiaires, et traités uniquement dans la machine de destination finale. Ainsi, de nouveaux en-têtes pouvaient être introduits sans affecter les routeurs et sans que ceux-ci aient besoin d'être mis à jour.

Ce schéma correspondait à l'architecture originale de l'Internet : le moins de traitements possible dans les nœuds intermédiaires, et toute l'intelligence aux extrémités. Mais ce modèle est désormais menacé par l'invasion de middleboxes plus ou moins invasives. Par exemple, pare-feux et répartiteurs de charge inspectent le paquet et prennent des décisions en fonction d'autres informations que l'en-tête initial (en général, elles regardent au moins l'en-tête TCP). Résultat, on ne peut plus prétendre que le réseau est transparent pour les en-têtes d'extension. Ces middleboxes doivent suivre toute la chaîne des en-têtes et ce travail est plutôt compliqué, car il n'existait pas (jusqu'au RFC 6564) de format uniforme pour les en-têtes. Il est donc difficile de l'accomplir à la vitesse du réseau, lorsque celui-ci est du 100 Gb/s ! Ce problème n'a pas de solution simple (il découle d'un mauvais choix lors de la création d'IPv6) mais on peut au moins spécifier rigoureusement ce qu'on attend de ces middleboxes.

En effet, certaines middleboxes, notamment les pare-feux, ont un comportement anormal. Un pare-feu est, par profession, paranoïaque : il rejette tout ce qu'il ne connait pas. Un en-tête inconnu et, hop, tout le paquet est jeté. Les en-têtes nouveaux ont donc peu de chances de réussir à se frayer un chemin dans l'Internet. Mais il y a pire : bien des pare-feux programmés avec les pieds par des gens qui n'ont jamais lu le RFC 2460 ne reconnaissent même pas la totalité des en-têtes d'extension originels. Ainsi, certaines fonctions d'IPv6, pourtant normalisées dès le début, comme la fragmentation, ont du mal à fonctionner.

Même si le programmeur de la middlebox a lu le RFC 2460, il risque de s'être simplifié la vie en ignorant la possibilité que de nouveaux en-têtes soient définis. L'IETF ne leur facilitait pas la tâche en ne fournissant pas de liste faisant autorité de tous les en-têtes déclarés. En effet, les numéros d'en-tête sont issus du même espace que les protocoles de transport (voir le registre). Et il n'y avait pas de moyen simple de savoir si le numéro N dans cet espace désigne un protocole de transport ou un en-tête d'extension, si l'application ne connait pas ce qui est désigné par ce N. Résultat, les nouveaux en-têtes ont peu de chance d'être déployés (ils se heurteront à toutes les middleboxes). On voit donc peu d'applications qui tentent d'utiliser des nouveaux en-têtes... ce qui ne motive pas les développeurs de middleboxes à réparer leurs engins. Le format uniforme des en-têtes, décrit dans le RFC 6564, arrangera un peu les choses, en permettant de passer un en-tête, même inconnu.

Après ces préliminaires, les exigences (section 2 de notre RFC). D'abord, un rappel, le traitement des en-têtes d'extension n'est pas une cerise sur le gâteau, c'est un composant indispensable d'IPv6 et toute machine qui prétend traiter l'IPv6 doit traiter ces en-têtes et, si elle veut accéder au contenu du paquet, doit être capable de traiter la chaîne complète des en-têtes. Un simple routeur (qui ne regarde pas le contenu des paquets) doit transmettre les paquets qu'ils aient des en-têtes d'extension ou pas (ce routeur n'a que l'en-tête fixe à regarder). Un engin qui a des fonctions supplémentaires (comme un pare-feu) doit examiner toute la chaîne si elle ne comprend que des en-têtes normalisés et notre RFC recommande que cela soit possible même s'il existe des en-têtes inconnus dans la chaîne. Maintenant qu'une liste des en-têtes normalisés est publiée, les programmeurs n'ont plus d'excuse.

Le RFC 2460 demandait que les machines de destination jettent les paquets contenant des en-têtes inconnus. Mais cela ne s'applique qu'aux machines de destination. Les machines intermédiaires, comme les pare-feux, ne doivent pas en faire autant, sinon il ne sera jamais possible de déployer de nouveaux en-têtes (je crains que cette excellente recommandation ne soit largement ignorée, dans un Internet de plus en plus ossifié).

Une machine intermédiaire peut avoir une option configurable pour jeter les paquets contenant des en-têtes normalisés mais cela doit être une option, non activée par défaut. (Pour les en-têtes inconnus, le choix par défaut peut être de les jeter.)

Une mention spéciale pour l'en-tête de routage (section 4.4 du RFC 2460). Il existe en plusieurs variantes, identifiées par un numéro de type. Si les types 0 et 1 ont été officiellement abandonnés pour des raisons de sécurité (RFC 5095), il n'y a aucune bonne raison de jeter les paquets contenant d'autres types, comme le type 2 (RFC 6275) ou le type 3 (RFC 6554).

Une autre mention concerne l'en-tête hop by hop, le seul que tous les routeurs sur le trajet sont censés examiner (c'est pour cela qu'il est obligatoirement en premier). Comme c'est très difficile à faire à pleine vitesse, notre RFC adopte une position réaliste en notant qu'il ne faut pas s'attendre à ce que tous les routeurs le fassent effectivement, et que ceux qui le feront utiliseront sans doute un chemin plus lent à l'intérieur du routeur.

La section 3 revient sur des questions de sécurité générales. Par exemple, elle rappelle que des en-têtes utilisant les valeurs marquées comme expérimentales (253 et 254) auront encore plus de problèmes que les autres à passer (RFC 4727).

Quant à la section 4, elle spécifie les changements à l'IANA visant à faciliter la tâche des programmeurs de code IPv6. D'abord, dans le registre des numéros de protocole, ajouter une colonne pour indiquer s'il s'agit d'un en-tête d'extension IPv6 (la nouvelle colonne « IPv6 Extension Header »). Ensuite, créer un nouveau registre ne contenant que ces numéros. L'enregistrement de nouveaux en-têtes continue à suivre les règles du RFC 2780.


Téléchargez le RFC 7045


L'article seul

RFC 7101: List of Internet Official Protocol Standards: Replaced by an Online Database

Date de publication du RFC : Décembre 2013
Auteur(s) du RFC : S. Ginoza (AMS)
Pour information
Première rédaction de cet article le 6 décembre 2013


Il fut une époque où le RFC Editor publiait une liste des normes techniques Internet, sous forme d'un RFC. Connue sous le nom de « xx00 », cette liste n'a plus été publiée depuis 2008 et il était donc temps de documenter sa disparition. Elle est désormais remplacée par une page Web.

Le premier RFC à jouer ce rôle était le RFC 1083. À partir du RFC 2200, cette liste était publiée dans des RFC dont le numéro se terminait par 00, ce qui a mené au surnom « xx00 » pour désigner la série. Le dernier a été le RFC 5000. La série étant terminée, des futurs RFC au numéro se terminant par 00 pourront apparaître, sans qu'ils aient de lien avec cette liste de normes.

De nos jours, une liste en ligne, mise à jour en permanence, est évidemment plus logique. Elle existe depuis maintenant dix ans, et, comme noté par le RFC 7100, en raison de cette existence, les RFC « xx00 » (également désignés par l'abréviation « STD 1 ») n'ont plus de sens.


Téléchargez le RFC 7101


L'article seul

RFC 7100: Retirement of the "Internet Official Protocol Standards" Summary Document

Date de publication du RFC : Décembre 2013
Auteur(s) du RFC : P. Resnick (Qualcomm Technologies)
Première rédaction de cet article le 6 décembre 2013


Un peu de rangement dans la bibliothèque des RFC. La section 2.1 du RFC 2026 indiquait qu'un RFC spécial (nommé « STD 1 ») contenait une liste de tous les RFC ayant le statut de norme. Maintenir un tel document était devenu trop coûteux et cette règle est désormais abandonnée. Le dernier de la série aura été le RFC 5000, qui n'aura donc pas de successeur (RFC 7101). Désormais, il ne reste plus que la liste publiée en ligne, maintenant la seule à faire foi. Si vous voulez connaître le statut d'un RFC, c'est là qu'il faut aller.


Téléchargez le RFC 7100


L'article seul

Utilité de DNSSEC contre un attaquant qui contrôle la clé privée de la racine

Première rédaction de cet article le 5 décembre 2013


Aujourd'hui, petit exercice intellectuel avec du DNS, de la cryptographie et de la sécurité. Si un attaquant peut injecter des fausses réponses DNS et le faire accepter par un résolveur, il peut empoisonner ce résolveur. DNSSEC protège contre cette attaque. Mais DNSSEC, comme le DNS, est arborescent. Si l'attaquant contrôle d'une façon ou d'une autre la racine, tout DNSSEC s'écroule-t-il ?

Cet exercice provident d'un article de Bruce Schneier où il décrit un des programmes d'espionnage de la NSA, QUANTUM. L'attention du public, suite aux révélations d'Edward Snowden, s'est surtout focalisée sur les attaques passives de la NSA, comme la copie des données stockées dans les grands silos états-uniens (programme PRISM). Mais QUANTUM est, lui, un programme d'attaque active. La NSA peut aussi injecter des paquets dans le réseau, afin de faciliter un espionnage passif ultérieur. Schneier ne parle pas du tout du DNS dans son article. Mais on peut néanmoins supposer que, parmi ces attaques actives de la NSA (ou d'autres attaquants), certaines vont consister à utiliser le DNS pour empoisonner les résolveurs, détournant les utilisateurs vers des copies des sites à visiter. Ce mécanisme (sur lequel, rappelez-vous, nous n'avons pas de preuve dans les documents Snowden), a été décrit dans un excellent article d'un expert DNS, Nicholas Weaver. Weaver dit « Since every communication starts with a DNS request, and it is only a rare DNS resolver that cryptographically validates the reply with DNSSEC, a packet injector can simply see the DNS request and inject its own reply. This represents a capability upgrade, turning a man-on-the-side into a man-in-the-middle. ».

Weaver mentionne DNSSEC comme une solution possible contre cette attaque. (Si vous ne connaissez pas DNSSEC, vous pouvez commencer par mon article à JRES.) Seulement, si l'attaquant est la NSA, il faut supposer qu'il peut signer des données quelconques avec la clé privée de la racine, cette racine étant sous le contrôle exclusif des États-Unis. Notez que je dis « l'attaquant peut signer des données », pas « l'attaquant peut mettre la main sur la clé privée ». En effet, cette clé est dans un HSM dont elle ne peut jamais, sauf bogue ou porte dérobée dans le HSM, sortir. Mais peu importe : la NSA peut certainement accéder au système de signature et faire signer ce qu'elle veut, pour injection ultérieure. La question est « est-ce réaliste techniquement ? » Accrochez-vous, la réponse peut être compliquée.

En théorie, oui, cette attaque va marcher et DNSSEC ne serait donc pas utile contre la NSA. En pratique, Nicholas Weaver est sceptique. Il fait remarquer qu'il faudrait que l'attaquant fabrique une chaîne complète. S'il veut faire une fausse signature pour www.slate.com (en supposant que ce domaine soit signé avec DNSSEC, ce qui n'est pas le cas aujourd'hui), il doit fabriquer un faux ensemble d'enregistrements NS pour .com, et que les machines ainsi désignées répondent aux autres requêtes pour .com, sinon l'attaque sera vite détectée. Ou alors faire un faux enregistrement NSEC pour convaincre le résolveur que .com n'est pas signé. Car le vrai .com l'est et cette information se retrouve très vite dans les caches de n'importe quel résolveur de la planète, rendant difficile l'empoisonnement. Pour empoisonner, il faut être rapide, avant que le résolveur ait pu apprendre qu'il y a un zone cut entre la racine et .com, et qu'il y a un DS pour .com.

Bien sûr, pour .com, il y a une autre solution, signer des données avec la clé privée de .com puisque son registre est également situé aux États-Unis et donc vulnérable aux demandes officielles. Mais si la NSA veut détourner www.petrobras.com.br, là, l'attaquant n'a pas cette possibilité et il doit donc bien fabriquer une chaîne entière, ou alors un faux NSEC.

Bref, on se retrouve dans un cas classique en sécurité : il y a bien une faiblesse, mais son exploitation effective n'est pas forcément de la tarte. Bien sûr, ce qui précède n'est qu'un raisonnement théorique. Si vous êtes un programmeur courageux, il serait intéressant d'essayer de réaliser cette attaque en laboratoire et de documenter le résultat.

D'autres points à garder en tête :

  • En pratique, il y a aujourd'hui trop peu de résolveurs validant avec DNSSEC. Donc, si j'étais la NSA, je ne m'embêterais pas immédiatement.
  • Les empoisonnements de résolveurs peuvent se détecter. Certes, les gérants des résolveurs sont parfois incompétents, négligents ou débordés de travail. Mais il suffirait d'un gérant de résolveur qui, au bout moment, fasse un dig pour examiner son propre cache, découvre les données mensongères mais signées et les publie. N'importe qui pourrait vérifier que la clé privée de la racine n'est plus digne de confiance et tout DNSSEC, pour lequel le gouvernement des États-Unis a beaucoup investi, s'écroulerait.
  • Si on n'a pas confiance dans la racine, une possibilité est de configurer son résolveur DNSSEC avec d'autres clés de confiance pour les zones situées plus bas. Par exemple, celles de .fr sont publiées. Mais attention : les conséquences en terme d'administration du résolveur sont sérieuses car il faut modifier ces clés de confiance lorsque le gérant de la zone ainsi protégée les change.
  • Si on a confiance dans les clés de zones gérées en dehors des États-Unis, il faut aussi se demander si ces clés sont correctement protégées contre des attaques techniques ou légales.

L'article seul

RFC 7085: Top-Level Domains that Are Already Dotless

Date de publication du RFC : Décembre 2013
Auteur(s) du RFC : J. Levine (Taughannock Networks), P. Hoffman (Cybersecurity Association)
Pour information
Première rédaction de cet article le 5 décembre 2013


La question du bon ou mauvais fonctionnement d'un nom de domaine fait d'un seul composant (par exemple com ou dk) a déjà fait l'objet de pas mal d'articles. (Le premier était apparemment le mien, en 2009.) Elle a pris plus d'importance avec la création massive de nouveaux TLD par l'ICANN, les premiers ayant été introduits dans la racine du DNS en 2013. Ce RFC a une approche documentaire : il n'étudie pas le fonctionnement de ces domaines d'un seul composant (dotless domains) mais il regarde quels TLD, aujourd'hui, sont dans ce cas.

Le choix a été fait de considérer comme « permettant de faire des noms d'un seul composant » tout TLD ayant un enregistrement A (adresse IPv4), un AAAA (adresse IPv6) ou un MX (relais de courrier). C'est assez arbitraire (les différents documents sur les dotless domains ne sont pas d'accord sur la définition). Avec cette définition, des domaines d'un seul composant (dotless domains) existent (rappelons que l'ICANN ne régule pas le DNS ; ses règles ne s'appliquent pas à tous les TLD).

Donc, test fait en septembre 2013 : 5 % des TLD avaient un des enregistrements DNS qui les rendent « capables de faire des noms d'un seul composant » et tous étaient des ccTLD. 18 TLD ont un enregistrement MX (dont deux français, .mq et .gp). 17 (pas forcément les mêmes) ont un enregistrement A. Un seul, .dk, a un enregistrement AAAA.

Ce RFC ne formule pas de recommandations. Il ne dit pas si les domaines d'un seul composant sont Bien ou Mal (personnellement, je ne vois pas quels problèmes ils pourraient sérieusement poser).

Pour les informaticiens, le script qui a servi à compter ces résultats est inclus dans le RFC :


#! /bin/sh

# Get the current list of TLDs from IANA
wget -O orig.txt http://data.iana.org/TLD/tlds-alpha-by-domain.txt
# Remove the comment at the top of the file
grep -v '^#' orig.txt > TLDs.txt
# Get all the nameservers
while read tld; do host -t NS $tld; done < TLDs.txt > TLD-servers.txt
# Do queries for each record type, and do them on each nameserver
for rec in A AAAA MX; do
     while read tld ignorea ignoreb ns; do
       host -t $rec $tld. $ns;
     done < TLD-servers.txt;
done > all-out.txt
# Print the results
grep "has address" all-out.txt | sort -uf
grep "has IPv6" all-out.txt | sort -uf
grep "mail is handled" all-out.txt | sort -uf

Notez que ce script a peu de traitement d'erreurs. Comme la racine, dont l'ICANN ne vérifie pas vraiment la qualité, a plusieurs erreurs, vous aurez quelques messages amusants si vous le faites tourner.

Voici une liste non exhaustive des articles et études sur la question des domaines d'un seul composant :


Téléchargez le RFC 7085


L'article seul

Avoir son propre résolveur DNS ?

Première rédaction de cet article le 4 décembre 2013


Faut-il avoir son propre résolveur DNS, sur sa machine (ou, au moins, sur son réseau local à soi) ? Question compliquée à laquelle je réponds désormais oui, en raison de l'intensification de la censure utilisant le DNS.

D'abord, un petit rappel : la quasi-totalité des activités sur l'Internet commencent par une requête DNS, une demande faite au résolveur DNS par les applications  « quelle est l'adresse IP de www.slate.fr ? » Le résolveur, après interrogation des serveurs DNS faisant autorité (gérés, dans le cas de ce nom de domaine, par la racine, par l'AFNIC et par Slate), va répondre aux applications et le reste de l'activité Internet pourra continuer. Comme tout commence par le DNS, ce service est particulièrement tentant pour tous ceux qui veulent censurer / dévier / détourner les activités de l'utilisateur. Il y a donc une histoire déjà ancienne de tentatives de filtrage via le DNS et une histoire tout aussi ancienne de textes expliquant pourquoi c'est une très mauvaise idée. Le filtrage via le DNS peut se faire dans le réseau, comme en Chine. Mais le plus courant est de le faire dans le résolveur. Cette machine est typiquement gérée, pour un accès Internet par un particulier, par son FAI. En raison de la concentration du marché, en contraignant les quatre ou cinq plus gros FAI à effectuer ce filtrage, on pourrait frapper un bon nombre des MM. Michu. Techniquement, c'est simple à faire, avec des systèmes comme RPZ. Et cette voie a déjà été suivie, en France par l'ARJEL.

Une solution évidente à ce filtrage est d'avoir son propre résolveur DNS, de ne plus compter sur celui du FAI. Cette solution a deux défauts, le premier est temporaire : sa mise en œuvre est encore trop complexe, comme déjà expliqué dans un de mes articles. La deuxième est moins visible : si chaque utilisateur de l'Internet a son propre résolveur DNS, ils ne partageront plus leur mémoire (leur « cache ») et la charge sur les serveurs faisant autorité s'aggravera. Pour cette raison, je prônais plutôt des systèmes comme dnssec-trigger qui installaient un résolveur local mais faisaient suivre les requêtes non résolues aux résolveurs (et donc aux caches) des FAI. C'est une solution simple et élégante (et qui permettait aussi de faire de la validation DNSSEC proprement).

Mais dnssec-trigger a une limite. Certes, avant d'utiliser les résolveurs du réseau local comme relais, il les teste pour s'assurer qu'ils transmettent les données DNSSEC correctement. Mais il ne teste pas s'ils mentent ou pas. Si le résolveur officiel du réseau local applique la censure, dnssec-trigger ne pourra plus accéder aux données (si DNSSEC est utilisé, on aura un code d'erreur, SERVFAIL, plutôt qu'une réponse mensongère comme l'adresse IP 127.0.0.1 dans l'exemple ci-dessous, mais cela ne change pas grand'chose ; DNSSEC protège contre le détournement, pas contre le déni de service qu'est la censure).

Or, l'usage du DNS pour la censure se répand. Ainsi, le 28 novembre 2013, un tribunal français a ordonné la censure par le DNS de sites Web de diffusion de films. Et cette censure semble effectivement appliquée. En testant depuis un très gros FAI français, avec dig :

% dig +short @192.168.2.254 A alloshare.com          
127.0.0.1

Or, cette adresse IP bidon (127.0.0.1 désigne la machine locale, donc ce mensonge renvoie votre navigateur Web vers votre machine) n'est pas la vraie. Avec mon résolveur personnel :

% dig +short A alloshare.com 
204.236.239.5

Cela vous semble exagéré de parler de censure, pour une affaire essentiellement commerciale (les intérêts des ayant-trop-de-droits) ? Sauf que cela commence comme ça puis, une fois que l'outil est au point, on pourra de la même façon demander la censure de n'importe quel nom qui déplait aux autorités. Il est donc normal que les citoyens se détournent des résolveurs DNS menteurs et veuillent configurer leur propre résolveur.

La situation technique n'est pas aujourd'hui tellement meilleure qu'à l'époque de mon précédent article sur le changement de résolveur. Mais le problème devenant plus crucial, il faut quand même se lancer.

Donc, d'abord, pour les systèmes que je connais le mieux, les Unix. Il faut 1) installer le logiciel résolveur 2) configurer la machine pour l'utiliser et surtout 3) faire en sorte que DHCP ne vienne pas écraser ce réglage. Pour le logiciel résolveur, on a plusieurs choix, notamment BIND et Unbound, disponibles sous forme de paquetage dans n'importe quel Unix. Un exemple de configuration BIND pour un résolveur, validant avec DNSSEC pendant qu'on y est :

options {
	// N'écouter que sur l'interface locale. Autrement, faites
	// attention à interdire l'accès aux machines non-locales, pour
	// ne pas faire un résolveur ouvert.
        listen-on {127.0.0.1;};
        dnssec-enable yes;
        dnssec-validation yes;
};
trusted-keys {
           "." LA CLÉ DNSSEC DE LA RACINE EST EN GÉNÉRAL DISTRIBUÉE AVEC BIND (fichier bind.keys)
};

Et pour Unbound :

server:
    interface: 127.0.0.1
    auto-trust-anchor-file: "/var/lib/unbound/root.key"

Pour récupérer de manière sûre la clé de la racine avec Unbound, le plus simple est un unbound-anchor -a "/var/lib/unbound/root.key". Une fois le résolveur démarré, testez avec dig qu'il peut résoudre les noms :

% dig @127.0.0.1 A www.techn0polis.net 
...
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
...
;; ANSWER SECTION:
www.techn0polis.net.	2917 IN	CNAME gpaas6.dc0.gandi.net.
gpaas6.dc0.gandi.net.	1156 IN	A 217.70.180.136
...
;; SERVER: 127.0.0.1#53(127.0.0.1)
...

Testez aussi depuis des machines extérieures que votre résolveur ne répond pas aux machines extérieures. Autrement, c'est un résolveur ouvert, ce qui est très dangereux. Si vous voulez rendre accessible votre joli résolveur depuis tout votre réseau local, vous devez également écouter sur les adresses IP du réseau local (et bien utiiser le contrôle d'accès de votre serveur - acl dans BIND et access-control: dans Unbound - pour ne pas devenir un résolveur ouvert).

Une fois que c'est fait, configurez votre machine pour interroger le serveur/résolveur en question. Mais attention, le problème est que DHCP vient souvent dans votre dos changer ce réglage. Donc, simplement éditer /etc/resolv.conf, comme on le lit parfois sur des forums de neuneus, n'est pas suffisant. Il faut modifier la configuration du client DHCP. Cela dépend du client mais, par exemple, sur une Debian, éditer /etc/resolvconf/resolv.conf.d/head pour y mettre :

nameserver 127.0.0.1

suffit. Une fois que c'est fait, vous pouvez tester avec dig sans indiquer @127.0.0.1 et la ligne SERVER dans la sortie doit vous indiquer quel serveur vous utilisez.

Pour Mac OS X, je n'ai pas d'expérience de ce système mais je suggère l'article de hukl. Sinon, Ludovic Hirlimann propose « installer MacPorts puis sudo port install unbound et c'est tout ». Experts OS X, si vous avez d'autres idées ?

Et pour Windows ? Apparemment, Unbound tourne sur Windows (si quelqu'un a une expérience d'utilisation à raconter...) Je ne connais pas assez Windows pour le reste mais je vous suggère une solution pour la partie « configurer sa machine pour accéder au résolveur local ». Un certain nombre de services commerciaux vous fournissent des résolveurs alternatifs, pour accéder plus rapidement à certains services bridés comme YouTube. Je ne vous dis pas d'utiliser ces résolveurs, qui sont aussi menteurs (même si c'est pour la bonne cause) mais tous viennent avec une documentation, conçue pour un large public, indiquant comment changer de résolveur. Par exemple, c'est le cas de la documentation de Unlocator.

Enfin n'oubliez pas que, si vous avez plusieurs machines sur votre réseau local, il n'est pas nécessaire qu'elles aient toutes leur propre résolveur, vous pouvez mettre un seul résolveur partagé.

Quelle sera la prochaine étape de la course aux armements entre les censeurs et les utilisateurs de l'Internet ? Peut-être d'essayer de faire filtrer le port 53. En attendant, voici d'autres documents sur le thème de cet article :


L'article seul

Atelier « anycast DNS » à AfriNIC

Première rédaction de cet article le 27 novembre 2013


AfriNIC organisait une réunion à Abidjan cette semaine. J'ai eu le plaisir d'y faire un atelier pratique consacré à l'anycast pour les serveurs DNS.

Il y avait environ 25 personnes, administrateurs système de divers sites en Afrique francophone. Les diapos de cet atelier sont disponibles ici au format PDF.


L'article seul

RFC 7059: A Comparison of IPv6 over IPv4 Tunnel Mechanisms

Date de publication du RFC : Novembre 2013
Auteur(s) du RFC : S. Steffann (S.J.M. Steffann Consultancy), I. van Beijnum (Institute IMDEA Networks), R. van Rein (OpenFortress)
Pour information
Première rédaction de cet article le 27 novembre 2013


Il existe d'innombrables techniques pour faire coexister IPv4 et IPv6 sur l'Internet. Tellement qu'on s'y perd facilement. Ce nouveau RFC se concentre sur une catégorie particulière, les tunnels « IPv6 sur IPv4 » et fait la liste de tous les mécanismes de cette catégorie (des plus répandus aux plus exotiques), avec leurs forces et leurs faiblesses.

Ces tunnels sont dictés par la nécessité. La bonne méthode pour se connecter en IPv6 est clairement d'utiliser une connexion native. Mais on n'a pas toujours le choix. Aujourd'hui, depuis de nombreuses années, et sans doute encore pour un certain temps, il existe de nombreuses îles IPv6, séparées les unes des autres par des réseaux purement IPv4. Par exemple, vous avez loué une machine virtuelle chez un fournisseur qui est resté à l'ancien protocole (comme Numergy) mais vous voulez accéder à l'Internet IPv6. Ou bien vous avez déployé IPv6 sur votre campus mais votre opérateur réseau n'est toujours pas capable de fournir de l'IPv6 ce qui vous désespère. Dans ces deux cas, et dans plusieurs autres, vous serez sans doute obligé d'utiliser un tunnel. Un tunnel fonctionne en encapsulant les paquets d'un protocole dans ceux d'un autre protocole. Ainsi, pour transporter de l'IPv6 sur l'IPv4, le routeur d'entrée de tunnel met le paquet IPv6 à l'intérieur d'un paquet IPv4, celui-ci voyage ensuite par les mécanismes IPv4 habituels, sur un réseau qui ne connait qu'IPv4 et, à l'arrivée sur le routeur de sortie de tunnel, le paquet IPv6 est décapsulé (extrait du paquet IPv4) puis continue son chemin dans le réseau IPv6.

Ce principe est le même pour toutes les techniques de tunnels. Mais les nombreuses techniques existent diffèrent par bien d'autres points, ce qui sème souvent la confusion chez les administrateurs réseau. D'autant plus que ces techniques ne se valent pas : certaines posent des gros problèmes de sécurité ou de fiabilité.

Ce RFC fait le tour de ces techniques. Attention : il ne couvre que le cas « IPv6 tunnelé dans IPv4 ». Il existe plein d'autres techniques de tunnels, pour faire des VPN par exemple. De même, ce RFC 7059 ne parle pas de DS-Lite, qui n'est pas une technologie de IPv6 sur IPv4 mais, au contraire, un moyen de transporter l'IPv4 sur des réseaux purement IPv6.

La section 3 est le gros morceau du RFC, contenant la liste de tous les mécanismes de tunnels étudiés (je ne les ai pas tous repris dans cet article). La plupart des tunnels font une encapsulation directe : pas d'intermédiaire entre l'en-tête IPv4 et le paquet IPv6. L'en-tête IPv4 a un champ « Protocole » qui contient la valeur 41, identifiant IPv6 (cf. section 5.1). L'adresse IPv6 des extrémités du tunnel est parfois automatiquement créée en fonction de l'adresse IPv4 (tunnels automatiques), pour trouver facilement l'extrémité du tunnel (ce point est détaillé en section 5.4). Au contraire, dans les tunnels manuels, il a fallu configurer explicitement les paramètres du tunnel (notamment l'adresse IPv4 de sortie). Un cas intermédiaire est celui où le tunnel est manuel mais la configuration se fait via un protocole auxiliaire de gestion du tunnel, qui dispense l'utilisateur de cette tâche.

D'autres tunnels ne font pas une encapsulation directe : ils mettent l'IPv6 dans de l'UDP qui est ensuite transporté sur IPv4. Cela permet la traversée des NAT et résout le problème de l'ossification de l'Internet v4, où seuls UDP et TCP arrivent à passer, les autres protocoles de couche 4 (comme le 41) étant de facto interdits en beaucoup d'endroits.

Commençons par les tunnels manuels, les plus anciens (ils étaient déjà dans le RFC 1933 en 1996). Leur norme actuelle est le RFC 4213. On les nomme aussi tunnels statiques ou bien 6in4. Le principe est de désigner explicitement, sur chaque point d'entrée, quel est le point de sortie du tunnel. Pour des exemples de configuration de tels tunnels, voir mes articles « Connecter un serveur dédié à IPv6 avec un tunnel manuel » et, plus compliqué « Un tunnel IPv6-in-v4 sur un tunnel GRE... ». Cette configuration manuelle rend cette solution « Michu-hostile » mais elle a des avantages : le réseau est prévisible (on sait exactement où les paquets vont passer) et facile à déboguer. À noter que la configuration peut être simplifiée par l'utilisation d'un courtier (broker). Les performances vont dépendre du choix de l'autre extrémité du tunnel (dans mon exemple au Cameroun, elle était à Londres, nous n'avions rien trouvé de plus proche). Autrefois, il était courant que le tunnel s'étende sur deux continents différents, allongeant sérieusement le RTT. Ces mauvais choix (tunnel trop long) ont souvent donné une mauvaise réputation aux tunnels. À tort : à titre personnel, je trouve qu'un tunnel manuel est une solution simple, fiable et efficace pour se connecter en IPv6 si on n'a pas de fournisseur IPv6 sous la main. Le seul piège est qu'il faut bien choisir son fournisseur de tunnel.

On peut aussi utiliser GRE (RFC 2784), qui est très répandu dans les routeurs (mais pas dans les machines terminales typiques). C'est un protocole d'encapsulation très généraliste (IPv4 sur IPv4, IPv6 sur IPv4, etc).

GRE est ultra-simple, avec son RFC de moins de neuf pages. Trop dans certains cas, alors on peut lui préférer SEAL (dont le RFC n'a pas encore été publié) qui prévoit quelques services supplémentaires dont un protocole de contrôle permettant aux deux extrémités du tunnel de dialoguer. Un autre exemple de « GRE++ » est AYIYA (pas encore de RFC non plus). Notez que SEAL, contrairement à GRE, n'a pas encore connu beaucoup d'utilisations.

Comme la nécessité d'une configuration manuelle refroidit beaucoup de gens et peut sembler un frein au déploiement d'IPv6, il existe des solutions de tunnels automatiques. Par exemple, le RFC 2893 décrivait une solution (supprimée depuis) où les adresses IPv6 étaient des adresses « compatibles IPv4 » (par exemple ::192.0.2.1, alias ::c000:201, équivalent IPv6 de 192.0.2.1). Le gros inconvénient de cette solution est qu'elle ne marchait qu'entre machines ayant cette technologie, et pas avec l'Internet IPv6. Elle n'a donc plus de rôle aujourd'hui.

Au contraire, 6to4 (RFC 3056) est très répandu (on le trouve dans plusieurs routeurs CPE). Il fonctionne automatiquement, en mettant l'adresse IPv4 du tunnel dans une adresse IPv6 préfixée par 2002::/16, et suivie de l'adresse IPv4. 6to4 dépend de relais (en général gérés bénévolement) capables de servir de point d'entrée et de sortie du tunnel. Grâce à l'anycast (RFC 3068) dont 6to4 avait été un des premiers utilisateurs, plusieurs relais sont accessibles pour un préfixe donné. Ils ont tous l'adresse IPv4 publique 192.88.99.1 (2002:c058:6301:: en IPv6). La route vers 2002::/16 est annoncée vers l'Internet IPv6 par tous les relais et le plus « proche » est sélectionné, répartissant ainsi automatiquement le travail. Sans configuration manuelle, 6to4 est bien adapté au petit réseau qui veut se connecter rapidement. Malheureusement, 6to4 est très imprévisible : les relais sont variés dans leur sérieux et la qualité de leur connexion, et on ne sait pas lequel on va utiliser. Le routage est en général asymétrique (on utilise un relais différent à l'aller et au retour) ce qui rend le débogage des problèmes de connectivité difficile. Le RFC 6343 liste les problèmes de 6to4 et ne recommande pas son usage. Le RFC 7526 est allé plus loin en abandonnant officiellement 6to4.

Pour résoudre ces problèmes sérieux de 6to4, certains FAI (comme Free en France) ont déployé 6rd (RFC 5969). 6rd leur permet de déployer IPv6 pour leurs clients, en ne changeant qu'une partie du réseau, sans qu'il soit nécessaire qu'il fonctionne intégralement en IPv6. 6rd ressemble beaucoup à 6to4 mais n'utilise pas le préfixe commun 2002::/16, mais un préfixe spécifique au FAI (ce qui veut dire que, dans le journal d'un serveur, on ne repère pas les clients 6rd, contrairement aux clients 6to4). Ce préfixe doit être envoyé au client, par exemple en DHCP. À noter que, comme les clients 6rd d'un même FAI partagent en général un préfixe IPv4 commun, il n'est pas nécessaire d'encoder tous les 32 bits de l'adresse IPv4 dans l'adresse IPv6, ce qui libère quelques bits (section 4 du RFC 5969). Si, contrairement à 6to4, 6rd ne peut pas être déployé par l'utilisateur seul, il a par contre l'avantage d'être bien plus prévisible et facile à déboguer. La responsabilité de la connectivité est bien plus claire, elle est entièrement chez le FAI, sans avoir besoin d'impliquer des relais extérieurs.

Comme 6to4, 6rd est sans état et les routeurs relais peuvent donc utiliser l'anycast.

6to4 et 6rd utilisent l'encapsulation directe, où le paquet IPv6 est mis directement dans IPv4, ce dernier l'indiquant par le numéro de protocole 41. L'un des inconvénients que cela présente est que cela empêche la traversée des NAT. Un autre protocole de tunnel, Teredo (RFC 4380), résout le problème en ajoutant UDP. On a donc IPv6-dans-UDP-dans-IPv4. Cela permet aussi d'avoir plusieurs clients derrière le même routeur NAT. Teredo étant activé par défaut dans certaines versions de Windows, son usage est répandu. Teredo inclut le port UDP, avec les adresses IPv4 du tunnel, dans l'adresse IPv6, qui est préfixée par 2001:0::/32.

Du point de vue de la fiabilité et des performances, Teredo est pire que 6to4, comme l'illustre l'article « Testing Teredo ».

Une solution de tunnel bien plus exotique et rare est LISP (RFC 6830). LISP n'a pas été spécialement conçu pour mettre de l'IPv6 dans l'IPv4, il est une solution générale de séparation de l'identificateur et du localisateur. Les identificateurs sont nommés EID dans LISP et les localisateurs RLOC. Tous les deux ont la forme d'une adresse IP. On peut avoir un EID IPv6 et un RLOC IPv4, réalisant ainsi un tunnel IPv6-sur-IPv4. Donc, LISP permet de faire nos tunnels mais c'est un protocole riche et complexe et l'utiliser uniquement pour cela semble exagéré.

Parmi les autres tunnels possibles, c'est dans ce RFC que j'ai appris l'existence de 6bed4. Son originalité est de fournir un mécanisme pour débrayer automatiquement le tunnel si le correspondant est joignable en IPv6 natif, par exemple s'il est sur le même réseau local. Cela lui permet d'atteindre des performances plus proches de celles de l'IPv4. Comme Teredo, 6bed4 met dans ses adresses IPv6 les adresses IPv4 et les numéros de ports UDP des routeurs du tunnel.

Les mécanismes de tunnel utilisent souvent des mécanismes auxiliaires, qui ne sont pas des tunnels mais qui aident à leur établissement et à leur gestion. La section 4 fait le tour des principaux. On y trouve par exemple le TSP du RFC 5572, qui permet de configurer automatiquement un tunnel, évitant l'étape « lecture de la doc' et tentative de la recopier ». Ce mécanisme est par exemple utilisé par Freenet6 et des exemples figurent dans mon article sur les serveurs de tunnel.

Un inconvénient des serveurs de tunnel se présente lorsque le client change d'adresse IPv4 (cas d'une adresse dynamique dans certains abonnements). Avant, il fallait arrêter le tunnel et en créer un nouveau. Le protocole SixXS Heartbeat permet d'éviter cela : le client envoie régulièrement des paquets au serveur de tunnel, qui peut ainsi apprendre un changement d'adresses et se reconfigurer. Le serveur de SixXS fait cela, et les clients typiques aussi. À noter qu'AYIYA inclut cette fonction de « battement de cœur ».

Enfin, après TSP, un autre protocole de négociation de paramètres et de création de tunnel est TIC, également utilisé à SixXS. Il a notamment été mis en œuvre dans un petit routeur CPE très populaire en Allemagne et aux Pays-Bas, le Fritz!Box AVM.

La section 5 de notre RFC discute les aspects communs à tous (ou en tout cas à une bonne partie) de ces mécanismes de tunnel. Par exemple, les routeurs NAT (plus exactement NAPT car ils changent le port, pas seulement l'adresse IP, et doivent donc connaître le protocole de couche 4 utilisé) et les pare-feux sont une cause fréquente de problème pour les tunnels, comme ils gênent d'ailleurs bien d'autres services. Ainsi, le protocole de « transport » 41 (encapsulation directe d'IPv6 dans IPv4) est souvent bloqué, ce qui a mené à l'utilisation d'UDP (par exemple par Teredo), pour contourner ce blocage. Puisqu'il n'a pas de port, le protocole 41 ne peut pas passer à travers un routeur NAPT. Il pourrait passer à travers un routeur NAT (rappelez-vous que la plupart des équipements NAT sont en fait du NAPT) dans certaines conditions. Mais, si l'adresse IPv6 est dérivée de l'IPv4, la traduction d'adresses va certainement casser le tunnel. C'est le cas de 6to4 et 6rd (6rd fonctionne en général car il ne traverse pas le routeur NAPT : il démarre sur ce routeur, qui est le point d'entrée du tunnel).

Par contre, GRE et les tunnels manuels peuvent fonctionner à travers un NAT. Il y a parfois des surprises et il peut être préférable d'utiliser un mécanisme prévu dès le début pour traverser le NAT, comme Teredo, AYIYA, ou 6bed4.

Et puis, bien sûr, une plaie récurrente de tous les tunnels est la question de la MTU (section 5.3). En raison de l'encapsulation, tout mécanisme de tunnel diminue la MTU effective de quelques octets. Normalement, la fragmentation et la découverte de la MTU du chemin devraient gérer cela et permettre au trafic de passer à travers le tunnel. En pratique, le nombre de pare-feux mal configurés qui bloquent les paquets ICMP nécessaires à la découverte de la MTU (message ICMP « Packet Too Big ») est tel que les problèmes sont fréquents. Si l'extrémité du tunnel est sur la machine terminale, celle-ci peut encore réussir à communiquer avec TCP, la MSS de ce dernier s'ajustera. Sinon, on aura des problèmes à première vue mystérieux comme le fait qu'un ping ordinaire passe mais pas un ping avec une taille différente. Ou bien on verra les connexions TCP s'établir, le client HTTP envoyer sa requête mais la réponse, plus grande et ne tenant pas dans la MTU, n'arrivera jamais. Ces problèmes liés à la MTU sont une des plaies de l'Internet et l'utilisation des tunnels les rend encore plus fréquents.

On le voit, la liste des solutions techniques pour tunneler IPv6 dans IPv4 est longue (et encore, je n'ai pas cité dans cet article tous ceux que mentionne le RFC). Comment choisir ? La section 6 du RFC est consacrée à l'évaluation de ces solutions (l'annexe A donne la iste des critères utilisés). D'abord, l'usage qu'ils font des adresses IPv4, celles-ci étant désormais très rares. Les tunnels manuels, qui dépendent d'une adresse IPv4 fixe et unique, ainsi que 6to4, ne peuvent pas marcher à travers un CGN, lorsque plusieurs clients se partagent une adresse IPv4. Teredo ou AYIYA, au contraire, ont été explicitement conçus pour bien marcher même à travers les pires NAT.

Deuxième critère d'évaluation, la topologie réseau permise. Certains tunnels (par exemple les tunnels manuels) sont point à point, entre deux machines fixes, les routeurs d'entrée et de sortie du tunnel. Cela facilite le débogage car le cheminement du trafic est parfaitement prévisible. D'autres (comme 6to4) sont plutôt un vaste réseau où plusieurs relais peuvent être utilisés pour fournir un lien virtuel qui est NBMA plutôt que point à point. Cela offre plus de souplesse et ne fait pas des deux routeurs d'extrémité du tunnel des SPOF.

En pratique, la section 6.2 du RFC penche nettement vers la première solution, une liaison point à point, qui colle bien au modèle traditionnel suivi par les liens physiques, et qui établit clairement les responsabilités de chaque acteur. Bien que l'autre topologie soit séduisante sur le papier, elle a en pratique entraîné beaucoup de problèmes de performance et de débogage.

Et à propos de SPOF, quelle est la fiabilité de ces techniques de tunnels lors d'une utilisation quotidienne ? L'expérience montre que les tunnels manuels sont plutôt fiables (une fois configuré, il n'y a guère de raison qu'ils arrêtent de marcher) et, surtout, ils sont simples dans leurs problèmes : soit le tunnel marche, soit rien ne passe. Pinguer l'extrémité du tunnel suffit en général à les superviser. D'où le tableau de la section 6.3, qui classe les techniques de tunnel par ordre de fiabilité décroissante, et qui met les tunnels configurés manuellement en haut, et Teredo et 6to4 tout en bas... (LISP est indiqué comme le plus fiable, à cause de ses mécanismes de réparation automatiques mais, contrairement à 6to4 ou aux tunnels, il n'a pas encore beaucoup été testé en vrai.)

Les problèmes de 6to4 ont été aggravés par le fait que certaines mises en œuvre de ce protocole ne testaient même pas que la machine avait une connectivité avec au moins un relais (RFC 6343 et RFC 7526).

Et les performances ? En raison de l'encapsulation, il y a forcément quelques octets perdus par le tunnel. Dans le cas d'une encapsulation directe, la moins coûteuse, cette perte représente 1,3 % d'un paquet de la taille maximale (1 500 octets). À part cette diminution de la charge utile, la performance dépend surtout des routeurs d'entrée et de sortie du tunnel. S'ils traitent les paquets « normaux » dans leur ASIC, mais l'encapsulation et la décapsulation en logiciel, dans leur relativement lent processeur, alors, oui, le tunnel sera lent. Mais ce n'est pas obligatoire. En fait, historiquement, le principal problème de performance des tunnels avait été le fait que les tunnels étaient souvent établis avec des machines relativement lointaines et c'est cet allongement du trajet qui ralentissait le service. Autrement, les tunnels ne sont pas synonymes de lenteur.

Bon, et la sécurité (section 7) ? Les tunnels (pas seulement ceux de IPv6 sur IPv4) sont souvent mauvais sur ce point. Par exemple, si l'entrée du tunnel ne fait rien pour vérifier les adresses IPv6 source des paquets qu'elle encapsule, le tunnel permettra peut-être de contourner les mécanismes anti-usurpation d'adresses (le cas de l'usurpation d'adresses avec 6to4 est couvert dans le RFC 3964). Il est donc important que le routeur d'entrée du tunnel prenne des précautions pour n'accepter que des paquets de ses clients légitimes. Autre faille possible : le tunnel permet d'établir une connectivité qui ne devrait pas « normalement » exister (dans le cas d'IPv6 sur IPv4, c'est son but explicite) et cela peut permettre de contourner les règles de sécurité qui sont en place (RFC 6169).


Téléchargez le RFC 7059


L'article seul

RFC 7069: DECoupled Application Data Enroute (DECADE)

Date de publication du RFC : Novembre 2013
Auteur(s) du RFC : R. Alimi (Google), A. Rahman (InterDigital Communications), D. Kutscher (NEC), Y. Yang (Yale University), H. Song (Huawei Technologies), K. Pentikousis (EICT)
Pour information
Première rédaction de cet article le 27 novembre 2013


L'architecture traditionnelle de l'Internet est celle d'un réseau « bête », transportant des paquets sans en comprendre le contenu, avec toute l'« intelligence » concentrée aux extrémités, dans les machines terminales. Un travail avait été commencé à l'IETF, dans le défunt groupe DECADE, pour voir s'il était possible de changer légèrement ce modèle pour certaines catégories d'applications (notamment pair-à-pair), en dotant le réseau de capacité de stockage des données (un peu comme le font, de manière non-standard, les CDN). Le projet a finalement échoué mais a publié quelques RFC, dont ce dernier document, qui décrit l'architecture d'un tel système.

Les deux autres RFC importants de DECADE étaient le RFC 6646, exposé détaillé du problème, et le RFC 6392, qui fait le tour des mécanismes disponibles. (Il est très recommandé de lire au moins le RFC 6646 avant ce RFC 7069.) Finalement, le projet a été abandonné et le groupe DECADE dissous, mais, pour ne pas perdre le travail effectué, il est publié dans ce nouveau RFC, qui décrit, en termes assez généraux, l'architeecture de DECADE. Comme exemple d'usage, prenons une machine connectée en ADSL. Elle a typiquement une capacité réseau « montante » très limitée. Mettre à jour le réseau pour augmenter cette capacité (par exemple pour passer en FTTH) risque d'être coûteux. Disposer dans le réseau des dispositifs de stockage permettant à cette machine de distribuer du contenu sur l'Internet sans tuer sa capacité ADSL limitée serait peut-être plus économique. (Notez aussi que cela soulève d'intéressants problèmes politiques de contrôle sur les données servies.)

Donc, l'idée est d'avoir des serveurs DECADE dans le réseau, qui stockent les données des clients DECADE. Les données pourront être copiées entre serveurs, et récupérées par d'autres clients que ceux qui les ont déposées. Pour cela, il faudra un protocole de gestion des ressources déposées, le DRP (DECADE Resource Protocol) et un protocole d'accès aux ressources, le SDT (Standard Data Transfer protocol). Pour ce dernier, il était prévu dès le début d'utiliser un protocole standard existant comme HTTP.

Les serveurs DECADE seront fournis par des fournisseurs de stockage, qui pourront être les FAI ou bien d'autres acteurs. Ces fournisseurs décideront de l'allocation de ressources (espace de stockage, capacité réseau).

Il n'était pas prévu que les utilisateurs accèdent aux serveurs DECADE directement mais que ceux-ci fournissent un service aux applications, service masqué aux utilisateurs. La section 3 de notre RFC contient un schéma qui illustre ce principe : une application veut envoyer des données à une autre application (les deux applications parlent entre elles avec un protocole pair-à-pair quelconque). Pour cela, elle envoie les données au serveur avec le SDT (rappelez-vous que c'est un protocole standard comme HTTP) et utilise le DRP pour indiquer au serveur les conditions d'accès aux données. L'autre application utilisera SDT pour récupérer les données. Selon le niveau de confidentialité des données, il y aura aussi peut-être une étape de récupération d'un jeton que l'envoyeur transmettra au destinataire (toujours avec leur protocole pair-à-pair à eux, qui ne regarde pas DECADE), et avec lequel le destinataire pourra prouver ses droits au serveur DECADE. Un peu comme les applications « passe-plat » existants comme http://dl.free.fr/ mais masqué à l'utilisateur. Entre parenthèses, ce scénario d'usage avait été réclamé dans un excellent dessin de xkcd.

La section 4 décrit l'architecture du service DECADE (s'il avait été construit ; rappelez-vous que le projet a été abandonné). En gros, DECADE fournira les données (data plane), l'application pair-à-pair la signalisation (control plane). DECADE se voulait indépendant de l'application, fournissant un service général de données. Les applications auraient géré les services comme l'indexation, le moteur de recherche dans les données, etc. Des systèmes de stockage des données séparant données et signalisation existent déjà. Le RFC mentionne Google File System, ou l'extension pNFS de NFS, décrite dans la section 12 du RFC 5661.

Une chose importante avec DECADE est que ce système ne prévoit pas de modifier le contenu déposé dans le stockage en réseau. Les objets écrits sont immuables (section 4.2). Ce principe permet de simplifier considérablement le système, puisqu'il n'y a plus de problème de synchronisation entre les différents serveurs de stockage. Si on veut vraiment modifier une ressource mise en ligne, il faut détruire l'ancienne et en mettre une nouvelle. Ce sera à l'application, pas à DECADE, de changer la correspondance entre le nom de la ressource et le nouvel objet qui, pour DECADE, sera un objet différent, sans lien avec le premier. Chaque application aura en effet son propre système de nommage. On peut comparer cela avec le nommage dans un système de fichiers (comme /home/stephane/Downloads/galaxy.avi) contre celui de plus bas niveau utilisé par le système de fichiers pour parler aux contrôleurs de disque.

Puisqu'on a commencé à parler d'identité (« le même objet ») et donc d'identificateurs, quels sont les identificateurs dans DECADE ? Chaque objet a un identificateur unique. Si un objet est répliqué sur plusieurs serveurs, toutes ces copies sont toujours désignées par le même identificateur. DECADE n'envisageait pas d'imposer un mécanisme unique de nommage mais le RFC suggère d'utiliser des condensats du contenu, comme dans le RFC 6920 (voir aussi la section 6.1). Là encore, l'immuabilité des objets stockés est essentielle pour que ce nommage par le contenu fonctionne.

La section 5 est plus concrète, décrivant certains des composants du système. Par exemple, elle couvre les jetons d'authentification, dont l'utilisation était prévue pour que le déposant d'un fichier puisse distribuer des droits d'accès à des lecteurs (voir aussi la section 6.2.1). Elle parle aussi de l'importance d'avoir un mécanisme de découverte (non spécifié : rappelez-vous que le travail sur DECADE avait été interrompu en route) pour localiser le serveur DECADE approprié.

La section 6, elle, est consacrée aux protocoles DRP (protocole de contrôle) et SDT (protocole de transport des données). Elle est également assez abstraite : l'idée originale est que des protocoles concrets seraient choisis ultérieurement. Ces protocoles ne sont pas utilisés seulement entre un client DECADE et un serveur DECADE mais aussi entre serveurs, notamment pour la réplication. Les données stockées dans DECADE peuvent en effet être automatiquement copiées de serveur à serveur pour augmenter les performances lors de la récupération (section 6.4). Une évaluation des protocoles possibles pour remplir ces rôles figure dans l'annexe A.

HTTP (RFC 7230) est évidemment le premier protocole considéré. C'est un candidat presque idéal pour le rôle de SDT mais il peut aussi servir de DRP. HTTPS fournit des mécanismes de sécurité bien compris et largement déployés. HTTP permet d'assurer les deux fonctions du SDT, en lecture mais aussi en écriture (avec les méthodes PUT et POST). Par contre, il lui manque quelques fonctions, comme des ACL ou comme des mécanismes de transmission de politique d'accès au serveur. Ceci dit, ces manques pourraient être comblés en ajoutant quelques en-têtes dans les requêtes et réponses HTTP. C'est ce que fait Google Storage. Ce dernier utilise OAuth (RFC 6749) pour les délégations d'accès.

Un autre candidat est CDMI. Il est basé sur HTTP mais avec de nombreux enrichissements. Lui dispose d'ACL aussi riches qu'on le veut. Et, question contrôle des données, il permet de spécifier des choses comme le nombre de copies à générer, leur placement géographique, la durée de conservation, etc. CDMI parait donc plus proche des besoins de DECADE.

Et la sécurité d'un système comme DECADE ? La section 8 la décrit en détail, en s'appuyant sur la section 5 du RFC 6646. Il y a évidemment le risque d'attaques par déni de service, par exemple si un client méchant envoie une quantité astronomique de données à stocker.

Pour l'accès aux données, DECADE comptait sur un mécanisme de délégation : on n'autorise pas le client, mais on distribue des jetons dont la possession suffit pour l'accès. Les problèmes de sécurité liés à ces mécanismes de délégation sont traités dans la section 10 du RFC 6749.

Un autre type d'attaque est dirigé contre le client : arriver à lui faire télécharger des données qui ne sont pas celles qu'il espérait. Ce genre d'attaques est courant dans le monde du téléchargement pair-à-pair où un fichier nommé hot-naked-women-at-the-beach.avi peut en fait contenir un discours d'un télévangéliste. S'il est difficile de se prémunir contre un nom trompeur, en revanche, DECADE peut sécuriser la liaison entre un nom et un objet. Ainsi, des adresses basées sur un condensat du contenu sont auto-validantes : après le téléchargement, on recalcule le condensat et on vérifie que le contenu est bien celui demandé. Cela ne règle qu'une partie du problème : la publicité mensongère, par exemple pour tromper un moteur de recherche, reste possible.


Téléchargez le RFC 7069


L'article seul

RFC 7065: Traversal Using Relays around NAT (TURN) Uniform Resource Identifiers

Date de publication du RFC : Novembre 2013
Auteur(s) du RFC : M. Petit-Huguenin (Impedance Mismatch), S. Nandakumar, G. Salgueiro, P. Jones (Cisco Systems)
Chemin des normes
Première rédaction de cet article le 23 novembre 2013


Ce court RFC normalise un nouveau plan d'URI, turn:, qui sera utilisé pour la configuration des clients TURN, un protocole de traversée des obstacles comme les routeurs NAT.

C'est le travail sur WebRTC qui a ravivé l'intérêt pour ce nouveau modèle d'URI (envisagé depuis longtemps mais jamais normalisé). WebRTC (RFC 8825) est un mécanisme de communication directe entre navigateurs Web. Souvent, les logiciels WebRTC vont devoir passer à travers des environnements hostiles comme des routeurs NAT. Une des techniques fréquemment utilisées pour aider ce passage est TURN, normalisé dans le RFC 8656, qui permet à un client TURN, en se connectant à un serveur TURN (en général installé par un fournisseur de services, par exemple SIP), de faire relayer ses paquets par le serveur TURN. TURN est une extension de STUN et s'utilise pour les cas désespérés, lorsque la seule solution pour communiquer est de faire relayer tout le trafic.

Mais, pour cela, il faut que le client soit configuré avec les coordonnées d'un serveur TURN. Actuellement, cela se fait d'une manière spécifique à chaque client. D'où l'idée d'avoir un mécanisme simple de désignation du serveur TURN, un URI comme turn:example.net. Il n'y aura plus qu'à le copier/coller à l'endroit indiqué. Cela simplifiera la configuration et la documentation. Combiné avec le mécanisme de résolution du RFC 5928, il n'y aura désormais presque rien à faire pour configurer TURN.

La section 3 fournit la syntaxe exacte. Il y a deux plans d'URI, turn: et turns:, le second servant aux connexions sécurisées avec TLS. Ils sont notés dans le registre IANA des plans. Un numéro de port est possible comme par exemple turns:provider.example:8888. S'il est absent, le port par défaut est 3478 pour turn: et 5349 pour turns:. Rappelez-vous que le nom du serveur, lui, sera déduit du nom de domaine indiqué dans l'URI par une recherche SRV, après passage par le mécanisme de résolution du RFC 5928.

Et les mises en œuvre ? Le logiciel turnuri (distribué en http://debian.implementers.org/stable/source/turnuri.tar.gz) met en œuvre les URI turn: ainsi que le mécanisme de résolution du RFC 5928. C'est également le cas de la bibliothèque libjingle, qu'utilise Chrome pour WebRTC (Firefox a sa propre implémenation).

Ce RFC a eu une histoire très longue et compliquée, remontant à plusieurs années. Ceux qui s'intéressent aux choix effectués (par exemple d'un plan turns: plutôt que d'un paramètre ;proto=tls dans l'URI) peuvent consulter un article de l'auteur sur son blog et la discussion à l'IETF. Parmi les nombreux messages échangés à l'IETF sur ces URI, je vous suggère la soumission originale et la discussion qui a suivi.


Téléchargez le RFC 7065


L'article seul

RFC 7064: URI Scheme for Session Traversal Utilities for NAT (STUN) Protocol

Date de publication du RFC : Novembre 2013
Auteur(s) du RFC : S. Nandakumar, G. Salgueiro, P. Jones (Cisco Systems), M. Petit-Huguenin (Impedance Mismatch)
Chemin des normes
Première rédaction de cet article le 23 novembre 2013


Ce court RFC normalise un nouveau plan d'URI, stun:, qui sera utilisé pour la configuration des clients STUN, un protocole de traversée des obstacles comme les routeurs NAT.

C'est le travail sur WebRTC qui a ravivé l'intérêt pour ce nouveau modèle d'URI (envisagé depuis longtemps mais jamais normalisé). WebRTC (RFC 8825) est un mécanisme de communication directe entre navigateurs Web. Souvent, les logiciels WebRTC vont devoir passer à travers des environnements hostiles comme des routeurs NAT. Une des techniques fréquemment utilisées pour aider ce passage est STUN, normalisé dans le RFC 8489, qui permet à un client STUN, en se connectant à un serveur STUN (en général installé par un fournisseur de services, par exemple SIP), d'apprendre son adresse IP extérieure et aussi d'autres caractéristiques utiles du NAT traversé.

Mais, pour cela, il faut que le client soit configuré avec les coordonnées d'un serveur STUN. Actuellement, cela se fait d'une manière spécifique à chaque client. D'où l'idée d'avoir un mécanisme simple de désignation du serveur STUN, un URI comme stun:example.net. Il n'y aura plus qu'à le copier/coller à l'endroit indiqué. Cela simplifiera la configuration et la documentation.

La section 3 fournit la syntaxe exacte. Il y a deux plans d'URI, stun: et stuns:, le second servant aux connexions sécurisées avec TLS. Ils sont notés dans le registre IANA des plans (après une discussion sur la liste d'examen des nouveaux plans). Un numéro de port est possible comme par exemple stuns:provider.example:8888. S'il est absent, le port par défaut est 3478 pour stun: et 5349 pour stuns:. Rappelez-vous que le nom du serveur, lui, sera déduit du nom de domaine indiqué dans l'URI par une recherche SRV (section 9 du RFC 5389).

Aujourd'hui, ces URI stun: sont utilisés dans des normes W3C comme celle de WebRTC. Ils sont acceptés par :


Téléchargez le RFC 7064


L'article seul

RFC 7084: Basic Requirements for IPv6 Customer Edge Routers

Date de publication du RFC : Novembre 2013
Auteur(s) du RFC : H. Singh, W. Beebee (Cisco Systems), C. Donley (CableLabs), B. Stark (AT&T)
Pour information
Réalisé dans le cadre du groupe de travail IETF v6ops
Première rédaction de cet article le 23 novembre 2013


Ce RFC du groupe de travail v6ops, qui se consacre aux problèmes pratiques du fonctionnement d'IPv6 (sans modification des protocoles, donc), porte sur les CPE (Customer Premises Equipment), alias CER (Customer Edge Routers), alias home gateway, qui sont les boîtiers installés chez l'utilisateur domestique ou dans la petite entreprise. Par exemple, en France, la Freebox ou la DartyBox sont des CPE. Certains d'entre eux gèrent le protocole IPv6 et ce RFC résume tout ce que doivent savoir les concepteurs de ces « boxes » pour faire de l'IPv6 proprement. Il succède, avec quelques changements, au RFC 6204, qui était le premier de cette série.

Ce RFC se focalise (section 1) sur le cas où IPv6 est natif (pas de traduction d'adresses entre v4 et v6), et sur le cas simple où il n'y a qu'un seul CPE, qui récupère sa configuration sur le WAN, puis la distribue aux machines IPv6 locales, puis route leurs paquets. Le déploiement de l'IPv6 dans le réseau de l'opérateur n'est pas discuté (cf. RFC 4779). Ce RFC concerne uniquement le « foyer, doux foyer ».

Ce RFC utilise un vocabulaire normatif, celui du RFC 2119, mais pas pour spécifier un protocole mais pour indiquer quel est le minimum qu'on peut attendre d'un CPE IPv6 aujourd'hui.

D'abord (section 3), un rappel du fonctionnement d'un CPE IPv4 aujourd'hui. Ce fonctionnement n'est spécifié nulle part, il résulte d'une accumulation de choix par les auteurs anonymes des CPE existants. Ces choix sont souvent erronés. En l'absence de norme formelle, la section 3.1 décrit le CPE « typique » de 2012. Ce CPE typique a une (et une seule) connexion avec l'Internet, une seule adresse IP publique (et encore, parfois, il y a même du NAT dans le réseau de l'opérateur) et il sert de routeur NAT aux machines IPv4 situées sur le réseau local. Par défaut, en raison du NAT, il bloque toutes les connexions entrantes (c'est la seule allusion à cette question qui soit restée dans la version finale du RFC). Ouvrir des ports entrants (port forwarding) se fait par une configuration manuelle du CPE, via une interface Web (cas de la Freebox) ou bien par UPnP. C'est donc un vrai Minitel 2.0. Un avantage de ces adresses privées est toutefois d'assurer la stabilité des adresses internes : elles ne changent pas si on quitte son FAI.

L'architecture ci-dessus est largement déployée et correspond au cas de la plupart des abonnés à l'Internet à la maison. À quoi ressemblera t-elle en IPv6 ? On ne peut évidemment pas encore être sûr, mais la section 3.2, qui la décrit en termes très généraux, suppose qu'elle ne sera pas très différente, à part que la présence de plusieurs réseaux (et donc plusieurs préfixes IP) sera peut-être un cas plus fréquent qu'aujourd'hui. Quelles adresses IP seront utilisées à l'intérieur ? On pense immédiatement au RFC 5902, qui n'est toutefois pas cité. Le RFC 7084 présente la possibilité que des adresse locales, les ULA (RFC 4193) soient utilisées pour le réseau local. Le CPE devra bien alors fournir un mécanisme de traduction. Pour les communications entre machines du réseau interne, il faudra utiliser les mécanismes du RFC 4191.

Alors, maintenant, quelles sont les exigences auxquelles devront se plier les futurs CPE IPv6 ? La section 4 est la liste de ces demandes. Elles sont nombreuses et, pour s'y retrouver, elles portent chacune un identificateur formel, indiquant la catégorie et un numéro. Par exemple, la première, G-1, rappelle qu'un routeur est aussi un nœud du réseau et doit donc suivre le protocole IPv6, tel qu'il s'applique à tous les nœuds IPv6, routeur ou machine terminale (RFC 8504). Parmi les autres exigences (je vous rassure, je ne vais pas les citer toutes), G-4 et G-5 précisent que, si le CPE n'a pas pu obtenir une connectivité IPv6 avec l'extérieur, il ne doit pas publier d'adresses IPv6 sur le réseau local (car beaucoup d'applications réagissent mal lorsque la machine a une adresse IPv6 mais pas de connectivité, cf. RFC 6555). Si le CPE n'a pas de connectivité globale, il doit émettre des annonces RA (Router Advertisement, RFC 4861) avec une durée de vie nulle.

Le CPE se connecte avec le reste de l'Internet en suivant les protocoles standard d'encapsulation pour IPv6 par exemple le RFC 2464 pour Ethernet et le RFC 5072 pour PPP (exigences WLL-1 et WLL-2).

Le CPE doit donc obtenir une adresse et une connectivité depuis l'amont, depuis le FAI. Cela peut se faire avec NDP ou avec DHCP (tous les deux fonctionnent sur tout type de lien, pas seulement sur Ethernet). C'est pour cela que, sur PPP, il n'y a pas de mécanisme en IPv6 pour allouer des adresses globales (RFC 5072). Donc, exigence W-1, le CPE doit utiliser NDP (RFC 4862) ou DHCP (RFC 8415) pour récupérer une adressse IPv6 globale. Avoir une adresse pour le CPE, c'est très joli, mais il faut aussi qu'il ait un préfixe à déléguer aux clients du réseau local, et il doit l'obtenir avec la technique DHCP du RFC 8415 (exigences W-4 et WPD-1).

Nouveauté de ce RFC par rapport au RFC 6204, W-6, le CPE doit aussi inclure un client PCP (Port Control Protocol, RFC 6887) pour son propre usage (il n'est pas obligé de fournir ce service à ces clients du LAN).

À côté d'autre exigences évidentes, portant sur des fonctions de base d'IPv6, le RFC demande aussi que le client DHCP dans le CPE utilise les options du RFC 3646 permettant de récupérer la liste des serveurs de noms (exigences WAA-3 et WAA-4).

Il devrait aussi avoir un serveur NTP (RFC 5905), mais pour son usage, pas forcément pour distribuer l'heure sur le réseau local (exigence WAA-5). La liste des serveurs NTP devrait également être récupérée dynamiquement et de manière standard avec les options DHCP du RFC 5908.

Justement, côté LAN, maintenant, que doit faire le bon CPE IPv6 ? Là encore, on trouve beaucoup d'exigences qui sont juste un rappel des fonctions de base d'IPv6. Mais d'autres sont moins évidentes comme la capacité à gérer des ULA (exigence ULA-1 et RFC 4193) ou le serveur DHCP pour les clients du réseau local (exigence L-8, en pratique, très rare sur les CPE d'aujourd'hui). Ce serveur DHCP peut servir à l'affectation des adresses IP (RFC 8415) ou bien uniquement à distribuer des paramètres statiques, comme le permet le RFC 8415. Aussi bien en DHCP (RFC 3646) qu'en RA (RFC 8106), le CPE doit fournir aux machines du réseau local les adresses des serveurs de noms, ainsi que quelques paramètres DNS.

Également côté LAN, le CPE devra fournir des adresses globales ou des ULA (les adresses locales au lien ne suffisent pas et, de toute façon, pas besoin d'un routeur pour en acquérir). La gestion des ULA (RFC 4193) est désormais obligatoire, et le CPE doit pouvoir mémoriser le préfixe ULA, même en cas de redémarrage, de façon à fournir un préfixe stable (et, idéalement, configurable) au réseau dont il a la charge (exigences ULA-1, ULA-2 et ULA-3).

Une autre nouveauté de ce RFC 7084 par rapport à son prédécesseur, le RFC 6204, est l'exigence que le CPE IPv6 gère certaines des techniques de coexistence et de transition IPv4-IPv6. Ainsi, le RFC recommande fortement 6rd (RFC 5969) et DS-Lite (RFC 6333).

La securité est la dernière sous-section de cette section 4. C'est un sujet très délicat, car il opposait, à l'IETF, ceux qui voulaient interdire par défaut les connexions entrantes, au nom de la sécurité (« Minitel 2.0 ») à ceux qui voulaient profiter du fait qu'IPv6, avec son abondance d'adresses globalement uniques, permettait de rétablit le modèle de bout en bout de l'Internet, qui permet à deux machines consentantes d'échanger les paquets qu'elles veulent. Le compromis entre les deux camps a finalement été que le CPE devait mettre en œuvre, dans son logiciel, cette capacité de bloquage, mais pas forcément l'activer par défaut. Un autre RFC, le RFC 6092, discute plus en détail des fonctions de pare-feu d'un CPE. Dans notre RFC 7084, on a juste la recommandation que, par défaut, le CPE filtre les adresses IP usurpées (RFC 2827) et les paquets clairement invalides (bogons, par exemple).

Quels sont les changements depuis le RFC 6204, qui avait été le premier à s'attaquer à cette difficile question de la spécification d'un CPE idéal ? Ils sont assez importants (surtout que le RFC 6204 est assez récent, vieux de seulement deux ans et demi), et décrits en annexe A. Les principaux :

  • L'ajout des techniques de transition comme 6rd et DS-Lite.
  • La normalisation de PCP dans le RFC 6887, qui permet désormais de l'indiquer comme obligatoire (mais seulement pour le CPE lui-même, pas forcément pour les machines du réseau local).
  • Des obligations en plus, comme les paramètres DNS, qui passent de SHOULD à MUST.
  • Plus de précision dans certaines demandes, par exemple sur le fait que le CPE doive cesser d'annoncer des routes IPv6 si lui-même n'a plus de connectivité vers le FAI.

Les CPE d'aujourd'hui mettent-ils en œuvre ces recommandations ? Difficile à dire, je ne connais pas d'étude systématique ayant été faite sur les capacités de ces engins (un projet est en cours), mais ce serait certainement très instructif.


Téléchargez le RFC 7084


L'article seul

RFC 7083: Modification to Default Values of SOL_MAX_RT and INF_MAX_RT

Date de publication du RFC : Novembre 2013
Auteur(s) du RFC : R. Droms (Cisco Systems)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dhc
Première rédaction de cet article le 23 novembre 2013


Choisir les valeurs numériques par défaut des paramètres réseaux est un art difficile. Et, parfois, on se trompe et il faut corriger. Depuis qu'il y a des réseaux IPv6 utilisant DHCP pour leur configuration, suivant la spécification du RFC 3315, on observe parfois des pics de trafic importants qui ont été attribués à la valeur maximale trop basse de deux paramètres, SOL_MAX_RT et INF_MAX_RT. Ce RFC remonte donc ces valeurs. (Ce RFC a été depuis intégré dans le RFC 8415.)

Ces paramètres étaient définis dans le RFC 3315 (remplacé depuis par le RFC 8415, qui a intégré notre RFC 7083). Un client DHCP, en l'absence de réponse, doit réessayer mais en augmentant progressivement son délai d'attente jusqu'à une valeur maximale, à partir de laquelle il réessaiera périodiquement. SOL_MAX_RT est la durée maximale qu'un client DHCP attendra s'il ne reçoit pas de réponses à ses messages de sollicitation (section 17.1.2 du RFC 3315). Et INF_MAX_RT est la durée maximale entre deux demandes d'informations. Si le serveur DHCP choisit de ne pas répondre aux demandes de sollicitation des clients, chaque client retransmettra toutes les deux minutes, la valeur qui était indiquée par le RFC 3315. S'il y a des dizaines de milliers de clients DHCP, c'est trop, le serveur supportera une charge excessive.

La section 3 de notre RFC contient les nouvelles valeurs par défaut : SOL_MAX_RT et INF_MAX_RT passent de 120 secondes à 3 600. La charge d'un serveur, dans le pire des cas, devrait donc être divisée par trente. À noter que rien n'a été observé dans le monde réel pour INF_MAX_RT mais il est également remonté par souci de cohérence avec SOL_MAX_RT.

Attention : les valeurs spécifiées dans la section 3 sont des valeurs par défaut. Un serveur DHCP peut les changer en utilisant les nouvelles options du même nom (SOL_MAX_RT, numéro 82 et INF_MAX_RT, numéro 83) décrites dans les sections 4 et 5 et désormais enregistrées à l'IANA. Ces deux options dans la réponse DHCP permettent de spécifier une autre valeur (entre 60 et 86 400 secondes) pour les paramètres SOL_MAX_RT et INF_MAX_RT.

À noter qu'il n'existe pas encore de mise en œuvre de ces nouvelles options. Un client mis à jour devra obéir à ces options et un serveur mis à jour permettra de les fixer.


Téléchargez le RFC 7083


L'article seul

Panne du service DNS chez Microsoft

Première rédaction de cet article le 22 novembre 2013


Une grande panne DNS a planté hier soir tous les services de Microsoft, comme Hotmail. Comme d'habitude, l'information diffusée dans les médias et les forums ne vaut pas grand'chose, donc, revenons aux faits.

Les cris ont commencé le 21 novembre vers 2250 UTC sur Twitter. Plein de services ne répondaient plus. Une rapide analyse montrait un problème DNS. Ainsi, en demandant à DNSyo vers 2301 UTC, on avait « I asked 500 servers for NS records related to microsoft.com, 199 responded with records and 301 gave errors » (les résolveurs ouverts interrogés par DNSyo et qui avaient réussi ont en fait utilisé leur cache). Vers 2330 UTC, le problème a disparu.

Le DNS est un service crucial pour toute présence en ligne, puisque quasiment toute opération sur l'Internet commence par des requêtes DNS. Celui-ci doit donc être proprement configuré et géré. Malgré cela, il est régulièrement oublié lors des investissements.

Mais plus précisement, pourquoi est-ce que les résolveurs interrogés par DNSyo n'ont pas pu résoudre microsoft.com (ou xbox.com ou outlook.com, tous hébergés sur les mêmes serveurs et victimes du même problème) ? Regardons vers 2300 UTC :

% check-soa -i microsoft.com
ns1.msft.net.
	2a01:111:2005::1:1: OK: 2013112102 (146 ms)
	65.55.37.62: ERROR: Timeout
ns2.msft.net.
	2a01:111:2006:6::1:1: OK: 2013112102 (97 ms)
	64.4.59.173: ERROR: Timeout
ns3.msft.net.
	2a01:111:2020::1:1: OK: 2013112102 (15 ms)
	213.199.180.53: ERROR: Timeout
ns4.msft.net.
	2404:f800:2003::1:1: OK: 2013112102 (287 ms)
	207.46.75.254: ERROR: Timeout
ns5.msft.net.
	2a01:111:200f:1::1:1: OK: 2013112102 (100 ms)
	65.55.226.140: ERROR: Timeout

C'est le point le plus amusant de la panne, et aucun média ou forum ne l'a noté : le problème ne frappait qu'IPv4. Tous les serveurs répondaient normalement en IPv6. Un résolveur qui pouvait utiliser IPv6 n'avait donc aucun problème et les services de Microsoft marchaient comme avant. (Vous pouvez tester avec la requête dig SOA droneaud.org. Si vous récupérez un SERVFAIL, c'est que votre résolveur n'a pas été mis à jour depuis le siècle dernier et ne parle toujours qu'IPv4.)

Bien, cela montre qu'il faut avoir des résolveurs modernes, connectés en IPv6. Mais pourquoi cette curieuse panne ? Qu'est-ce qui a pu rendre tous ces serveurs, situés dans des réseaux très différents, inaccessibles en IPv4 tout en étant joignables en IPv6 ?

J'avoue que je ne sais pas. La liste des serveurs de noms est stable (vu avec DNSDB) depuis longtemps. RIPEstat, pas assez réactif, n'a pas encore de données sur cette panne. Une attaque par déni de service sur les machines n'épargnerait pas IPv6 (quoi que, attention, les services IPv4 et IPv6 correspondant à un même nom ne sont pas forcément sur la même machine). C'est encore plus vrai pour une attaque sur le réseau. Une panne d'une machine ou d'un réseau n'allait pas affecter tous les serveurs de Microsoft. Donc, pas d'explication simple, on peut se laisser aller à la spéculation. (Microsoft n'a évidemment rien communiqué et ne communiquera rien.)


L'article seul

RFC 7073: A Reputation Response Set for Email Identifiers

Date de publication du RFC : Novembre 2013
Auteur(s) du RFC : N. Borenstein (Mimecast), M. Kucherawy
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF repute
Première rédaction de cet article le 22 novembre 2013


Le cadre général du système de requête sur la réputation a été défini dans le RFC 7070. Il reste à le décliner en diverses applications. L'une des utilisations les plus importantes pour un système de réputation est évidemment la lutte contre le spam et c'est donc à cela qu'est consacré notre RFC : la réputation des identifiants de courrier électronique.

L'application se nomme donc email-id (et est enregistrée dans le registre des applications). Les assertions possibles sur un acteur du courrier sont :

  • abusive : envoie-t-il des messages abusifs, par exemple de harcèlement ou de menaces ?
  • fraud : envoie-t-il des messages frauduleux, par exemple de hameçonnage ? (Voir à ce sujet le RFC 5901.)
  • invalid-recipients : envoie-t-il des messages à des utilisateurs inexistants (ce qui est courant chez les spammeurs, soit parce que leurs listes sont de mauvaise qualité, soit parce qu'ils testent de nouvelles adresses).
  • malware : envoie-t-il du logiciel malveillant ?
  • spam : envoie-t-il du spam ?

Dans le cadre du RFC 7070, ces assertions ne sont pas binaires : une entité a, pour chaque assertion, un classement qui va de 0 (assertion tout à fait fausse) à 1 (assertion vraiment vraie). Ainsi, example.net pourrait avoir un classement de 0,01 à l'assertion malware (il n'envoie quasiment jamais de logiciels malveillants) mais de 0,8 à l'assertion spam (il envoie souvent du spam). Les classements sont linéaires donc une entité qui aurait un classement de 0,4 pour le spam pourrait être décrite par « est deux fois moins spammeur que example.net ».

On note que toutes ces assertions sont « négatives », décrivent un comportement qu'on désapprouve. L'annexe A du RFC rappelle que certains pensent qu'il serait plus intéressant de travailler sur des assertions positives (et donc des bonnes réputations), car on peut échapper à des mauvaises réputations (on achète un nouveau nom de domaine et hop, on repart de zéro). Cela se fera peut-être dans le futur.

En réponse à une requête d'application email-id et comportant une ou plusieurs de ces assertions (celles qui intéressent le client du service de réputation), le serveur de réputation renvoie un reputon, une information structurée en JSON comportant un certain nombre de membres obligatoires (cf. RFC 7071) et, dans le cadre de cette application email-id, deux autres :

  • email-id-identity qui indique comment a été identifié l'émetteur (la réputation ne vaut évidemment pas grand'chose sans authentification mais, parfois, on n'a pas le choix et on a des identités non authentifiées) : DKIM (l'identité doit alors être la valeur de l'étiquette d=), SPF, adresse IP, valeur du champ HELO dans la connexion SMTP, valeur du champ MAIL FROM dans la communication SMTP (ce qu'on nomme le « RFC 5321 from »), valeur de l'en-tête From: du message (ce qu'on nomme le « RFC 5322 from »),
  • sources qui indique le nombre de sources qui ont contribué à l'établissement de cette réputation (le membre standard sample-size est le total de rapports, mais ils peuvent tous provenir d'une seule source).

L'identité (email-id-identity) est cruciale car on dispose de plusieurs identités dans un message (le From: de l'en-tête n'est pas forcément le même que le MAIL FROM de l'enveloppe SMTP), et elles n'ont pas toujours la même force. Par exemple, le From: de l'en-tête n'a subi aucune validation et peut valoir n'importe quoi. Au contraire, une signature DKIM permet de rattacher un message à un domaine responsable. Si le client n'est intéressé que par un seul type d'identité (par exemple SPF), il peut le préciser dans la requête.

Un exemple de reputon ? OpenDKIM a un service de distribution de réputation DKIM (donc, seuls les domaines utilisant DKIM y sont présents) :


% wget -O - 'http://repute.opendkim.org/repute.php?subject=amazon.com&assertion=spam&application=email-id&service=repute.opendkim.org'
...
{
  "application": "email-id",
  "reputons": [
    {
	"rater": "repute.opendkim.org",
	"assertion": "spam",
	"rated": "amazon.com",
	"rating": 0.000229625,
	"identity": "dkim",
	"rate": 1013,
	"sample-size": 181,
	"generated": 1384331169
    }
  ]
}


Téléchargez le RFC 7073


L'article seul

RFC 7070: An Architecture for Reputation Reporting

Date de publication du RFC : Novembre 2013
Auteur(s) du RFC : N. Borenstein (Mimecast), M. Kucherawy, A. Sullivan (Dyn)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF repute
Première rédaction de cet article le 22 novembre 2013


Il y a des tas de fois dans l'Internet où on souhaite se renseigner automatiquement sur la réputation d'une entité (une adresse IP, un nom de domaine, etc). Aujourd'hui, chaque application qui souhaite le faire développe une technologie spécifique pour l'accès à cette réputation (comme les listes noires DNS du RFC 5782). L'idée du projet repute de l'IETF est de créer des mécanismes communs, utilisables par une variété d'applications. Ce premier RFC est la fondation du projet et décrit l'architecture générale du système de réputation. D'autres RFC vont décrire les détails.

Un des principes fondateurs de l'Internet est qu'on n'a pas besoin de montrer patte blanche avant d'accéder à un service. Par exemple, pour une des applications les plus répandues, le courrier électronique, n'importe qui peut écrire à n'importe qui sans introduction préalable. On entend souvent des gens qui n'ont pas réfléchi à la question dire que cela contribue aux problèmes de sécurité de l'Internet. Mais cela a surtout contribué à son succès ! Comme le note à juste titre le RFC 5218, un système plus rigide, avec mécanismes de sécurités dès le début, avec authentification obligatoire avant d'envoyer un message, plairait certes aux dirigeants chinois ou saoudiens, et permettrait certainement de mieux traiter certains problèmes comme le spam. Mais il aurait aussi certainement à coup sûr tué le courrier électronique avant même qu'il ne décolle (ce n'est pas un avis personnel : c'est une constatation fondée sur l'observation de systèmes concurrents, bien oubliés aujourd'hui).

Donc, la plupart des services de l'Internet n'authentifient pas (l'émetteur d'un courrier peut mettre ce qu'il veut dans le champ From:...) et, même lorsqu'ils le font (en cas d'utilisation de TCP, l'adresse IP est relativement authentifiée), l'authenticité d'un pair ne nous renseigne pas sur son honnêteté et sa sincérité. Cette confusion entre authentification et autorisation est très fréquente, elle a même mené certains spammeurs à être les premiers à déployer certaines techniques (comme DKIM), en espérant jouer sur cette confusion. Si certains administrateurs de serveurs de messagerie étaient assez bêtes pour retirer des points de « spamicité » uniquement parce qu'un message avait une signature DKIM valide, le spammeur pouvait espérer injecter quelques spams en plus.

Résultat, les services de l'Internet, comme le courrier électronique, sont un grand succès mais, suite logique de ce succès, sont affligés de nombreux problèmes de sécurité (« Any real ecosystem has parasites », dirait Cory Doctorow). Comment lutte-t-on contre ces problèmes ? Une méthode courante est d'utiliser la réputation, c'est-à-dire des affirmations par un tiers comme quoi telle ou telle entité est digne de confiance. Son utilisation est particulièrement courante dans le cadre de la lutte contre le spam : on demande à un service de réputation « cette adresse IP est-elle souvent émettrice de spam ? » Si oui, on peut décider de ne pas accepter son message. Cette fois, on ne se limite pas à l'authentification : on bâtit au-dessus d'elle.

Si le monde du courrier électronique fut le premier à utiliser à grande échelle ces systèmes de réputation, d'autres dans l'Internet pourraient y venir. C'est pour les aider qu'a été développé ce modèle, et les protocoles qui l'accompagnent. En effet, les mécanismes actuels (le plus connu étant les DNSBL décrites dans le RFC 5782 mais il y a aussi le système du RFC 5518 pour se porter garant) sont très simplistes, notamment par le fait que leur réponse est binaire. On aurait besoin de nuances, et de la capacité d'apporter des détails (le RFC cite comme exemple la différence entre « approuver un chèque » et une institution très typiquement états-unienne, « faire un credit report complet »). Autre exemple où les systèmes actuels sont insuffisants, le cas où un acteur a une réputation différente selon ses services. Par exemple, un site de commerce en ligne peut avoir une mauvaise réputation pour les délais de livraison, mais un bonne réputation pour la qualité de l'information qu'il donne en cas de problème.

Compte tenu de tous ces points, le groupe de travail a développé un modèle, qui est résumé en section 2 de ce RFC. La réputation se gère à trois. On a un acteur qu'on veut évaluer, désigné par un identificateur. Un client qui est intéressé par la réputation de cet acteur. Et un service de réputation qui va distribuer de l'information sur les acteurs. Le service de réputation peut être public ou accessible seulement à des abonnés. Le client devra être configuré pour accéder à ce service de réputation. Les identificateurs utilisés peuvent être variés : noms de domaine, adresses de courrier électronique, adresses IP, etc.

Descendons un peu plus dans les détails (sections 4 à 6). L'architecture du système est celle d'un simple protocole question/réponse, qui peut utiliser comme transport sous-jacent divers mécanismes comme par exemple HTTP, le DNS... La syntaxe exacte dépend de l'application (rappelez-vous que ce RFC ne décrit qu'un cadre général). Un format possible des informations de réputation est normalisé dans le RFC 7071, un des protocoles d'accès, fondé sur HTTP, est dans le RFC 7072, et les identificateurs utilisés dans le cas du courrier électronique sont dans le RFC 7073.

Prenons l'exemple d'une application, un logiciel qui reçoit le courrier électronique, et qui utilise DKIM (RFC 6376) pour authentifier le domaine expéditeur. Ce nom étant authentifié, elle pourra s'en servir comme base de l'évaluation du message : on authentifie l'envoyeur du courrier avec DKIM, on interroge un serveur de réputation sur la réputation de cet envoyeur, et on décide alors d'accepter le message ou de l'envoyer dans le dossier « Spam ». DKIM apporte l'authentification, le système de notre RFC ajoute la réputation, et les deux ensemble permettent l'autorisation.

Que retourne un serveur de réputation ? Trois choses importantes :

  • Le nom de l'entité qu'il vient d'évaluer (dans l'exemple précédent, ce pourrait être gmail.com, le domaine expéditeur qui signe avec DKIM).
  • Une (ou plusieurs) assertion(s). Une assertion est une affirmation, plus ou moins fausse, sur le comportement de l'entité. Pour un domaine expéditeur, cela pourrait être « envoie du spam ». Pour un site de commerce en ligne, « livre dans les temps ». Pour quelqu'un qui modifie Wikipédia, « vandalise des articles ».
  • Un classement. Contraitrement aux DNSBL, le système de réputation n'est pas binaire. Une assertion peut être plus ou moins fausse et c'est ce qu'exprime le classement. Un classement va de 0 (assertion complètement fausse) à 1 (assertion toujours vraie). Ainsi, un domaine qui envoie rarement du spam pourrait avoir un classement de 0,2 à l'assertion « envoie du spam » alors qu'un domaine plus spammeur aurait un classement de 0,6.

Rappelez-vous que les assertions pertinentes, ainsi que la signification des classements, dépendent de l'application. Chaque application (réception de courrier, jugement des commentaires sur un blog, etc) aura donc sa propre spécification, décrivant les réponses attendues. Les applications ainsi spécifiées sont stockées dans un registre IANA.

La réponse structurée est dans un objet nommé « reputon ». Les détails de sa syntaxe dépendent du transport utilisé et de l'application. Mais si vous voulez voir des exemples de reputons, regardez le RFC 7071.

Pour obtenir un reputon en réponse, le client aura dû envoyer le nom de l'entité qu'il veut évaluer, le nom de l'application (tiré du registre IANA cité plus tôt) et, éventuellement, les assertions qui l'intéressent (le serveur de réputation peut en stocker plusieurs pour une même entité).

Comme le note la section 8, tout ceci peut poser des problèmes de préservation de la vie privée. Les informations de réputation peuvent dans certains cas être considérées sensibles et pas distribuables publiquement. Et il n'y a pas que la réponse qui peut être sensible, la question l'est aussi parce qu'elle révèle un intérêt du client (« le MP3 tina-turner-total-eclipse-of-the-heart.mp3 de condensat SHA-256 5ba214e312254abd22e7aae38af865a92f93cbd01e180051ab5bd443ceeae594, que je m'apprête à télécharger, est-il de bonne qualité ? ») Le RFC insiste donc sur la nécessité de fournir de la confidentialité si les données le justifient. Par exemple, le DNS, qui ne fournit aucune confidentialité, ne doit en aucun cas être utilisé pour des services sensibles. Si on se sert de HTTP comme transport de données de réputation sensibles, il faut utiliser HTTPS et, si on se sert du courrier, PGP ou équivalent.

De même, un accès non autorisé à la base de données d'un serveur de réputation pourrait causer des dommages, si ces données sont privées.

Mais il y a aussi des problèmes de sécurité qui ne sont pas liées à la vie privée (section 9). Par exemple, que se passe t-il si le serveur de réputation ment, distribuant délibérement des informations trop ou pas assez favorables à certaines entités ? Si un client accède à des informations de réputation, c'est probablement pour s'en servir pour prendre des décisions et des informations fausses peuvent donc avoir des conséquences concrètes désagréables. Imaginez un serveur de courrier qui accepterait du spam (ou, au contraire, rejetterait des messages légitimes) parce que le serveur de réputation l'a trompé.

Il n'y a pas de solution miracle à ce problème. Utiliser un serveur de réputation, c'est sous-traiter, c'est faire confiance. Cela implique le risque d'être trompé. Au minimum, le RFC conseille de ne faire confiance qu'à des services de réputation qui publient leurs pratiques de classement, qu'on puisse les analyser (voir le RFC 6471 pour ce problème dans le cas des listes noires de spammeurs dans le DNS).

Les motivations pour le projet de réputation ont été décrites dans les supports de la première présentation à l'IETF.

Pour des exemples d'utilisation et des informations sur les mises en œuvre de ce système, voir mes articles sur le RFC 7071 et sur le RFC 7072. Merci à Murray S. Kucherawy pour son aide.


Téléchargez le RFC 7070


L'article seul

RFC 7072: A Reputation Query Protocol

Date de publication du RFC : Novembre 2013
Auteur(s) du RFC : N. Borenstein (Mimecast), M. Kucherawy
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF repute
Première rédaction de cet article le 22 novembre 2013


Comment obtenir de l'information sur la réputation d'une entité (un nom de domaine, une adresse IP, etc) sur l'Internet ? Il existe actuellement tout un tas de méthodes ad hoc et le but du groupe de travail IETF repute est de fournir une alternative standard. Le RFC 7070 décrit le fonctionnement général de ce système. Ce cadre général autorise plusieurs protocoles concrets de récupération de l'information et ce RFC décrit un de ces protocoles, fondé sur HTTP.

Le mécanisme est assez simple et le RFC très court. Le client qui veut se renseigner auprès d'un serveur de réputation travaille en deux temps :

  • Il récupère un gabarit auprès du serveur de réputation, et l'utilise pour fabriquer un URI,
  • Il récupère ensuite le reputon, exprimé en JSON (cf. RFC 7071), via cet URI.

Ce mécanisme en deux étapes permet de la souplesse : les reputons peuvent se trouver derrière des URI très différents, qui n'ont pas besoin d'être « en dur » dans le client.

Ainsi, le service de réputation d'OpenDKIM, accessible en repute.opendkim.org a le gabarit http://{service}/repute.php{?subject,application,assertion,service,reporter} ce qui s'expanse en http://repute.opendkim.org/repute.php?subject=nom-de-domaine&application=email-id&assertion=spam&service=repute.opendkim.org (reporter est optionnel). Rappel de syntaxe des gabarits : le point d'interrogation ne s'applique pas qu'à la variable suivante mais à toutes les variables entre crochets.

Il n'y a pas de mécanisme de découverte d'un serveur de réputation : typiquement, cela se fait manuellement. En pratique, beaucoup de ces services nécessiteront une inscription ou un abonnement, de toute façon. Notez que le RFC ne spécifie pas de mécanisme d'authentification du client : on se sert par exemple des solutions classiques de HTTP. De même, si on veut de la confidentialité, on doit utiliser les mécanismes de chiffrement habituels, donc HTTPS (voir section 5 de ce RFC).

Le client doit aussi connaître le nom de l'application et le nom de l'assertion à tester. Il récupére ensuite le gabarit, en utilisant un URI « bien connu » (RFC 8615), /.well-known/repute-template (désormais dans le registre IANA des URI bien connus). Ce gabarit suit la syntaxe du RFC 6570. Le client remplace alors les variables. Par exemple, pour le gabarit ci-dessus, la variable application va être remplacée par email-id (le serveur de réputation peut gérer plusieurs applications). Pour reprendre l'exemple du RFC, si le gabarit du service example.com avait été http://{service}/{application}/{subject}/{assertion}, et qu'on cherchait des informations sur la réputation de example.org dans le cadre de l'application email-id (normalisée dans le RFC 7073), sur l'assertion spam, l'expansion du gabarit donnerait http://example.com/email-id/example.org/spam. Quelles sont les variables possibles dans un gabarit ?

  • application est le nom de l'application, pris dans le registre IANA,
  • service est le nom (ou l'adresse IP) du service de réputation demandé (celui d'où on a obtenu le gabarit),
  • subject est l'entité dont on veut connaître la réputation,
  • assertion est l'assertion qui nous intéresse, les valeurs possibles dépendant de l'application,
  • Sans compter des variables spécifiques à l'application.

Si un paramètre est optionnel mais que la syntaxe du gabarit ne permet pas de l'omettre, le client met une chaîne de caractères vide. L'auteur du gabarit doit veiller à ce que cela ne mène pas à des URI incorrects. Ainsi, le gabarit http://{service}/{application}/{subject}/{assertion}/{a}/{b}, si a est facultatif, pourrrait mener à une expansion où on aurait deux barres obliques de suite, ce que bien des serveurs HTTP réduisent à une seule, faussant ainsi la lecture de l'URI. Une bonne solution serait d'utiliser le mécanisme des gabarits du RFC 6570 pour les paramètres optionnels et donc de réécrire le gabarit vers http://{service}/{application}/{subject}/{assertion}/{?a,b}.

La réponse générée par le serveur de réputation sera alors un reputon (RFC 7071), étiqueté application/reputon+json.

Il existe une implémentation (due à Murray S. Kucherawy, un des auteurs du RFC) dans OpenDKIM à partir de la 2.9 (actuellement en version beta), le serveur est écrit en PHP (le serveur produit du JSON avec printf...) et le client en C. Testons-là avec le service public repute.opendkim.org. On récupère le gabarit :

% curl http://repute.opendkim.org/.well-known/repute-template
http://{service}/repute.php{?subject,application,assertion,service,reporter,format}

On fabrique ensuite une requête curl à la main (un vrai client du service de réputation le ferait automatiquement à partir du gabarit) :

% curl 'http://repute.opendkim.org/repute.php?subject=gmail.com&assertion=spam&application=email-id&service=repute.opendkim.org'
Content-Type: application/reputon+json

{
  "application": "email-id",
  "reputons": [
    {
	"rater": "repute.opendkim.org",
	"assertion": "spam",
	"rated": "gmail.com",
	"rating": 0.0113348,
	"identity": "dkim",
	"rate": 1735,
	"sample-size": 181,
	"generated": 1383463475
    }
  ]
}

On voit que Gmail émet apparemment peu de spam (classement à 0,0113348). Ce service est mis en œuvre avec les messages reçus par le domaine opendkim.org et seulement s'ils sont signés par DKIM (donc, n'essayez pas avec un domaine non signé comme laposte.net, vous aurez un No data available).


Téléchargez le RFC 7072


L'article seul

RFC 7071: A Media Type for Reputation Interchange

Date de publication du RFC : Novembre 2013
Auteur(s) du RFC : N. Borenstein (Mimecast), M. Kucherawy
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF repute
Première rédaction de cet article le 22 novembre 2013


Le cadre général d'accès à l'information sur la réputation d'une entité (identifiée par son nom de domaine, son adresse IP ou d'autres identificateurs) a été défini dans le RFC 7070. Cet autre RFC est plus concret et définit le format d'un reputon, une information structurée (en JSON) sur la réputation d'une entité, ainsi que le type de media associé, le nouveau application/reputons+json. Il crée également des registres IANA pour les noms d'applications de réputation et les réponses possibles selon l'application.

Le cadre du RFC 7070 prévoit que l'accès aux informations de réputation peut se faire par plusieurs mécanismes comme par exemple HTTP (RFC 7072). Mais le format transporté est toujours le même, celui d'un reputon. Un reputon est un objet JSON comportant les informations de réputation : identificateur de l'entité jugée, assertions sur cette identité, classement de l'identité selon ces assertions. Une requête va donc renvoyer un ou plusieurs reputons.

La section 3 liste les attributs d'un reputon, notamment :

  • L'identité de l'entité (rater) qui a jugé de la réputation,
  • Celle de l'entité jugée (rated),
  • L'assertion,
  • Le classement (rating) de l'entitée jugée, selon cette assertion, de 0,0 (assertion complètement fausse) à 1,0 (assertion tout à fait vraie).

Les identités dépendent de l'application et peuvent être des noms de domaine, des adresses IP, etc. La section 4 décrit en détail la notion de classement. Il y a aussi des attributs facultatifs dans un reputon :

  • Degré de confiance du juge vis-à-vis de son classement, de 0,0 à 1,0,
  • Classement considéré comme normal, pour pouvoir estimer si l'entité jugée est « dans les clous » ou pas,
  • Taille de l'échantillon sur lequel s'est fondé le jugement,
  • Date et heure où le classement a été établi (generated),
  • Date et heure à partir desquelles le jugement cessera d'être valable (expires).

Ces deux derniers attributs sont représentés par un nombre de secondes depuis le 1er janvier 1970. L'attribut expires permet (mais n'oblige pas) de mettre en place des caches devant le serveur qu'on interroge (section 5). Le RFC recommande de mettre des durées de validité d'autant plus courtes qu'on n'est pas sûr du jugement, par exemple parce qu'on n'a pas encore récolté beaucoup de données.

La section 6 indique la syntaxe concrète des reputons, sous forme d'un objet JSON, dont les membres (couples {clé, valeur}) représentent les attributs présentés plus haut. Les reputons sont mis dans un tableau JSON, puisqu'on peut en avoir plusieurs (s'il existe plusieurs assertions). Les assertions présentes dans un reputon sont typiquement celles qui ont été demandées par le client. Si ce dernier ne précise rien, le serveur peut renvoyer toutes les assertions qu'il connait. Un reputon peut être vide, si le serveur n'a aucune information sur l'entité et l'assertion demandées.

Voici l'exemple de reputon donné par le RFC, emprunté au baseball :

{
       "application": "baseball",
       "reputons": [
         {
           "rater": "RatingsRUs.example.com",
           "assertion": "is-good",
           "rated": "Alex Rodriguez",
           "rating": 0.99,
           "sample-size": 50000
         }
       ]
}

On a un seul reputon, pour l'assertion « est un bon joueur ». Vu le classement (quasiment 1), on peut dire que RatingsRUs.example.com estime qu'Alex Rodriguez est un bon joueur.

L'assertion est ici très générale. Elle pourrait être plus précise, si les concepteurs de l'application baseball le voulaient :

{
       "application": "baseball",
       "reputons:" [
         {
           "rater": "baseball-reference.example.com",
           "assertion": "hits-for-power",
           "rated": "Alex Rodriguez",
           "rating": 0.99,
           "sample-size": 50000
         },
         {
           "rater": "baseball-reference.example.com",
           "assertion": "strong-hitter",
           "rated": "Alex Rodriguez",
           "rating": 0.4,
           "confidence": 0.2,
           "sample-size": 50000
         }
       ]
}

Si vous ne connaissez pas le baseball et que vous vous demandez ce que veut dire hits-for-power (ne frappe pas forcément beaucoup mais fort) ou strong-hitter (frappe souvent des coups sûrs), voyez Wikipédia. On voit que le même Alex Rodriguez a une nettement moins bonne réputation pour strong-hitter que pour hits-for-power. Notez aussi l'indication de la taille de l'échantillon (ici, 50 000 points de mesure), qui permet aux statisticiens de se faire une idée de la validité de ces classements.

Un exemple moins artificiel de service de réputation serait évidemment lié à la lutte contre le spam. Prenons donc cette fois une application réelle, enregistrée dans le registre IANA des applications de réputation, l'application email-id définie dans le RFC 7073. Ce tableau contient deux reputons :

     {
       "application": "email-id",
       "reputons": [
         {
           "rater": "rep.example.net",
           "assertion": "spam",
           "identity": "dkim",
           "rated": "example.com",
           "confidence": 0.95,
           "rating": 0.012,
           "sample-size": 16938213,
           "updated": 1317795852
         },
         {
           "rater": "rep.example.net",
           "assertion": "spam",
           "identity": "spf",
           "rated": "example.com",
           "confidence": 0.98,
           "rating": 0.023,
           "sample-size": 16938213,
           "updated": 1317795852
         }
       ]
     }

Il se lit ainsi : « example.com, authentifié par DKIM (regardez l'attribut identity, spécifique à cette application) envoit du spam 1,2 % du temps. L'échantillon compte près de 17 millions de messages ». À noter que le second reputon, basé sur SPF, indique presque deux fois plus de spam. Cela peut vouloir dire que la liste des serveurs SMTP autorisés par SPF comprend quelques moutons noirs.

Ces reputons seront étiquetés avec le nouveau type application/reputons+json désormais enregistré à l'IANA. Il utilise les suffixes (+json) du RFC 6839. Est également enregistrée à l'IANA la liste des applications. Les nouvelles applications qui voudraient être incluses dans ce registre doivent avoir un examen par l'IETF ou bien une spécification stable (le RFC 5226 contient la liste des règles d'enregistrement à l'IANA).

Vous voulez voir des vrais reputons ? Il n'y a pas encore beaucoup de services disponibles publiquement. Essayons avec celui d'OpenDKIM :


% curl 'http://repute.opendkim.org/repute.php?subject=ietf.org&assertion=spam&application=email-id&service=repute.opendkim.org'
Content-Type: application/reputon+json

{
  "application": "email-id",
  "reputons": [
    {
	"rater": "repute.opendkim.org",
	"assertion": "spam",
	"rated": "ietf.org",
	"rating": 0,
	"identity": "dkim",
	"rate": 4,
	"sample-size": 2,
	"generated": 1338014959
    }
  ]
}

Très bon score pour ietf.org, une spamicité nulle. Mais faites attention à la taille de l'échantillon, seuls deux messages ont été examinés...

Merci à Vincent Levigneron pour ses explications sur le baseball (les erreurs qui restent sont les miennes, je n'ai pas forcément tout compris).


Téléchargez le RFC 7071


L'article seul

Un "shunt" BGP observé en vrai

Première rédaction de cet article le 21 novembre 2013
Dernière mise à jour le 26 novembre 2013


On sait depuis longtemps qu'il est trivial d'annoncer sur l'Internet des routes pour d'autres adresses IP que les siennes. On peut ainsi capter le trafic de sa victime pour la couper du réseau (attaque par déni de service) ou peut-être pour se faire passer pour sa victime et, par exemple, recevoir du courrier qui ne vous est normalement pas destiné. Mais cette attaque est vite détectée car la victime ne reçoit plus (ou plus beaucoup) de trafic. D'où l'idée, très ancienne, de réinjecter le trafic à sa victime, après espionnage ou modification, pour retarder cette détection. Cela se nomme un shunt BGP, en référence à un dispositif électrique. Une étude récente de Renesys semble être la première à avoir mis en évidence cette attaque dans le monde réel.

L'attaque observée par Renesys comprend deux parties : une annonce BGP usurpée (comme dans la classique attaque de Pakistan Telecom contre YouTube) et un mécanisme (apparemment pas décrit dans l'article de Renesys) pour s'assurer de l'existence d'un chemin de retour, un clean path qui ne voit pas l'annonce BGP usurpée, de manière à ce qu'il transmette le trafic à la victime. La première partie, l'annonce BGP usurpée, est quelque chose de relativement fréquent dans l'Internet, la deuxième a été vérifiée par Renesys en envoyant des paquets vers un réseau détourné et en testant qu'ils arrivaient bien à destination, juste via une route très longue et très anormale (voir les traceroute dans l'article de Renesys). L'un des détournements était fait vers la Biélorussie, l'autre vers l'Islande (attention, le vrai responsable n'est pas forcément dans ces deux pays, il peut être caché derrière un opérateur piraté).

Si la possibilité d'un shunt BGP était connue depuis longtemps, les détails pratiques (il n'est pas évident de détourner un préfixe IP depuis tout l'Internet, tout en maintenant le clean path pour le retour) n'ont été décrits qu'en 2008 dans un article fameux de Kapela et Pilosov. Pour maintenir le chemin de retour, Kapela et Pilosov utilisaient l'AS prepending, l'ajout des numéros d'AS des opérateurs du chemin de retour à l'annonce usurpée, afin que ces opérateurs n'acceptent pas cette annonce (cela n'a pas été fait ici, voir l'annonce plus loin). À noter que Kapela et Pilosov proposaient également des méthodes pour rendre la détection plus difficile, comme de modifier le TTL dans les paquets IP pour tromper traceroute (cette astuce ne semble pas avoir été utilisée ici). Le travail de Kapela et Pilosov était théorique, il semble bien que les deux attaques étudiées par Renesys marquent le passage de leur méthode dans le monde réel.

Et les solutions ? À court terme, il est important de se rappeler qu'il faut chiffrer son trafic. Même si on pense être en sécurité car la communication est à courte distance (« mon trafic va uniquement de Denver à Denver, il n'y a pas de méchants à Denver »), l'étude de Renesys montre bien qu'un trafic local peut devenir distant grâce à l'attaque BGP et le faire passer par des endroits non sûrs. Quels que soient ses inconvénients, la cryptographie est une technologie à utiliser.

À un peu plus long terme, il faut mettre en place des systèmes de détection. Utiliser traceroute ne va pas forcément marcher (l'attaquant peut vous tromper en bricolant les TTL). Votre opérateur ou vous-même ont donc tout intérêt à utiliser des systèmes d'alarme BGP. L'attaquant peut faire bien des choses mais, par construction, il ne peut pas empêcher ses manipulations de se voir dans la table de routage globale. Bien sûr, ces systèmes n'empêcheront pas l'attaque mais, au moins, vous serez prévenus.

L'attaquant ne peut pas non plus violer les lois de la physique : en une milli-seconde, la lumière ne peut parcourir plus de 300 km. Un trajet de Denver à Denver qui prend moins d'une milli-seconde n'a certainement pas été détourné par l'Islande. Il faut donc mesurer le RTT et sonner l'alarme s'il augmente brusquement. Pour ceux qui utilisent les scripts de test compatibles Nagios, c'est le rta, le premier chiffre dans les seuils d'alerte de check_ping (le second étant le taux de pertes). Dans le futur, les sondes RIPE Atlas disposeront d'un mécanisme de test équivalent.

À plus long terme, la solution sera peut-être le déploiement massif de la RPKI mais on en est très loin aujourd'hui.

Plusieurs articles dans les médias ont été consacrés à cette attaque mais la plupart du temps, sans valeur ajoutée par rapport à l'article de Renesys, à part l'addition d'erreurs plus ou moins drôles. L'article d'Arik Hesseldahl n'est pas sans reproche (une erreur sur la notion d'attaque de l'homme du milieu) mais au moins il a fait un effort de pédagogie pour expliquer l'attaque à un public plus large que celui des lecteurs du blog de Renesys. J'en profite pour rappeler un très bon article sur la façon de faire une attaque en détournant le trafic, et comment le détourner, l'article d'Andree Toonk.

Et enfin, cherchons la vraie annonce BGP, dont Renesys ne donne qu'un résumé. (Attention, cela sera un peu plus technique.) On va se servir des archives de RouteViews, librement accessibles en ligne et qui remontent à 1997. Renesys donne l'heure exacte d'une des attaques, 07:36:36 UTC le 31 juillet. Les URL des archives de RouteViews sont prévisibles donc on sait que l'annonce qui nous intéresse va être dans le fichier bgpdata/2013.07/UPDATES/updates.20130731.0730.bz2 (updates.ANNÉE MOIS JOUR . HEURE MINUTE). On regarde les archives récoltées au LINX, plus proche de l'Islande (en vrai, j'avais d'abord regardé les archives récoltées par l'ISC en Californie, qui contenaient moins de choses). Donc :

% wget ftp://archive.routeviews.org/route-views.linx/bgpdata/2013.07/UPDATES/updates.20130731.0730.bz2

%  bunzip2 updates.20130731.0730.bz2

Le fichier ainsi obtenu est binaire, au format MRT (RFC 6396). On le transforme en texte avec bgpdump :

% bgpdump updates.20130731.0730 > updates.20130731.0730.txt

Et on examine tranquillement le fichier texte. Connaissant l'heure de l'attaque et l'AS d'origine de l'annonce usurpée, on finit par trouver une des annonces mensongères :

TIME: 07/31/13 07:36:46
TYPE: BGP4MP/MESSAGE/Update
FROM: 195.66.236.35 AS6067
TO: 195.66.237.222 AS6447
ORIGIN: IGP
ASPATH: 6067 6677 48685
NEXT_HOP: 195.66.236.35
ANNOUNCE
  64.81.96.0/24
  64.81.97.0/24
...

Que voit-on dans cette annonce ? L'heure correspond à ce qu'indique Renesys (les collecteurs de RouteViews n'ont pas forcément des horloges exactes à la seconde près et, de toute façon, la propagation BGP n'est pas instantanée). Le message a un chemin d'AS qui commence en 48685 et continue en 6677, comme le notait Renesys, avant d'arriver à l'AS 6067, un opérateur anglais, fournisseur de RouteViews. C'est donc là qu'on voit que l'attaquant n'utilisait pas d'AS prepending pour se créer un chemin de retour. Enfin, on a les préfixes annoncés, appartenant à Megapath, un opérateur états-unien, qui n'a certainement pas de fournisseur en Islande. L'annonce est donc clairement anormale, même si, juridiquement parlant, on peut estimer qu'on n'a pas de preuve qu'elle soit malveillante. (Jolie analyse, mais j'ai triché, j'ai été guidé par un informateur qui veut rester anonyme.)


L'article seul

Peut-on usurper une adresse IP ?

Première rédaction de cet article le 14 novembre 2013
Dernière mise à jour le 15 novembre 2013


Question technique du jour : peut-on usurper une adresse IP source sur l'Internet, c'est-à-dire peut-on envoyer un paquet IP en utilisant une adresse IP source qui n'est pas la sienne et qu'on n'a normalement pas « le droit » d'utiliser ? Tous les gens qui connaissent un peu l'Internet vont répondre « oui, on peut, c'est même une faiblesse de sécurité connue ». Mais la réalité est plus complexe.

La possibilité d'envoyer un paquet IP avec une adresse source usurpée découle du mode « datagramme » de fonctionnement d'IP. Chaque paquet est indépendant, porte des adresses source et destination que l'émetteur met à la valeur qui lui chante et, le paquet n'étant routé que sur la destination, il devrait arriver sans problème. Un certain nombre d'attaques, comme les attaques par réflexion, fonctionnent sur cette base.

Sur une machine Unix, par exemple, l'envoi d'un tel paquet se fait facilement avec hping :

% sudo hping --syn --spoof 192.0.2.42 -p 80 www.example.com

Notez que cela nécessite d'être root. À l'époque des gros mainframes très chers sur lesquels on n'avait qu'un compte utilisateur, c'était une limite. Aujourd'hui que chacun est root sur son PC ou sur son Pi, cela n'est plus un obstacle.

En raison des possibilités d'attaque, cet envoi avec une fausse adresse est très mal vue. La position officielle de l'IETF est que les FAI et autres acteurs des réseaux doivent interdire cet envoi, et c'est documenté dans deux RFC connus collectivement sous le nom de « BCP 38 » (BCP pour Best Current Practices), les RFC 2827 et RFC 3704. BCP 38 est loin d'être déployé par tous les opérateurs, comme le montrent les statistiques du Spoofer Project et cela explique pourquoi les attaques par réflexion continuent, et ne semblent pas devoir disparaître de si tôt. Néanmoins, certains opérateurs bloquent les paquets usurpés. (Un projet plus récent, visant à aller plus loin que BCP 38, est SAVI, RFC 6959.)

J'ai fait quelques tests avec hping et avec un logiciel écrit spécialement, afin de tester aussi en IPv6 (hping ne parle toujours pas IPv6 et son concurrent nping très mal et j'avais la flemme d'installer hping6). Sur trois fournisseurs différents de VPS, trois échecs. Chez un FAI grand public, idem (la box de ce FAI peut être configurée de deux façons différentes et je n'en ai testé qu'une, l'autre est peut-être plus favorable à l'usurpation). En IPv4, le NAT gêne probablement beaucoup toute tentative de triche. (Mais il y a une astuce, chez ce FAI, pour réussir à faire sortir les paquets usurpés malgré le NAT.)

Donc, si vous voulez vous lancer dans l'usurpation d'adresses IP, attention, ne vous attendez pas à ce que cela marche partout (mes tests ont été faits à partir d'accès accessibles au grand public ; cela peut être différent si l'usurpateur contrôle un réseau entier, avec un fournisseur de transit qui ne vérifie rien). Mais il y a d'autres obstacles que ceux de la couche 3. En effet, bien des protocoles utilisés au dessus d'IP nécessitent une réponse or l'usurpateur ne recevra pas forcément les réponses à ses paquets, puisqu'il a mis une autre adresse que la sienne. Distinguons deux cas : dans le premier, l'usurpateur peut voir les réponses (par exemple parce qu'il est sur le même réseau local que la victime dont il a usurpé l'adresse, et que ce réseau local n'a pas de protection contre le sniffing ; ou bien parce qu'il pratique le détournement de préfixes entiers par une attaque contre les protocoles de routage, ce qui est possible mais bien plus sophistiqué). Alors, l'usurpateur, s'il n'est pas bloqué par BCP 38, pourra envoyer des paquets avec une adresse mensongère et, voyant les réponses, pourra entretenir le dialogue.

Mais le second cas est plus fréquent : l'usurpateur ne voit pas du tout les paquets de retour, il doit travailler en aveugle. C'est beaucoup plus embêtant pour lui, car les protocoles sont en général conçus pour rendre la vie difficile pour un attaquant aveugle. Ainsi, TCP a un numéro de séquence dans les paquets et ce numéro part d'un numéro initial, l'ISN (Initial Sequence Number) qui est désormais choisi de manière imprévisible (si tout le monde suit bien les RFC 6528 et RFC 5961). Ne sachant pas quel est l'ISN, l'usurpateur ne pourra pas tenir un dialogue avec son correspondant. C'est pour la même raison que l'IETF recommande des ports source imprévisibles dans le RFC 6056. Et c'est aussi pour cela que le DNS a ses Query ID, un nombre imprévisible mis dans la requête et qui doit être renvoyé dans la réponse, pour que celle-ci soit acceptée. Malheureusement, dans le cas du DNS, ce Query ID, avec ses 16 bits, est trop petit et un usurpateur a donc toujours une chance. Et la technique de TCP n'est pas imparable non plus.

En résumé, oui, IP permet de tricher sur l'adresse source mais si vous voulez utiliser cette possibilité pour l'amusement, la gloire ou le fric, étudiez bien la question : cela peut être plus difficile à exploiter que cela n'en a l'air.


L'article seul

Peut-on se passer des métadonnées dans les protocoles Internet ?

Première rédaction de cet article le 12 novembre 2013


Dans les discussions sur les risques d'espionnage des utilisateurs sur l'Internet, le terme de métadonnées revient souvent. Ce sont les données qui, sans faire partie du contenu de la communication, servent à son acheminement. On sait qu'un espion qui n'aurait accès qu'à ces métadonnées peut récolter plein d'informations intéressantes. Peut-on empêcher cela ?

Par exemple, dans un paquet IP, les métadonnées sont entre autres les adresses IP source et destination. Dans un message de courrier électronique, les adresses de l'expéditeur et du destinataire (MAIL FROM et RCPT TO dans le dialogue SMTP). Pourquoi parle-t-on souvent des métadonnées lors de discussions sur les risques de l'espionnage et la protection de la vie privée ? Parce qu'elles sont particulièrement difficiles à sécuriser et parce qu'elles donnent certes moins d'informations que le contenu des messages mais que c'est encore trop.

Elles sont difficiles à sécuriser car les équipements intermédiaires en ont besoin pour acheminer les informations. La protection la plus évidente (et, effectivement, souvent la plus efficace) contre l'espionnage est le chiffrement. Celui-ci rend les données inaccessibles à l'espion. Mais il laisse les métadonnées. Dans le cas d'IP, l'utilisation d'une technique comme IPsec (RFC 4301) masque le contenu du paquet mais laissent intactes les adresses de source et de destination. Les techniques comme SSH (RFC 4251) ou TLS (RFC 5246) laissent encore plus de métadonnées visibles (le protocole de couche 4, et les ports). Dans le cas du courrier électronique, chiffrer le message avec PGP (RFC 4880) laisse les métadonnées SMTP (MAIL FROM, l'adresse de l'expéditeur, RCPT TO, celle du destinataire) en clair (ainsi que celles de l'en-tête du message, cf. RFC 5322).

Bien sûr, c'est moins intéressant pour l'espion que d'avoir tout le contenu du message et le chiffrement reste donc une excellente idée. Mais l'accès aux métadonnées reste un puissant outil. Il permet l'analyse de trafic.

Alors, comment éviter cela ? Supprimer les métadonnées ? Certaines sont implicites et ne sont pas modifiables facilement. Par exemple, l'écart temporel entre les messages est une métadonnée et elle peut être une source utile d'informations. Si on voit trois connexions HTTPS vers trois serveurs donnés, dans un intervalle très court, on pourra se dire que c'est sans doute la même page Web et on pourra chercher quelle page a des ressources sur ces trois serveurs (un jeu d'enfant pour Google). Autre exemple d'une métadonnée utile à l'écoutant, la taille des messages transmis. On peut en déduire, par exemple lors d'une connexion HTTPS s'il y a eu lecture d'une page Web ou bien envoi d'un fichier. Mais changer la taille d'un message n'est pas trivial. Comme on ne peut pas la réduire à volonté, la seule méthode est de bourrer en ajoutant des données aux messages trop courts. Cela a un coût en matière d'occupation de la capacité réseau. On trouve là un cas classique en sécurité : la nécessité de faire des compromis, ici entre vie privée et développement durable.

D'autres métadonnées sont explicites comme les adresses d'expéditeur et de récepteur. Comment les supprimer ? Parfois, c'est relativement facile. Par exemple, si on chiffre son courrier avec PGP, l'objet du message (champ Subject:) reste en clair. Il n'y a aucune bonne raison pour que cela soit le cas, à part la compatibilité avec le courrier traditionnel. Les logiciels qui chiffrent avec PGP devraient chiffrer tout le message (type message/rfc822) et le mettre comme partie MIME d'un message dont l'objet serait banalisé (Subject: this is a message). Mais d'autres métadonnées explicites sont là pour de bonnes raisons et vont être plus dures à éradiquer.

Le problème avec l'adresse de récepteur, c'est qu'elle est indispensable au routage. Les équipements intermédiaires ont besoin de cette adresse pour acheminer le message. Pour ne pas avoir d'adresse de destinataire visible, la seule solution est, là encore, très coûteuse en ressources réseau : il faut diffuser à tout le monde, comme le fait BitMessage.

Et pour l'adresse de l'expéditeur ? Elle n'est pas indispensable à l'acheminement, non ? On pourrait la supprimer (proposition dite « sourceless protocols »). Par exemple, sans changer le format des paquets IP, on pourrait imaginer une adresse source standard qui indiquerait « ce paquet est anonyme, il ne dira pas d'où il vient ». Mais ce n'est pas toujours aisé. Par exemple, parfois, il faut pouvoir envoyer un avis de non-remise comme les messages ICMP Destination Unreachable, ou comme les messages de courrier du RFC 8098. Pour cela, il faut bien avoir une adresse à qui envoyer ces notifications. Autrement, l'expéditeur enverra dans le noir, en ne sachant jamais si son message est arrivé.

Et c'est encore plus vrai pour les protocoles qui exigent un dialogue alors que la couche basse ne fournit qu'un service de messages. Par exemple, le protocole de transport le plus utilisé dans l'Internet, TCP, nécessite que les messages puissent circuler dans les deux sens, ce qui impose que les adresses IP mises dans le paquet soient joignables.

Notez que les protocoles à connexion ne posent pas les mêmes problèmes car ils peuvent être « sans source ». Dans le vieux X.25 (ce n'est pas moi qui ai choisi l'exemple, c'est Rémi Després, lors d'une discussion/pizza), le serveur n'avait pas forcément l'adresse du client. Chaque routeur sur le trajet établissait une connexion avec le routeur suivant, ce qui fait qu'une machine ne connaissait que son prédécesseur. Il est amusant de noter que Tor fonctionne comme cela, mais avec bien des services en plus pour limiter encore davantage la fuite d'information (routeurs gérés par plusieurs organisations pour qu'ils ne puissent pas s'informer mutuellement, chiffrement systématique). Faudra-t-il donc remplacer IP par un protocole à connexion ?

Aujourd'hui, pour sécuriser le courrier électronique, il faudra combiner plusieurs techniques. Par exemple PGP pour du chiffrement de bout en bout (s'assurer que les serveurs intermédiaires ne pourront pas lire le message) et SMTP sur TLS (RFC 3207) pour chiffrer les métadonnées vis-à-vis d'un écoutant situé sur le trajet. Certes, SMTP sur TLS a des tas de limites, question sécurité (notamment, peu de MTA vérifient le certificat du pair) mais c'est mieux que de laisser les messages PGP circuler en clair, avec les métadonnées.

À noter qu'un écoutant peut quand même savoir qu'il y a un trafic SMTP. Si la communication est entre deux serveurs SMTP personnels, ayant peu de comptes ou même un seul, il pourra, même si tout est chiffré avec TLS, savoir qu'il y échange de courrier entre deux personnes identifiées. On est mieux protégé contre ce genre d'espionnage si on utilise un gros serveur. L'écoutant ne sera guère avancé en sachant juste qu'un utilisateur de Yahoo écrit à un utilisateur de Gmail. Dans le cas de ces gros silos, le danger est évidemment ailleurs, dans leur envoi d'informations à la NSA. Il faudrait donc des gros serveurs, mais gérés par des organismes honnêtes. Pas facile, la sécurité.

Un dernier mot sur une technique qui peut aider à résoudre notre problème : le chiffrement homomorphique. Comme il permet de faire des opérations sur des données chiffrées, il offre (théoriquement, car je ne crois pas que cet usage ait déjà été exploré) la possibilité de combiner routage et chiffrement des métadonnées.


L'article seul

L'IETF et l'espionnage, et maintenant ?

Première rédaction de cet article le 7 novembre 2013


J'ai déjà parlé ici de l'attitude de l'IETF face à l'espionnage massif (pervasive surveillance est le terme le plus répandu à l'IETF) auquel se livrent des organisations comme la NSA. Maintenant que la réunion IETF de Vancouver est bien avancée, quelles vont être les suites ?

Quelques informations sur la plénière technique du 6 novembre, qui a symboliquement marqué le passage de l'IETF en mode « on est vraiment fâchés ». Les documents, diapos, etc sont tous en ligne. La plénière a été filmée et le film est aussi en ligne (chez un fournisseur de PRISM, ce qui est amusant). La partie sur la surveillance commence après 23 minutes environ quand Alissa Cooper, auteure du RFC 6973, monte à la tribune.

La vedette était Bruce Schneier, qui a bien fixé les objectifs : empêcher toute surveillance n'est pas réaliste, ce contre quoi on peut lutter, c'est la surveillance de masse. Schneier a posé le problème en termes financiers : la surveillance est trop bon marché aujourd'hui et peut donc être faite massivement. Des réformes techniques pourraient contribuer à la rendre plus coûteuse, forçant les agences d'espionnage à revenir à de la surveillance ciblée, ce qui serait mieux que rien. Il a également insisté sur le « partenariat public/privé » : la NSA ne fait pas tout toute seule, elle est aidée par les géants du Web, qui lui fournissent des données (c'est un des points dont l'IETF, où des entreprises comme Google sont très présentes, n'aime pas discuter, et cela explique certains manques dans le RFC 6973).

Du point de vue pratique, Schneier a rappelé l'importance de l'ergonomie (ne pas fournir d'options dans les logiciels de sécurité, car elles seront mal utilisées), et de la sécurité par le nombre (si peu de gens utilisent le chiffrement, celui-ci est négatif, il attire l'attention sur eux ; il faut du chiffrement massif).

Brian Carpenter a fait l'historique des RFC parlant de vie privée, du RFC 1126 (le premier à parler de sécurité... pour dire qu'il ne s'en occuperait pas) puis au RFC 1543, qui a rendu obligatoire la fameuse section Security Considerations. Il a aussi rappelé le contexte notamment la lutte de certains pays (la France a été citée) contre la cryptographie dans les années 80 et 90.

Stephen Farrell est ensuite passé au concret : que peut faire l'IETF ? (Il a aussi illustré son exposé d'une jolie photo d'un parc mais il aurait pu choisir de l'herbe.) Le nouveau groupe IETF perpass (abréviation de pervasive passive monitoring) est chargé de trier les idées : le travail concret se fera ensuite dans des groupes de travail spécialisés. L'orateur a noté la menace particulière que faisait planer l'Internet des objets : « la NSA saura quand vous tirez la chasse ».

Enfin, les chercheurs en sécurité noteront l'annonce d'un atelier de l'IAB « Internet Hardening » à Londres le 28 février 2014. Préparez vos articles !

La plénière technique à l'IETF n'est pas composée que d'exposés formels mais contient aussi une discussion. Cooper a introduit cette discussion en appelant les membres de l'IETF à la responsabilité (« plein de gens vous écoutent », ce qui a fait éclater la salle de rire). De nombreux thèmes ont été abordés : vue la disproportion des moyens, pouvons-nous vraiment gêner la NSA (Schneier : « oui, ils ont des limites, ne serait-ce que les lois de la physique »), intérêt de disperser les services à surveiller (il est plus coûteux de surveiller 100 000 serveurs de messagerie qu'un seul Gmail), et même l'argument très traditionnel « mais on n'est pas des terroristes, on n'a rien à cacher » (Cooper : « on veut de la vie privée même pour des activités légales, songez à vos visites chez le docteur, par exemple »)

La proposition de « durcir l'Internet » pour rendre la surveillance moins facile a été largement adoptée, par la pittoresque procédure du « hum ». Sans surprise, le communiqué officiel prend acte de ce consensus et s'en félicite. Mais cela ne veut pas dire que tout se passera comme sur des roulettes après. Il y a eu des critiques (plus ou moins voilées) contre ce projet (personne n'ose s'y opposer frontalement mais cela n'empêche pas les attaques indirectes) et, surtout, voter des motions est facile, développer de nouvelles techniques et protocoles et les déployer est une autre histoire.

Ce sera justement le premier travail du groupe perpass. Il s'est réuni juste après la plénière et avait un agenda chargé ! (Les documents sont eux aussi en ligne). Dave Thaler a notamment fait un remarquable exposé sur l'état des menaces sur la vie privée. Cet exposé tordait le cou à la légende très répandue comme quoi les cybercriminels auraient la partie trop facile, l'Internet leur permettrait l'anonymat, etc. C'est tout le contraire : la vie privée est aujourd'hui extrêmement difficile à préserver dans les réseaux numériques.

Et les solutions envisagées ? L'IETF a plein d'idées :

  • Évidemment, généraliser le chiffrement. Les gens de XMPP se sont promis de le faire pour leur protocole de messagerie instantanée avant mai 2014.
  • Un terme souvent revenu dans les discussions est celui d'opportunistic encryption. Il n'est pas très rigoureusement défini. Des fois, il veut dire « chiffrement sans authentification préalable » (ce qui protège d'un attaquant passif mais pas d'un homme du milieu), des fois, il signifie « chiffrement sans configuration manuelle préalable » et, là, c'est très souhaitable si on veut avoir des chances de généraliser le chiffrement.
  • Minimisation des données envoyées. Le chiffrement ne protège pas si le destinataire transmet vos données à un tiers (cas de Facebook, par exemple). Il est donc également nécessaire de diminuer la quantité de données envoyées. Christian Huitema a ainsi lancé un appel à ce que les résolveurs DNS arrêtent d'envoyer la question complète aux serveurs faisant autorité.

Alissa Cooper a bien résumé la démarche perpass : « 1) envoyer le moins de données possibles 2) les chiffrer ». Il n'y a plus qu'à réaliser ce programme.

Y a-t-il consensus sur cette démarche ? Comme indiqué plus haut, les opposants se font très discrets. Mais certaines remarques négatives ont déjà été entendues, par exemple que la généralisation du chiffrement de bout en bout va empêcher les intermédiaires d'examiner ou de modifier les messages (ce qui me semble une bonne chose mais ce n'est pas l'opinion de tout le monde, d'autant plus qu'il y a des craintes que les attaquants s'adaptent et cherchent d'autres moyens) ou, autre exemple, que la gestion opérationnelle des réseaux va en souffrir (un ennui courant avec la cryptographie).

Et puis, même si tout le monde est d'accord, le principe de réalité ne manquera pas de frapper : certains des changements proposés auront un coût et certains, qui ont applaudi avec enthousiasme à la proposition de renforcer la sécurité de l'Internet, reculeront peut-être devant ce coût.

D'autres articles intéressants sur cette question :


L'article seul

RFC 7066: IPv6 for 3GPP Cellular Hosts

Date de publication du RFC : Novembre 2013
Auteur(s) du RFC : J. Korhonen (Renesas Mobile), J. Arkko (Ericsson), T. Savolainen (Nokia), S. Krishnan (Ericsson)
Pour information
Réalisé dans le cadre du groupe de travail IETF v6ops
Première rédaction de cet article le 5 novembre 2013


Il y a désormais des tas d'engins mobiles connectés à l'Internet, par la 3G ou bientôt par la 4G (mon Dieu, je mets des termes marketroïdo-publicitaires sur mon blog...) Les spécifications de ces protocoles imposent normalement IPv6 mais, en pratique, on ne trouve quasiment jamais d'IPv6 sur ces réseaux mobiles (tiens, le RFC utilise le terme états-unien, cellular). D'ailleurs, ça veut dire quoi « gérer IPv6 » pour ces engins ? Quels sont, parmi les nombreux RFC sur IPv6, ceux qu'il faut absolument mettre en œuvre ? Les caractéristiques du monde mobile (capacité réseau très limitée, par exemple) ont-elles des conséquences particulières pour IPv6 ? Ce RFC fait le point sur « IPv6 sur réseaux mobiles ». Il succède au RFC 3316, qui avait été le premier, en 2003, à se lancer dans ce travail.

Ces technologies de réseaux mobiles permettent à un appareil comme le smartphone d'avoir, lui aussi, une connexion permanente à l'Internet, comme l'ADSL le permet aux machines fixes. Cela a commencé avec le GPRS, puis l'UMTS et quelques autres techniques. Résultat, des centaines de millions d'engins mobiles sont connectés et chacun a besoin d'une adresse IP. IPv4 n'y suffit plus depuis longtemps, et, aujourd'hui, avoir un accès Internet sur son mobile impose quasiment toujours d'être coincé avec une adresse privée (RFC 1918). D'où l'intérêt d'IPv6, qui permettra à chaque machine d'avoir son adresse publique. UMTS a apparemment été le premier réseau mobile où IPv6 était mentionné dans la spécification. Pour les réseaux EPS/LTE, voir le RFC 6459.

Normalement, « avoir IPv6 », pour une machine terminale, est facile à définir. Cela veut dire respecter les règles du RFC 8504, qui rassemble en un document la liste des exigences. D'ailleurs, notre RFC 7066 ne prétend pas remplacer ce RFC 8504 : il le complète, pour préciser les points spécifiques aux réseaux mobiles (« cellulaires », comme si on était en prison). Il vise surtout les programmeurs qui vont mettre ou maintenir IPv6 dans Android, iOS, etc. À noter que le RFC distingue trois types de machines terminales connectées aux réseaux mobiles :

  • Celles complètement fermées, où l'utilisateur ne peut rien changer (un téléphone classique),
  • Celles où l'utilisateur peut ajouter des applications (le smartphone typique),
  • Celles où l'accès 3G est extérieur à la machine, par exemple un ordinateur portable muni d'une clé 3G, où les applications (et même une bonne partie du système) ne savent pas qu'elles utilisent la 3G.

Ce RFC se focalise sur l'IPv6, pas sur les techniques de transition d'IPv4 vers IPv6 ou de coexistence temporaire entre les deux protocoles. Il rappelle que la meilleure technique est la « double-pile » du RFC 4213 : que chaque machine ait deux adresses, une v4 et une v6, le temps de la transition.

Le RFC commence par les exigences de base (Basic IP), celles qui s'appliquent dans tous les cas (section 2). La machine doit évidemment mettre en œuvre la norme IPv6 de base (RFC 2460), ainsi que les mécanismes de découverte du voisin du RFC 4861.

Toutefois, il faut nuancer. Dans les réseaux GPRS, UMTS et EPS, la liaison est point-à-point : une machine n'a qu'un seul voisin, déjà connu car il s'annonce comme routeur (ce routeur est appelé par des sigles pittoresques qui dépendent de la technologie utilisée, comme GGSN ou PGW). Et donc, logiquement, il n'y a pas d'adresse de niveau 2, donc pas besoin d'un protocole pour résoudre les adresses IP en adresses de niveau 2, comme le fait NDP. Même si le routeur répondait aux messages Neighbor Solicitation, sa réponse ne contiendrait pas d'adresses de niveau 2. Le mécanisme NUD (Neighor Unreachability Detection) du RFC 4861, section 7.3, reste nécessaire (des détails dans l'annexe A). Ces messages permettent de s'assurer que le voisin répond bien. Mais il ne faut pas en abuser : les engins connectés à un réseau mobile ont en général une batterie à capacité limitée. Notre RFC recommande donc, pour s'assurer que le voisin est toujours vivant, de compter avant tout sur des indications indirectes, comme le retour des paquets TCP, ou comme les réponses DNS lorsqu'on a utilisé UDP pour les questions. Avec les protocoles de téléphonie comme RTP (RFC 3550) ou SIP (RFC 3261), il faut se servir des mécanismes de rétroaction de ces protocoles, pour confirmer la joignabilité. On ne doit faire du NUD qu'en dernier recours.

Le mobile ainsi connecté doit configurer sa propre adresse IPv6 avec SLAAC (StateLess Address AutoConfiguration, RFC 4862), ce qui veut dire qu'il doit accepter les RA (Router Advertisment) envoyés d'en face. Aucun besoin de faire de la détection d'adresses dupliquées (RFC 4862, section 5.4) puisqu'on est seul sur le lien (avec le routeur). En revanche, DHCP (RFC 8415) n'est pas obligatoire, mais on peut l'utiliser, par exemple pour récupérer les adresses des serveurs SIP (RFC 8415 et RFC 3319) ou pour obtenir la délégation d'un préfixe à utiliser sur le réseau local (RFC 8415, au cas où le mobile serve lui-même de routeur pour un tel réseau, par exemple en WiFi).

Le mécanisme d'adressage est très différent de celui des réseaux fixes. Le préfixe de l'adresse est fourni par le routeur et est unique par connexion 3G. Le suffixe est également choisi par le routeur, en général au hasard, il n'y a pas d'adresse MAC en dur dans l'engin mobile. L'annexe A rappele les particularités de l'adressessage IPv6 en 3G.

Le mobile doit également savoir trouver les adresses des résolveurs DNS avec SLAAC, comme normalisé dans le RFC 8106. Certes, ces adresses sont normalement transmises au mobile en 3G, sans passer par un protocole IP, mais il peut y avoir sur le trajet des intermédiaires qui ont du mal à passer cette option.

À ce sujet, on a parfois du PPP (RFC 1661) entre le mobile et un autre équipement, notamment dans le cas d'ordinateurs avec clé 3G. Dans ce cas, il faut utiliser le protocole de contrôle PPP pour IPv6, IPv6CP, normalisé dans le RFC 5072.

Des problèmes de vie privée ? Forcément, oui. Un mobile étant mobile, pouvoir le suivre à la trace serait très intéressant pour certains, et néfaste pour la vie privée de son propriétaire. Il est donc recommandé de mettre en œuvre les adresses temporaires du RFC 8981 mais lisez plus loin, la question de l'adressage IPv6 sur les réseaux 3G est plus compliquée qu'elle n'en a l'air. Comme le rappelle la section 7, la partie spécifique à la machine (Interface Identifier) de l'adresse IPv6 est donnée par le réseau, elle n'est pas une propriété constante de la machine (comme l'est une adresse Ethernet) et le suivi à la trace via les adresses 3G est donc nettement moins possible. En fait, c'est plutôt le préfixe et pas le suffixe qui identifie une machine, car il reste constant pendant le déplacement.

Et une dernière chose à bien garder en tête : la MTU. Les réseaux mobiles utilisent beaucoup de tunnels et les paquets peuvent donc avoir une taille maximum plus faible que prévue. Il est donc impératif que les mobiles tiennent compte de l'option MTU dans les messages RA (section 4.6.4 du RFC 4861).

Une fois ces questions de base réglées et correctement mises en œuvre dans le mobile, le RFC a encore deux courtes sections. La section 3 concerne la sécurité. Elle rappelle qu'IPsec n'est pas obligatoire (bien que, évidemment, son usage sécuriserait tout le trafic du mobile, avant son envoi sur les ondes radio). Elle note aussi qu'un mobile peut s'attendre à recevoir des paquets fragmentés, que ceux-ci posent des problèmes de sécurité fréquents, et qu'il faut donc suivre les RFC 5722 et RFC 6980. La sécurité est également discutée en section 7.

La dernière section d'exigences, la section 4, concerne la mobilité. Dans le monde 3G, elle est gérée par les couches basses et il n'est donc pas du tout nécessaire de mettre en œuvre les techniques de mobilité IP (par exemple celles du RFC 5555).

L'annexe B résume les changements depuis le RFC 3316. Rien de révolutionnaire, essentiellement des clarifications, l'ajout de technologies récentes comme la découverte des résolveurs DNS par le RFC 6106, beaucoup de points liés à la sécurité, suite au RFC 6583, etc.

Je ne fournis dans cet article aucun exemple concret : c'est parce que les opérateurs qui font de l'IPv6 sur la 3G sont en nombre infime (aucun en France). Par exemple, regardez le dernier point fait par SFR, aucune date n'était annoncée.


Téléchargez le RFC 7066


L'article seul

RFC 7050: Discovery of the IPv6 Prefix Used for IPv6 Address Synthesis

Date de publication du RFC : Novembre 2013
Auteur(s) du RFC : T. Savolainen (Nokia), J. Korhonen (Nokia Siemens Networks), D. Wing (Cisco Systems)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF behave
Première rédaction de cet article le 5 novembre 2013


Lorsqu'on utilise le mécanisme NAT64 du RFC 6146 pour donner accès à l'Internet historique IPv4 depuis des machines IPv6, seul le traducteur NAT64 connait le préfixe IPv6 utilisé pour la traduction. Les machines ordinaires du réseau local ne le savent pas. Ce nouveau RFC fournit un moyen standard de découvrir ce préfixe.

Un tout petit rappel sur NAT64 (RFC 6146) et son copain DNS64 (RFC 6147) : leur but est de fournir une connectivité IPv4 (par exemple pour accéder à des machines qui n'ont toujours pas IPv6) aux réseaux modernes qui seront entièrement en IPv6 (RFC 6144). Pour cela, le serveur DNS64 « ment » en répondant aux requêtes de type AAAA (demande d'une adresse IPv6) par une réponse synthétisée, lorsque le nom demandé n'a qu'un A (adresse IPv4). Cette réponse synthétique utilise un préfixe configuré à la fois dans le serveur DNS64 et dans le traducteur NAT64 qui, voyant une adresse portant ce préfixe dans le champ Destination, va traduire l'IPv6 en IPv4 (et réciproquement au retour).

La plupart du temps, les machines IPv6 situées sur le réseau local n'auront aucun besoin de savoir ce qui se passe. Pour elles, tous les services externes sont accessible en IPv6 et elles ne connaissent pas la magie sous-jacente. Bien sûr, en regardant les adresses IPv6 obtenues, elles pourront s'étonner de voir que tant d'entre elles commencent par le même préfixe, mais qu'elles le fassent ou pas ne change rien. NAT64 est prévu pour fonctionner entièrement dans le routeur d'accès, sans participation (et donc sans mise à jour du logiciel) des machines terminales.

Sauf qu'il y a des cas où il serait utile que ces machines terminales bossent un peu. Par exemple, DNS64 ne sert à rien si l'application n'utilise pas le DNS. Si on a un URL http://192.168.0.33/, qui est légal (quoique déconseillé) et devrait marcher, DNS64 ne sera jamais appelé et NAT64 échouera donc. Pourtant, cet URL pourrait fonctionner à travers NAT64 si seulement la machine terminale faisait le travail de DNS64 en synthétisant l'adresse IPv6 correspondant à 192.168.0.33. Un problème analogue avec DNS64 se pose si la machine terminale fait la validation DNSSEC elle-même (ce qui est souvent une bonne idée). Dans ce cas, les réponses « mensongères » du serveur DNS64 seront refusées. Dans ces deux cas, on souhaite que la machine terminale synthétise une adresse IPv6 elle-même et, pour cela, elle doit connaître le préfixe qui permettra au routeur NAT64 de savoir ce qu'il doit faire.

Ce préfixe « magique » (les adresses utilisant tout autre préfixe seront traitées par le routeur comme de l'IPv6 ordinaire) peut être de deux types :

  • Un préfixe bien connu, réservé à cet usage, le WKP (Well-Known Prefix) qui vaut 64:ff9b::/96. Il est décrit dans le RFC 6052.
  • Ou bien un préfixe décidé localement, un NSP (Network-Specific Prefix), 2001:db8:1:64::/96 dans les exemples suivants.

Dans les deux cas, ce préfixe doit être configuré à l'identique dans le routeur NAT64 et dans le serveur DNS64. Et, si on utilise la synthèse locale (locale à la machine terminale) des adresses IPv6, il ,doit aussi être connu des machines terminales, ce qui est le but de ce RFC. Attention, il peut y avoir non pas un, mais plusieurs préfixes utilisés simultanément.

La technique utilisée dépend entre autres d'un nom bien connu, ipv4only.arpa, qui n'aura jamais que des adresses IPv4, et d'adresses IPv4 bien connues, les WKA (Well-Known Addresses), 192.0.0.170 et 192.0.0.171.


% dig +short A ipv4only.arpa
192.0.0.170
192.0.0.171

% dig +short AAAA ipv4only.arpa

Le principe (section 3 de notre RFC) est de faire une requête DNS de type AAAA (adresse IPv6) pour ce nom ipv4only.arpa. Comme ce nom n'a que des enregistremments A (adresse IPv4), si on obtient des enregistrements AAAA, c'est qu'il y a du DNS64 sur le trajet, qui synthétise ces enregistrements. Sinon, il n'y a pas de service DNS64. (La requête doit se faire avec le bit CD - Checking Disabled - à 0, autrement le serveur DNS64 ne fait pas la synthèse.) À la place d'un serveur DNS64, il peut aussi y avoir un serveur menteur qui répond même en l'absence de données (cela est fréquent sur les portails captifs). Dans ce cas, le client doit aussi faire une requête pour un nom qui n'existe pas (il n'est pas si facile que cela d'en trouver un) et vérifier qu'il récupère bien NXDOMAIN.

Une fois reçue sa réponse, la machine doit examiner tous ces AAAA et en déduire le (ou les) préfixe(s) utilisé(s) pour la synthèse. Si le préfixe est le WKP, c'est facile. Si c'est un NSP, c'est un peu plus dur. C'est là que les WKA sont utilisées : comme la machine connait les adresses IPv4 originales, elle peut les retrouver dans les adresses IPv6. Avec les examples plus haut, la machine fait une requête AAAA pour ipv4only.arpa, obtient comme réponse 2001:db8:1:64::192.0.0.170 (qu'on peut également écrire 2001:db8:1:64::c000:aa) et en déduit que le préfixe utilisé est 2001:db8:1:64::/96. Par exemple, avec BIND, et ce fichier de configuration :

options {
        ...
        dns64 2001:db8:1:64::/96 { // Network-Specific Prefix
              clients { me; };
        };

On obtiendra :

% dig +nodnssec AAAA ipv4only.arpa
...
;; ANSWER SECTION:
ipv4only.arpa.		3485 IN	AAAA 2001:db8:1:64::c000:ab
ipv4only.arpa.		3485 IN	AAAA 2001:db8:1:64::c000:aa

Si cela ne marche pas (par exemple si on ne trouve pas les WKA comme 192.0.0.170 dans la réponse), alors la recherche du préfixe a échoué (format d'adresses inhabituel ou un truc comme ça) et on doit laisser tomber et donc ne pas faire de synthèse d'adresses IPv6 sur la machine cliente. La procédure de ce RFC ne prétend pas marcher dans tous les cas.

Au fait, pourquoi deux adresses WKA, 192.0.0.170 et 192.0.0.171 ? L'annexe B du RFC discute ce choix, dû au désir de limiter les faux positifs (par exemple si la chaîne de bits qui compose une des deux adresses apparait également dans le préfixe NAT64.)

Notons que, si le canal entre le client et le serveur DNS64 n'est pas protégé, un attaquant peut facilement informer le client avec un mauvais préfixe. On peut (sauf pour le WKP) valider l'information avec DNSSEC (je ne détaille pas ici, voir la section 3.1 du RFC).

C'est bien joli d'avoir appris le préfixe mais rappelez-vous que ce RFC propose essentiellement une heuristique : il ne donne pas de garanties. Il faut donc tester le préfixe qu'on vient d'obtenir. Après tout, des tas de choses peuvent déconner. La machine cliente peut faire les tests qu'elle veut (viser des amers publics). Mais le RFC suggère une procédure que le FAI qui a déployé NAT64 peut mettre en place. Le FAI doit configurer une machine de test (qui répond aux paquets ICMP Echo et n'a pas de limitation de trafic) et mettre deux informations dans le DNS. La machine finale fait une requête DNS de type PTR pour une adresse WKA (192.0.0.170 ou 192.0.0.171) représentée en IPv6 et traduite au format ip6.arpa. Puis elle fait une requête de type A sur le nom obtenu et cela donne l'adresse de la machine de test du FAI, si celui-ci a suivi les recommandations de notre RFC. Avec les exemples de préfixes plus haut, on utilisera l'adresse 2001:db8:1:64::192.0.0.170, la requête PTR portera sur a.a.0.0.0.0.0.c.0.0.0.0.0.0.0.0.4.6.0.0.1.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa et, si elle renvoie le nom ping.example.net, la requête A portera sur ce nom. Mettons qu'on obtienne 192.0.2.33, on synthétisera 2001:db8:1:64::192.0.2.33 et on verra bien si ça marche. (L'annexe A du RFC contient un exemple complet de fichier de zone DNS standard utilisant cette technique.)

Par contre, les clients ne doivent pas faire de tests de connectivité avec les adresses obtenues en interrogeant ipv4only.arpa. (Elles ne sont pas censées répondre.)

Notre RFC rappelle aussi que cette technique ne change rien au fait que NAT64 est fondamentalement un bricolage provisoire, que le résultat est « mieux que rien » mais que la bonne solution est évidemment le passage généralisé à IPv6.

Ah, et, pendant qu'on parle de ce que configure localement le FAI, le RFC n'interdit pas des déploiements de NAT64 où les clients utilisent un autre nom que ipv4only.arpa, par exemple si le FAI veut ne dépendre que de ses propres noms (ipv4only.example.net).

Les sections 4 et 5 donnent quelques conseils pratiques pour le déploiement de l'infrastructure nécessaire. Ainsi, le domaine ipv4only.arpa devra avoir un long TTL, au moins une heure, pour bénéficier des caches. Il doit être signé avec DNSSEC.

Comme pour toutes les techniques de transition (ici, d'IPv4 vers IPv6), l'IETF impose une description d'une stratégie de sortie. Comment fera t-on lorsque NAT64 et DNS64 ne seront plus nécessaires ? La section 6 demande que les machines terminales qui ont la possibilité de découvrir le préfixe NAT64, et de synthétiser elles-mêmes les adresses IPv6, aient un mécanisme pour couper cette possibilité, le jour où elle sera abandonnée.

Enfin, un peu de bureaucratie IANA en section 8. Le domaine « spécial » ipv4only.arpa a été enregistré selon les règles des RFC 3172, et RFC 6761, règles qui n'avaient pas vraiment été respectées, ce qui a nécessité une correction dans le RFC 8880. Le domaine a été placé dans le registre des noms spéciaux. Les adresses WKA, elles, ont été enregistrées selon les règles des RFC 5736 (qui gère 192.0.0.0/24) et RFC 6890. Elles sont donc désormais dans le registre des adresses spéciales.

Il existe au moins une mise en œuvre de NAT64 qui inclus la technique de découverte de préfixe de ce RFC.


Téléchargez le RFC 7050


L'article seul

Mes premiers bitcoins

Première rédaction de cet article le 4 novembre 2013


Je viens de payer, puis de dépenser, mes premiers bitcoins. Cette monnaie décentralisée, qui ne dépend pas d'un État n'est pas encore très répandue mais elle suscite l'intérêt de beaucoup, notamment par sa sémantique proche de l'argent liquide : les paiements sont « anonymes », comme on pouvait le faire avec de l'argent liquide, et la sécurité est celle des données qu'on garde sur son disque dur. Si celui-ci est en panne, l'argent disparait.

Comment obtient-on des bitcoins ? Il existe plusieurs méthodes. Profitant de la réunion IETF de Vancouver, j'ai décidé de tester le Robocoin, le premier distributeur de bitcoins du monde, installé il y a quelques jours, au café Waves, à deux blocs de l'hôtel où se tient la réunion IETF, et géré par la société Bitcoiniacs. L'appareil ressemble à un DAB : robocoin.jpg

On peut s'en servir pour retirer des bitcoins (en échange d'argent liquide) ou au contraire pour vendre ses bitcoins. On peut utiliser un portefeuille bitcoin existant ou bien en créer un. N'ayant pas encore installé les logiciels nécessaires, j'ai créé un portefeuille sur le distributeur. Celui-ci imprime alors un petit papier indiquant la clé privée du compte et un code QR. Une fois qu'on a son portefeuille, on revient à la machine, on numérise le code QR et on peut alors mettre un billet (en l'occurrence, de 20 dollars, ce qui m'a fait 0,077 bitcoins) et obtenir des bitcoins, matérialisés par un autre petit papier, contenant l'adresse du compte créé précédemment (ce dernier n'est pas indispensable sauf en cas de désaccord avec la société qui gère le Robocoin). À noter qu'il existe une sécurité supplémentaire, au cas où on oublie son papier près de l'appareil : la machine a enregistré vos empreintes digitales et les redemande à chaque utilisation.

Ensuite, on prend un café pour réfléchir, en contemplant ses deux papiers. On discute avec ses voisins. L'appareil suscite beaucoup de curiosité et les autres clients du café demandent ce que vous faites et on passe donc beaucoup de temps à expliquer. Puis on rentre chez soi chercher comment on transfère cet argent sur son ordinateur. Il existe plein de logiciels client. J'ai choisi le logiciel Electrum (oui, d'accord, sécurité modérée mais c'est pour une expérimentation). Il est très simple à utiliser. Si j'avais commencé par Electrum, je créais un portefeuille et l'indiquais au Robocoin. Mais j'ai déjà créé un portefeuille que je vois rentrer dans Electrum. N'ayant pas envie de chercher un logiciel de lecture de QR code, j'ai tapé la clé privée (menu Import -> Private keys). Electrum a ensuite automatiquement reçu la transaction et, oh, joie, mes 0,077 bitcoins sont arrivés. Si on garde le papier contenant la clé privée, par exemple pour pouvoir récupérer ses sous en cas de perte des fichiers sur l'ordinateur, il faut la ranger à l'abri des regards indiscrets !

Je n'ai plus eu ensuite qu'à les dépenser en donnant à l'EFF, qui accepte les bitcoins. Il suffit de rentrer dans Electrum (bouton Send) l'adresse Bitcoin qu'indique l'EFF electrum-balance.jpg.

Merci à John Levine pour avoir signalé ce distributeur de bitcoins aux participants à la réunion IETF (nous avons été quelques centaines à en profiter), et à Cryptomars pour son aide technique. Au lieu d'Electrum, j'aurais pu utiliser Multibit. Parmi les bons articles sur ce distributeur, je suggère celui de Vanessa Collette. L'appareil ayant eu une période de maintenance après mon passage, cela a permis de prendre des photos de l'intérieur. Un premier bilan après une semaine indiquait 100 000 $ échangés. À noter l'amusante façon dont un escroc a détourné ce distributeur.


L'article seul

L'IETF, l'espionnage et les protocoles Internet

Première rédaction de cet article le 2 novembre 2013


Du 4 au 8 novembre 2013 se tient à Vancouver la 88ème réunion de l'IETF. Elle verra notamment un grand nombre de discussions sur l'espionnage de masse auquel se livrent des organisations comme la NSA, et aux moyens d'adapter la sécurité de l'Internet à ce type de menaces.

Le terme important est de masse. La réalité de l'espionnage sur l'Internet est connue depuis longtemps, même si beaucoup préféraient faire l'autruche. Mais même les experts en sécurité dont tout le monde se moquait, en les traitant de « paranoïaques », n'osaient pas forcément envisager l'ampleur de l'espionnage mené par des organisations puissantes et placées en dehors de tout contrôle démocratique, comme la NSA. Grâce aux révélations d'Edward Snowden, on sait désormais que les paranoïaques ne l'étaient pas assez. Il ne s'agit pas de combattre un sniffer isolé qui écoute de temps en temps les communications (contre ce type d'attaques, l'IETF a déjà une large panoplie de techniques). Il s'agit de faire face à un attaquant très puissant, qui peut se permettre d'écouter beaucoup de gens, tout le temps. Ce type d'attaques, qui a déjà un nom en jargon IETF, le pervasive monitoring, nécessite de repenser la sécurité de l'Internet.

Bien sûr, le problème est surtout politique, et c'est sur le champ politique qu'il va essentiellement se jouer. La technique seule ne peut pas grand'chose contre un attaquant qui contrôle autant de leviers. Mais, à une réunion IETF, il est normal qu'on se pose la question « Que peut faire l'IETF ? » Il y a deux axes importants :

  • Défendre les normes IETF contre les attaques visant à affaiblir délibérement leur sécurité pour faciliter l'écoute. Parmi les révélations de Snowden, en effet, se trouvait la preuve que des processus de normalisation étaient subvertis par la NSA pour lui faciliter la tâche (notamment l'affaire du générateur aléatoire du NIST). Faut-il changer les processus IETF pour diminuer ce risque ?
  • Rendre l'Internet plus résistant à l'espionnage.

Le premier axe a déjà été évoqué, par exemple par Jari Arkko, président de l'IETF, dans un exposé au RIPE à Athènes expliquant qu'il n'y avait sans doute pas trop de risque de subversion d'un processus de normalisation IETF. Contrairement à des organismes gouvernementaux comme le NIST, qui ne peut rien refuser à la NSA, l'IETF a un travail complètement ouvert, les normes sont relues par des tas de gens, peu diplomates et qui n'hésitent pas à poser des questions lorsque quelque chose n'est pas clair, ou à râler lorsque la sécurité semble en danger. Il serait difficile, dans une telle maison de verre, de glisser des modifications affaiblissant la sécurité.

Le second axe est un gros travail, déjà baptisé d'un nom de code IETF, « Internet hardening ». Il s'agit de durcir l'Internet, de le rendre moins aisé à écouter (ce qui voudra sans doute dire aussi, moins aisé à utiliser). Le projet a été exposé dans un article d'Arkko. À Vancouver, il fera l'objet notamment de la réunion plénière technique. Celle-ci, qui se tiendra le mercredi 8 novembre et sera diffusée en ligne, verra les exposés suivants :

  • Bruce Schneier expliquera ce qu'on sait et ce qu'on ne sait pas sur la surveillance généralisée. Malgré les révélations de Snowden, nous n'avons pas encore tous les détails et nous devons définir des techniques contre des attaques que nous ne connaissons pas toutes.
  • Brian Carpenter rappellera que l'IETF a déjà travaillé sur des sujets liés à l'espionnage et à la vie privée, par exemple dans les RFC 1984 et RFC 2804 (où l'IETF dit clairement qu'il ne faut pas architecturer le réseau pour faciliter les écoutes, contrairement à ce que fait l'UIT avec son projet NGN qui inclut un volet LI - Legal Interception), le RFC 3365 (sur l'importance de prendre en compte la sécurité dans les protocoles Internet), et le RFC 6973, qui est le premier à décrire une politique globale de protection de la vie privée dans les protocoles IETF. Je ne sais pas si Carpenter en parlera mais les RFC ne sont pas tous aussi honorables et il faudrait peut-être aussi mentionner le RFC 3924...
  • Stephen Farrell résumera le travail du groupe informel PERPASS. Ce groupe n'est pas un groupe de travail officiel de l'IETF car ceux-ci ont toujours des tâches bien précises, avec un calendrier. PERPASS a une activité plutôt exploratoire, regarder ce qu'on peut faire pour améliorer la résistance de l'Internet à l'espionnage.

Le groupe PERPASS a déjà vu passer plusieurs documents. Ainsi, http://tools.ietf.org/id/draft-tschofenig-perpass-surveillance, de Hannes Tschofenig décrit les menaces. Il différencie les attaques exploitant une faille du protocole, celles exploitant une faiblesse de la cryptographie, celles exploitant une bogue dans une mise en œuvre, et celles enfin qui s'appuient sur des mauvais choix lors du déploiement. Les premières sont les seules à être complètement du ressort de l'IETF. Par exemple, la faille BEAST était une faille du protocole TLS et a été réparée par le RFC 4346. Dans ce cas, la correction était assez simple. C'est plus difficile lorsque des choix d'architecture ont été faits : on ne peut pas en général les remettre en cause. Ainsi, le fait que les serveurs DNS (même ceux de la racine) reçoivent le nom complet du site auquel on veut accéder est certainement une faiblesse, pour la protection de la vie privée, mais ne peut pas être modifié, sauf à remplacer le DNS par un protocole nouveau et incompatible. Le draft cite aussi d'autres responsabilités de l'IETF : par exemple, peu de fournisseurs de voix sur IP ont déployé des mécanismes de protection cryptographiques mais l'IETF ne leur a certainement pas facilité la tâche en ayant pas moins de trois mécanismes de sécurisation concurrents. Et puis, déployer la sécurité a posteriori sur un protocole qui ne l'avait pas au début, est toujours difficile. (D'un autre côté, les protocoles qui ont la sécurité dès le début ne sont en général pas déployés du tout, car ils sont trop pénibles à utiliser.)

Mais les failles menaçant la vie privée ne sont pas en général dans les protocoles et le problème dépasse donc les seuls moyens de l'IETF. Ainsi, les protocoles IETF sécurisés dépendent en général de la cryptographie mais l'IETF elle-même ne fait pas de cryptographie, elle s'appuie sur des normes extérieures existantes. Par exemple, l'IETF a souvent suivi les recommandations du NIST, alors qu'on sait maintenant que cet organisme sabotait ses propres normes sur ordre de la NSA. La plupart des protocoles IETF sont « crypto-agiles » ce qui signifie que le protocole n'est pas lié à un seul algorithme cryptographique mais peut en changer. Cela permet d'abandonner un algorithme dont on sait qu'il est cassé mais cela ne dit pas quels algorithmes sont dangereux, car affaiblis délibérement par la NSA.

Et, bien sûr, il y a la mise en œuvre du protocole. Il y a nettement plus de bogues dans les programmes que de failles dans les protocoles. Écrire ces programmes n'est pas le rôle de l'IETF mais celle-ci a quand même une responsabilité : offrir aux programmeurs des spécifications claires, sans ambiguité et lisibles. Outre les bogues accidentelles, les réalisations concrètes des protocoles IETF ont aussi des faiblesses dues à des mauvais choix de sécurité. Ainsi, livrer une machine avec un mot de passe par défaut, dont on sait bien que la plupart des utilisateurs ne le changeront pas, n'est pas formellement une bogue mais cela a un effet désastreux sur la sécurité de l'Internet. Le draft fait aussi remarquer qu'évidemment, les programmes dont le code source n'est pas publié sont bien plus dangereux, d'autant plus qu'ils peuvent contenir des portes dérobées (trois ont été découvertes dans des routeurs dans les deux semaines précédant la réunion IETF).

Enfin, le draft de Tschofenig fait remarquer que même avec des protocoles parfaits, de la cryptographie sans faille et des programmes sans bogues, le déploiement effectif peut introduire des vulnérabilités et il cite le cas d'architectures où plusieurs serveurs sont utilisés pour contribuer à rendre le service (multi-tier) et où les communications entre ces serveurs ne sont pas sécurisées (ce qui était le cas de Google il y a peu, et avait fait l'objet du programme MUSCULAR de la NSA).

Un autre document PERPASS, pas encore officiellement publié, est le draft-huitema-perpass-analthreat de Christian Huitema. Il fait le tour des menaces, analysant ce qu'il est possible de faire en exploitant les protocoles Internet, notamment les fameuses métadonnées. Par exemple, pour le traditionnel téléphone, la simple connaissance de qui parle à qui, même sans accéder au contenu des communications, permet déjà de connaître le graphe des relations. La quantité de trafic, elle, permet de savoir que quelque chose se prépare. Bref, la collecte des métadonnées est une vraie menace pour la vie privée (section 2 du draft). Dans le monde IP, des données comme celles récoltées par NetFlow (RFC 3954), adresses IP source et destination, quantité de données échangées, présentent les mêmes dangers.

Huitema analyse aussi la liaison entre une adresse IP et une personne. Traditionnellement, c'était fait en demandant au FAI de fournir les informations « lequel de vos abonnés avait l'adresse 192.0.2.49 hier à 20:13 ? » Mais il note bien (section 4) qu'il existe d'autres méthodes de lier l'adresse IP à une identité, par exemple l'examen des sites Web visités, qui, ensemble, forment une véritable signature d'un individu. Autre exemple, l'analyse des en-têtes Received: dans les courriers électroniques permet de récupérer ce lien entre une adresse IP (en général explicitement indiquée) et une adresse de courrier donc sans doute un individu.

Huitema envisage aussi les solutions (section 5). S'il n'y a guère d'espoir d'empêcher techniquement l'espionnage, on peut en tout cas le rendre plus pénible et plus coûteux. D'abord, il faut développer le chiffrement. L'analyse des en-têtes Received: mentionnée plus haut serait plus difficile si SMTP utilisait systématiquement TLS (RFC 3207). On pourrait aussi, même si cela rendra le débogage plus difficile, rendre ces en-têtes moins bavards, par exemple en n'indiquant pas l'adresse IP de l'émetteur original. Peut-être aussi faudrait-il revenir de la tendance à avoir des adresses IP stables : si elles changeaient souvent, cela serait moins pratique pour l'utilisateur mais cela rendrait le traçage plus difficile. On pourrait aussi utiliser le multi-homing de manière plus créative, en envoyant une partie des paquets d'un flot par un lien et le reste par un autre lien, rendant la reconstitution du flot plus difficile. Il y a aussi des idées plus futuristes (et qui ne font pas l'objet pour l'instant d'une spécification rigoureuse) comme de modifier l'architecture de l'Internet pour le rendre « sans source ». L'en-tête des paquets IP ne porterait plus que l'adresse destination, pas la source, celle-ci serait contenue plus loin dans le paquet, chiffrée, pour les cas où on veut une réponse (la plupart des usages).

Parmi les documents PERPASS, le Internet draft draft-hardie-perpass-touchstone de Ted Hardie choisit une autre question : comment évaluer la sécurité des systèmes ? Un système peut être sûr pour protéger une information triviale d'un script-kiddie mais pas pour protéger des informations cruciales contre la NSA. Et, entre les deux, il y a plein d'intermédiaires. Hardie propose donc un test de Litmus pour discuter des futurs protocoles IETF : « est-ce qu'un homosexuel en Ouganda peut l'utiliser sans craindre pour sa sécurité ? » L'Ouganda a été choisi pour deux raisons : c'est un pays où il y a une répression active (y compris par la loi) de l'homosexualité, et c'est un pays pauvre, où on peut être tenté de sacrifier la sécurité aux performances. Et pourquoi l'homosexualité ? Parce que, comme le note l'auteur, la surveillance mène à l'auto-censure, au repli sur soi, et que les jeunes homosexuels qui n'arrivent pas à rejoindre une communauté qui les soutient courent énormément de risques (dont le suicide). Si la réponse au test est Oui, cela ne signifie pas que le système résistera à la NSA ou à un autre attaquant déterminé, mais qu'il sera suffisant pour une très large variété d'usages.

Autres lectures sur cette réunion et sur le rôle de l'IETF :


L'article seul

RFC 7039: Source Address Validation Improvement Framework

Date de publication du RFC : Octobre 2013
Auteur(s) du RFC : Jianping Wu, Jun Bi (Tsinghua University), Marcelo Bagnulo (UC3M), Fred Baker (Cisco), Christian Vogt (Ericsson)
Pour information
Réalisé dans le cadre du groupe de travail IETF savi
Première rédaction de cet article le 1 novembre 2013


Une des choses agaçantes sur l'Internet est qu'il est trivial de tricher sur son adresse IP source. Une machine qui a comme adresse 2001:db8:1:2::42 peut parfaitement émettre un paquet où l'adresse IP source est 2001:db8:9fe:43::1 et, là plupart du temps, ce paquet arrivera à destination (le routage ne se fait que sur la destination, pas sur la source), trompant le récepteur sur la vraie source de l'envoi. Cette faiblesse a donc des tas de conséquences pour la sécurité. Il existe des bonnes pratiques documentées pour empêcher l'émission de tels paquets (RFC 2827 et RFC 3704) mais elles sont peu déployées en pratique. Le projet SAVI (Source Address Validation Improvement) vise à propose des mécanismes pour rendre plus difficile l'utilisation d'adresses IP usurpées. Ce document est son cadre général, exposant les principes.

Les attaques possibles sont documentées dans le RFC 6959, qui explique la portée du projet SAVI. Les deux RFC cités plus haut, collectivement connus sous le nom de « BCP 38 » (RFC 2827 et RFC 3704), assurent, lorsqu'ils sont déployés, une validation de la source avec pour granularité celle d'un préfixe IP. Ainsi, un FAI dont les adresses IP sont en 2001:db8:1::/32 peut empêcher un de ses clients de sortir avec l'adresse 2001:db8:9fe:43::1 (qui n'est pas dans le même préfixe) mais BCP 38 ne traite pas le cas où le client 2001:db8:1:2::42 veut usurper 2001:db8:1:2:73:66:e5:68 (même préfixe). Il existe des mécanismes privés pour traiter ce cas (comme le Source Guard de Cisco) mais pas encore de norme. C'est le but de SAVI.

Son principe (section 2) est que tout est fait dans le réseau, pas dans les machines (puisque celles-ci peuvent être sous le contrôle d'un méchant). Il y a trois étapes dans une validation SAVI :

  • Déterminer les adresses IP légitimes pour une machine,
  • Attacher ces adresses IP à une propriété au niveau 2, propriété qui doit être difficile à usurper. Cela peut être par exemple le port physique du commutateur.
  • Tester que les paquets ayant cette adresse source obéissent bien à cette propriété.

C'est vague ? Parce que ce n'est qu'un modèle. D'autres RFC, par exemple le RFC 6620, spécifieront rigoureusement cet attachement entre une adresse IP et une propriété de la couche 2. Le RFC 6620 prévoit que le commutateur note les adresses IP source utilisées et refuse ensuite les paquets ayant cette adresse source (le principe est donc « premier arrivé, premier servi ») sauf si un test montre que l'adresse n'est plus joignable sur l'ancien port.

L'entité qui accomplit les trois étapes ci-dessus est appelée « instance SAVI ». Dans l'exemple donné, c'est le commutateur mais cela peut aussi être un routeur ou un autre équipement. C'est typiquement le commutateur qui est le mieux placé pour vérifier les adresses locales (le routeur a du mal à empêcher une machine d'usurper l'adresse d'une autre machine du même lien). Le principe de base est que SAVI est d'autant mieux mis en œuvre qu'on est proche de la source des paquets. Si on s'éloigne :

  • Il est plus difficile de déterminer les adresses légitimes,
  • On n'a plus de propriétés de niveau 2 à attacher à une adresse,
  • On protège moins puisque la machine menteuse pourra toujours parler aux machines proches.

Toutefois, SAVI prévoit le cas où on ne peut pas utiliser la solution idéale (par exemple parce que le commutateur où sont connectées les machines est pré-SAVI et ne gère pas ce RFC), et où on se contente d'une solution imparfaite. Notez qu'un certain nombre de commutateurs ont déjà des fonctions analogues à SAVI, mais de manière non-standard.

La section 3 couvre ces options de déploiement. Toute solution SAVI concrète va dépendre du mécanisme d'allocation d'adresses (le RFC 7513 couvre le cas de DHCP et le RFC 6620 celui des adresses auto-attribuées, par exemple via le RFC 4862) et des caractéristiques de la couche 2. Pour le mécanisme d'allocation d'adresse, il faut noter que plusieurs mécanismes peuvent coexister sur un même lien (section 6).

Pour l'attachement d'une adresse IP à une propriété de couche 2, on a le choix :

  • Adresse MAC (déconseillé par le RFC car trop facile à usurper),
  • Port physique du commutateur (attention, il peut y avoir plusieurs machines derrière un port),
  • Association de sécurité WPA entre une machine et sa base, pour un lien WiFi,
  • Identifiant d'une session PPP,
  • Identifiant du tunnel, si la machine est connectée via GRE, MPLS, etc.

Chacun de ces cas va nécessiter une incarnation concrète des principes de ce RFC 7039.

Comme souvent en sécurité, le déploiement de la sécurisation va créer de nouveaux problèmes et de nouveaux motifs de panne. La section 5 en expose certains. Par exemple, un commutateur qui mémorise une association adresse<->port et qui redémarre perd ces associations et va alors se mettre à refuser tous les paquets, avant de réapprendre les associations. Ou bien une machine change brusquement de port et, pendant un moment, ne peut plus communiquer. SAVI doit donc prévoir des mécanismes de rattrapage, par exemple, lorsque beaucoup de paquets sont refusés, tester si l'adresse IP est unique sur le lien et, si oui, en déduire que c'était bien la machine légitime qui émettait. (À noter que ces mécanismes sont mis en défaut si la machine légitime était éteinte à ce moment.)

Comme noté par la section 7, une machine SAVI a aussi intéret à connaître le préfixe IP légitime du lien, pour faire un test supplémentaire de validité. Elle peut le faire par configuration explicite, en écoutant les annonces RA (Router Advertisment) du routeur IPv6, en écoutant les messages DHCP de délégation de préfixe, … (RFC 7513)

N'espérez pas de miracle de SAVI. La section 10, qui résume l'analyse de sécurité, note bien que SAVI rend l'usurpation plus difficile mais ne « prouve » pas l'adresse IP source, au sens où une signature cryptographique prouve l'authenticité d'un document, par exemple. Si on veut faire mieux, il faut passer à des protocoles avec authentification cryptographique de la source (comme HIP).

Notez que SAVI a une longue histoire à l'IETF, chaude et contestée. Le projet se nommait auparavant SAVA (Source Address Validation Architecture, cf. RFC 5210) et avait des objectifs bien plus ambitieux, au point de faire peur à beaucoup, d'autant plus que les propositions venaient de Chine. L'ancien SAVA prévoyait un cadre englobant tout l'Internet, avec intégration de « BCP 38 » (RFC 2827 et RFC 3704) et communication entre opérateurs pour garantir la validation de bout en bout. À la réunion IETF de Prague en 2008, SAVA s'était fait chaudement allumer. Personne n'avait osé le dire tout haut pendant la réunion mais la salle bruissait de « on ne va pas changer l'architecture de l'Internet pour faire plaisir aux communistes ». Le seul orateur à mentionner ce problème l'avait fait diplomatiquement en disant que SAVA risquait d'amener dans Internet des préoccupations qui sont traditionnellement celles des telcos (comme la facturation à l'usage). SAVI est donc désormais la version light, plus focalisée du point de vue technique, et avec acceptation du fait que tout le monde n'a pas envie d'être fliqué (SAVI soulève quand même plein de problèmes pour la vie privée, qui ne sont pas traités dans ce RFC).


Téléchargez le RFC 7039


L'article seul

Un problème DNSSEC : pas assez de NSEC3

Première rédaction de cet article le 24 octobre 2013


C'est une banalité que de noter que DNSSEC est complexe. Heureusement, cette complexité est souvent cachée par les outils utilisés. Mais, parfois, elle resurgit lorsque quelque chose ne marche pas. C'est le cas à l'instant du tout nouveau TLD .онлайн, dont les enregistrements NSEC3 sont insuffisants.

.онлайн s'écrit en Punycode xn--80asehdb. Comme tous les nouveaux TLD, il est signé avec DNSSEC. Interrogeons un résolveur DNS qui valide avec DNSSEC, un du ODVR :


% dig @149.20.64.20   SOA xn--80asehdb

; <<>> DiG 9.8.4-rpz2+rl005.12-P1 <<>> @149.20.64.20 SOA xn--80asehdb
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 44970
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 5, ADDITIONAL: 9

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;xn--80asehdb.		IN SOA

;; ANSWER SECTION:
xn--80asehdb.		84319 IN SOA anycast10.irondns.net. secretariat.corenic.org. (
				1310231925 ; serial
				21600      ; refresh (6 hours)
				3600       ; retry (1 hour)
				604800     ; expire (1 week)
				86400      ; minimum (1 day)
				)
xn--80asehdb.		84319 IN RRSIG SOA 10 1 86400 20131106172547 (
				20131023172547 38327 xn--80asehdb.
				ZUg0BUeRcEyTuyUmhcUC95U/iSd8/6GQS1D7k8YnADJa
				QV1nBPJ+9EOW7ycMKtg0XokKl+i8SqlCLqOs2mUs6nFg
				p9jB/T1sUar/w1QAjtClM9JcIliXC7AdDi4bmg5G15yX
				rgkrdgXrm/8kyUEbMUlto6LNdBz/IYP5fS4hlvo= )
...
;; Query time: 215 msec
;; SERVER: 149.20.64.20#53(149.20.64.20)
;; WHEN: Thu Oct 24 16:20:02 2013
;; MSG SIZE  rcvd: 726

Bon, tout va bien, on obtient bien l'enregistrement SOA demandé, et la réponse inclut le bit AD (Authentic Data) montrant que la validation s'est bien faite. Des outils de tests plus sophistiqués comme Zonecheck ne montrent pas non plus de problèmes. Mais ils ne testent pas assez. Cherchons cette fois un nom qui n'existe pas, www.xn--80asehdb :


% dig @149.20.64.20   SOA www.xn--80asehdb

; <<>> DiG 9.8.4-rpz2+rl005.12-P1 <<>> @149.20.64.20 SOA www.xn--80asehdb
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 38016
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;www.xn--80asehdb.	IN SOA

;; Query time: 744 msec
;; SERVER: 149.20.64.20#53(149.20.64.20)
;; WHEN: Thu Oct 24 16:20:20 2013
;; MSG SIZE  rcvd: 45

Aïe ! On n'a pas le NXDOMAIN qu'on attendait mais un SERVFAIL qui semble indiquer un problème DNSSEC. Pour être sûr, demandons au résolveur de tester sans validation, avec l'option CD (Checking Disabled) :


% dig +cd @149.20.64.20   SOA www.xn--80asehdb

; <<>> DiG 9.8.4-rpz2+rl005.12-P1 <<>> +cd @149.20.64.20 SOA www.xn--80asehdb
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 28571
;; flags: qr rd ra cd; QUERY: 1, ANSWER: 0, AUTHORITY: 4, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;www.xn--80asehdb.	IN SOA

;; AUTHORITY SECTION:
xn--80asehdb.		0 IN SOA anycast10.irondns.net. secretariat.corenic.org. (
				1310231925 ; serial
				21600      ; refresh (6 hours)
				3600       ; retry (1 hour)
				604800     ; expire (1 week)
				86400      ; minimum (1 day)
				)
xn--80asehdb.		0 IN RRSIG SOA 10 1 86400 20131106172547 (
				20131023172547 38327 xn--80asehdb.
				ZUg0BUeRcEyTuyUmhcUC95U/iSd8/6GQS1D7k8YnADJa
				QV1nBPJ+9EOW7ycMKtg0XokKl+i8SqlCLqOs2mUs6nFg
				p9jB/T1sUar/w1QAjtClM9JcIliXC7AdDi4bmg5G15yX
				rgkrdgXrm/8kyUEbMUlto6LNdBz/IYP5fS4hlvo= )
1kj9h96b2lh023ss088d4sv4fldblii8.xn--80asehdb. 0 IN RRSIG NSEC3 10 2 43200 20131106172200 (
				20131023172200 38327 xn--80asehdb.
				ConuMwi7xtPhtcwzZxH9+hrjE1yGVwYp7ql8nWbiUDqh
				AjUyzisxCjGUwSjiFTESUFMVnVuhd38Ns89pWxOfevPo
				jFVCo9kyNhZJ/OlIFTPto/Fi2gTsWiug/RDOD4rQ+66T
				Jr0GNZQFQHN/TEb7OywBKXWw9DegLyFRdbBdlaA= )
1kj9h96b2lh023ss088d4sv4fldblii8.xn--80asehdb. 0 IN NSEC3 1 0 12 7740536091A63907 HFVHO12QAPRRRKQ16K4R241K2OE81BLP NS SOA RRSIG DNSKEY NSEC3PARAM

;; Query time: 280 msec
;; SERVER: 149.20.64.20#53(149.20.64.20)
;; WHEN: Thu Oct 24 16:20:31 2013
;; MSG SIZE  rcvd: 557

Là, tout a marché. Aucun doute, c'est un problème DNSSEC. Mais lequel ? (Je triche, Mark Andrews a donné l'explication sur la liste dns-operations, je n'ai pas trouvé tout seul.) C'est parce que l'enregistrement NSEC3 ci-dessus, 1kj9h96b2lh023ss088d4sv4fldblii8.xn--80asehdb, ne couvre pas tout, seulement l'apex. Il faut plusieurs enregistrements NSEC3 pour prouver une non-existence. Les enregistrements NSEC3, normalisés dans le RFC 5155 sont considérés, à juste titre, comme une des parties les plus terribles de DNSSEC, et ce RFC comme un des plus difficiles à lire. Essayons quand même de comprendre. D'abord, récupérons les paramètres réglables de NSEC3 pour ce TLD :

% dig +short NSEC3PARAM xn--80asehdb
1 0 12 7740536091A63907
...

Donc, le sel est 7740536091A63907, l'algorithme de condensation 1 et il faut faire 12 itérations. Calculons ce que ça donne pour l'apex de la zone :

% nsec3hash 7740536091A63907 1 12 xn--80asehdb 
1KJ9H96B2LH023SS088D4SV4FLDBLII8 (salt=7740536091A63907, hash=1, iterations=12)

(Cet outil est livré avec BIND.) Bon, c'est bien la partie gauche de l'enregistrement NSEC3. Sa partie droite était HFVHO12QAPRRRKQ16K4R241K2OE81BLP. Et quel était le NSEC3 du nom qu'on demandait ?

% nsec3hash 7740536091A63907 1 12 www.xn--80asehdb 
VFAQP7GOV8SECOUA5KL7QMUPU09ABPF3 (salt=7740536091A63907, hash=1, iterations=12)

Et voilà l'explication du problème. Le condensé VFAQP7GOV8SECOUA5KL7QMUPU09ABPF3 n'est pas entre 1KJ9H96B2LH023SS088D4SV4FLDBLII8 et HFVHO12QAPRRRKQ16K4R241K2OE81BLP, le résolveur validant ne peut donc pas valider. Il faudrait en fait plusieurs enregistrements NSEC3, pas seulement celui qui couvre l'apex. Regardez avec un autre TLD signé comme .fr :


% dig SOA nexistepasdutout.fr

; <<>> DiG 9.8.4-rpz2+rl005.12-P1 <<>> SOA nexistepasdutout.fr
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 16892
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 8, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;nexistepasdutout.fr.	IN SOA

;; AUTHORITY SECTION:
fr.			5400 IN	SOA nsmaster.nic.fr. hostmaster.nic.fr. (
				2222302497 ; serial
				3600       ; refresh (1 hour)
				1800       ; retry (30 minutes)
				3600000    ; expire (5 weeks 6 days 16 hours)
				5400       ; minimum (1 hour 30 minutes)
				)
fr.			5400 IN	RRSIG SOA 8 1 172800 20131223203009 (
				20131024193009 62646 fr.
				DaGlS0gg6ZdrpPAlrGgTLnX7YIpuNy+drz9PXug4OQop
				DFDNbn5RGCyHaAwGI2C97F/unRNfJWxfJbvahKXjSxUk
				h1TV/HuJNR7NQ7B7ZbQhrXM+WJJOG2HMfM0ZjbuV7EDj
				i65zhfM4y+a9gxEofMtFpxvG/GLtmkToq0XYT5s= )
gbncp12fmut57r0t7oncls9uqlmlodmk.fr. 5400 IN RRSIG NSEC3 8 2 5400 20131222134010 (
				20131023124010 62646 fr.
				YMskIKa5wXIfNeM7nFuS+t7CrkIBj8yDbViY/UFaJHyY
				Fi6DluzDmzMro1P9JGtjMfOyCoHzELF/ypyP1AbD6gl6
				Q+8M+pWFaVcAqw2YM8gj5tTs/EaeBHkRt5LN+ieP46em
				24eW00n3hYVbbPzH16675tHQc6AQhKHV8XPilrE= )
gbncp12fmut57r0t7oncls9uqlmlodmk.fr. 5400 IN NSEC3 1 1 1 BADFE11A GBO5LRV9JCF6S1Q2IULLHM3S2E0HFNKT NS DS RRSIG
meqimi6fje5ni47pjahv5qigu1lv3jlj.fr. 5400 IN RRSIG NSEC3 8 2 5400 20131217141424 (
				20131018141424 62646 fr.
				HSlFBLGerg9v8cVNw/QtYfw9gtCxqsx4EI9GcL9loqUg
				FzYrpbEp/1Du6h3me1zmxY1QvywljEUqnYBVFN9S3JC2
				jDqxY+/xoHauiiz7ZCIWKaMT7UIo5o4Q/i+II1QfGRj1
				YoSZfH/qjASnitYaRse2rDa8R2MmZ9Hn56nO9j0= )
meqimi6fje5ni47pjahv5qigu1lv3jlj.fr. 5400 IN NSEC3 1 1 1 BADFE11A MER9S1NKQCO41NBRBJLTPKQ93HEONLR8 NS SOA TXT NAPTR RRSIG DNSKEY NSEC3PARAM
s450cin37ia3u7s37vsnc0po8vj2igth.fr. 5400 IN RRSIG NSEC3 8 2 5400 20131217141424 (
				20131018141424 62646 fr.
				bU6ZhqlPC0h6hf8xLqAtzpgkqyrHL/OZNJOlzUutjreL
				mL34i00G9eWIUAsjvKC2PZviFkvwhAuapD7OAGcAJvMS
				o3R+KYqTSQ39AmYTX80uVSupkRHw5CGIX3g87LY7CbQ+
				TRZ+LUUoYQ8vng3Ogi2IKEJwr9FAB9SCjHNeVSk= )
s450cin37ia3u7s37vsnc0po8vj2igth.fr. 5400 IN NSEC3 1 1 1 BADFE11A S45UOSDK5KJKQABLBLSBP7B5UK3R1MSV NS DS RRSIG

;; Query time: 37 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Thu Oct 24 22:40:14 2013
;; MSG SIZE  rcvd: 1006

On peut voir graphiquement ce problème avec DNSviz. Il faut activer l'option Denial of existence qui ne l'est pas par défaut (et peut donc rassurer à tort).

Pourquoi cette erreur ? NSEC3, on l'a dit, est très complexe. Mais on ne fabrique pas ses NSEC3 à la main ! La très grande majorité des administrateurs DNS qui utilisent DNSSEC n'auront jamais à analyser des problèmes comme celui-ci. On utilise un outil pour générer signatures et NSEC3, et aucun outil n'oublierait une partie de l'espace à protéger. Soit le registre a développé un outil à lui, ce qui serait une opération délicate et dangereuse, et c'est donc peu vraisemblable, soit quelque chose a cafouillé au moment de la publication des données.

Merci à Marco Davids pour le diagnostic initial.


L'article seul

RFC 7049: Concise Binary Object Representation (CBOR)

Date de publication du RFC : Octobre 2013
Auteur(s) du RFC : C. Bormann (Universitaet Bremen TZI), P. Hoffman (VPN Consortium)
Chemin des normes
Première rédaction de cet article le 24 octobre 2013


Il existait un zillion de formats binaires d'échange de données ? Et bien il y en a désormais un zillion plus un. CBOR (Concise Binary Object Representation) est un format qui utilise un modèle de données très proche de celui de JSON, mais est encodé en binaire, avec comme but principal d'être simple à encoder et décoder, même par des machines ayant peu de ressources matérielles. (Il a depuis été remplacé par le RFC 8949.)

Parmi les autres formats binaires courants, on connait ASN.1 (plus exactement BER ou DER, utilisés dans plusieurs protocoles IETF) ou MessagePack mais ils avaient des cahiers des charges assez différents (l'annexe E du RFC contient une comparaison). CBOR se distingue d'abord par sa référence à JSON (RFC 8259), dont le modèle de données sert de point de départ à CBOR, puis par le choix de faciliter le travail des logiciels qui devront créer ou lire du CBOR. CBOR doit pouvoir tourner sur des machines très limitées. Par contre, la taille des données encodées n'est qu'une considération secondaire (section 1.1 du RFC pour une liste prioritisée des objectifs de CBOR). Quant au lien avec JSON, l'idée est d'avoir des modèles de données suffisamment proches pour qu'écrire des convertisseurs CBOR->JSON et JSON->CBOR soit assez facile, et pour que les protocoles qui utilisent actuellement JSON puissent être adaptés à CBOR sans douleur excessive.

La spécification complète de CBOR est en section 2 de ce RFC. Chaque élément contenu dans le flot de données commence par un octet dont les trois premiers bits indiquent le type majeur. Les cinq suivants donnent des détails. Ce mécanisme permet de programmeur un décodeur CBOR avec une table de seulement 256 entrées (l'annexe B fournit cette table et l'annexe C un décodeur en pseudo-code très proche de C). Si la valeur que codent ces cinq bits suivants est inférieure à 24, elle est utilisée telle quelle. Sinon, cela veut dire que les détails sont sur plusieurs octets et qu'il faut lire les suivants (la valeur des cinq bits codant la longueur à lire). Selon le type majeur, les données qui suivent le premier octet sont une valeur (c'est le cas des entiers, par exemple) ou bien un doublet {longueur, valeur} (les chaînes de caractères, par exemple). L'annexe A de notre RFC contient de nombreux exemples de valeurs CBOR avec leur encodage.

Quels sont les types majeurs possibles ? Si les trois premiers bits sont à zéro, le type majeur est un entier non signé. Si les cinq bits suivants sont inférieurs à 24, c'est la valeur de cet entier. S'ils sont égaux à 24, c'est que l'entier se trouve dans l'octet suivant l'octet initial, s'ils sont égaux à 25, que l'entier se trouve dans les deux octets suivants, et ainsi de suite (31 est réservé pour les tailles indéterminées, décrites plus loin). L'entier 10 se représentera donc 00001010, l'entier 42 sera 00011000 00101010, etc. Presque pareil pour un type majeur de 1, sauf que l'entier sera alors signé, et négatif. La valeur sera -1 moins la valeur encodée. Ainsi, -3 sera 00100010. Vous voulez vérifier ? L'excellent terrain de jeu http://cbor.me vous le permet, essayez par exemple http://cbor.me?diag=42.

Le type majeur 2 sera une chaîne d'octets. La longueur est codée d'abord, en suivant la même règle que pour les entiers. Puis viennent les données. Le type 3 indique une chaîne de caractères et non plus d'octets. Ce sont forcément des caractères Unicode, encodés en UTF-8 (RFC 3629). Le champ longueur (codé comme un entier) indique le nombre d'octets de l'encodage UTF-8, pas le nombre de caractères (pour connaître ce dernier, il faut un décodeur UTF-8). Vous voulez des exemples ? Connectez-vous à http://www.cbor.me/?diag=%22lait%22 et vous voyez que la chaîne « lait » est représentée par 646c616974 : 64 = 01100100, type majeur 3 puis une longueur de 4. Les codes ASCII suivent (rappelez-vous qu'ASCII est un sous-ensemble d'UTF-8). Avec des caractères non-ASCII comme http://www.cbor.me/?diag=%22caf%C3%A9%22, on aurait 65636166c3a9 (même type majeur, longueur 5 octets, puis les caractères, avec c3a9 qui code le é en UTF-8).

Le type majeur 4 indique un tableau. Rappelez-vous que CBOR utilise un modèle de données qui est très proche de celui de JSON. Les structures de données possibles sont donc les tableaux et les objets (que CBOR appelle les maps). Un tableau est encodé comme une chaîne d'octets, longueur (suivant les règles des entiers) puis les éléments du tableau, à la queue leu leu. La longueur est cette fois le nombre d'éléments, pas le nombre d'octets. Les éléments d'un tableau ne sont pas forcément tous du même type.

Le type majeur 5 indique une map (ce qu'on appelle objet en JSON et dictionnaire ou hash dans d'autres langages). Chaque élément d'une map est un doublet {clé, valeur}. L'encodage est le même que pour les tableaux, la longueur étant le nombre de doublets. Chaque doublet est encodé en mettant la clé, puis la valeur. Donc, le premier scalaire est la clé de la première entrée de la map, le deuxième la valeur de la première entrée, le troisième la clé de la deuxième entrée, etc.

Les clés doivent être uniques (une question problématique en JSON où les descriptions existantes de ce format ne sont ni claires ni cohérentes sur ce point).

Je passe sur le type majeur 6, voyez plus loin le paragraphe sur les étiquettes. Le type majeur 7 sert à coder les flottants (encodés ensuite en IEEE 754) et aussi d'autres types scalaires et le break code utilisé dans le paragraphe suivant. Les autres types scalaires, nommés « valeurs simples » (simple values) sont des valeurs spéciales comme 20 pour le booléen Faux, 21 pour le Vrai, et 22 pour le néant. Elles sont stockées dans un registre IANA.

Dans la description ci-dessus, les types vectoriels (tableaux, chaînes, maps) commencent par la longueur du vecteur. Pour un encodeur CBOR, cela veut dire qu'il faut connaître cette longueur avant même d'écrire le premier élément. Cela peut être contraignant, par exemple si on encode au fil de l'eau (streaming) des données en cours de production. CBOR permet donc d'avoir des longueurs indéterminées. Pour cela, on met 31 comme « longueur » et cette valeur spéciale indique que la longueur n'est pas encore connue. Le flot des éléments devra donc avoir une fin explicite cette fois, le break code. Celui-ci est représenté par un élément de type majeur 7 et de détails 31, donc tous les bits de l'octet à 1. Par exemple, http://cbor.me/?diag=%28_%20%22lait%22%29 nous montre que la chaîne « lait » ainsi codée (le _ indique qu'on veut un codage en longueur indéterminée) sera 7f646c616974ff. 7f est le type majeur 3, chaîne de caractères, avec la longueur 31, indiquant qu'elle est indéterminée. Puis suit la chaîne elle-même (les chaînes indéterminées en CBOR sont faites par concaténation de châines de longueur déterminée), puis le break code ff.

La même technique peut être utilisée pour les chaînes d'octets et de caractères, afin de ne pas avoir à spécifier leur longueur au début. À noter que cette possibilité de listes de longueur indéterminée n'existait pas dans les premières versions de CBOR. Elle a été ajoutée pour faciliter la vie du streaming.

Revenons au type majeur 6. Il indique une étiquette (tag), qui sert à préciser la sémantique de l'élément qui suit. Un exemple typique est pour indiquer qu'une chaîne de caractères est un fait une donnée structurée, par exemple une date ou un numéro de téléphone. Un décodeur n'a pas besoin de comprendre les étiquettes, il peut parfaitement les ignorer. Les valeurs possibles pour les étiquettes sont stockées dans un registre IANA.

Quelques valeurs d'étiquette intéressantes ? La valeur 0 indique une date au format du RFC 3339 (une chaîne de caractères). La valeur 1 étiquette au contraire un entier, et indique une date comme un nombre de secondes depuis le 1er janvier 1970. Les valeurs 2 et 3 étiquettent une chaîne d'octets et indiquent qu'on recommande de l'interpréter comme un grand entier (dont la valeur n'aurait pas tenu dans les types majeurs 0 ou 1). Les décodeurs qui ne gèrent pas les étiquettes se contenteront de passer à l'application cette chaîne d'octets, les autres passeront un grand entier.

Autre cas rigolos, les nombres décimaux non entiers. Certains ne peuvent pas être représentés de manière exacte sous forme d'un flottant. On peut alors les représenter par un couple [exposant, mantisse]. Par exemple, 273,15 est le couple [-2, 27315] (l'exposant est en base 10). On peut donc l'encoder en CBOR sous forme d'un tableau de deux élements, et ajouter l'étiquette de valeur 4 pour préciser qu'on voulait un nombre unique.

D'autres étiquettes précisent le contenu d'une chaîne de caractères : l'étiquette 32 indique que la chaîne est un URI, la 34 que la chaîne est du Base64 (RFC 4648), la 35 dit qu'on va rencontrer une expression rationnelle et la 36 que cela va être un message MIME (RFC 2045). Comme l'interprétation des étiquettes est optionnelle, un décodeur CBOR qui n'a pas envie de s'embêter peut juste renvoyer à l'application cette chaîne.

Une astuce amusante pour finir les étiquettes, et la spécification du format : l'étiquette 55799 signifie juste que ce qui suit est du CBOR, sans modifier sa sémantique. Encodée, elle sera représentée par 0xd9d9f7 (type majeur 6 sur trois bits, puis détails 25 qui indiquent que le nombre est sur deux octets puis le nombre lui-même, d9f7 en hexa). Ce nombre 0xd9d9f7 peut donc servir de nombre magique. Si on le trouve au début d'un fichier, c'est probablement du CBOR (il ne peut jamais apparaître au début d'un fichier JSON, donc ce nombre est particulièrement utile quand on veut distinguer tout de suite si on a affaire à du CBOR ou à du JSON).

Maintenant que le format est défini rigoureusement, passons à son utilisation. CBOR est conçu pour des environnements où il ne sera souvent pas possible de négocier les détails du format entre les deux parties. Un décodeur CBOR générique peut décoder sans connaître le schéma utilisé en face. Mais, en pratique, lorsqu'un protocole utilise CBOR pour la communication, il est autorisé (section 3 du RFC) à mettre des restrictions, ou des informations supplémentaires, afin de faciliter la mise en œuvre de CBOR dans des environnements très contraints en ressources. Ainsi, on a parfaitement le droit de faire un décodeur CBOR qui ne gérera pas les nombres flottants, si un protocole donné n'en a pas besoin.

Un cas délicat est celui des maps (section 3.7). CBOR ne place guère de restrictions sur le type des clés et un protocole ou format qui utilise CBOR voudra souvent être plus restrictif. Par exemple, si on veut absolument être compatible avec JSON, restreindre les clés à des chaînes en UTF-8 est souhaitable. Si on tient à utiliser d'autres types pour les clés (voire des types différents pour les clés d'une même map !), il faut se demander comment on les traduira lorsqu'on enverra ces maps à une application. Par exemple, en JavaScript, la clé formée de l'entier 1 est indistinguable de celle formée de la chaîne de caractères "1". Une application en JavaScript ne pourra donc pas se servir d'une map qui aurait de telles clés, de types variés.

On a vu que certains élements CBOR pouvaient être encodés de différentes manières, par exemple un tableau peut être représenté par {longueur, valeurs} ou bien par {valeurs, break code}. Cela facilite la tâche des encodeurs mais peut compliquer celle des décodeurs, et cela peut rendre certaines opérations, comme la comparaison de deux fichiers, délicates. Existe t-il une forme canonique de CBOR ? Non, pas en standard, et ce point a suscité de chaudes discussions à l'IETF. Néanmoins, un protocole ou format donné, qui utilise CBOR, peut définir une telle forme canonique. La section 3.9 donne quelques pistes à ce sujet et suggère les règles suivantes :

  • Mettre les entiers sous la forme la plus compacte possible. L'entier 2 peut être représenté par un octet (type majeur 0 puis détails égaux à 2) ou deux (type majeur 0, détails à 24 puis deux octets contenant la valeur 2), voire davantage. La forme canonique recommandée est la première (un seul octet). Même règle pour les longueurs (qui, en CBOR, sont encodées comme les entiers.)
  • Trier les clés d'une map de la plus petite à la plus grande. (Selon leur représentation en octets, pas selon l'ordre alphabétique.)
  • Mettre les tableaux et les chaînes sous la forme {longueur, valeurs}.

Tous les encodeurs CBOR qui suivent ces règles (qui seront peut-être un jour normalisées dans un nouveau RFC définissant le « CBOR canonique ») produiront, pour un même jeu de données, le même encodage.

Autre question pratique importante, le comportement en cas d'erreurs. Que doit faire un décodeur CBOR si deux clés sont identiques dans une map, ce qui est normalement interdit en CBOR ? Ou si un champ longueur indique qu'on va avoir un tableau de 5 éléments mais qu'on n'en rencontre que 4 avant la fin du fichier ? Ou si une chaîne de caractères, derrière son type majeur 3, n'est pas de l'UTF-8 bien formé ? Les sections 3.3, 3.4 et 3.10 décrivent la question. CBOR n'est pas pédant : un décodeur a le droit d'ignorer certaines erreurs, de remplacer les valeurs par ce qui lui semble approprié. CBOR penche nettement du côté « être indulgent avec les données reçues » ; il faut dire qu'une application qui utilise CBOR peut toujours le renforcer en ajoutant l'obligation de rejeter ces données erronées. Un décodeur strict peut donc s'arrêter à la première erreur. Ainsi, un pare-feu qui analyse du CBOR à la recherche de contenu malveillant a tout intérêt à rejeter les données CBOR incorrectes (puisqu'il ne sait pas trop comment elles seront interprétées par la vraie application, la section 8 revient sur ce point). Bref, la norme CBOR ne spécifie pas de traitement d'erreur unique.

Comme CBOR a un modèle de données proche de celui de JSON, on aura souvent envie d'utiliser CBOR comme encodage efficace de JSON. Comment convertir du CBOR en JSON et vice-versa sans trop de surprises ? La section 4 du RFC se penche sur ce problème. Depuis CBOR vers JSON, les traductions suivantes sont suggérées :

  • Les entiers deviennent évidemment des nombres JSON.
  • Les chaînes d'octets sont encodées en base64 et deviennent des chaînes de caractères JSON (JSON n'a pas d'autre moyen de transporter du binaire).
  • Les chaînes de caractères deviennent des chaînes de caractères JSON (ce qui nécessite d'en échapper certains, RFC 8259, section 7).
  • Les tableaux deviennent des tableaux JSON et les maps des objets JSON (ce qui impose de convertir les clés en chaînes UTF-8, si elles ne l'étaient pas déjà).
  • Etc.

En sens inverse, de JSON vers CBOR, c'est plus simple, puisque JSON n'a pas de constructions qui seraient absentes de CBOR.

Pour les amateurs de futurisme, la section 5 discute des éventuelles évolutions de CBOR. Pour les faciliter, CBOR a réservé de la place dans certains espaces. Ainsi, le type majeur 7 permettra d'encoder encore quelques valeurs simples (cela nécessitera un RFC sur le chemin des normes, cf. RFC 5226 et la section 7.1 de notre RFC). Et on peut ajouter d'autres valeurs d'étiquettes (selon des règles qui dépendent de la valeur numérique : les valeurs les plus faibles nécessiteront une procédure plus complexe, cf. section 7.2).

CBOR est un format binaire. Cela veut dire, entre autres, qu'il n'est pas évident de montrer des valeurs CBOR dans, mettons, une documentation, contrairement à JSON. La section 6 décrit donc un format texte (volontairement non spécifié en détail) qui permettra de mettre des valeurs CBOR dans du texte. Nulle grammaire formelle pour ce format : il est prévu pour l'utilisation par un humain, pas par un analyseur syntaxique. Ce format ressemble à JSON avec quelques extensions pour les nouveautés de CBOR. Par exemple, les étiquettes sont représentées par un nombre suivi d'une valeur entre parenthèses. Ainsi, la date (une chaîne de caractères étiquetée par la valeur 0) sera notée :

0("2013-10-12T11:34:00Z")

Une map de deux éléments sera notée comme en JSON :

{"Fun": true, "Amt": -2}  

Même chose pour les tableaux. Ici, avec étiquette sur deux chaînes de caractères :

[32("http://cbor.io/"), 34("SW5zw6lyZXogaWNpIHVuIMWTdWYgZGUgUMOicXVlcw==")]

Lors de l'envoi de données encodées en CBOR, le type MIME à utiliser sera application/cbor. Comme l'idée est d'avoir des formats définis en utilisant la syntaxe CBOR et des règles sémantiques spécifiques, on verra aussi sans doute des types MIME utilisant la notation plus du RFC 6839, par exemple application/monformat+cbor.

Un petit mot sur la sécurité (section 8) : il est bien connu qu'un analyseur mal écrit est un gros risque de sécurité et d'innombrables attaques ont déjà été réalisées en envoyant à la victime un fichier délibérement incorrect, conçu pour déclencher une faille de l'analyseur. Ainsi, en CBOR, un décodeur qui lirait une longueur, puis chercherait le nombre d'éléments indiqué, sans vérifier qu'il est arrivé au bout du fichier, pourrait déclencher un débordement de tampon. Les auteurs de décodeurs CBOR sont donc priés de programmer de manière défensive, voire paranoïaque : ne faites pas confiance au contenu venu de l'extérieur.

Autre problème de sécurité, le risque d'une attaque par déni de service. Un attaquant taquin peut envoyer un fichier CBOR où la longueur d'un tableau est un très grand nombre, dans l'espoir qu'un analyseur naïf va juste faire malloc(length) sans se demander si cela ne consommera pas toute la mémoire.

Enfin, comme indiqué plus haut à propos du traitement d'erreur, comme CBOR ne spécifie pas de règles standard pour la gestion des données erronées, un attaquant peut exploiter cette propriété pour faire passer des données « dangereuses » en les encodant de telle façon que l'IDS n'y voit que du feu. Prenons par exemple cette map :

{"CodeToExecute": "OK",
 "CodeToExecute": "DANGER"}

Imaginons qu'une application lise ensuite la donnée indexée par CodeToExecute. Si, en cas de clés dupliquées, elle lit la dernière valeur, elle exécutera le code dangereux. Si un IDS lit la première valeur, il ne se sera pas inquiété. Voilà une bonne raison de rejeter du CBOR invalide (les clés dupliquées sont interdites) : il peut être interprété de plusieurs façons.

Pour les amateurs d'alternatives, l'annexe E du RFC compare CBOR à des formats analogues. Attention, la comparaison se fait à la lumière du cahier des charges de CBOR, qui n'était pas forcément le cahier des charges de ces formats. Ainsi, ASN.1 (ou plutôt ses sérialisations comme BER ou DER, PER étant nettement moins courant puisqu'il nécessite de connaître le schéma des donnéees) est utilisé par plusieurs protocoles IETF (comme LDAP) mais le décoder est une entreprise compliquée.

MessagePack est beaucoup plus proche de CBOR, dans ses objectifs et ses résultats, et a même été le point de départ du projet CBOR. Mais il souffre de l'absence d'extensibilité propre. Plusieurs propositions d'extensions sont restées bloquées à cause de cela.

BSON (connu surtout via son utilisation dans MongoDB) a le même problème. En outre, il est conçu pour le stockage d'objets JSON dans une base de données, pas pour la transmission sur le réseau (ce qui explique certains de ses choix). UBJSON est un autre encodage binaire de JSON. Contrairement à CBOR, il se tient étroitement au modèle de données de JSON. Enfin, MSDTP, spécifié dans le RFC 713, n'a jamais été réellement utilisé.

Rappelez-vous que CBOR prioritise la simplicité de l'encodeur et du décodeur plutôt que la taille des données encodées. Néanmoins, un tableau en annexe E.6 compare les tailles d'un même objet encodé avec tous ces protocoles : BSON est de loin le plus bavard (BER est le second), MessagePack et CBOR les plus compacts.

Une liste des implémentations est publiée en http://cbor.io/. Au moins quatre existent, en Python, Ruby, JavaScript et Java. J'avais moi-même écrit un décodeur CBOR très limité (pour un besoin ponctuel) en Go. Il est disponible ici et son seul rôle est d'afficher le CBOR sous forme arborescente, pour aider à déboguer un producteur de CBOR. Cela donne quelque chose du genre :

% ./read-cbor test.cbor
Array of 3 items
	String of length 5: C-DNS
	Map of 4 items
		Unsigned integer 0
 => 		Unsigned integer 0
		Unsigned integer 1
 => 		Unsigned integer 5
		Unsigned integer 4
 => 		String of length 70: Experimental dnstap client, IETF 99 hackathon, data from unbound 1.6.4
		Unsigned integer 5
 => 		String of length 5: godin
	Array of indefinite number of items
		Map of 3 items
			Unsigned integer 0
 => 			Map of 1 items
				Unsigned integer 1
 => 				Array of 2 items
					Unsigned integer 1500204267
					Unsigned integer 0
			Unsigned integer 2
 => 			Map of indefinite number of items
				Unsigned integer 0
 => 				Array of 2 items
					Byte string of length 16
					Byte string of length 16
...

Merci à Carsten Bormann pour sa relecture.


Téléchargez le RFC 7049


L'article seul

RFC 7042: IANA Considerations and IETF Protocol and Documentation Usage for IEEE 802 Parameters

Date de publication du RFC : Octobre 2013
Auteur(s) du RFC : Donald Eastlake (Huawei), Joe Abley (ICANN)
Première rédaction de cet article le 24 octobre 2013


Les identificateurs IEEE 802 comme les adresses MAC d'Ethernet ne sont pas gérés par l'IETF et ne sont pas dans un registre IANA. C'est l'IEEE qui les distribue et en garde trace. Toutefois, certains protocoles IETF dépendent de ces identificateurs et ce RFC documente cet usage. Il décrit l'OUI (Organizationally Unique Identifier) attribué à l'IANA, le 00-00-5E, et indique à quoi il peut servir et comment. Ce nouveau RFC remplace l'ancien RFC 5342, avec quelques changements importants.

Parmi les exemples d'utilisation d'identificateurs IEEE 802, on peut citer les adresses d'IPv6 qui, en auto-configuration sans état, sont dérivées de l'adresse MAC. Ou bien les types de paquets Ethernet comme 0x0800 pour IPv4 et 0x86DD pour IPv6. Mais la plus grande partie de ce RFC est consacrée à l'OUI (Organizationally Unique Identifier) de l'IANA, et comment allouer des identificateurs commençant par cet OUI. Ce RFC en écrit certains, comme ceux réservés à la documentation. Fini de choisir des adresses Ethernet au hasard lorsqu'on rédige un cours ou un manuel sur ARP ! Normalement, depuis la publication de notre RFC, on utilise désormais des adresses prévues à cet effet, suivant les recommandations des RFC 2606 et RFC 5737.

On l'a dit, c'est l'IEEE qui tient le registre de ces identificateurs. L'IEEE est l'héritier de la société Xerox qui avait créé le registre. Tout le monde peut obtenir des valeurs dans ce registre mais l'IEEE, organisation très traditionnaliste, fait payer très cher (570 $ pour la norme Ethernet, certaines sont distribuées gratuitement), et ne publie pas la liste intégrale des enregistrements. Toutefois, les autres SDO peuvent obtenir gratuitement certaines valeurs.

Parmi ces paramètres, les OUI, identificateurs uniques d'une organisation (registre à l'IEEE). Ils sont surtout connus car ils servent à préfixer les adresses Ethernet. Dell ayant entre autres l'OUI 18-03-73 (l'IEEE publie une liste partielle, on trouve une liste dans le programme arpwatch, installée en /usr/share/arpwatch/ethercodes.dat et une autre est en ligne), une machine de ce constructeur peut avoir, par exemple, l'adresse 18-03-73-66-e5-68 sur sa carte Ethernet (notre RFC utilise le tiret comme séparateur - cf. section 1.1 - alors qu'on voit souvent le deux-points dans d'autres contextes). L'IANA, on l'a vu, a l'OUI 00-00-5E. L'IEEE ne fournit pas d'OUI pour les documentations, donc l'IANA a réservé des identificateurs sous son OUI à elle, pour cet usage.

Le gros morceau du RFC, la section 2, concerne les adresses MAC de type Ethernet, l'utilisation la plus connue du registre IEEE. Aujourd'hui, elles existent en deux formats, le classique, de 48 bits, nommé EUI-48, un format plus récent sur 64 bits, l'EUI-64, et l'IEEE est actuellement en train d'étudier la possibilité de créer un format EUI-128 sur 128 bits.

Les EUI-48, archi-connus en raison de leur rôle dans l'adressage Ethernet, Wi-Fi, etc, sont mondialement uniques. Si une machine a 38-59-f9-7d-b6-47, elle sera la seule au monde dans ce cas (sauf erreur dans les processus de fabrication des cartes réseaux). Les six octets de ces adresses se divisent en un OUI de trois octets (38-59-f9 dans l'exemple précédent, identifiant la société Foxconn alias Hon Hai) et trois octets attribués par le titulaire de l'OUI (l'IEEE n'enregistre donc pas les adresses individuelles mais seulement les OUI). À noter que, dans les trois octets initiaux, ceux de l'OUI, deux bits ont une signification spéciale. Le Group bit indique si l'adresse MAC est multicast (s'il est à 1) ou unicast. Le Local bit dit si l'adresse MAC est mondialement unique (s'il est à 0) ou si elle est gérée localement sans souci du reste du monde (si le bit est à 1). Dans les OUI attribués par l'IEEE, comme le 00-00-5E de l'IANA, le Local bit est à 0. Ainsi, avec un seul OUI, on peut fabriquer des identificateurs unicast ou multicast. De même, les identificateurs peuvent être globaux ou purement locaux (et, dans ce dernier cas, l'OUI n'a plus d'importance).

Il y a quelques plages d'adresses spéciales sous l'OUI IANA. Ainsi, en unicast, les plages de 00-00-5E-00-00-00 à 00-00-5E-00-00-FF et de 00-00-5E-00-52-00 à 00-00-5E-00-52-FF sont réservées pour de futures allocations par l'IANA, celles de 00-00-5E-00-01-00 à 00-00-5E-00-01-FF et de 00-00-5E-00-02-00 à 00-00-5E-00-02-FF pour le protocole VRRP, du RFC 5798, protocole qui nécessite que la machine change son adresse MAC. Et 00-00-5E-00-53-00 à 00-00-5E-00-53-FF est réservée pour la documentation. Vous pouvez trouver la liste complète dans le registre IANA. Si je regarde les adresses MAC des voisins de ma machine :

% ip -6 neighbor show                                
fe80::10:dbff:feff:4070 dev eth1 lladdr 00:10:db:ff:40:70 router REACHABLE

Je peux trouver le type de machine dans la liste locale des OUI :

% grep 0:10:db /usr/share/arpwatch/ethercodes.dat 
0:10:db	Juniper Networks, Inc.

Et si j'écris une documentation sur le protocole NDP, je vais mettre à la place des jolies adresses réservées pour la documentation :

% ip -6 neighbor show                                
fe80::5eff:feff:4070 dev eth1 lladdr 00:00:5e:ff:40:70 router REACHABLE

Les allocations IANA doivent correspondre à un travail de normalisation d'un protocole (décrit dans un RFC ou bien un Internet-Draft), et ne doivent pas être utilisées comme moyen d'échapper aux règles « normales » de l'IEEE. Dans la plage de 00-00-5E-00-52-00 à 00-00-5E-00-52-FF, la procédure est simplement celle d'un examen par un expert (section 4.1 du RFC 5226), et le RFC recommande un examen léger (l'espace d'adressage est large et il n'est pas nécessaire d'économiser). Dans celle de 00-00-5E-00-00-00 à 00-00-5E-00-00-FF, la procédure est un cas nouveau, non documenté dans le RFC 5226 et nommé « ratification par l'IESG ». Le concept de « ratification par l'IESG » est introduit dans ce RFC 7042 (section 5.1) pour dire « examen par un expert, puis, après son accord, passage devant l'IESG qui peut refuser ». L'annexe A de notre RFC contient les formulaires à remplir pour demander ces enregistrements.

Et pour les EUI-64 ? La section 2.2 rappelle leurs usages, comme la fabrication de la partie droite, l'« Interface Identifier », des adresses IPv6 (section 2.5.1 et annexe A du RFC 4291 et annexe A du RFC 5214), ou comme l'adressage FireWire. Attention, dans les adresses IPv6, le sens du Local bit a été inversé (0 veut dire que l'adresse est locale). En EUI-64 modifié (avec cette inversion du bit local), le préfixe IANA est 02-00-5E.

On y retrouve des plages analogues à celles des EUI-48 comme celle de 02-00-5E-10-00-00-00-00 à 02-00-5E-10-00-00-00-FF pour la documentation, avec des règles identiques.

Outre le préfixe IANA 00-00-5E, il existe deux autres préfixes utilisés dans la normalisation IETF (section 2.3), 33-33, pour du multicast IPv6 (RFC 2464), et CF pour PPP (RFC 2153). Le premier doit sa valeur à l'adresse du PARC, 3333 Coyote Hill Road, Palo Alto, Californie, où a été conçu Ethernet. Le second est officiellement fermé aux nouveaux enregistrements.

Après cette section 2 consacrée aux adresses MAC, la section 3 regroupe tous les autres paramètres IEEE utilisés par l'IETF. On y trouve notamment les types Ethernet qui, placés dans la trame Ethernet après les adresses, indique le type du protocole de niveau supérieur. Ils comportent deux octets, 0x0800 pour IPv4, 0x0806 pour ARP, 0x86DD pour IPv6, 0x22F3 pour TRILL, etc. Ils sont gérés par l'IEEE mais sont mentionnés ici (annexe B pour une liste partielle) pour compléter l'information. Un mécanisme d'extension est prévu pour utiliser des types plus longs que deux octets et c'est ainsi que 00-00-5E-00-42 est un numéro de protocole valable, réservé pour la documentation.

Les OUI sont aussi utilisés comme préfixes pour d'autres choses, par exemple les sélecteurs d'un algorithme de chiffrement dans IEEE 802.11. La section 4 décrit l'allocation de paramètres sous le préfixe IANA pour ces usages. Là encore, cela ne doit être fait que dans le cadre d'un processus de normalisation, avec spécification publiée.

Les changements depuis le RFC 5342 ne sont peut-être pas spectaculaires mais sont importants. Il y a l'ajout des adresses MAC de documentation. Mais il y a surtout la suppression de la règle (section 2.1.2 du RFC 5342) « allocation pour l'unicast et le multicast en même temps » qui devait simplifier le travail de l'IANA mais qui s'est avérée trop difficile à suivre. Désormais, on peut donc réserver séparement pour l'unicast et le multicast.

Autres changements, l'intégration des réflexions actuellement en cours sur la restructuration des registres IEEE, en raison des risques d'épuisement des identificateurs IEEE, et ajout des types d'enregistrement DNS EUI48 et EUI64 pour les adresses MAC (décrits en détail dans le RFC 7043).


Téléchargez le RFC 7042


L'article seul

RFC 7043: Resource Records for EUI-48 and EUI-64 Addresses in the DNS

Date de publication du RFC : Octobre 2013
Auteur(s) du RFC : J. Abley (TekSavvy Solutions)
Pour information
Première rédaction de cet article le 24 octobre 2013


Tout le monde connait les identifiants EUI-48 et EUI-64 même si ce n'est pas sous ce nom là. Normalisés par l'IEEE, ils servent notamment d'adresses Ethernet. Désormais, on peut les mettre dans le DNS, en utilisant les nouveaux types créés par ce RFC. Attention : pour des raisons liées à la protection de la vie privée, il n'est pas prévu que ces enregistrements DNS EUI48 et EUI64 se retrouvent dans le DNS public, seulement dans des zones locales (un point qui a soulevé des controverses).

Donc, d'abord, le type EUI48 (section 3). Il a le numéro 108 dans le registre IANA. En binaire, c'est simplement un groupe de six octets. Sous la forme texte (par exemple dans un fichier de zone), c'est six groupes (séparés par des tirets) de chacun deux chiffres hexadécimaux, par exemple :

host.example.   86400   IN   EUI48 00-00-5e-00-53-2a

(Notez que l'adresse MAC utilise le préfixe IANA et les valeurs réservées pour les exemples par le RFC 7042.)

C'est quasiment pareil pour le type EUI64. Numéro 109, huit octets à la suite en binaire, huit groupes de chiffres hexa en mode texte :

host.example.   86400   IN   EUI64 00-00-5e-ef-10-00-00-2a

Mais à quoi cela sert, ces adresses Ethernet dans le DNS ? La section 5 répond à la question en décrivant le cas d'usage qui avait motivé ce RFC. Au Canada, les FAI utilisant le câble utilisent DHCP pour fournir des adresses IP aux abonnés. Souvent, cela passe par un revendeur qui ne contrôle pas tout le réseau. Le revendeur connait l'adresse EUI-48 de son client mais pas l'adresse IP allouée. La correspondance entre l'adresse IP et l'adresse MAC, a décidé le régulateur, doit être publiée dans le DNS (document « Implementation of IP Address Tracking in DOCSIS Networks (TIF18) » du CRTC Interconnection Steering Committee Network Working Group, voir leurs documents). Avant ce RFC, les méthodes utilisées étaient variables et pas forcément très jolies (des enregistrements TXT, par exemple).

Cela pose quelques problèmes de sécurité, notamment liés à la protection de la vie privée. Une adresse MAC est en effet (en théorie) unique au niveau mondial et peut donc permettre de suivre une machine. Elle change moins que l'adresse IP attribuée et fournit donc un meilleur moyen de traque, permettant de suivre un utilisateur donné. C'est pour cela que la section 8 du RFC dit clairement que les types EUI48 et EUI64 ne doivent apparaître que dans des zones privées, non accessibles au public. (Cela n'a pas suffit à certains participants à l'IETF qui réclamaient qu'on ne mette jamais ces adresses EUI48 et EUI64 dans le DNS, zones privées ou pas.)

Ces deux nouveaux types d'enregistrement DNS sont mis en œuvre dans NSD en expérimental (ticket #496, il faut compiler avec l'option --enable-draft-rrtypes) et dans Knot, apparemment depuis la version 1.3.0.


Téléchargez le RFC 7043


L'article seul

Fiche de lecture : CultureNum

Auteur(s) du livre : Ouvrage collectif coordonné par Hervé le Crosnier
Éditeur : C&F
978-2-915825-31-2
Publié en 2013
Première rédaction de cet article le 19 octobre 2013


Ce livre rassemble un certain nombre de textes de réflexions autour de la notion de « Culture numérique ». Le numérique (en pratique, le livre parle beaucoup, mais pas uniquement, de l'Internet) est souvent abordé sous l'angle technique (les routeurs, les serveurs, les câbles, les logiciels...) ou sous l'angle anecdotique, rarement sous celui des réelles pratiques de ses innombrables utilisateurs. Ce livre vise à aborder le numérique d'une autre façon : les utilisateurs ne se comportent pas comme le voudraient les marketeux, ils ne se limitent pas aux quelques excès ou délires pointés par le presse à sensation. Mais, alors, ils font quoi ?

Comme la plupart des ouvrages collectifs, celui-ci n'a guère d'unité, à part cette volonté de considérer que l'Internet est aussi défini par les choix de ses utilisateurs. « L'Internet est trop souvent vécu comme un réseau dominé par des acteurs industriels et des décisions institutionnelles [par exemple dans les débats sur la gouvernance], alors que ce sont les usagers qui forment l'élement majeur du succès du numérique » (p. 8).

Ainsi, si de nombreux penseurs ont glosé sur le numérique chez les adolescents, peu sont allés étudier ce que faisaient vraiment lesdits ados. Élisabeth Schneider est allé enquêter et raconte ses trouvailles (j'ai bien aimé la moyenne des 15 SMS envoyés par heure de cours, p. 22...) Karine Aillerie est partie voir ces mêmes ados pour regarder comment ils recherchent et s'informent sur l'Internet. Si leur usage de Google est souvent cité, celui de Wikipédia l'est moins, notamment sur le pourquoi de la confiance accordée (Wikipédia est vue par les ados comme une « marque », immédiatement reconnaissable, et cohérente dans toute ses pages, cf. p. 61). L'auteur note bien, comme l'ont déjà fait d'autres, que tous ces outils ne dispensent pas d'« apprendre à chercher », chose très rare aujourd'hui (p. 67).

Laurent Matos se demande dans ce livre comment les bibliothèques peuvent s'adapter au numérique, par exemple en prêtant des liseuses. Mais la complexité technique de l'offre, la variété des formats et bien sûr les DRM forment des obstacles colossaux à une implication plus grande des bibliothèques dans le numérique (p. 82-83). Guénaël Boutouillet, lui, a voulu renouveler les traditionnels ateliers d'écriture en les faisant via le Web (p. 87), notant le paradoxe que ces ateliers, la plupart du temps, n'utilisent pas les outils qui sont le quotidien de tous (écran et clavier).

Le livre, je l'ai signalé, est à plusieurs voix, et ces voix ne chantent pas tous en chœur. On trouve même un long texte corporatiste d'Alain Charriras de défense des ayant-droits (p. 108). Le problème est complexe mais bien expliqué par l'auteur, qui défend la taxe « copie privée » sans nuances. Mais il note aussi que la nullité de l'offre légale est une des principales explications de la copie illégale.

Le numérique envahit aussi la radio et Xavier de la Porte a un excellent article (p. 116) sur la mutation de « la radio la plus vieillotte » (France Culture). De l'époque des Nagra emportés en reportage, au montage d'interviews sur ordinateur et ses conséquences. Le fait que les interviews ne soient plus coupés par le changement de bande magnétique ne permet plus de s'arrêter pour réflechir... Le fait que les moteurs de recherche n'indexent pas le son limite la visibilité des émissions de radio sur l'Internet...

Un exemple typique où le contenu est créé par les utilisateurs et non pas consommé passivement par eux est le fansubbing (les passionnés d'une série télévisée étrangère qui en assurent eux-mêmes le sous-titrage pour leurs compatriotes moins polyglottes), couvert par Brigitte Chapelain avec plusieurs autres pratiques créatives du numérique (p. 142). J'en profite pour remercier « Honey Bunny » qui fait un travail très rapide (quoique pas toujours très rigoureux mais même ses coquilles sont amusantes comme « va sceller mon cheval ») de sous-titrage de Game of Thrones.

Alors, le numérique est-il bon ou mauvais ? Comme le note Hervé le Crosnier (p. 179), il est comme un médicament, soignant certains, en rendant d'autres malades, et le tout dépendant de la dose et de la façon dont elle est administrée et reçue. Il y a eu des promesses délirantes liées au numérique (Hervé le Crosnier démolit les plus ridicules, celles portant sur l'éducation, notamment au e-learning, p. 181 et 183) mais aussi des transformations radicales, souvent dans le sens d'une plus grande participation du peuple.

Avertissement : j'ai reçu un exemplaire gratuit de l'éditeur, mais cela n'a pas affecté mon jugement, je suis incorruptible, d'autant plus qu'il n'y avait pas de chocolats joints à l'envoi.


L'article seul

RIPEstat, plein de données sur l'Internet

Première rédaction de cet article le 17 octobre 2013


L'Internet est une ressource cruciale aujourd'hui, mais peu connue. Pour beaucoup de gens, y compris des administrateurs réseau, l'Internet est une boîte noire, un mystère. Lorsqu'il marche, tant mieux, s'il plante, on ne sait pas quoi faire. Pourtant, une des caractéristiques de l'Internet est que tout est accessible. Ainsi, l'outil RIPEstat du RIPE-NCC donne accès à plein d'informations techniques sur le fonctionnement de l'Internet. Démonstration, avec plein de chiffres et de faits.


L'article complet

Le routeur Wi-Fi ASUS WL 330 NUL

Première rédaction de cet article le 13 octobre 2013


La publicité d'ASUS le présente comme le plus petit routeur Wi-Fi du monde, ou à peu près. Que peut faire cet engin ?

Grand comme une clé USB, il sert à combler les trous de la connectivité lorsqu'on voyage. Si vous n'avez qu'une seule machine, et qu'elle a Ethernet et Wi-Fi, ce routeur ne vous servira pas à grand'chose. Il est utile si vous avez des engins qui manquent de la connectivité requise, ou si vous avez plusieurs machines. Le routeur a deux prises, une USB et une Ethernet. L'USB sert à l'alimentation électrique, mais aussi à la connectivité réseau si une de vos machines peut faire de l'Ethernet sur USB. On branche le routeur sur un PC via USB, on le configure via un navigateur Web (http://192.168.1.1/) et c'est parti. Ce routeur permet, entre autres :

  • De connecter une machine qui n'a que Wi-Fi lorsque la seule connectivité disponible est Ethernet, et réciproquement.
  • De connecter plusieurs machines, même si une seule est normalement autorisée (l'interface du routeur permet de facilement changer l'adresse MAC, fonction « Clone MAC »).

Le routeur peut à la fois être connecté à l'Internet en Wi-Fi et distribuer du Wi-Fi aux alentours (quelque chose que je n'ai jamais réussi à faire avec mon PC Ubuntu). En Wi-Fi, il peut gérer un réseau protégé par WPA2 (fonction « Réseau privé »), ou bien un réseau ouvert avec portail captif (fonction « Réseau invité »). Dans ce second cas, le portail peut authentifier par mot de passe ou bien envoyer un message à l'administrateur, qui autorise alors le client via l'interface Web.

Ce que j'apprécie dans cet engin : son faible prix, son faible encombrement, sa simplicité de configuration. Ce que je n'apprécie pas : pas d'IPv6, aucune statistique disponible via l'interface Web.

La fonction « Historique du système » permet de voir quels logiciels utilise ce routeur :

Jan  1 08:00:15 syslogd started: BusyBox v1.17.4
Jan  1 08:00:15 stop_nat_rules: apply the redirect_rules!
Jan  1 08:00:16 WAN Connection: Ethernet link down.
Jan  1 08:00:18 dnsmasq[366]: started, version 2.55 cachesize 1500
Jan  1 08:00:18 dnsmasq[366]: compile time options: IPv6 GNU-getopt no-RTC no-DBus no-I18N DHCP TFTP
Jan  1 08:00:18 dnsmasq[366]: asynchronous logging enabled, queue limit is 5 messages
Jan  1 08:00:18 dnsmasq-dhcp[366]: DHCP, IP range 192.168.1.2 -- 192.168.1.254, lease time 1d
Jan  1 08:00:18 dnsmasq[366]: read /etc/hosts - 3 addresses
Jan  1 08:00:18 dnsmasq[366]: failed to read /etc/resolv.conf: No such file or directory
Jan  1 08:00:19 WL-330NUL: start macreceiver
Jan  1 08:00:19 WL-330NUL: start httpd
...
Oct 13 22:37:04 dnsmasq-dhcp[366]: DHCPREQUEST(br0) 10.50.2.7 5c:b5:24:b4:ee:f3 
Oct 13 22:37:04 dnsmasq-dhcp[366]: DHCPNAK(br0) 10.50.2.7 5c:b5:24:b4:ee:f3 wrong network
Oct 13 22:37:08 dnsmasq-dhcp[366]: DHCPDISCOVER(br0) 5c:b5:24:b4:ee:f3 
Oct 13 22:37:08 dnsmasq-dhcp[366]: DHCPOFFER(br0) 192.168.1.254 5c:b5:24:b4:ee:f3 
Oct 13 22:37:08 dnsmasq-dhcp[366]: DHCPREQUEST(br0) 192.168.1.254 5c:b5:24:b4:ee:f3 
Oct 13 22:37:08 dnsmasq-dhcp[366]: DHCPACK(br0) 192.168.1.254 5c:b5:24:b4:ee:f3 android-c38952bf32157985
Oct 13 22:41:08 dnsmasq-dhcp[366]: DHCPREQUEST(br0) 192.168.1.254 5c:b5:24:b4:ee:f3 
Oct 13 22:41:08 dnsmasq-dhcp[366]: DHCPACK(br0) 192.168.1.254 5c:b5:24:b4:ee:f3 android-c38952bf32157985
Oct 13 22:45:39 dnsmasq-dhcp[366]: no address range available for DHCP request via wlan0-vxd

Quelques engins similaires, signalés par de fidèles lecteurs que je remercie :


L'article seul

Ma conférence à Paris-Web sur la sécurité des sites Web

Première rédaction de cet article le 11 octobre 2013


Hier, jeudi 10 octobre, j'ai eu le plaisir de faire un exposé général sur la sécurité des sites Web à http://www.paris-web.fr/. Cet exposé, intitulé « Deux ou trois choses que vous ne savez peut-être pas sur la sécurité de votre site Web », passait très rapidement sur des attaques que les programmeurs Web connaissent déjà (XSS, injections SQL, etc) et se focalisait sur trois grandes catégories d'attaques : celles par déni de service, celles utilisant les noms de domaines et celles sur HTTPS.

Les supports utilisés sont disponibles ici. C'est du reveal.js, un système que j'ai récemment choisi. Je débute dans toutes ces techniques Web donc la présentation n'est pas parfaite sur tous les navigateurs (ça semble marcher mieux avec Chromium). Bref, vous pouvez regarder, si vous ne connaissez pas reveal.js, c'est la touche F pour passer en plein écran (Esc pour en sortir), et N pour la page suivante.

La vidéo est disponible en ligne.

Merci à Ève Demazière pour son aide pour la rédaction de la proposition faite à Paris Web et pour la réalisation des supports.


L'article seul

RFC 6950: Architectural Considerations on Application Features in the DNS

Date de publication du RFC : Octobre 2013
Auteur(s) du RFC : J. Peterson (NeuStar), O. Kolkman (NLnet Labs), H. Tschofenig (Nokia Siemens Networks), B. Aboba (Microsoft Corporation)
Pour information
Première rédaction de cet article le 10 octobre 2013


Le DNS est un des plus grands succès de l'Internet : une base de données répartie, fiable, sur laquelle on peut compter, et qui est très souple dans ses usages, lui permettant d'être utilisée pour beaucoup de choses (seuls les journalistes écrivent encore que « le DNS sert à trouver une adresse IP à partir d'un nom de domaine » : la réalité est bien plus riche). Mais, justement, la disponibilité et l'efficacité du DNS font qu'il est utilisé par beaucoup d'applications dont les auteurs ne sont pas forcément conscients des forces et faiblesses du DNS. Ne faudrait-il pas les appeler à réfléchir deux secondes sur ces forces et ces faiblesses ?

Le DNS permet de récupérer des données (quelconques : ce ne sont pas forcément des adresses IP) à partir d'un nom de domaine. Il est même utilisé par des applications dont les identifiants ne sont pas des noms de domaine : une petite transformation pour convertir l'identifiant en nom de domaine et hop (ONS, ENUM, etc). Le premier RFC à avoir décrit l'usage du DNS pour autre chose qu'une correspondance nom->adresse est le RFC 974 en 1986. C'est dire que c'est ancien et cela explique mes critiques sévères des ignorants qui continuent à considérer le DNS comme un simple moyen de trouver des adresses. Depuis ce RFC 974, qui introduisait l'enregistrement MX, l'idée a suivi son chemin. Un mécanisme plus général, le SRV, a été introduit par le RFC 2052 (remplacé depuis par le RFC 2782). Et, pour faire des mécanismes de délégation aussi compliqués qu'on le souhaite, il y a le NAPTR créé par le RFC 2168, généralisé ensuite par le RFC 3401. Enfin, il y a des applications qui mettent simplement leurs données dans le très général et pas structuré enregistrement TXT, ce que fait par exemple DKIM (RFC 6376).

Mais ce succès, comme tous les succès, a aussi son revers : les applications demandent de plus en plus au DNS alors que son vaste déploiement est largement dû à sa focalisation sur un petit nombre de fonctions qu'il réalise très bien. La mentalité fréquente aujourd'hui de « on met tout dans le DNS » (illustrée par un gadget fameux) est parfois en conflit avec les principes du DNS. La confidentialité est un bon exemple : elle était délibérement exclue du cahier des charges du DNS (et à juste titre : lisez le RFC 3414 si vous voulez un exemple de la complexité que la confidentalité apporte à un protocole requête-réponse). Vouloir l'ajouter aujourd'hui risque fort de faire perdre au DNS ses propriétés intéressantes (il n'est pas cité par ce RFC, mais c'est l'une des raisons de l'échec de DNScurve, qui essayait de faire trop de choses). Bien des applications qui veulent utiliser le DNS ont réclamé une certaine dose de confidentialité, alors que le DNS doit une partie de son efficacité au fait que toutes les données sont publiques. Ainsi, un cache n'a pas à s'inquiéter si les données qu'il mémorise doivent être servies à tous ou pas.

Ce nouveau RFC de l'IAB vise donc à aider les concepteurs d'applications en exposant clairement ce que le DNS fait bien, ce qu'il peut faire, et ce qu'il ne sait pas faire. C'est un excellent document pour qui veut comprendre en détail le DNS et, malgré sa longueur, il mérite d'être lu attentivement. Il fournit les informations nécessaires pour que ledit concepteur puisse répondre intelligemment à la question « Dois-je mettre cette information dans le DNS ou bien ailleurs ? » Il complète le RFC 5507, qui restait plutôt sur les questions de syntaxe, alors que ce nouveau RFC 6950 adopte une vue plus générale, plus tournée vers l'architecture du système. Pour le résumer en deux mots : le DNS doit son succès à ce qu'il n'essaie pas de résoudre tous les problèmes mais un ensemble bien précis de problèmes, pour lesquels il est une bonne solution. Comme il existe d'autres protocoles que le DNS, une application ou un service qui envisage d'utiliser le DNS dit sérieusement étudier s'il est vraiment la solution la plus adaptée (parfois oui mais parfois non).

La section 2 de notre RFC présente un certain nombre d'usages du DNS par des applications. Il commence évidemment par le routage du courrier, avec les enregistrements MX. Le MX était la première utilisation du DNS pour faire autre chose que de la simple traduction de nom en adresse IP. En partie droite d'un MX, on trouve le nom du ou des serveurs qui gèrent la messagerie pour le domaine en partie gauche. Bien sûr, une convention de nommage (du genre « le serveur de messagerie de example.org se nomme mail.example.org ») aurait pu jouer un rôle similaire. Mais les MX sont plus souples (le serveur d'un domaine n'est pas obligé d'avoir un nom dans le domaine, cf. RFC 4367) et offrent des possibilités supplémentaires (plusieurs serveurs, avec des priorités différentes). Mais le MX est spécifique au courrier électronique. Les enregistrements SRV, créés par le RFC 2052 (aujourd'hui RFC 2782), ont étendu le principe à tous les protocoles qui voulaient en profiter (avec des choses en plus comme l'indication du numéro de port ou bien comme la répartition de charge). Tous les protocoles créés depuis utilisent ces enregistrements, à la triste exception de HTTP qui, stupidement (l'avis est le mien, il n'est pas dans le RFC), ne fournit pas de mécanisme pour trouver le serveur d'un domaine (obligeant à utiliser des conventions de nommage comme www.example.com ou, pire, à mettre une adresse IP sur le domaine lui-même, et empêchant d'utiliser le DNS pour la répartition de charge et la résilience, ce qu'auraient permis les SRV).

Autre service fourni aux applications par le DNS, les enregistrements NAPTR. L'idée au début était de pouvoir trouver n'importe quel identificateur, même distinct d'un nom de domaine, dans le DNS (RFC 2915). Les NAPTR permettent de spécifier des transformations complexes depuis une famille d'identificateurs, vers les noms de domaine. L'idée est ancienne. Sa première manifestation avait été le domaine in-addr dans le RFC 883 (c'était un TLD à l'époque, il est devenu in-addr.arpa dans le RFC 973). Son but était de permettre de traduire des adresses IP en noms, en convertissant d'abord l'adresse IP en un nom de domaine se terminant en in-addr. Ce genre de transformation textuelle sur un identificateur pour en faire un nom de domaine a ensuite été reprise par tpc.int (RFC 1530, un mécanisme pour router des appels téléphoniques via l'Internet, qui allait déboucher sur ENUM). Ces mécanismes ne changent pas le protocole DNS mais ils changent la manière dont on se sert du DNS, et apportent de nouveaux utilisateurs, ayant de nouvelles attentes.

Une des demandes de ces « nouvelles » applications est de stocker des données quelconques dans le DNS. On peut mettre ce qu'on veut dans un URI (et même directement des données, cf. RFC 2397). Donc, comme un NAPTR mène à un URI, il peut nous mener à n'importe quoi. Mais, avant même cette astuce, le DNS pouvait déjà stocker n'importe quoi. Il existe même un type d'enregistrement, TXT, spécialement prévu pour des données non structurées. La souplesse du TXT et son absence de contraintes ont attiré plein de gens, malgré les conseils de prudence du RFC 5507. Il y a même eu une proposition de structurer le contenu des TXT (RFC 1464).

Bon, mais qui y a-t-il de mal à ce que les gens se servent du DNS pour y mettre des informations ? En combinant les différentes techniques vues ci-dessus, on pourrait faire tenir n'importe quel protocole requête/réponse dans le DNS. Mais ce n'est pas complètement exact. La section 3 décrit les défis auxquels son succès confronte le DNS. Certes, le DNS est une base de données répartie, fiable, et rapide. Mais lorsqu'on dit « base de données », certains utilisateurs voudraient que le DNS fournisse des services classiques des bases de données, comme la confidentialité, le contrôle d'accès, l'introspection (utiliser le protocole d'accès pour découvrir le schéma) et la possibilité de requêtes structurées complexes, un peu comme ce que fournit SQL. Mais le DNS n'a pas été conçu pour cela et ce RFC argumente que, plutôt que de forcer le DNS à fournir ces services, on utiliserait mieux son temps à développer d'autres protocoles ou tout simplement à utiliser d'autres protocoles existants. Le succès du DNS et ses qualités viennent justement de ce qu'il n'essayait pas de tout faire.

Les exemples donnés par le RFC sont tous empruntés au monde ENUM (RFC 6116) mais les questions soulevées ne sont pas spécifiques à ENUM.

D'abord, les critères de recherche : dans le DNS, la clé d'accès est le triplet {nom de domaine, classe, type}, par exemple (en syntaxe dig) www.afnic.fr. IN AAAA, et la correspondance doit être exacte (pas de recherche floue). Or, certains souhaiteraient pouvoir exprimer des requêtes plus riches. Des tentatives ont été faites pour mettre des critères supplémentaires dans le nom de domaine lui-même (par exemple, pour ENUM, tg011.0.0.4.5.4.3.4.1.7.5.1.e164.arpa pour ajouter au nom normal, 0.0.4.5.4.3.4.1.7.5.1.e164.arpa, qui est dérivé du numéro de téléphone, le trunk group tg011) mais cela devient vite pénible lorsque le nombre de critères augmente.

Autre solution envisagée, EDNS (RFC 6891), en passant les critères supplémentaires comme options EDNS. Mais cela ne marche pas comme certains le prévoient car EDNS est de saut en saut et pas de bout en bout : un serveur DNS relais ne va pas transmettre les options EDNS.

Enfin, les requêtes complexes posent un problème pour les caches, si fréquents avec le DNS. Les caches actuels considèrent que la réponse ne varie qu'avec le triplet {nom de domaine, classe, type} et pourrait donc garder en cache à tort des réponses faites à des requêtes plus complexes.

Autre demande fréquente des nouveaux utilisateurs du DNS, avoir des réponses « à la tête du client », dépendant de l'émetteur de la question. Il est par exemple courant aujourd'hui de servir des réponses différentes selon l'adresse IP de la source (option view de BIND). Tant que cela ne sert qu'à présenter des versions adaptés d'un contenu (un portail Web différent selon le pays d'origine de la requête), sans problème de sécurité, ce n'est pas trop grave : une erreur n'aura pas de conséquences trop ennuyeuses. Pour des cas plus sensibles, cela peut être gênant. D'autant plus que l'adresse IP de la source n'est pas celle du vrai client, mais celle du résolveur qu'il utilise. Dans certains cas (Google Public DNS), la distance entre les deux peut être énorme. Une option EDNS a été proposée pour que le résolveur puisse indiquer au serveur faisant autorité la vraie adresse IP du client mais elle n'est pas encore adoptée (entre autres, elle pose des problèmes si le client a une adresse IP privée, genre RFC 1918).

Le DNS a d'autres limites lorsqu'on veut l'utiliser comme base de données générique, par exemple la taille des noms de domaine (limitée à 63 caractères par composant) et la taille des réponses. Quelle limite de taille ? L'ancienne limite de 512 octets n'est normalement plus qu'un souvenir (mais il existe encore des pare-feux bogués ou mal gérés qui imposent cette limite) mais il y a deux autres seuils derrière, la MTU (si la réponse est plus grosse, on risque de la fragmentation) et les 4 096 octets qui sont, en pratique, la limite de la plupart des serveurs. Si la réponse est un URI, notez que le RFC 2397 sur les URI data: indique que ceux-ci doivent être « courts » mais il ne définit pas cet adjectif. Le RFC note que, dans le contexte d'ENUM, stocker des sonneries de téléphone rigolotes sous forme de fichiers MP3 dans un URI data: n'est probablement pas raisonnable.

En outre, le DNS reposant sur UDP, qui ne garantit pas l'adresse IP source, des données de grande taille augmentent les risques d'attaque avec amplification (RFC 4732, section 3). Dans ces attaques, le méchant émet une requête DNS (de petite taille, donc) en usurpant l'adresse IP source de sa victime. Le serveur va alors répondre à celle qu'il croit être l'émetteur et la réponse est souvent bien plus grande que la question (le RFC cite l'exemple d'un certificat stocké dans le DNS, comme dans le RFC 4398). L'attaquant pourra donc obtenir ainsi un trafic plus important que ce qu'il peut lui-même générer. C'est d'ailleurs une des raisons pour lesquels les serveurs de .com, par exemple, limitent leurs réponses à 1 460 octets. Bref, malgré EDNS, on ne peut pas espérer faire passer dans le DNS des données de taille quelconque. Le DNS est prévu pour des informations courtes.

Autre limite du DNS lorsqu'on essaie de s'en servir comme d'une base de données générique, la non-correspondance des frontières administratives avec celles du DNS : les frontières des composants d'un nom de domaine ne sont pas forcément celles qu'on voudrait. Par exemple, pour la téléphonie, les anciennes numérotations étaient très hiérarchiques (et correspondaient donc bien au DNS) alors que, depuis la portabilité des numéros de téléphone, ce n'est plus le cas et il n'est donc pas évident de savoir où déléguer les noms ENUM. Ce n'est pas juste un problème esthétique : le bon fonctionnement du DNS dépend des délégations qui sont « cachées » (gardées en mémoire) dans les résolveurs, et qui épargnent à la racine la grande majorité des requêtes. Avec la portabilité des numéros téléphoniques, il faut interroger la racine ENUM pour tout numéro (puisqu'on ne peut pas savoir à l'avance quel opérateur téléphonique le gère). C'est d'autant plus ennuyeux pour la racine ENUM que les correspondances entre un numéro et un opérateur changent et qu'on souhaite souvent une portabilité rapide (de l'ordre de quinze minutes), peu compatible avec une racine simple et efficace.

Si vous pensez que ce n'est pas si grave, que .com est un espace plat avec de nombreux noms et des changements rapides, ce qui démontre que le DNS peut s'en tirer, pensez que dans les seuls États-Unis, il y a trois cents millions de numéros de téléphone attribués, trois fois la taille de .com.

Le problème n'est évidemment pas spécifique à ENUM : si on créait un mécanisme de portabilité pour les adresses IP, les domaines comme in-addr.arpa auraient les mêmes problèmes.

La section 4 est entièrement consacrée à un problème particulier qui a fait couler beaucoup d'encre, le désir d'avoir des réponses DNS « à la tête du client ». Officiellement, le DNS présent une vue unique à tous les utilisateurs (ce point est développé dans le RFC 2826) qui affirme que les noms doivent être uniques et donc donner un résultat unique. Mais il existe une forte demande pour avoir des noms qui ne fonctionnent que dans un espace privé (à l'intérieur d'une entreprise, par exemple), afin de limiter l'accès à certaines ressources. Il existe plusieurs solutions techniques pour avoir des réponses différentes en local et en public mais aucune n'est parfaitement satisfaisante. Par exemple, si on utilise des noms locaux avec un TLD bidon comme .prive ou .local, ces noms « fuiront » un jour ou l'autre, seront vus à l'extérieur, ce qui générera de la confusion (section 3.3 du RFC 5507).

Bien, après toutes ces critiques et toutes ces limites du DNS, quels conseils pratiques donner à ceux et celles qui voudraient quand même utiliser le DNS ? La section 5 est composée d'excellents conseils pour les développeurs d'applications ou de services utilisant le DNS. En gros, le DNS sera sans doute une bonne solution si le service qui veut l'utiliser a toutes ces propriétés :

  • Les données à publier peuvent être distribuées (et mémorisées dans les caches) en utilisant les mécanismes standards du DNS,
  • Les données sont accessibles par des clés qu'on peut convertir en noms de domaine sans violer leur sémantique,
  • Les clés en question (les noms de domaine) doivent être utilisées dans leur totalité (pas de recherche sur un nom partiel),
  • Les réponses ne dépendent pas du demandeur,
  • Une fois ses informations obtenues, l'application utilisera le DNS pour trouver le pair à contacter.

Si une seule de ces propriétés manque, le DNS n'est peut-être pas la bonne solution pour le problème. À l'inverse, de bons signaux d'alarme, indiquant qu'on utilise le DNS à tort, sont :

  • On a besoin de rajouter des données indiquant les frontières administratives (ce que les applications n'ont normalement pas besoin de connaître),
  • Les identificateurs utilisés ont une sémantique ou un modèle radicalement différent de celui du DNS (par exemple, ils sont dans un espace plat, alors que le DNS doit son efficacité à son modèle hiérarchique),
  • On veut distribuer des données à certaines personnes et pas à d'autres,
  • Les réponses sont de grande taille, poussant les limites du DNS trop loin.

Bon, mais si on n'utilise pas le DNS, alors quoi ? Le RFC suggère que, dans beaucoup de cas de protocole requête/réponse, HTTP convient parfaitement (par exemple, il a de l'authentification, il peut transporter des données de taille quelconque, il est largement déployé...)

Pendant l'élaboration de ce RFC, des commentaires intéressants ont été enregistrés dans le système de suivi des tâches.


Téléchargez le RFC 6950


L'article seul

La crypto n'a pas que des avantages

Première rédaction de cet article le 4 octobre 2013
Dernière mise à jour le 14 février 2015


Suite aux révélations du héros Edward Snowden, bien des gens ont pris conscience de ce que tous les experts en sécurité annonçaient depuis longtemps : les services d'espionnage espionnent et ne respectent aucune limite. Notamment, tout le trafic envoyé sur l'Internet peut être écouté, si on ne prend pas de précautions particulières. La solution technique la plus souvent citée est l'usage systématique de la cryptographie. Ce choix est tout à fait justifié. Mais il ne faut pas s'imaginer qu'il va être gratuit : tout chiffrer va faire perdre certaines possibilités, notamment en matière de débogage.

Cet article a été motivé par une formation où on programmait des accès à un service réseau, via une API qui reposait sur HTTPS. Un moment, on avait un doute sur ce qu'on envoyait, quelqu'un a dit « on va utiliser Wireshark pour examiner ce qu'on envoie vraiment » et paf : à cause du S de HTTPS, la session était entièrement chiffrée par TLS et Wireshark ne pouvait pas aider. Une décision de sécurité parfaitement justifiée (ne permettre l'accès qu'en HTTPS) a fait perdre un remarquable outil de débogage des applications HTTP.

Bien sûr, compte tenu des révélations de Snowden citées plus haut, il n'y a guère le choix. Même si on n'est pas sûr que la cryptographie protège bien contre un adversaire de la puissance de la NSA, ne pas se protéger serait une folie, puisque la NSA et tous les espions plus petits pourraient alors regarder le contenu du trafic sans problème. Donc, il faut chiffrer. Mais, personnellement, je regrette que les géniaux outils de débogage réseau comme tcpdump et Wireshark soient de moins en moins utiles à cause du « tout chiffrement ».

Alors, certains et certaines vont me dire « mais il existe des outils qui savent déchiffrer le trafic chiffré, si on leur fournit la(les) clés privée(s), par exemple Wireshark ». Mais ce n'est plus vrai non plus. Voyons d'abord les outils disponibles :

  • tcpdump ne sait déchiffrer que l'IPsec, protocole peu utilisé.
  • ssldump sait déchiffrer le TLS (autrefois nommé SSL).
  • Wireshark sait déchiffrer le TLS.
  • Aucun ne sait déchiffrer le SSH.

Naturellement, ssldump et Wireshark vont avoir besoin de la clé privée du serveur pour cela (autrement, TLS ne servirait à rien). Si on utilise ssldump sans cette clé privée, on voit la négociation TLS :

% ssldump -d -r /tmp/tls.pcap
...
1 1  0.2319 (0.2319)  C>S  Handshake
      ClientHello
        Version 3.1 
        cipher suites
        TLS_DHE_RSA_WITH_AES_128_CBC_SHA
...
1 2  0.4557 (0.2238)  S>C  Handshake
      ServerHello
        Version 3.1 

Mais plus rien ensuite :

...
1 11 0.8215 (0.0110)  C>S  application_data
1 12 1.6280 (0.8065)  S>C  application_data
1 13 1.6845 (0.0564)  S>C  application_data
1 14 1.6993 (0.0148)  S>C  application_data
...

(Notez quand même que la négociation TLS se passe en clair, ce qui peut donner des informations à un espion.)

Si on copie la clé privée server.key sur le serveur TLS et qu'on permet à ssldump de s'en servir :

% ssldump -d -k server.key -r /tmp/tls.pcap

On ne récupère rien de plus ! C'est encore par la faute de la NSA. Celle-ci stocke apparemment les communications chiffrées sur ses disques durs, dans l'espoir de pouvoir les déchiffrer plus tard, soit par les progrès de la cryptanalyse, soit simplement en obtenant la clé privée (par espionnage, injonction d'un tribunal, etc). Les sessions TLS sont donc vulnérables à ces attaques du futur, ce qui a mené au concept de PFS (Perfect Forward Secrecy). La PFS est la propriété comme quoi un attaquant qui a copié la session et qui a obtenu la clé privée ne pourra quand même pas déchiffrer le message. Elle est mise en œuvre dans TLS via des algorithmes comme ceux dont le nom contient DHE (Diffie-Hellman éphémère), comme le TLS_DHE_RSA_WITH_AES_128_CBC_SHA de l'exemple plus haut. Avec cette procédure DHE, les deux parties (le client et le serveur TLS) se mettent d'accord sur des clés qui ne sont pas transmises et donc pas conservées dans les enregistrements de trafic. (Les autres algorithmes sont souvent nommés « RSA statique ». Avec eux, une clé de session est générée et envoyée, après chiffrement RSA, au pair. Elle sera donc accessible dans le trafic capturé.) Ainsi, ssldump et Wireshark ne peuvent rien faire (Wireshark affiche piteusement « Entire conversation (0 bytes) »). Les mises en œuvre modernes de TLS choisissent souvent ces algorithmes et, si vous avez du TLS récent et que vous n'avez pas changé la configuration, vous avez souvent du PFS par défaut... et donc pas de débogage possible. Vous voyez en général qu'on a le PFS lorsque la négociation TLS comprend un ServerKeyExchange (section 7.4.3 du RFC 5246). Avec ssldump :

1 4  0.4582 (0.0025)  S>C  Handshake
      ServerKeyExchange

Au fait, pour comparaison, une session TLS où on n'a pas employé la PFS, le serveur ne la gérant pas :

...
1 8  0.7662 (0.1631)  S>C  ChangeCipherSpec
1 9  0.7664 (0.0002)  S>C  Handshake
      Finished
1 10 0.7762 (0.0097)  C>S  application_data
    ---------------------------------------------------------------
    GET / HTTP/1.0
    Host: www.example.net
    Accept: text/html, text/plain, text/css, text/sgml, */*;q=0.01
    Accept-Encoding: gzip, compress, bzip2
    Accept-Language: en
    User-Agent: Lynx/2.8.8dev.15 libwww-FM/2.14 SSL-MM/1.4.1 GNUTLS/2.12.20
...

Cette fois, ssldump peut déchiffrer la communication en HTTP. Ne tentez pas cela avec le paquetage ssldump de Debian, il a une bogue énorme et jamais réparée, qui fait qu'on ne peut pas l'utiliser pour déchiffrer.

Donc, une nouvelle fois, la sécurité n'a pas été gratuite. La PFS est indispensable contre les attaquants modernes, mais elle fait perdre la possibilité d'utiliser les outils de débogage avec déchiffrement. Le caractère très ouvert et très visible de l'Internet, qui m'avait tant facilité la vie lorsque j'avais appris TCP/IP avec un sniffer, en a pris un coup.

Des bonnes lectures :


L'article seul

RFC 7027: Elliptic Curve Cryptography (ECC) Brainpool Curves for Transport Layer Security (TLS)

Date de publication du RFC : Octobre 2013
Auteur(s) du RFC : J. Merkle (secunet Security Networks), M. Lochter (BSI)
Pour information
Première rédaction de cet article le 3 octobre 2013
Dernière mise à jour le 21 mai 2014


Rien d'extraordinaire dans ce très court RFC : juste l'enregistrement de trois nouvelles courbes elliptiques, collectivement nommées Brainpool, pour utilisation dans TLS.

Ces courbes Brainpool avaient été normalisées originellement dans le RFC 5639 (et leur description était dans « ECC Brainpool Standard Curves and Curve Generation - v. 1.0 »). Le protocole TLS permet d'utiliser des courbes elliptiques depuis le RFC 4492. Ces trois courbes Brainpool avaient déjà des OID mais TLS nécessitait en plus l'enregistrement de noms, ce qui est désormais fait.

Les trois courbes sont ainsi nommées, avec la syntaxe de TLS :

enum {
             brainpoolP256r1(26),
             brainpoolP384r1(27),
             brainpoolP512r1(28)
        } NamedCurve;

Et elles figurent désormais dans le registre IANA.

Au fait, pourquoi de nouvelles courbes elliptiques alors qu'il y en a déjà plein, dont certaines normalisées par le NIST ? C'est parce qu'il existe de sérieux soupçons que les courbes NIST aient été délibérement affaiblies sur ordre de la NSA (voir l'exposé « Crypto Won't Save You Either », p. 73).

Pour ceux qui lisent la langue de Konrad Zuse, il existe un site Web sur Brainpool en allemand.


Téléchargez le RFC 7027


L'article seul

Le principe de robustesse, une bonne ou une mauvaise idée ?

Première rédaction de cet article le 1 octobre 2013


On attribue souvent le succès de l'Internet, et notamment sa résilience, au principe de robustesse. Ce principe, attribué à Jon Postel, s'énonce « Be conservative in what you do, be liberal in what you accept from others. ». Que veut-il dire ? Était-ce un bon principe d'ingéniérie à l'époque ? Et l'est-il toujours aujourd'hui ?

On trouve ce principe formellement énoncé dans plusieurs RFC, parfois avec une formulation légèrement différente. Ainsi, le RFC 793 utilise le texte ci-dessus alors que le RFC 791 (également écrit par Postel) dit « In general, an implementation must be conservative in its sending behavior, and liberal in its receiving behavior. ». En se rappelant que liberal en anglais veut bien dire ce qu'il veut dire (contrairement au français où il désigne en général un partisan de laisser les forts écraser les faibles), ce principe veut dire qu'un programme qui met en œuvre un protocole réseau devrait être dur avec lui-même mais indulgent avec les autres. Par exemple, si la norme dit « un nombre entier est envoyé sous forme texte et peut comprendre des zéros au début si le nombre est inférieur à 1 000 », le programme qui suit Jon Postel ne va jamais envoyer ces zéros initiaux (afin d'être sympa avec des programmes qui n'ont pas fait attention à ce détail de la norme) mais, lorsqu'il reçoit des entiers, il acceptera des zéros initiaux. S'il est très « postelien », il les acceptera même si le nombre est supérieur à 1 000. Le « postelisme » est donc le contraire du pédantisme : le but est l'interopérabilité, que les programmes arrivent à se parler et à travailler ensemble. C'est plus important que de respecter rigoureusement la norme. (Merci à Anahi pour l'exemple, qui vient du proverbe espagnol, « como un cero a la izquierda », qui veut dire « inutile comme un zéro à gauche ».)

On comprend mieux le principe de robustesse de Postel lorsqu'on compare avec le projet qui était le principal concurrent des protocoles TCP/IP, le projet OSI de l'ISO. La culture dominante du monde OSI était au contraire d'extrême pédantisme et les programmeurs prenaient un malin plaisir à refuser les messages des autres programmes, en arguant du fait qu'ils n'étaient pas parfaitement conformes à la norme. Résultat, l'interopérabilité était très faible. C'est ainsi que, au début des années 90, un stagiaire et moi avons pu constater que deux mises en œuvre de FTAM (le concurrent OSI de FTP) développées par le même constructeur (Digital), ne pouvaient pas échanger un fichier... Et cela n'avait l'air de gêner personne dans le monde OSI.

Donc, oui, le choix de Postel s'expliquait et a en effet contribué au succès de l'Internet, OSI n'étant plus qu'un énorme gaspillage bien oublié.

Mais l'histoire ne s'arrête pas là. Car le principe de robustesse, comme n'importe quel bon principe, peut aussi, si on le pousse jusqu'au bout, donner des résultats ridicules. Car de savoir que les récepteurs seront indulgents peut pousser les envoyeurs à ne pas faire attention et à envoyer n'importe quoi, se disant que le récepteur se débrouillera. Le code du récepteur suit le principe de robustesse ? On va envoyer des entiers avec des zéros initiaux, puis on va envoyer des flottants, puis des chiffres suivis par des lettres en comptant que l'analyseur du récepteur s'arrêtera proprement. Et, rapidement, les programmes bien élevés et qui veulent interopérer seront de facto obligés de gérer ces horreurs, sous peine de ne pas pouvoir interopérer. Un exemple historique parfait est celui du langage HTML. Les premiers navigateurs acceptaient n'importe quoi, donc les webmestres ont pris l'habitude d'écrire du HTML sans faire attention à la syntaxe et, aujourd'hui, la plupart des pages Web sont incorrectes syntaxiquement (malgré d'excellents services comme le validateur du W3C) et les navigateurs sont obligés d'accepter cela : un navigateur qui rejetterait les pages mal formées ne pourrait regarder qu'une petite partie du Web. Et aucune autorité (et certainement pas le W3C, dans ce cas, où l'IETF pour les protocoles réseau) ne peut décider autrement, elles n'ont ni le pouvoir, ni l'envie. Résultat, le code est inutilement compliqué et fragile. Et HTML n'est certainement pas le seul exemple.

Le principe de robustesse est particulièrement délicat à appliquer lorsqu'il s'agit de sécurité. Une façon de résumer le principe de robustesse est de dire « ne soyez pas un fasciste psycho-rigide, essayez de comprendre votre interlocuteur au lieu d'insister qu'il a tort ». Bref, il pousse à deviner ce que voulait dire le programme d'en face. En sécurité, c'est souvent une mauvaise idée car on peut deviner mal et ouvrir ainsi une faille de sécurité. Ainsi, le protocole DNSSEC vise à permettre d'authentifier, par des signatures cryptographiques, les enregistrements DNS envoyés. Pour éviter les attaques par rejeu, les signatures DNSSEC ont une durée de vie maximale. Bien des administrateurs DNS ont signé leurs zones sans prêter suffisamment attention à la nécessité de re-signer les enregistrements avant l'expiration. Résultat, les résolveurs DNS validants n'acceptaient plus ces enregistrements. Vu l'ampleur de ce problème, le résolveur DNS validant Unbound, par défaut, accepte des enregistrements expirés (jusqu'à 10 % de leur durée de vie totale, c'est réglable avec les paramètres val-sig-skew-min et val-sig-skew-max). C'est sympa. Mais on voit le paradoxe : un logiciel de sécurité qui décide d'accepter des enregistrements mal signés, pour ne pas être trop méchant... Si Unbound était le résolveur le plus utilisé, on verrait sans doute les administrateurs DNS ne pas trop s'inquiéter de l'expiration des signatures, disant « oui, c'est expiré mais ça va marcher encore quelque temps, grâce au principe de robustesse ».

On lit parfois que ce principe de robustesse n'avait de sens qu'autrefois, dans un Internet mythifié où de joyeux hackers hippies échangeaient des paquets librement et sans se soucier du lendemain. Mais je ne pense pas que cela soit la raison pour laquelle ce principe marchait à l'époque, et marche moins bien aujourd'hui. C'est plutôt que le principe était bon mais que les principes ne doivent pas être appliqués aveuglément, comme des règles religieuses. Ils sont un guide pour l'ingénieur, pas un moyen d'éviter de penser. C'est pour avoir oublié cela que tant de logiciels aujourd'hui doivent se battre avec des pairs mal écrits et qui les bombardent de messages bizarres.

Un débat au sujet de cet article a lieu sur SeenThis.


L'article seul

RFC 6988: Requirements for Energy Management

Date de publication du RFC : Septembre 2013
Auteur(s) du RFC : J. Quittek, M. Chandramouli (Cisco Systems), R. Winter (NEC Europe), T. Dietz (NEC Europe), B. Claise (Cisco Systems)
Pour information
Réalisé dans le cadre du groupe de travail IETF eman
Première rédaction de cet article le 1 octobre 2013


L'augmentation considérable des coûts de l'énergie, et la montée plus que justifiée des préoccupations écologiques, fait que la question de la consommation énergétique des équipements informatiques devient de plus en plus cruciale (certaines études estiment que la consommation d'énergie de l'Internet dépasse celle d'un pays comme la Russie). Les gros centres de données du nuage, usines à consommer du mégawatt, sont particulièrement visés. Cela a amené l'IETF à se lancer dans un domaine nouveau pour elle, et à créer un groupe de travail consacré à la gestion de l'énergie, EMAN, dont voici le premier vrai RFC, le cahier des charges du problème.

Le modèle envisagé est celui d'engins qui consomment ou fournissent de l'énergie, typiquement sous forme électrique, et qu'on veut pouvoir à la fois surveiller (monitoring function) et piloter (control function). Ces engins ont parfois une adresse IP, permettant de leur parler directement, et parfois pas, et il faut alors passer par un relais, qui va être la face visible de l'engin. Ce premier RFC du groupe EMAN définit les services indispensables dans les futures normes de gestion de l'énergie, suivant le modèle décrit dans le RFC 7326 (attention, ce RFC est un cahier des charges pour les normes, les futurs RFC d'EMAN, pas forcément pour les mises en œuvres qui suivront).

La gestion d'engins connectés au réseau n'est évidemment pas un problème nouveau et il existe déjà solutions et normes. Mais la gestion de l'énergie a trois particularités :

  • L'information intéressante n'est pas forcément obtenable auprès de l'engin géré. Ainsi, une machine peut être incapable d'indiquer sa consommation électrique, alors qu'on peut l'obtenir en interrogeant le dispositif qui l'alimente en électricité (par exemple un commutateur PoE) Ce genre de demandes indirectes sera fréquent dans le cadre de la gestion de l'énergie.
  • Même chose pour le contrôle (allumer ou éteindre l'engin), qui doit parfois se faire indirectement.
  • Et rappelez-vous qu'il sera fréquent que les engins connectés ne soient pas directement accessibles en IP et qu'il faille passer par un relais, ce qui est un cas bien plus rare en gestion de réseaux traditionnelle.

Avant d'aborder le cahier des charges proprement dit, la section 2 de notre RFC expose la terminologie, car tous les participants à l'IETF, bien versés dans le vocabulaire TCP/IP, ne connaissent pas forcément celui du monde de l'énergie (l'IEEE a un « Authoritative Dictionary of IEEE Standards Terms » d'où le RFC extrait plusieurs termes, mais je ne trouve pas ce dictionnaire en ligne). Donc, révisons un peu physique et ingéniérie :

  • Énergie (Energy) : dans le cadre de l'informatique et des réseaux, c'est typiquement de l'énergie électrique, mesurée en kWh (ne surtout pas écrire kW/h comme on le voit trop souvent).
  • Puissance (Power) : le taux d'usage, de production ou de transmission de l'énergie. En kW, parfois en joules par seconde.
  • Attributs (Power attributes) : les caractéristiques du courant électrique comme la tension, la phase ou la fréquence. Voir le « International Electrotechnical Vocabulary » de l'IEC.
  • Gestion de l'énergie (Energy management) : les fonctions qui permettent de mesurer, modéliser, planifier, optimiser, etc l'énergie.
  • Système de gestion de l'énergie (Energy management system) : le matériel et le logiciel qui assurent les fonctions ci-dessus.
  • Supervision de l'énergie (Energy monitoring) : le sous-ensemble de la gestion de l'énergie qui s'occupe de mesurer passivement.
  • Contrôle de l'énergie (Energy Control) : le sous-ensemble de la gestion de l'énergie qui s'occupe d'agir activement, par exemple en éteignant des machines inutiles.

La section 3 complète cette section 2 de terminologie en exposant quelques problématiques générales, qu'il faut avoir en tête lorsqu'on veut gérer l'énergie. D'abord, la notion d'état (Power state) : un engin peut être en état normal (il fonctionne, il répond et il consomme du courant), endormi (il consomme moins de courant, il ne répond pas aux requêtes normales mais il peut revenir en état normal rapidement) ou éteint (il ne consomme plus rien mais peut prendre un certain temps à se rallumer et à redevenir opérationnel). Les engins les plus simples n'ont que deux états, allumé et éteint. Les plus perfectionnés en ont plus que trois : par exemple, ils peuvent avoir des modes de basse consommation où l'engin reste complètement opérationnel mais avec des performances réduites. Sur des engins composés de plusieurs parties relativement indépendantes, il est parfois possible de couper le courant dans une partie de ces sous-ensembles et pas seulement dans l'engin entier.

Le but ultime de la gestion de l'énergie est d'économiser du courant. Comme rien n'est parfait en ce bas monde, cela se fera souvent au prix d'un service moins bon. Il sera donc en général nécessaire de faire des compromis.

La gestion de l'énergie peut être entièrement locale (à l'intérieur de l'engin lui-même) ou bien globale au réseau. Un exemple de gestion locale est une machine qui se met en sommeil automatiquement lorsqu'elle n'a pas eu d'activité depuis N minutes. Cela peut se faire sans réseau, sans collecter l'information et sans système central. Un exemple de gestion globale est un système qui voit que la consommation électrique du réseau devient trop importante (en coût ou, tout simplement, par rapport aux capacités du fournisseur d'énergie) et qui éteint alors autoritairement certains engins. Le système de gestion ayant plus d'informations que les machines locales, il peut prendre des décisions plus appropriées, et tenir compte de politiques globales (on éteint les machines dans le bureau la nuit). Les deux méthodes ont leurs avantages et leurs inconvénients et, en général, on combine les deux.

À noter (section 3.4) que la supervision de la consommation d'énergie, à elle seule, ne diminue pas la consommation. Elle va même l'augmenter, puisque le système de supervision consomme lui-même du courant. Pour que ce système mène à une diminution de la consommation, il faut aussi qu'il soit utilisé pour chercher les économies possibles, évaluer les mesures de réduction de consommation, assurer la comptabilité de chaque entité, etc.

Pour assurer une bonne supervision, avec une granularité permettant cette comptabilité, il va falloir des identificateurs pour désigner les différentes entités (section 4). Une entité peut être une machine ou bien seulement une partie d'une machine (un disque dur, par exemple, ou bien une line card). En effet, certaines mesures d'économie d'énergie peuvent être à ce niveau de détail (éteindre une seule line card). Il existe déjà de tels identificateurs, par exemple dans les MIB des RFC 4133 et RFC 3621. Il faudra donc lier les informations de gestion de l'énergie à ces identificateurs, traitant des problèmes comme la persistence en cas de redémarrage.

Ensuite, il faut connaître, pour chaque entité supervisée et/ou contrôlée, un certain nombre d'informations (section 5). Par exemple, il est préférable de connaître l'importance d'une entité, pour éviter d'éteindre une machine importante alors qu'on voulait économiser quelques watts. Une autre propriété utile est l'ensemble des caractéristiques statiques de son alimentation électrique : utilise-t-elle du courant continu ou alternatif, quelle est la tension normale, la fréquence normale (par exemple, 230 V à 50 Hz), etc. Il faut aussi connaître la liste des interfaces utilisées pour l'énergie, et s'il s'agit de production (power outlet, par où on envoie de l'énergie) ou de consommation (power inlet, par où on reçoit de l'énergie).

Et il y a des caractéristiques dynamiques :

  • Est-ce que le courant est disponible sur la prise ? Est-il utilisé ? Si oui, quelle est la puissance consommée ou produite en ce moment ? Attention, ce dernier point peut nécessiter des équipement de mesure coûteux. Certaines machines ne vont pas être capables de mesurer précisement leur propre consommation.
  • Et la consommation ou production d'énergie (rappel : l'énergie est la puissance multipliée par le temps) ? Que vaut-elle sur un intervalle de temps donné ?
  • Pour faciliter les alarmes, le RFC suggère aussi que la machine soit capable de signaler que la puissance tombe en dessous d'une certaine valeur, ou grimpe au-dessus d'un maximum.
  • Quelles sont la tension et l'intensité actuelles ?
  • Quel est l'état de la machine supervisée, allumée, éteinte, en basse consommation, en veille ? Et quels sont les états possibles (ils ne sont pas les mêmes pour toutes les machines) ? Là encore, pour les alarmes, un mécanisme de notification non sollicitée, permettant d'être informé des changements d'état, est demandé.
  • Il y a bien d'autres choses à superviser comme l'état des batteries (en train de se charger ? de se décharger ?), leur charge (pleine ? vide ? à moitié vide ?), mesurée en mAh avec évidemment des alarmes en dessous d'un certain seuil ou comme leur température.

Après la supervision, le contrôle (section 6). Contrairement à la supervision, il est actif. Il s'agit d'agir. Agir sur quoi ?

  • Couper ou allumer le courant (le RFC avertit que certains engins peuvent ne pas aimer une coupure brutale et que cette fonction doit donc se faire dans le cadre d'un système de gestion plus général, qui ne prend pas en compte que la consommation d'énergie).
  • Faire passer l'engin d'un état (basse consommation, veille, hibernation, etc) à un autre.

Une section 9 détaillée couvre les problèmes de sécurité. On a beaucoup parlé des risques de sécurité des SCADA, souvent connectés à l'Internet sans réflechir. Ces systèmes de contrôle, souvent anciens et n'ayant pas fait l'objet d'une analyse de sécurité sérieuse, sont parfois reliés à ce réseau mondial sans précautions. Contrôler l'état des machines et leur fourniture d'électricité est clairement une fonction très sensible. La sécurité doit donc être soigneusement pesée. Tout doit être authentifié et autorisé. Et les engins qui mettent en œuvre les services décrits dans ce RFC ne devraient pas être connectés à l'Internet public sans une très bonne raison (section 9.2).

Il n'y a pas que le contrôle qui pose des problèmes de sécurité. Par exemple, la supervision soulève des problèmes de vie privée, comme cela a été plusieurs fois évoqué dans le débat sur les compteurs intelligents.

Depuis ce cahier des charges, plusieurs RFC sur le sujet ont été publiés comme les RFC 7326 et le RFC 7603.


Téléchargez le RFC 6988


L'article seul

On ne « tombe » pas dans le domaine public

Première rédaction de cet article le 30 septembre 2013


Le passage des œuvres de Guillaume Apollinaire dans le domaine public (94 ans après sa mort, ce qui donne une idée du niveau de délire atteint par le droit soi-disant d'auteur) est l'occasion de revenir sur un point de vocabulaire important : contrairement à ce qu'on écrit souvent, ses œuvres ne sont pas tombées dans le domaine public, elles y sont montées.

La nuance est d'importance car le terme le plus courant, « tombé dans le domaine public », est idéologiquement très chargé. Il vient des défenseurs de l'appropriation intellectuelle et sous-entend que le domaine public est une chute en dehors du monde (forcément plus élevé) du contrôle par les ayant-trop-de-droits.

Voilà pourquoi je reprends les gens qui utilisent ce terme erroné et que je dis que les œuvres d'Apollinaire sont montées dans le domaine public. Pour citer dwarfpower, « l'œuvre sort du patrimoine personnel pour entrer dans le patrimoine humain ».

D'autres termes seraient possibles. J'ai lu des suggestions de dire :

  • « élevé dans le domaine public » ce qui serait un meilleur contraire à « tombé » (« monté » serait plutôt le contraire de « descendu »). Pourquoi pas ?
  • « entré dans le domaine public », terme qui semble à ses défenseurs plus neutre, entre les extrêmes que sont « tombé dans le domaine public » et « monté dans le domaine public ». Mais je ne vois pas pourquoi il faudrait être neutre : je pense moi aussi qu'appartenir à tous est moralement et politiquement supérieur à n'appartenir qu'aux héritiers.
  • « libéré ». Là, par contre, cela me semble une erreur : un auteur peut parfaitement décider de publier sous une licence libre (c'est le cas de ce blog), son œuvre ne sera pas pour autant dans le domaine public (le droit moral s'y opposant).

Bref, je préfère « monté ».


L'article seul

Le service d'hébergement de machines virtuelles de Numergy

Première rédaction de cet article le 30 septembre 2013


Profitant d'une offre d'essai gratuite (qui semble toujours d'actualité), j'ai testé le service de machines virtuelles (IaaS) de Numergy.

Ce service est un des survivants du défunt projet Andromède, qui visait à faire un « cloud français », en oubliant au passage que des fournisseurs de solution infonuagiques existaient déjà depuis des années en France. Andromède s'est cassé la figure et le relais a été pris par deux projets, Numergy et Cloudwatt. À ma connaissance, Cloudwatt n'a toujours pas d'offre opérationnelle mais Numergy en a une.

Pour l'utilisateur ordinaire, rien de nouveau : on se crée un compte sur une interface Web (qui accepte mon adresse, ce qui est rare), on demande la création d'une VM et quelque temps après (c'est assez long), on se connecte et on est root.

Curieusement, on n'a pas d'adresse IPv4 publique, mais une adresse du RFC 1918 :

% ifconfig 
eth0      Link encap:Ethernet  HWaddr 00:50:56:95:42:e1  
          inet addr:10.200.0.73  Bcast:10.200.15.255  Mask:255.255.240.0
          inet6 addr: fe80::250:56ff:fe95:42e1/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:4846090 errors:0 dropped:409062 overruns:0 frame:0
          TX packets:161835 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:441749938 (441.7 MB)  TX bytes:46077749 (46.0 MB)

Ce n'est pas pour économiser des adresses IPv4 puisque chaque client peut rediriger à sa guise les ports d'une adresse publique vers son serveur. Numergy dit que cette architecture inhabituelle obéit à des raisons de sécurité. Peut-être aussi cette indirection (de l'adresse publique vers l'adresse privée) leur permet-elle davantage de souplesse dans la gestion du réseau. En tout cas, cela a été l'occasion de vérifier que le support répondait, et assez vite. Et par courrier électronique, pas besoin de passer par une exaspérante interface Web qui essaie de vous retarder le plus possible en posant plein de questions.

Comme vous pouvez le voir ci-dessus, Numergy ne fournit pas d'IPv6. C'est incroyable en 2013, et cela met Numergy très loin derrière les fournisseurs qui font du cloud en France depuis des années, qui ont tous IPv6 depuis longtemps.

On est routé par le réseau de SFR, comme le montre un traceroute :

...
 5  neuf-telecom.sfinx.tm.fr (194.68.129.178)  7.352 ms  7.458 ms  7.518 ms
 6  250.29.3.109.rev.sfr.net (109.3.29.250)  9.926 ms  9.230 ms  9.207 ms
 7  30.12.6.109.rev.sfr.net (109.6.12.30)  10.825 ms  9.792 ms  9.827 ms
 8  145.29.3.109.rev.sfr.net (109.3.29.145)  8.127 ms  8.015 ms  8.025 ms
 9  202.49.6.109.rev.sfr.net (109.6.49.202)  8.202 ms  8.050 ms  8.004 ms
10  cld2001rt.trp.sfr-sh.net (212.23.184.68)  17.466 ms  17.357 ms  17.537 ms
11  * * *
12  * * *

Le tout est fiable : supervisé par Icinga, ma machine n'a eu que trois heures de défaillance en deux mois (et le problème peut être du côté de mon système de supervision, je n'ai pas creusé plus loin).

Via l'interface Web, on peut configurer la redirection de ports entrants, les règles de filtrage (dans Administration -> Flux), etc. Il existe aussi une API REST mais que je n'ai pas testée (pour l'instant, c'est celle d'OpenStack). Globalement, rien de nouveau ou d'extraordinaire dans ce service. Juste un autre hébergeur de VPS.


L'article seul

RFC 7033: WebFinger

Date de publication du RFC : Septembre 2013
Auteur(s) du RFC : Paul E. Jones, Gonzalo Salgueiro (Cisco Systems), Michael B. Jones (Microsoft), Joseph Smarr (Google)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF appsawg
Première rédaction de cet article le 28 septembre 2013
Dernière mise à jour le 2 mai 2017


Ce RFC décrit (même si elle n'est pas présentée ainsi) la deuxième version du protocole WebFinger. La première était informelle et permettait de récupérer de l'information sur une personne ou une organisation à partir de son adresse de courrier. La deuxième version, la première officiellement normalisée, généralise WebFinger : la clé d'entrée dans l'information est un URI, qui peut être une adresse de courrier (mailto:, RFC 6068) mais pas forcément.

WebFinger doit son nom à l'antique protocole Finger, normalisé dans le RFC 1288. Finger permettait de récupérer de l'information sur une personne, identifiée par login@nom-de-machine en se connectant sur le port 79 de la dite machine. On obtenait une réponse non structurée (du texte libre). Au contraire, WebFinger tourne sur le port 80, celui de HTTP, utilise REST, et envoie une réponse structurée, en JSON, qui est donc analysable par un programme. On nomme cette réponse le JRD, JSON Resource Descriptor.

Que contient ce JRD ? Ce qu'on veut. Pas grand'chose si on est soucieux de vie privée et, sinon, une adresse, un numéro de téléphone, une photo, etc. WebFinger peut être utilisé pour des entités non humaines (une imprimante, une machine à café, etc), pour obtenir de l'information sur leurs capacités. Par contre, WebFinger est prévu pour de l'information relativement statique, et pas pour se renseigner sur l'état actuel. Pour une imprimante, il peut servir à apprendre qu'elle sait faire de la couleur, ou seulement du noir & blanc, mais pas à connaître la quantité de feuilles de papier restant dans le bac.

(Pour des raisons historiques, certaines mises en œuvre de WebFinger distribuent un XRD, la même chose mais en XML. D'une manière générale, attention à ce que vous trouvez avec un moteur de recherche, lorsque vous demandez « webfinger » : ce seront souvent des informations complètement dépassées.)

Et quel genre d'URI peut-on utiliser en argument ? Ce qu'on veut mais, en pratique, l'usage le plus courant aujourd'hui est avec les URI acct: (normalisés dans le RFC 7565).

WebFinger reste délibérement ouvert : le RFC spécifie un protocole et un format mais pas une sémantique. Ainsi, le JRD peut avoir un contenu très varié selon les applications. L'idée est que chaque application de WebFinger spécialisera ce protocole et ce format, en indiquant plus précisément le type d'URI attendu et les informations contenues dans le JRD de réponse. À noter que ce point avait fait l'objet de vives controverses à l'IETF, à la fin du processus de normalisation. Tel que spécifié, WebFinger semblait à certains terriblement vague, un framework plutôt qu'un protocole. Selon les mots de Pete Resnick lors de la discussion entre l'IESG et les auteurs, « I suspect that the semantics are so underspecified that there could not possibly be interoperable implementations without lots of out-of-band information ». C'est pour cela que le RFC intègre aujourd'hui ces précisions : la sémantique sera dans d'autres spécifications (la section 8 du RFC détaille ce choix et ses conséquences).

La section 3 donne deux exemples d'utilisation, le premier dans le cas d'OpenID Connect et le second pour récupérer des métadonnées sur une page Web. Dans le premier cas, Carol veut s'authentifier auprès d'un site Web et donne son identificateur OpenID Connect, carol@example.com. Le site qui authentifie va utiliser WebFinger (avec l'URI acct:carol@example.com, avec le plan acct:) pour trouver le fournisseur OpenID de Carol. Dans le second cas, le client WebFinger va interroger le site qui héberge la page Web et demander en utilisant comme URI celui de la page Web.

À noter que les versions préliminaires de ce RFC avaient également plein d'exemples très hypothétiques, jamais utilisés en vrai, et qui ont été ensuite supprimés. On y trouvait par exemple un mécanisme possible pour l'autoconfiguration du client de courrier électronique, qui n'apportait rien par rapport au RFC 6186.

Avant de se plonger dans le protocole lui-même, la section 2 rappelle quelques points de vocabulaire. WebFinger étant, comme son nom l'indique, fondé sur le Web, il fait un grand usage des liens, tels que décrits dans le RFC 8288, pour indiquer une relation. La relation a un type et une information liée. En HTTP, le RFC 8288 utilise ainsi les attributs rel (type de la relation) et href (information liée) dans un en-tête Link:. WebFinger représente le même concept en JSON avec des objets JSON links (un tableau JSON), chacun comportant un membre rel et un membre href. Un exemple, pour une entité qui est un article publié sur le Web (le deuxième cas d'exemple cité plus haut, la recherche de métadonnées), les liens seraient :

"links" : [
    {
         "rel" : "copyright",
         "href" : "http://www.example.com/copyright"
    },
    {
         "rel" : "author",
         "href" : "http://blog.example.com/author/steve",
    }
]

Cet exemple se lit : l'entité interrogée via WebFinger a un copyright (qu'on peut trouver en http://www.example.com/copyright) et un auteur, décrit en http://blog.example.com/author/steve.

La section 4 décrit le protocole complet. C'est du REST, donc au-dessus de HTTP. Le client WebFinger doit spécifier l'URI de l'entité sur laquelle il veut des informations et il peut aussi spécifier un ou plusieurs types de relations qui l'intéressent (par défaut, il va tout recevoir). À noter que WebFinger impose l'usage de HTTPS, ce protocole étant souvent utilisé pour transporter des données sensibles (section 9.1, et c'était un des points de discussion les plus chauds à l'IETF). La requête WebFinger va utiliser un chemin qui utilise le préfixe .well-known du RFC 8615 et le suffixe webfinger (désormais enregistré dans les noms bien connus). Si l'URI de l'entité qui nous intéresse contient un nom de machine, c'est cette machine que contacte le client WebFinger (sinon, il doit se débrouiller, d'une manière non précisée). La méthode HTTP utilisée est toujours GET (section 9.3 du RFC 2616). Prenons un exemple, celui de l'article http://blog.example.com/article/id/314 sur lequel on voudrait plus d'informations. Le client WebFinger va se connecter à blog.example.com en HTTPS et envoyer la requête HTTP :

GET /.well-known/webfinger?resource=http%3A%2F%2Fblog.example.com%2Farticle%2Fid%2F314 HTTP/1.1
Host: blog.example.com

Le composant de requête (section 3.4 du RFC 3986) resource est l'URI (ici pour-cent encodé) de l'entité qui nous intéresse.

Si le serveur WebFinger connait l'entité en question, et accepte de répondre, il répond par le JRD (les données en JSON, étiquetées application/jrd+json, et décrites plus loin, en section 4.4 du RFC). Dans tous les autres cas, il répond par les codes HTTP traditionnels (400 « tu as oublié un truc, peut-être la resource », 403 « pas question que je te réponde à toi », 404 « je ne connais pas cette entité », 500 « j'ai un problème », 429 « trop de travail, je craque », etc).

Et si le client a inclus un ou plusieurs rel dans sa requête, indiquant qu'il n'est pas intéressé par tous les types de données mais seulement par certains ? Cela n'influe que sur le membre links du JRD, qui n'incluera alors que ce qui est demandé. Reprenons l'exemple de notre page Web et ne cherchons que l'auteur :

GET /.well-known/webfinger?resource=http%3A%2F%2Fblog.example.com%2Farticle%2Fid%2F314&rel=author HTTP/1.1
Host: blog.example.com
...
"links" : [
    {
         "rel" : "author",
         "href" : "http://blog.example.com/author/steve",
    }
]

Quel est l'intérêt (après tout, le client pourrait ainsi bien filtrer les types de liens après les avoir tous récupérés) ? Économiser des ressources sur le serveur (certaines informations peuvent nécessiter des requêtes compliquées dans une base de données) et diminuer le débit réseau. Notez toutefois, si vous écrivez un client, que tous les serveurs ne gèrent pas ce paramètre rel dans la requête et que le client risque donc toujours de tout récupérer, et de devoir trier ensuite.

Le format complet du JRD (JSON Resource Descriptor, annexe A du RFC 6415 et dérivé du XRD) figure en section 4.4. C'est un objet JSON (RFC 8259) comprenant les membres subject, aliases, properties et links que nous avons déjà vu. subject, le seul obligatoire, est un identificateur de l'entité sur laquelle on se renseigne (en général le même que le paramètre resource), properties sont les informations sur l'entité (un registre IANA les stocke, en échange d'une spécification écrite, cf. section 10.4.2) et links les liens. links est le plus complexe. Chaque lien est un objet JSON comportant plusieurs membres. rel est le seul obligatoire et sa valeur est, soit un type enregistré à l'IANA selon le RFC 8288, soit un URI (on peut ainsi « créer » ses propres types). Les autres membres possibles sont type (un type MIME), href (pointe vers la valeur du lien), titles (un texte humainement lisible, par exemple pour le présenter à l'utilisateur, marqué par une étiquette de langue) et properties (informations diverses). Voici un exemple complet, tiré du RFC, toujours au sujet de notre page Web intéressante :

{
       "subject" : "http://blog.example.com/article/id/314",
       "aliases" :
       [
         "http://blog.example.com/cool_new_thing",
         "http://blog.example.com/steve/article/7"
       ],
       "properties" :
       {
         "http://blgx.example.net/ns/version" : "1.3",
         "http://blgx.example.net/ns/ext" : null
       },
       "links" :
       [
         {
           "rel" : "copyright",
           "href" : "http://www.example.com/copyright"
         },
         {
           "rel" : "author",
           "href" : "http://blog.example.com/author/steve",
           "titles" :
           {
             "en" : "The Magical World of Steve",
             "fr" : "Le Monde Magique de Steve"
           },
           "properties" :
           {
             "http://example.com/role" : "editor"
           }
         }
      ]
}

La section 7 du RFC couvre un cas délicat, celui de services WebFinger hébergés. Si on souhaite sous-traiter WebFinger à un tiers, comment l'indique-t-on ? La seule solution est de faire une redirection HTTP depuis son site. Par exemple, avec Apache, on mettra dans la configuration :

Redirect /.well-known/webfinger http://wf.example.net/.well-known/webfinger

Et les requêtes WebFinger qu'on recevra seront gérées par le prestataire wf.example.net par le biais d'une redirection HTTP.

La section 8 décrit ce que veut dire « spécifier l'usage de WebFinger pour une application ». On a vu que WebFinger fournissait un protocole et un format très général. Chaque application qui compte se servir de WebFinger doit préciser un certain nombre de choses, notamment le contenu du JRD attendu. Si vous voulez vous servir de WebFinger pour un nouveau service très cool, vous allez devoir lire cette section et rédiger les détails. Première chose, le type d'URI attendu (acct: ? un autre ?) Deuxième chose, comment trouver le serveur à interroger. Si l'URI utilise le plan http:, c'est trivial. Mais pour les acct: ou les mailto: ? L'application doit donc préciser comment on trouve le serveur WebFinger (cela peut être aussi simple que d'avoir un serveur WebFinger central, codé en dur dans les programmes, pour tous les URI de l'application...)

Enfin, l'application doit spécifier le contenu attendu : quelles properties sont obligatoires dans la réponse, par exemple ? Même chose pour les liens : quels types rel peuvent/doivent être utilisés dans les liens ?

Ce n'est pas un peu indiscret, toutes ces informations distribuées à tout vent ? Si, et ce point a fait l'objet de vives discussions à l'IETF, ce qui a fini par donner naissance aux sections 6 et 9.2 de ce RFC. Le principal avantage de WebFinger (un seul endroit où aller pour récupérer toutes les informations sur une entité, et sous une forme structurée, ce qui est très pratique pour les programmes qui vont l'analyser) est aussi son principal risque (comme dit le RFC «  The easy access to user information via WebFinger was a design goal of the protocol, not a limitation »). Le RFC cite l'exemple de données qui permettraient le harcèlement d'une personne. L'article « Abusing social networks for automated user profiling » illustrait bien comment le recoupement d'informations provenant de différents réseaux sociaux permettait de découvrir plein de choses sur les utilisateurs.

Ces sections « vie privée » du RFC rappellent qu'un serveur WebFinger ne distribue que ce qu'il veut. En cas de demande d'information sur une personne, par exemple, la norme technique qu'est ce RFC ne spécifie pas qu'on doive distribuer l'adresse et le numéro de téléphone. C'est un choix des administrateurs du serveur. (Au passage, c'est exactement la même chose pour le protocole whois, RFC 3912, un protocole dont les usages sont proches de ceux de WebFinger. Le RFC spécifie un protocole, pas une politique de distribution des données.)

Ensuite, le serveur n'est pas obligé d'être ouvert à tout le monde. Il peut parfaitement utiliser l'authentification HTTP (ou d'autres mécanismes de contrôle d'accès comme l'adresse IP du client) pour restreindre la distribution d'informations à certains. Un serveur WebFinger est également, cela va de soi, autorisé à fournir des réponses différentes selon le client. Par exemple, on peut imaginer une réponse minimale pour les clients inconnus, et davantage de détails pour ceux qui s'authentifient. Le RFC ne cite pas les questions légales (hors sujet pour une norme technique) mais, par exemple, un serveur WebFinger d'une entreprise qui distribuerait des détails personnels sur ses employés, comme des photos, sans leur autorisation, serait certainement en violation de la directive européenne sur la protection des données personnelles.

La section 9.2 demande donc que, pour tout service WebFinger, il existe une interface permettant aux utilisateurs d'indiquer de manière simple s'ils veulent que des informations à leur sujet soient publiées ou pas, et lesquelles. Par exemple, pour un réseau social typique, on peut imaginer que les utilisateurs choisissent quels éléments d'information sur eux soient publics et, dans ce cas, que seuls les éléments ainsi marqués soient distribués par WebFinger. Le RFC demande aussi que, par défaut, rien ne soit publié (ce qui n'est certainement pas la pratique des gros silos de données comme Facebook).

Les liens fournis en réponse à une requête WebFinger peuvent d'ailleurs eux aussi pointer vers des ressources dont l'accès est contrôlé ou limité. Bref, ce n'est pas de la faute de WebFinger si des informations sensibles circulent, il n'est qu'un outil, à utiliser intelligemment.

Autre problème de sécurité avec WebFinger, le fait que la réponse est différente selon que la ressource existe ou pas (code HTTP 200 dans le premier cas et 404 dans le second). Ainsi, même si la réponse est vide, un client WebFinger peut, par essais répétés, se constituer une liste des ressources existantes. Cela peut permettre d'énumérer les utilisateurs d'un réseau social, ou bien les adresses de courrier valides (information certainement utile pour un spammeur). Le RFC recommande donc que des mesures techniques, comme une limitation du trafic par adresse IP du client, soient déployées.

Autre cas où l'utilisation maladroite de WebFinger peut avoir des conséquences néfastes, les requêtes automatiques. Supposons un MUA qui ferait automatiquement une requête WebFinger sur le champ From: du message lorsque celui-ci est lu. Un spammeur pourrait générer un champ From: différent par destinataire et les requêtes WebFinger entrantes lui diraient quels destinataires ont lu le message... Le RFC recommande donc de ne pas effectuer de requêtes WebFinger automatiquement.

Enfin, le RFC note que rien ne garantit que les valeurs renvoyées par WebFinger soient correctes (là encore, c'est un problème que les utilisateurs de whois connaissent déjà bien). Il y a en effet des choses fausses sur le Web.

Question mises en œuvre, ce n'est pas cela qui manque, y compris en logiciel libre. Il en existe une liste incomplète. Par exemple, GNU Social gère ce protocole.

Voici quelques exemples de requêtes WebFinger réelles, faites avec le client REST curl :

% curl -v 'https://packetizer.com/.well-known/webfinger?resource=acct:paulej@packetizer.com'
HTTP/1.1 200 OK
Server: Apache/2.2.22 (Fedora)
Access-Control-Allow-Origin: *
Content-Type: application/jrd+json; charset=UTF-8
...
{
  "subject" : "acct:paulej@packetizer.com",
  "aliases" :
  [
    "h323:paulej@packetizer.com"
  ],
  "properties" :
  {
    "http://packetizer.com/ns/name" : "Paul E. Jones",
    "http://packetizer.com/ns/name#zh-CN" : "保罗‧琼斯",
    "http://packetizer.com/ns/activated" : "2000-02-17T03:00:00Z"
  },
  "links" :
  [
    {
      "rel" : "test1",
      "href" : "http://example.com/author?q=acct%3Apaulej%40packetizer.com",
      "titles" :
      {
        "en-us" : "Test Link"
      }
    },
    {
      "rel" : "test2",
      "href" : "http://example.org/%E7%A7%81%E3%81%AE%E6%96%87%E6%9B%B8.txt"
    },
    {
      "rel" : "http://webfinger.net/rel/avatar",
      "type" : "image/jpeg",
      "href" : "http://www.packetizer.com/people/paulej/images/paulej.jpg"
    },
    {
      "rel" : "http://specs.openid.net/auth/2.0/provider",
      "href" : "https://openid.packetizer.com/paulej"
    },
    {
      "rel" : "http://packetizer.com/rel/share",
      "type" : "text/html",
      "href" : "http://hive.packetizer.com/users/paulej/"
    },
    {
      "rel" : "http://webfinger.net/rel/profile-page",
      "type" : "text/html",
      "href" : "http://www.packetizer.com/people/paulej/"
    },
    {
      "rel" : "http://packetizer.com/rel/blog",
      "type" : "text/html",
      "href" : "http://www.packetizer.com/people/paulej/blog/",
      "titles" :
      {
        "en-us" : "Paul E. Jones' Blog"
      }
    },
    {
      "rel" : "http://packetizer.com/rel/businesscard",
      "type" : "text/vcard",
      "href" : "http://www.packetizer.com/people/paulej/paulej.vcf"
    },
    {
      "rel" : "http://schemas.google.com/g/2010#updates-from",
      "type" : "application/atom+xml",
      "href" : "http://www.packetizer.com/people/paulej/blog/blog.xml"
    },
    {
      "rel" : "http://microformats.org/profile/hcard",
      "type" : "text/html",
      "href" : "http://www.packetizer.com/people/paulej/"
    },
    {
      "rel" : "http://bitcoin.org/rel/address",
      "href" : "bitcoin:17XoqvUCrf12H7Vc7c7uDxib8FDMXFx2p6"
    }
  ]
}

Autre exemple, pour l'URI acct:javier@seed.gluu.org, avec beaucoup moins d'information distribuée :

% curl -v 'https://seed.gluu.org/.well-known/webfinger?resource=acct:javier@seed.gluu.org'
...
{
    "subject": "acct:javier@seed.gluu.org",
    "links": [{
        "rel": "http://openid.net/specs/connect/1.0/issuer",
        "href": "https://seed.gluu.org"
    }]
}

En théorie, si on était sérieux, on ajouterait à curl l'option --header "Accept: application/jrd+json" pour indiquer au serveur qu'on ne comprend que ce format, le seul actuellement standard pour WebFinger (la syntaxe jrd+json, c'est-à-dire langage + format, est décrite dans le RFC 6839). Mais beaucoup de serveurs n'en tiennent pas compte (certains vous servent du XRD si vous mettez --header "Accept: application/xrd+xml").

WebFinger est également utilisé par Mastodon donc tout serveur Mastodon est également un serveur WebFinger. Essayons avec mon compte Mastodon, bortzmeyer@mastodon.gougere.fr :

% curl 'https://mastodon.gougere.fr/.well-known/webfinger?resource=bortzmeyer@mastodon.gougere.fr'
{"subject":"acct:bortzmeyer@mastodon.gougere.fr","aliases":["https://mastodon.gougere.fr/@bortzmeyer"],"links":[{"rel":"http://webfinger.net/rel/profile-page","type":"text/html","href":"https://mastodon.gougere.fr/@bortzmeyer"},{"rel":"http://schemas.google.com/g/2010#updates-from","type":"application/atom+xml","href":"https://mastodon.gougere.fr/users/bortzmeyer.atom"},{"rel":"salmon","href":"https://mastodon.gougere.fr/api/salmon/369"},{"rel":"magic-public-key","href":"data:application/magic-public-key,RSA._AmUWXDlwOkzKtqUsxUC94_B9yRZct-C8QqrxLWhGzA3zKNZwic0KWKMBuVRuQ7GXOq5lsyhA2pvXBTnh-Sk_8G5uLY6I7C0sjgAQKyiHVCmOBAGwcw67qfxIoN5-l2NrIZ0IygxnMOY_GU1q6fg8v6_1_bepnjCduWRVAdDBoo_HzSn91LYVleAg3E3oK8eXWYb28_DaCq9tJy5hHYLDK92XKTtk7t0Ii9U7znFvSrqgqD-qEc3KQHS5kOFRD1EfK9CI6872og0M_b6FVhNfcITaVjjk3S0uM0mpHiQuqPtfytdkRlEBd4uZUce3dPk0sODQaNcVrAMHf0KFm3w1w==.AQAB"},{"rel":"http://ostatus.org/schema/1.0/subscribe","template":"https://mastodon.gougere.fr/authorize_follow?acct={uri}"}]}  

Enfin, pour terminer cet article, une question que se posent certainement tous mes lecteurs qui connaissent le DNS. Pourquoi diable avoir décidé que le serveur WebFinger était le nom de domaine dans l'URI, ce qui manque de souplesse (si l'URI est acct:twitter.com, cela oblige Twitter à avoir le serveur WebFinger au même endroit que le serveur Web) plutôt que d'avoir une indirection, fournie par les très utiles enregistrements SRV ? Je suis d'accord, cela aurait été la bonne solution et cela aurait résolu bien des problèmes. Hélas, le groupe de travail WebFinger a fait un autre choix, pour les raisons suivantes :

  • Le Web n'utilise malheureusement pas les SRV (HTTP est un des rares protocoles où on n'a pas d'intermédiaire entre le nom de domaine et le nom du serveur, obligeant à mettre des adresses directement dans son nom de domaine).
  • JavaScript dans le navigateur (une des principales utilisations prévues) ne permet pas de faire des requêtes SRV.
  • Beaucoup d'hébergeurs DNS sont tellement mauvais qu'il ne permettent pas l'avitaillement d'enregistrements SRV via l'interface Web fournie au client.

Vous pouvez lire une discussion qui avait eu lieu à l'époque.

Autres lectures sur WebFinger, la synthèse de l'auteur du RFC, et un argumentaire pro-WebFinger de sa part.


Téléchargez le RFC 7033


L'article seul

RFC 1996: A Mechanism for Prompt Notification of Zone Changes (DNS NOTIFY)

Date de publication du RFC : Août 1996
Auteur(s) du RFC : Paul Vixie (Internet Software Consortium)
Chemin des normes
Première rédaction de cet article le 27 septembre 2013


Avant ce RFC, il n'existait pas de mécanisme dans le DNS pour prévenir les serveurs esclaves de la disponibilité de nouvelles données chez le serveur maître. Il fallait attendre que l'esclave contacte le maître (mécanisme de polling). Depuis notre RFC 1996, un serveur maître peut prévenir ses esclaves avec un message NOTIFY, entraînant ainsi une mise à jour plus rapide des zones DNS.

Avant cela, le rythme de mise à jour était contrôlé par le champ Refresh de l'enregistrement SOA. Ce champ indiquait à quel rythme l'esclave devait contacter le maître à la recherche de nouvelles données. En moyenne, donc, le temps de mise à jour de tous les serveurs faisant autorité (maître et esclaves) était de la moitié du Refresh. Par exemple, la zone eu.org a un Refresh de 3 600 secondes :

% dig SOA eu.org
...
;; ANSWER SECTION:
eu.org.			86400 IN SOA ns.eu.org. hostmaster.eu.org. (
				2013092601 ; serial
				3600       ; refresh (1 hour)
				1800       ; retry (30 minutes)
				604800     ; expire (1 week)
				86400      ; minimum (1 day)
				)
...

Ce qui fait que les esclaves testeront le maître à intervalles d'une heure, lui demandant s'il a des nouvelles données depuis le numéro de série 2013092601. Si le maître répond aux requêtes SOA de ces esclaves avec un numéro de série plus récent, l'esclave transférera la zone (RFC 5936). Le problème est qu'on peut attendre longtemps. Dans le pire cas (si l'esclave a testé le maître juste avant que ce dernier ne soit mis à jour), on attendra une heure. La synchronisation entre serveurs faisant autorité (maîtres et esclaves) contribue donc au délai total de réjuvénation.

Le message NOTIY complète ce mécanisme de polling par un mécanisme d'interruption. Le maître envoit ce message à ses esclaves dès la mise à jour, et ceux-ci testent immédiatement.

À noter que le graphe des relations entre serveurs faisant autorité n'est pas forcément composé que d'un maître et d'esclaves transférant depuis le maître. On peut avoir des configurations plus complexes avec des esclaves transférant depuis un autre esclave, plusieurs maîtres, etc (c'est d'ailleurs pour cela que l'ancienne terminologie de serveur primaire et secondaires a été abandonnée).

La section 3 décrit le NOTIFY. Les messages DNS ont un champ nommé Opcode (section 4.1.1 du RFC 1035) dont les valeurs possibles sont dans un registre IANA. Le principal opcode rencontré dans la nature, et de loin, est le 0, QUERY, indiquant une requête DNS normale. NOTIFY est un autre opcode possible, de numéro 4. Lorsqu'un serveur a des données nouvelles, il envoie un message NOTIFY à tous ses esclaves, message auquel les esclaves répondront, pour rassurer le maître sur la bonne réception de ses informations. Autrement, le maître réessaiera (les NOTIFY, comme la plupart des messages DNS, sont transportés sur UDP et peuvent donc se perdre), un certain nombre de fois (le RFC recommande cinq fois). Le message du maître peut aussi contenir les nouvelles données. Dans les exemples ci-dessous, les maîtres envoient le nouveau SOA de la zone. Si le message avec un nouveau SOA est bien reçu par l'esclave, celui-ci se comporte comme si le délai Refresh était écoulé : il interroge le maître sur son numéro de série (les NOTIFY ne sont pas authentifiés et peuvent donc être trompeurs, cf. section 5) et, s'il y a bien eu mise à jour, transfère la zone.

La section 4 du RFC donne quelques exemples, mais j'ai plutôt inclus les miens. Tout d'abord, un serveur maître sur NSD. Sa configuration pour la zone bortzmeyer.42 comprendra la liste des esclaves à notifier (ici, un seul) :

zone:
     	name: "bortzmeyer.42"
	zonefile: "primary/bortzmeyer.42"
	notify: 204.62.14.153 NOKEY

Maintenant, le serveur a de nouvelles données. Au moment où l'administrateur tape nsdc reload, le serveur envoie un NOTIFY que tcpdump montre ainsi :


22:58:53.934862 IP (tos 0x0, ttl 55, id 0, offset 0, flags [DF], proto UDP (17), length 59)
    217.70.190.232.51962 > 204.62.14.153.53: [udp sum ok] 32223 notify [b2&3=0x2400] SOA? bortzmeyer.42. (31)
22:58:53.935055 IP (tos 0x0, ttl 64, id 26939, offset 0, flags [none], proto UDP (17), length 59)
    204.62.14.153.53 > 217.70.190.232.51962: [bad udp cksum 0x733f -> 0x1d3a!] 32223 notify*- q: SOA? bortzmeyer.42. 0/0/0 (31)

Le maître a notifié, l'esclave a répondu positivement.

Avec BIND, il n'est pas nécessaire de lister les serveurs esclaves, il les trouve par défaut dans l'enregistrement NS de la zone (contrairement à NSD, BIND a un résolveur interne). On peut compléter cette liste (ajouter des esclaves) avec la directive also-notify. Voici une notification envoyée par BIND :


23:11:40.781190 IP6 (hlim 55, next-header UDP (17) payload length: 100) 2001:67c:2218:3::1:4.1396 > 2605:4500:2:245b::42.53: [udp sum ok] 46225 notify [b2&3=0x2400] [1a] SOA? langtag.net. langtag.net. [0s] SOA ns4.generic-nic.net. hostmaster.langtag.net. 2013092301 30480 26400 2419200 86400 (92)
23:11:40.781462 IP6 (hlim 64, next-header UDP (17) payload length: 37) 2605:4500:2:245b::42.53 > 2001:67c:2218:3::1:4.1396: [udp sum ok] 46225 notify*- q: SOA? langtag.net. 0/0/0 (29)

On trouve quelques enregistrements de trafic DNS avec NOTIFY sur pcapr : http://www.pcapr.net/browse?q=dns+notify (avec quelques faux positifs, aussi).

Si on veut envoyer à la main un NOTIFY, à des fins de test ou de débogage, NSD a un outil utile, la commande nsd-notify :

% nsd-notify -z bortzmeyer.42 ns3.example.net

Si l'esclave n'est pas configuré pour recevoir des notifications de ce maître, NSD répond avec un refus :

[1379966010] nsd-notify[3346]: warning: bad reply from ns3.example.net \
    for zone bortzmeyer.42., error response REFUSED (5).

Alors que le RFC recommandait plutôt d'ignorer ce message NOTIFY inattendu. La configuration dans NSD pour accepter les notifications se fait avec la directive allow-notify :

allow-notify: 217.70.190.232 NOKEY

(Si vous voulez authentifier les NOTIFY, voyez mon autre article sur TSIG.)


Téléchargez le RFC 1996


L'article seul

SNMP v3 sur Unix, pour Cacti et Icinga

Première rédaction de cet article le 25 septembre 2013


Le protocole SNMP d'accès distant à l'information d'une machine est utilisé depuis bientôt un quart de siècle. Bien que la version actuelle de SNMP, la v3, ait été normalisée il y a quinze ans, il semble que les antiques versions 1 et 2 soient toujours largement utilisées. Voici des exemples de configuration d'un serveur Unix avec SNMP v3, et on interrogation par le logiciel de supervision Icinga et le logiciel de statistiques Cacti.

C'est que SNMP v3 est plus complexe, aussi bien lorsqu'on veut lire les RFC qui le normalisent (RFC 3414, RFC 3415, etc) que lorsqu'on regarde la configuration des logiciels clients et serveurs. Mais il présente un avantage décisif en matière de sécurité. En SNMP v1 (RFC 1157), il n'y avait aucune confidentialité : tout écoutant du réseau pouvait savoir ce qu'on faisait. Et aucune authentification sérieuse non plus : le mot de passe (baptisé « communauté » pour faire croire qu'il n'était pas aussi sensible qu'un mot de passe) circulait en clair et était donc interceptable. SNMP v3, au contraire, fournit un authentification fiable et, si on le veut, de la confidentialité.

Sur un serveur Unix, le logiciel Net-SNMP fournit un serveur capable de parler le v3. Sa configuration est baroque mais on trouve d'innombrables documentations en ligne comme celle de Tom Clegg ou celle de Nathan Drier, toutes les deux pour Debian, ou bien celle du Wiki officiel pour Arch Linux.

Par exemple, sur une Debian, je fais :

% sudo aptitude install snmpd

Puis j'édite /etc/snmp/snmpd.conf pour lui dire d'écouter sur toutes les adresses, IPv4 et IPv6. La ligne pertinente est :

agentAddress udp:161,udp6:[::]:161

(Oui, SNMP tourne sur UDP, port 161.) Pendant qu'on édite snmpd.conf, on modifie aussi les variables sysLocation et sysContact pour avoir des informations plus précises. On teste avec lsof que le serveur écoute bien :

% sudo lsof -i:snmp             
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
snmpd   19240 snmp    8u  IPv4 227237      0t0  UDP *:snmp 
snmpd   19240 snmp   11u  IPv6 227238      0t0  UDP *:snmp 

Ici, tout est bon.

Il reste à configurer un utilisateur, avec son mot de passe (qui ne sera pas transmis en clair). Les administrateurs système ordinaires vont choisir un nom « parlant » comme admin. Les paranoïaques vont tirer ce nom au hasard, pour augmenter la difficulté d'une attaque :

% dd if=/dev/random bs=16 count=1 | md5sum   
1+0 records in
1+0 records out
16 bytes (16 B) copied, 4.2661e-05 s, 375 kB/s
b5e9b185d879ee20b27be80195e9522a  -

Et on choisirait b5e9b185d879ee20b27be80195e9522a comme nom d'utilisateur... Pour le reste de cet article, je vais être petit-bras et prendre un nom et un mot de passe lisible, pour faciliter la lecture (le nom d'utilisateur est de toute façon en clair, même si on utilise l'option de chiffrement, qui ne chiffre que les données). Le nom sera clinique et le mot de passe cahuzac (une très mauvaise combinaison dans la réalité, puisque trop facile à trouver).

Le moyen le plus simple de créer un utilisateur est sans doute :

# Oui, il faut arrêter le serveur pour cela...
% /etc/init.d/snmpd stop

% sudo net-snmp-config --create-snmpv3-user -a SHA -x AES
Enter a SNMPv3 user name to create: 
clinique
Enter authentication pass-phrase: 
cahuzac
Enter encryption pass-phrase: 
  [press return to reuse the authentication pass-phrase]

Ici, on a donné à la commande net-snmp-config les paramètres -a SHA (l'algorithme de condensation utilisé pour l'authentification sera donc SHA) et -x AES (l'algorithme de chiffrement utilisé pour la confidentialité sera AES). Le but est d'utiliser systématiquement l'option de chiffrement. On utilise le même mot de passe pour les deux services. Après cette commande, vous devriez avoir un rouser clinique (ou rouser authOnlyUser) dans votre snmpd.conf (rouser = Read-Only User).

Une autre méthode consiste à modifier /var/lib/snmp/snmpd.conf (qui n'est pas le /etc/snmp/snmpd.conf) pour y mettre :

createUser clinique SHA "cahuzac" AES "cahuzac"

Lorsqu'on relancera le démon (c'est pour cela qu'il doit être arrêté), le fichier /var/lib/snmp/snmpd.conf sera réécrit et les mots de passe en clair disparaîtront. Une troisième méthode de création (merci à Vincent Bernat pour le rappel) d'un compte utilise SNMP lui-même, en écrivant dans la table snmpUsmUserTable (par exemple via le programme snmpusm).

On redémarre le serveur et, maintenant, il est temps de tester. Commençons par des essais avec un client SNMP en ligne de commande, snmpwalk, issu du même paquetage Net-SNMP, en supposant que le nom de la machine visée est dans la variable MYSERVER :

% snmpwalk -v 3 -u clinique -a SHA -A  cahuzac -x AES -X cahuzac \
    -l authPriv $MYSERVER

(Préciser -a SHA est obligatoire car, sinon, MD5 est utilisé par défaut. Quant à -l authPriv, Authentication & Privacy, cela active le chiffrement, afin de garantir la confidentialité des données. Voir la section 2.2 du RFC 3415.) Vous devez obtenir quelque chose comme :

SNMPv2-MIB::sysDescr.0 = STRING: Linux foobar.example.net 3.9.3-x86_64-linode33 #1 SMP Mon May 20 10:22:57 EDT 2013 x86_64
SNMPv2-MIB::sysObjectID.0 = OID: NET-SNMP-MIB::netSnmpAgentOIDs.10
DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (3442047) 9:33:40.47
SNMPv2-MIB::sysContact.0 = STRING: root@example.net
SNMPv2-MIB::sysLocation.0 = STRING: Floor 3, Row 12, Rack 5
...
IF-MIB::ifOutOctets.1 = Counter32: 791502
IF-MIB::ifOutOctets.2 = Counter32: 0
IF-MIB::ifOutOctets.3 = Counter32: 142039121

Si ce n'est pas le cas, à part une mauvaise saisie du mot de passe, vérifiez les points suivants :

  • Tester depuis le serveur, en faisant un snmpwalk ... 127.0.0.1. Si cela marche, mais que cela échoue à distance, vous avez peut-être un pare-feu zélé sur le trajet, ou bien le démon n'écoute que sur les adresses locales (cf. lsof plus haut et, sur une Debian, la variable SNMPDOPTS dans /etc/default/snmpd).
  • Question sécurité, vous avez peut-être installé TCP wrapper. Auquel cas, vérifiez qu'ils autorisent SNMP. Par exemple, si tous les accès se feront depuis les machines 192.0.2.3 et 2001:db8:ba27::3, mettez dans /etc/hosts.allow quelque chose comme snmpd: 192.0.2.3,[2001:db8:ba27::3].

Si cela marche, parfait, on va pouvoir passer à des clients SNMP plus riches. Ah, au passage, la même commande avec une adresse IPv6 (qu'il faut mettre entre crochets) :

% snmpwalk -v 3 -u clinique -a SHA -A  cahuzac -x AES -X cahuzac \
    -l authPriv "udp6:[2001:db8:dc0::1:cafe]"

Configurons maintenant Cacti pour produire de jolis graphes grâces à SNMP. Dans le menu Devices de la console de Cacti, on sélectionne Add (en haut à droite), on va indiquer SNMP Version = 3, le nom, le mot de passe, les algorithmes de cryptographie utilisés. On laisse le champ Context vide. Cacti met apparemment automatiquement le niveau de sécurité à authPriv. Lorsqu'on enregistre cette configuration, Cacti affiche le résultat d'une requête SNMP (description de la machine, contact, localisation, etc). S'il affiche à la place SNMP error, c'est qu'il y a une erreur dans la configuration (vous avez bien testé avec snmpwalk avant ?) Si tout marche, on peut alors créer les graphes via Cacti.

Et pour Icinga ? D'abord, quel est l'intérêt de SNMP pour un logiciel de supervision ? C'est qu'Icinga utilise les mêmes tests que Nagios et qu'un des tests Nagios, check_snmp a une option très pratique pour surveiller le trafic réseau. Les MIB habituelles de SNMP ne fournissent que des valeurs instantanées. On souhaiterait souvent avoir des taux, par exemple des bits/seconde et pas juste un total de bits, afin de pouvoir déclencher une alarme, par exemple en cas d'une attaque par déni de service. Certaines MIB (celle de Juniper) fournissent des variables pour cela, mais tout le monde n'a pas un Juniper. Alors, on va utiliser une option très pratique de check_snmp, --rate, qui enregistre les mesures sur disque pour pouvoir calculer un taux. (Attention donc à ce qu'Icinga ait le droit d'écrire dans le répertoire en question.) Créons une commande :

define command{
        command_name    check_snmp_myserver
        command_line    $USER1$/check_snmp -H $HOSTADDRESS$ -P 3 -a SHA -x AES -U clinique -A cahuzac -X cahuzac  -L authPriv --rate -o $ARG1$ -w $ARG2$ -c $ARG3$  
    }

Et utilisons là dans la configuration :

define service{
       use                              generic-service
       host_name                        myserver
       service_description              OUT_PACKET_RATE
       check_command                   check_snmp_myserver!ifOutUcastPkts.3!1000!4000!
   }

Ici, on utilise la variable SNMP ifOutUcastPkts (nombre de paquets sortants) sur la troisième interface réseau. Si on voit plus de 1 000 p/s, Icinga lève un avertissement, si on voit plus de 3 000 p/s, une alerte. On verra dans le journal :

[1380120148] SERVICE ALERT: myserver;OUT_PACKET_RATE;CRITICAL;SOFT;2;SNMP RATE CRITICAL - *5370*

À noter qu'une autre solution est suggérée dans la documentation d'Icinga, en récupérant les données de MRTG.


L'article seul

RFC 1288: The Finger User Information Protocol

Date de publication du RFC : Décembre 1991
Auteur(s) du RFC : David Paul Zimmerman (Rutgers University, Center for Discrete Mathematics and Theoretical Computer Science (DIMACS))
Chemin des normes
Première rédaction de cet article le 24 septembre 2013


Il y a bien longtemps, dans l'Internet, toutes les machines Unix connectées au réseau avaient un serveur finger. Ce protocole permettait d'obtenir des informations sur les utilisateurs de cette machine, à la fois de l'information statique (leur numéro de téléphone, le numéro de leur bureau à l'université...) mais aussi de l'information dynamique (est-ce qu'ils sont connectés ou pas, actifs ou pas, quand ont-il lu leur courrier pour la dernière fois, ...) Aujourd'hui, on utiliserait Facebook pour cela mais, dans les années 80 et 90, pour se renseigner sur un collègue ou un confrère, on se servait de finger. L'importance croissante donnée à la vie privée a petit à petit conduit au démantelement de cet utile service (remplacé, on l'a vu, par de gros silos de données qui sont bien pires, notamment parce que l'information n'est pas sous le contrôle de l'utilisateur). Finger, normalisé dans ce RFC, n'a plus aujourd'hui qu'un intérêt historique.

Je ne connais pas aujourd'hui beaucoup de serveurs finger encore en activité (mais je suis sûr que les lecteurs de mon blog vont m'en trouver plusieurs). Alors, j'en ai créé un, par nostalgie, blog@www.bortzmeyer.org. Vous pouvez utiliser un client finger comme l'outil Unix du même nom pour l'interroger. Il ne donne pas de renseignements sur une personne mais sur un service, comme le faisaient un certain nombre de serveurs finger. Ainsi, il existait un quake@geophys.washington.edu qui donnait de l'information sur les derniers tremblements de terre détectés, et un nasanews@space.mit.edu qui servait les informations de la NASA sur ses vols spatiaux. Ces deux-là ont disparu, mais les toilettes du MIT diffusent toujours des informations :

% finger @bathroom.mit.edu
Random Hall Bathroom Server v2.1

                         Bonfire Kitchen: vacant for 28 min
                         Bonfire  Lounge: vacant for 3 min
                          Pecker  Lounge: vacant for 2 hr
                          Pecker Kitchen: *IN*USE* for 16 min
   K 282  L  290 K          Clam Kitchen: vacant for 43 min
   ... ... ... ...          Clam  Lounge: *IN*USE* for 33 min
  | o : o | o : x |          BMF  Lounge: vacant for 3 min
  | o : x | o : o |          BMF Kitchen: vacant for 52 min
  | o : o | o : o |         Loop Kitchen: vacant for 75 min
  | o : x | - : o |         Loop  Lounge: vacant for 3 min
 ~~~~~~~~~~~~~~~~~~~  Black Hole  Lounge: vacant for 42 min
                      Black Hole Kitchen: vacant for 33 min
      o = vacant!        Destiny Kitchen: vacant for 2 min
      x = in use          Destiny Lounge: *IN*USE* for 33 min
                                     Foo: vacant for 17 min

For more information finger help@bathroom.mit.edu

(2146055)

Plus sérieux, le projet FreeBSD a toujours un serveur finger actif @freebsd.org donc vous pouvez vous informer sur n'importe quel commiter :


%  finger roberto@freebsd.org 
Login: roberto        			Name: Ollivier Robert
Directory: /home/roberto            	Shell: /usr/local/bin/zsh
Office: Bretigny s/Orge FRANCE		Office Phone: +33-1-69887290
No Mail.
Plan:
Home address: <roberto@keltia.net>
Work address: <ollivier.robert@eurocontrol.int>

Twitter: @Keltounet

pub  1024D/7DCAE9D3 1997-08-21 Ollivier Robert <roberto@keltia.net>
uid                            Ollivier Robert <roberto@keltia.freenix.fr>

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.2.1 (FreeBSD)

mQGiBDP8ElkRBADQrtDGMaOawsdVCxQTrtCoa+VFeSebgBgIdfrgduTTOteV+bqz
RYa94GBx3Df/LCxEtb8bgcL6DlD/B5nCjzMfwzW+JkqXDz7g96oVWW48jUIeNrYL
qBZruvcopUEmH3iBZU8ig3lpJ5/XbN+IYGP474E2rnTNfaY26E0iWkWqtQCg/wIY
...

Autre serveur finger utile, celui de météorologie qui permet d'obtenir un rapport sur n'importe quelle ville du monde (ici, Budva) :

% date
Tue Feb 16 08:31:00 CET 2016

% finger budva@graph.no
               -= Meteogram for montenegro/budva/budva~3203106 =-               
 'C                                                                   Rain (mm) 
 23                                                                   
 21   ---                                               |             9 mm 
 19                                                     |             8 mm 
 17---   ^^^      ^^^^^^                                |             7 mm 
 15         ======         =====|                       |             6 mm 
 13                     ^^^     |^^^===   ^^^         ==|             5 mm 
 11                             |      =--   ---=--===  |         ^^^ 4 mm 
  9                             |     |                 |=-----       3 mm 
  7              |           |  |     |                 |      ^^^    2 mm 
  5           |  |           |  |     |              |  |             1 mm 
   _10_13 19 01_07_13 19 01_07_13 19 01_07_13 19 01_07_13 19 01_07_13 Hour
 
    NE SE NE  S  S SW NW  N NE  E NE NW NW  W NW NE NE SW NW NW NW SW Wind dir.
     2  2  2  4  2  0  1  2  2  1  2  1  2  3  2  1  1  2  2  2  1  2 Wind(mps)

Legend left axis:   - Sunny   ^ Scattered   = Clouded   =V= Thunder   # Fog
Legend right axis:  | Rain    ! Sleet       * Snow
Mail a "thank you" to finger@falkp.no if you like the service.  

Si vous voulez installer, vous aussi, un serveur finger, je vous mets en garde : c'est un service sensible et qui peut ouvrir des failles de sécurité. Après tout, son rôle est de distribuer de l'information. Et l'information peut être utile à un méchant.

Comment fonctionne ce protocole ? Difficile de faire plus simple (section 2.1). À l'époque, le moyen le plus courant de faire un protocole d'accès à l'information était de réserver un port TCP (ici, 79), de dire au client de se connecter à ce port et d'envoyer sa question sous forme d'une simple chaîne de caractères, et de dire au serveur d'écouter sur ce port, et de répondre à question par... ce qu'il veut. De nombreux protocoles avaient été conçus ainsi, comme whois (port 43, RFC 3912) ou comme daytime (port 13, RFC 867) qui était encore plus simple (même pas de question, de la part du client). Écrire un logiciel client pour ces protocoles est trivial (exercice de première heure de la première année en réseaux) et on peut même se contenter d'un simple telnet :


% telnet www.bortzmeyer.org finger
Trying 2605:4500:2:245b::42...
Connected to www.bortzmeyer.org.
Escape character is '^]'.
blog
Debian GNU/Linux      Copyright (C) 1993-1999 Software in the Public Interest
...
Connection closed by foreign host.

Notez bien (section 2.2) que la fin de la ligne « question » doit être composée de deux caractères, CR et LF. Certains serveurs finger sont plus tolérants que d'autres si vous violez cette règle. Si on utilise netcat comme client, on va préciser ces deux caractères :

% echo -n -e "blog\r\n" | nc www.bortzmeyer.org finger

On peut aussi utiliser un client whois puisque les deux protocoles sont très proches :

% whois -h www.bortzmeyer.org -p finger blog

Et le format de la réponse ? Il n'est pas du tout défini par ce RFC (section 2.5) qui dit juste que c'est du texte libre, conçu pour être analysé par un humain et pas par un programme. (C'est exactement la même chose avec whois.)

Le RFC donne des indications sur les informations utiles à distribuer. Mais il précise aussi que la liste effective est entièrement sous le contrôle de l'administrateur système. Dans le reste de cet article, je donnerai des exemples de configuration empruntés à deux serveurs finger distribués en logiciel libre, efingerd et cfingerd. Par exemple, le RFC cite le numéro de téléphone, l'adresse, le nombre de minutes depuis la dernière activité sur cet ordinateur. Avec cfingerd, on peut décider d'afficher (signe plus) ou au contraire de ne pas activer (signe moins) l'envoi de ces informations, et on peut le faire pour les utilisateurs locaux à la machine (le second booléen) ou distants (le premier booléen). Un exemple dans le cfingerd.conf est :

CONFIG finger_display  = {
...
        +REAL_NAME              = [FALSE, TRUE],
        +DIRECTORY              = [FALSE, TRUE],
        +SHELL                  = [FALSE, TRUE],
        +ROOM_NUMBER            = [FALSE, TRUE],
        +WORK_NUMBER            = [FALSE, TRUE],
        +HOME_NUMBER            = [FALSE, TRUE],
        +LAST_TIME_ON           = [FALSE, TRUE],
        +IF_ONLINE              = [FALSE, TRUE],
        +TIME_MAIL_READ         = [FALSE, TRUE],
        +DAY_MAIL_READ          = [FALSE, TRUE],
        +ORIGINATION            = [FALSE, TRUE],
        +PLAN                   = [TRUE, TRUE],
        +PROJECT                = [TRUE, TRUE],
        +PGP                    = [TRUE, TRUE],
...

Avec efingerd, cela se configure en éditant le script shell luser qui, par défaut, utilise la commande locale finger qui peut être très bavarde (certains serveurs finger affichaient même l'expéditeur du dernier courrier reçu !). Voici un exemple :

Login: stephane       			Name: 
Directory: /home/stephane           	Shell: /usr/bin/zsh
On since Tue Sep 24 06:39 (UTC) on pts/0 from central.example.net
   1 minute 54 seconds idle
Last login Tue Sep 24 06:39 (UTC) on pts/2 from central.example.net
Mail forwarded to "| procmail -d"
New mail received Tue Sep 24 05:41 2013 (UTC)
     Unread since Tue Sep 24 13:28 2013 (UTC)
No Plan.

Notez que ces deux logiciels serveurs permettent de ne pas envoyer d'information sur un utilisateur particulier (bien que le RFC se demande à quoi cela sert de faire tourner un serveur finger dans ces conditions). Avec efingerd, c'est en éditant le script luser.

Parfois, le nom passé au serveur finger n'est pas celui d'un utilisateur humain mais celui d'un service (comme blog plus haut). La section 2.5.5 discute du cas où le service est un distributeur automatique et demande que finger renvoie la liste des produits actuellement disponibles dans la machine...

Une technique courante était de permettre aux utilisateurs de mettre un fichier nommé .plan dans leur répertoire maison. Ce fichier était alors envoyé après la réponse finger et contenait des informations supplémentaires comme une clé PGP. Les serveurs modernes permettent également aux utilisateurs de mettre un programme (et pas un simple fichier texte) dont le résultat sera envoyé au client finger. Inutile de décrire les risques de sécurité que cela entraine (section 3.2.5)...

finger offrait une autre possibilité : avoir la liste de tous les utilisateurs actuellement connectés, en indiquant une question vide. Donc, la commande finger @machine-distante (sans nom devant le @) donnait la liste de qui était branché. Particulièrement indiscrète, cette possibilité (qui n'avait en outre de sens que pour les grosses machines multi-utilisateurs) a été la première à disparaître (éditer le script nouser pour efingerd et option SYSTEM_LIST pour cfingerd).

À noter qu'il existe d'autres serveurs finger que ceux cités, par exemple IcculusFinger qui en prime est disponible sur le site de l'auteur :

% finger ryan@icculus.org 
IcculusFinger v2.1.24


                              /Nothing to report./

--------------------------------------------------------------------
.plan archives for this user: finger ryan?listarchives=1@icculus.org
Powered by IcculusFinger v2.1.24 (http://icculus.org/IcculusFinger/)
Stick it in the camel and go.

Et la sécurité ? Absente du premier RFC, le RFC 742, elle est au contraire très présente dans ce RFC 1288, notamment en section 3. Il y a plusieurs aspects. D'abord, la sécurité de la mise en œuvre du serveur finger, qui fut illustrée par le ver de Morris. Notons que ce n'était pas un problème spécifique au protocole finger : tout serveur réseau devrait être programmé de manière défensive, de façon à ne pas être vulnérable lorsque le client envoie des données inattendues (très longues, par exemple). Ne pas avoir de serveur finger aujourd'hui, à cause d'une faille de sécurité d'un logiciel qui n'est plus utilisé depuis longtemps, est donc idiot.

Mais finger a évidemment un autre problème, déjà cité, vis-à-vis de la vie privée. On n'a pas forcément envie que n'importe qui sur l'Internet soit au courant de ses heures de présence au bureau ou du rythme auquel on reçoit du courrier. C'est pourquoi le RFC exige qu'on puisse ajuster l'information présentée (cfingerd fournit un contrôle très fin dans son fichier de configuration, efingerd vous laisse programmer ce que vous voulez dans les scripts qu'il exécute).

Si vous avez un serveur finger et que vous voulez le superviser depuis Icinga, cela peut se faire avec la configuration :

define service{
        use   generic-service
        host_name            MonServeur
        service_description       Finger
        check_command             check_finger!utilisateur!chaîne à chercher
}

Elle lèvera une alarme si le texte chaîne à chercher n'apparait pas dans la réponse du serveur. La commande check_finger est définie ainsi :

define command {
        command_name    check_finger
        command_line    /usr/local/share/nagios/libexec/check_finger $HOSTADDRESS$ $ARG1$ $ARG2$ $ARG3$
        }

Et le script check_finger (inspiré d'un équivalent pour whois) est disponible ici.

Notre RFC succède au RFC 1196 et le premier RFC sur finger était le RFC 742. Comme beaucoup de protocoles Internet, finger a d'abord été mis en œuvre (parfois sous le nom de « Name » et pas « Finger »), puis normalisé. La section 1.2 du RFC résume une longue et glorieuse histoire. Le RFC note que la norme actuelle est fondée avant tout sur le comportement du serveur finger d'Unix BSD. Par rapport à son prédécesseur, le RFC 1196, on note surtout une définition plus rigoureuse : le RFC 1196 était souvent très vague. Aujourd'hui, on l'a vu, finger est une survivance du passé, mais le standard IETF de récupération d'information sur une entité, WebFinger (RFC 7033), lui rend hommage par son nom. Autre idée inspirée de finger (et l'utilisant), le réseau social expérimental Thimbl. Comme le dit un contributeur d'Une contre-histoire des Internets, « Je me souviens de finger, seul service interrogeable qui indiquait les services accessibles sur un host »...


Téléchargez le RFC 1288


L'article seul

RFC 7001: Message Header Field for Indicating Message Authentication Status

Date de publication du RFC : Septembre 2013
Auteur(s) du RFC : M. Kucherawy
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF appsawg
Première rédaction de cet article le 21 septembre 2013


Il existe désormais plusieurs techniques pour authentifier les courriers électroniques. Certaines peuvent nécessiter des calculs un peu compliqués et on voudrait souvent les centraliser sur une machine de puissance raisonnable, dotée de tous les logiciels nécessaires. Dans cette hypothèse, le MUA ne recevra qu'une synthèse (« Ce message vient bien de example.com ») et pourra alors prendre une décision, basée sur cette synthèse. C'est le but de l'en-tête Authentication-Results:, normalisé originellement dans le RFC 5451 quatre ans plus tôt, RFC que ce nouveau RFC met légèrement à jour (il y a peu de changements). Il a lui-même été remplacé, depuis, par le RFC 7601.

Avec des techniques d'authentification comme DKIM (RFC 6376) ou SPF (RFC 7208), les calculs à faire pour déterminer si un message est authentique peuvent être complexes (DKIM utilise la cryptographie) et nécessiter la présence de bibliothèques non-standard. Les installer et les maintenir à jour sur chaque machine, surtout en présence d'éventuelles failles de sécurité qu'il faudra boucher en urgence, peut être trop pénible pour l'administrateur système. L'idée de ce RFC est donc de séparer l'opération en deux : l'authentification est faite sur un serveur, typiquement le premier MTA du site (cf. annexe D pour une discussion de ce choix), celui-ci ajoute au message un en-tête indiquant le résultat de ladite authentification et le MUA (ou bien le MDA, voir la section 1.5.3 pour un bon rappel sur ces concepts) peut ensuite, par exemple par un langage de filtrage comme procmail ou Sieve, agir sur la base de ce résultat. Cet en-tête marche pour tous les protocoles d'authentification et surpasse donc les en-têtes spécifiques comme le Received-SPF: de SPF (section 1 du RFC). Le filtrage des messages non authentifiés n'est pas obligatoire (section 1.4) : agir - ou pas - sur la base de l'en-tête Authentication-Results: est une décision politique locale.

J'ai utilisé le terme de « site » pour désigner un ensemble de machines gérées par la même organisation mais le RFC a un terme plus rigoureux, ADMD (ADministrative Management Domain). La frontière d'un ADMD est la « frontière de confiance » (trust boundary), définie en section 1.2. Un domaine administratif de gestion est un groupe de machines entre lesquelles il existe une relation de confiance, notamment du fait que, à l'intérieur de l'ADMD, l'en-tête Authentication-Results: ne sera pas modifié ou ajouté à tort (section 1.6 : l'en-tête n'est pas protégé, notamment il n'est pas signé). Il existe de nombreuses variantes organisationnelles du concept d'ADMD. Un ADMD inclus typiquement une organisation (ou un département de celle-ci) et d'éventuels sous-traitants. Il a un nom, l'authserv-id, défini en section 2.2.

L'en-tête Authentication-Results: lui-même est formellement défini en section 2. Il appartient à la catégorie des en-têtes de « trace » (RFC 5322, section 3.6.7 et RFC 5321, section 4.4) comme Received: qui doivent être ajoutés en haut des en-têtes et jamais modifiés. La syntaxe de Authentication-Results: est en section 2.2. L'en-tête est composé du authserv-id, le nom de l'ADMD et d'une série de doublets (méthode, résultat), chacun indiquant une méthode d'authentification et le résultat obtenu. L'annexe C fournit une série d'exemples. Elle commence (annexe C.1) par un message sans Authentication-Results: (eh oui, il n'est pas obligatoire). Puis (tiré de l'annexe C.3), une authentification SPF réussie, au sein de l'ADMD example.com, donnera :

        Authentication-Results: example.com;
                  spf=pass smtp.mailfrom=example.net
        Received: from dialup-1-2-3-4.example.net
                      (dialup-1-2-3-4.example.net [192.0.2.200])
                  by mail-router.example.com (8.11.6/8.11.6)
                      with ESMTP id g1G0r1kA003489;
                  Wed, Mar 14 2009 17:19:07 -0800
        From: sender@example.net
        Date: Wed, Mar 14 2009 16:54:30 -0800
        To: receiver@example.com

Rappelez-vous qu'il peut y avoir plusieurs authentifications. Voici un cas (annexe C.4) avec SPF et l'authentification SMTP du RFC 4954 :

       Authentication-Results: example.com;
                  auth=pass (cram-md5) smtp.auth=sender@example.net;
                  spf=pass smtp.mailfrom=example.net
        Received: from dialup-1-2-3-4.example.net (8.11.6/8.11.6)
                      (dialup-1-2-3-4.example.net [192.0.2.200])
                  by mail-router.example.com (8.11.6/8.11.6)
                      with ESMTP id g1G0r1kA003489;
                  Fri, Feb 15 2002 17:19:07 -0800
        Date: Fri, Feb 15 2002 16:54:30 -0800
        To: receiver@example.com
        From: sender@example.net

L'une des authentifications peut réussir et l'autre échouer. Un exemple (annexe C.6) avec deux signatures DKIM, une bonne et une qui était correcte au départ (regardez le premier Authentication-Results:) mais plus à l'arrivée, peut-être parce qu'un gestionnaire de liste de diffusion a modifié le message :

       Authentication-Results: example.com;
              dkim=pass reason="good signature"
                header.i=@mail-router.example.net;
              dkim=fail reason="bad signature"
                header.i=@newyork.example.com
        Received: from mail-router.example.net
                  (mail-router.example.net [192.0.2.250])
              by chicago.example.com (8.11.6/8.11.6)
                  for <recipient@chicago.example.com>
                  with ESMTP id i7PK0sH7021929;
              Fri, Feb 15 2002 17:19:22 -0800
        DKIM-Signature: v=1; a=rsa-sha256; s=furble;
              d=mail-router.example.net; t=1188964198; c=relaxed/simple;
              h=From:Date:To:Message-Id:Subject:Authentication-Results;
              bh=ftA9J6GtX8OpwUECzHnCkRzKw1uk6FNiLfJl5Nmv49E=;
              b=oINEO8hgn/gnunsg ... 9n9ODSNFSDij3=
        Authentication-Results: example.net;
              dkim=pass (good signature) header.i=@newyork.example.com
        Received: from smtp.newyork.example.com
                  (smtp.newyork.example.com [192.0.2.220])
              by mail-router.example.net (8.11.6/8.11.6)
                  with ESMTP id g1G0r1kA003489;
              Fri, Feb 15 2002 17:19:07 -0800
        DKIM-Signature: v=1; a=rsa-sha256; s=gatsby;
              d=newyork.example.com;
              t=1188964191; c=simple/simple;
              h=From:Date:To:Message-Id:Subject;
              bh=sEu28nfs9fuZGD/pSr7ANysbY3jtdaQ3Xv9xPQtS0m7=;
              b=EToRSuvUfQVP3Bkz ... rTB0t0gYnBVCM=
        From: sender@newyork.example.com
        Date: Fri, Feb 15 2002 16:54:30 -0800
        To: meetings@example.net

La liste complète des méthodes figure dans un registre IANA (section 6). De nouvelles méthodes peuvent être enregistrées en utilisant la procédure « Examen par un expert » du RFC 5226.

La section 2.3 détaille l'authserv-id. C'est un texte qui identifie le domaine, l'ADMD. Il doit donc être unique dans tout l'Internet. En général, c'est un nom de domaine comme laposte.net. (Il est possible d'être plus spécifique et d'indiquer le nom d'une machine particulière mais cette même section du RFC explique pourquoi c'est en général une mauvaise idée : comme les MUA du domaine n'agissent que sur les Authentication-Results: dont ils reconnaissent l'authserv-id, avoir un tel identificateur qui soit lié au nom d'une machine, et qui change donc trop souvent, complique l'administration système.)

La section 2.5 explique les résultats possibles pour les méthodes d'authentification (en rappelant que la liste à jour des méthodes et des résultats est dans le registre IANA). Ainsi, DKIM (section 2.5.1) permet des résultats comme pass (authentification réussie) ou temperror (erreur temporaire au cours de l'authentification, par exemple liée au DNS). Des résultats similaires sont possibles pour SPF (section 2.5.3).

Notons la normalisation d'une méthode traditionnelle d'authentification faible, le test DNS du chemin « adresse IP du serveur -> nom » et retour. Baptisée iprev, cette méthode, bien que bâtie sur la pure superstition (cf. section 7.11) est utilisée couramment. Très injuste (car les arbres des résolutions inverses du DNS, in-addr.arpa et ip6.arpa, ne sont pas sous le contrôle du domaine qui envoie le courrier), cette méthode discrimine les petits FAI, ce qui est sans doute un avantage pour les gros, comme AOL qui l'utilisent. Attention aux implémenteurs : aussi bien la résolution inverse d'adresse IP en nom que la résolution droite de nom en adresse IP peuvent renvoyer plusieurs résultats et il faut donc comparer des ensembles. (Cette méthode qui, contrairement aux autres, n'avait jamais été exposée dans un RFC avant le RFC 5451, est décrite en détail dans la section 3, avec ses sérieuses limites.)

Autre méthode mentionnée, auth (section 2.5.4) qui repose sur l'authentification SMTP du RFC 4954. Si un MTA (ou plutôt MSA) a authentifié un utilisateur, il peut le noter ici.

Une fois le code d'authentification exécuté, où mettre le Authentication-Results: ? La section 4 fournit tous les détails, indiquant notamment que le MTA doit placer l'en-tête en haut du message, ce qui facilite le repérage des Authentication-Results: à qui on peut faire confiance (en examinant les en-têtes Received: ; en l'absence de signature, un Authentication-Results: très ancien, situé au début du trajet, donc en bas des en-têtes, ne signifie pas grand'chose). On se fie a priori aux en-têtes mis par les MTA de l'ADMD, du domaine de confiance. L'ordre est donc important. (La section 7 revient en détail sur les en-têtes Authentication-Results: usurpés.)

Ce n'est pas tout de mettre un Authentication-Results:, encore faut-il l'utiliser. La section 4.1 s'attaque à ce problème. Principe essentiel pour le MUA : ne pas agir sur la base d'un Authentication-Results:, même si ce n'est que pour l'afficher, sans l'avoir validé un minimum. Comme le Authentication-Results: n'est pas signé, n'importe qui a pu en insérer un sur le trajet. Le RFC précise donc que les MUA doivent, par défaut, ne rien faire. Et qu'ils doivent ne regarder les Authentication-Results: qu'après que cela ait été activé par l'administrateur de la machine, qui indiquera quel authserv-id est acceptable.

Naturellement, le MTA d'entrée du domaine devrait supprimer les Authentication-Results: portant son propre authserv-id qu'il trouve dans les messages entrants : ils sont forcément frauduleux (section 5). (Le RFC accepte aussi une solution plus simpliste, qui est de supprimer tous les Authentication-Results: des messages entrants, quel que soit leur authserv-id.)

Arrivé à ce stade de cet article, le lecteur doit normalement se poser bien des questions sur la valeur du Authentication-Results:. Quel poids lui accorder alors que n'importe quel méchant sur le trajet a pu ajouter des Authentication-Results: bidons ? La section 7, consacrée à l'analyse générale de la sécurité, répond à ces inquiétudes. 7.1 détaille le cas des en-têtes usurpés. Les principales lignes de défense ici sont le fait que le MUA ne doit faire confiance aux Authentication-Results: que s'ils portent le authserv-id de son ADMD et le fait que le MTA entrant doit filtrer les Authentication-Results: avec son authserv-id. Comme l'intérieur de l'ADMD, par définition, est sûr, cela garantit en théorie contre les Authentication-Results: usurpés. Le RFC liste néanmoins d'autres méthodes possibles comme le fait de ne faire confiance qu'au premier Authentication-Results: (le plus récent), si on sait que le MTA en ajoute systématiquement un (les éventuels Authentication-Results: usurpés apparaîtront après ; mais certains serveurs les réordonnent, cf. section 7.3). Pour l'instant, il n'y a pas de méthode unique et universelle de vérification du Authentication-Results:, le RFC propose des pistes mais ne tranche pas.

Comme toujours en sécurité, il faut bien faire la différence entre authentification et autorisation. Un spammeur a pu insérer un Authentication-Results: légitime pour son authserv-id. Même authentifié, il ne doit pas être considéré comme une autorisation (section 7.2).

Plusieurs mises en œuvre de ce système existent déjà comme dans MDaemon, sendmail (via sid-milter), Courier, OpenDKIM, etc. Si on veut analyser les en-têtes Authentication-Results: en Python, on a le module authres. Parmi les grosses usines à courrier centralisées, Gmail met systématiquement cet en-tête, par exemple :

Authentication-Results: mx.google.com; spf=pass \
           (google.com: domain of stephane@sources.org designates 217.70.190.232 \
               as permitted sender) smtp.mail=stephane@sources.org

Outre Gmail, à la date de publication du RFC, Yahoo et Hotmail ajoutaient cet en-tête.

Les changements depuis le RFC 5451 sont peu nombreux. Outre la correction d'erreurs, on trouve l'intégration du RFC 6577, une libéralisation des règles d'enregistrement de nouvelles méthodes d'authentification, des nouvelles méthodes (dont je n'ai pas parlé ici) comme le VBR du RFC 6212 et divers changements éditoriaux. Le RFC 7601, qui l'a ensuite remplacé, n'a pas non plus fait de changements énormes.


Téléchargez le RFC 7001


L'article seul

RFC 7021: Assessing the Impact of Carrier-Grade NAT on Network Applications

Date de publication du RFC : Septembre 2013
Auteur(s) du RFC : C. Donley (CableLabs), L. Howard (Time Warner Cable), V. Kuarsingh (Rogers Communications), J. Berg (CableLabs), J. Doshi (University of Colorado)
Pour information
Première rédaction de cet article le 20 septembre 2013


Sous le nom générique (et souvent erroné) de NAT se trouve tout un zoo de techniques variées et n'ayant en commun que leur complexité et leur fragilité. Ce nouveau RFC documente les problèmes liés à une technique particulière, nommée « double NAT » ou « NAT 444 » ou encore « CGN ». Lorsqu'un malheureux paquet IP subit deux traductions, qu'est-ce qui va casser ?

L'idée du CGN (un terme marketing, qu'il vaudrait mieux remplacer par NAT 444 pour « deux NAT sur le trajet d'un paquet IPv4 ») est de faire beaucoup d'efforts et de dépenser beaucoup d'argent pour ne pas migrer vers IPv6. Au lieu de déployer IPv6, ce qui simplifierait beaucoup les choses, notamment pour les applications, on déploie de gros routeurs NAT chez le FAI (loin des utilisateurs, d'où le nom de CGN - Carrier-Grade NAT - par opposition au NAT CPE des boxes actuelles). En toute rigueur, on peut avoir du CGN sans avoir du double NAT (c'est par exemple courant dans les offres 3G). Mais ce RFC se focalise sur le cas typique de l'accès Internet à la maison ou au bureau où les paquets IPv4 subiront une double traduction, par une box chez le client puis par le routeur CGN chez le FAI. On aura donc deux NAT à la suite.

Ce RFC n'est pas une analyse théorique. Au contraire, il décrit le résultat de tests effectifs menés par un labo des FAI et deux FAI importants (CableLabs, Time Warner Cable et Rogers), qui ont testé en vrai le NAT 444 et les problèmes qu'il pose. La première campagne de tests a été faite en 2010 et avait montré que des applications comme le streaming vidéo, les jeux en ligne et le partage de fichiers en pair-à-pair avaient des ennuis. Une seconde série de tests a été faite en 2011 par CableLabs seul, en essayant du matériel de plusieurs vendeurs (A10, Juniper, Alcatel-Lucent) pour faire le CGN. D'une manière générale, les tests n'ont été faits qu'avec les applications qui avaient des chances (ou plutôt des malchances) d'avoir des problèmes : un simple accès en lecture seule à une page Web ordinaire ne présente pas de risques et n'a donc pas été testé. La liste des applications testées est longue ;

Ce RFC est essentiellement consacré à rendre compte des résultats de cette seconde campagne de tests.

La section 2 du RFC commence par décrire les architectures utilisés pour les tests. Par exemple, le premier cas (section 2.1.1) est le cas le plus simple : une seule machine terminale (« client »), un seul réseau local, un seul FAI. Le deuxième cas correspond à une maison avec plus d'équipements puisqu'il y a deux machines terminales. Tous les cas avec deux machines chez l'utilisateur permettent de tester des applications pair-à-pair entre ces deux machines. Le troisième cas a deux réseaux locaux mais un seul FAI donc, avec le CGN, possibilité que les machines des deux réseaux se présentent à l'extérieur avec la même adresse publique (voir le cas des Xbox plus loin). Et le quatrième cas a deux machines terminales, chez des FAI différents (donc avec des routeurs CGN différents et des adresses IP différentes).

Divers petits routeurs ont été utilisés comme CPE pendant les tests (Netgear, Linksys, etc). Les machines terminales étaient des ordinateurs Windows ou Mac OS, des consoles Xbox, des tablettes iPad, des lecteurs Blu-Ray connectés, etc.

Résultats ? Les activités les plus traditionnelles comme envoyer et recevoir du courrier, ou comme lire le Web, n'ont pas été affectées par le CGN. Les technologies de transition vers IPv6 comme 6to4 (RFC 3056) avaient été testées lors des essais de 2010 et les résultats étaient très mauvais. Ces tests n'ont pas été refaits en 2011. Autrement, qu'est-ce qui n'a pas marché ?

Plusieurs applications pair-à-pair par exemple de jeu en ligne ou de téléphonie SIP ont échoué dès qu'un CGN était là. Dans le cas de la Xbox, deux utilisateurs situés chez le même FAI n'arrivent pas à se connecter entre eux s'il y a du NAT444. Cela a apparemment été réglé par Microsoft dans une mise à jour de décembre 2011. Dans le cas de PJSIP, les appels passant par un fournisseur SIP marchaient mais pas ceux effectués en pair-à-pair.

μTorrent a fonctionné dans certains cas mais pas dans tous. Il utilise une variété de techniques pour passer à travers les NAT (y compris STUN).

Pourquoi ces échecs, lorsque ça marche avec du NAT « habituel » ? Il existe plusieurs raisons (analysées dans le RFC) mais, pour prendre l'exemple de la Xbox, c'est parce que le serveur des Xbox sait dire à deux consoles qui se connectent depuis la même adresse IPv4 publique : « vous êtes toutes les deux derrière un routeur NAT, communiquez directement sur vos adresses privées ». Cela fonctionne si les deux Xbox sont sur le même réseau local et peuvent en effet se parler sans intermédiaire. Mais s'il y a du CGN, et qu'elles sont sur des réseaux locaux différents, connectés par le même FAI, elles présentent au serveur de Microsoft la même adresse IPv4 publique mais elles ne peuvent pas se joindre avec leurs adresses privées.

Les tests ont été qualitatifs (ça marche ou ça ne marche pas) mais aussi quantitatifs avec mesure de la latence ou de la gigue, pour lesquelles le CGN ne semble pas avoir d'impact négatif.

Soyons optimistes, il y a eu des améliorations entre les tests de 2010 et ceux de 2011, notamment grâce à l'utilisation plus fréquente de STUN ou de relais permettant de contourner les problèmes du NAT. Le RFC ne parle pas de l'aspect économique mais je note que, lorsqu'on évalue le coût des CGN, il faut voir que c'est aux auteurs d'application de payer pour les FAI, en augmentant la complexité de leurs applications pour contourner les obstacles.

Certains problèmes restent et semblent consubstantiels du CGN, comme la difficulté qu'il y a à fournir des informations aux autorités en cas d'enquête sur un comportement anormal : l'adresse IP publique qui est vue par les serveurs distants est partagée entre un grand nombre d'utilisateurs (RFC 6269).

Les résultats bruts des tests de 2010 figurent en section 5 et ceux des tests de 2011 en section 4, sous forme de tableau indiquant ce qui marche et ce qui ne marche pas.

Que recommander après ces résultats ? La section 6 traite de la gestion de ces problèmes liés au double NAT. Elle recommande notamment l'utilisation de PCP (Port Control Protocol, RFC 6887), pour que les applications puissent ouvrir les ports nécessaires dans le routeur CGN.

Un exposé de CableLabs résumant leurs observations est disponible en « Carrier Grade NAT - Observations and Recommendations ».


Téléchargez le RFC 7021


L'article seul

RFC 2993: Architectural Implications of NAT

Date de publication du RFC : Novembre 2000
Auteur(s) du RFC : T. Hain (Microsoft)
Pour information
Première rédaction de cet article le 19 septembre 2013


Ce RFC est la synthèse (vieille de treize ans, mais toujours juste) de l'analyse architecturale du NAT par l'IETF. Elle décrit les conséquences du NAT pour l'Internet et appelle à considérer son usage avec prudence (comme chacun peut le voir, cet appel n'a pas été entendu). C'est le document à lire pour avoir une vision de haut niveau du NAT.

Techniquement, le NAT a été décrit en 1994 dans le RFC 1631 (et dans le RFC 2663). Cette méthode était un des moyens envisagés pour gérer le problème de l'épuisement des adresses IPv4. Mais le RFC 1631 appelait à la prudence : « NAT has several negative characteristics that make it inappropriate as a long term solution, and may make it inappropriate even as a short term solution. » Entre le RFC 1631 et ce RFC 2993 (et encore plus depuis), la traduction d'adresses a été très largement déployée, sans tenir compte de ses inconvénients. Cassandre n'est jamais écoutée... Il avait même été question d'arrêter le développement et le déploiement d'IPv6, avec l'argument que le NAT suffisait à résoudre le problème de l'épuisement d'adresses IPv4 (ce point est développé en détail dans la section 8 du RFC). Il est d'autant plus difficile de faire une analyse des avantages et inconvénients du NAT que le débat est souvent très passionnel. Les Pour font remarquer que le NAT fonctionne sans intervention particulière, pour des applications très populaires (comme le Web ou le courrier). Mieux, le NAT résout un vieux problème d'IP, la confusion de l'identificateur et du localisateur : l'adresse IP interne est un identificateur, l'externe un localisateur. Le NAT divise l'Internet, autrefois unifié autour de l'unicité de l'adresse IP, en plusieurs domaines indépendants, chacun ayant son propre espace d'adressage (souvent tiré du RFC 1918). Les Contre reprochent au NAT son caractère de bricolage et sa non-transparence pour beaucoup d'applications, notamment pair-à-pair. En effet, si l'application vérifie que l'en-tête IP reste cohérent (c'est le cas de l'AH d'IPsec, cf. section 9) ou si elle transporte des adresses IP dans ses données (comme le fait SIP, et pour de bonnes raisons), elle ne fonctionnera pas à travers le NAT sans gros efforts de programmation (le principe du NAT est de déplacer les coûts, des FAI vers les programmeurs). Le NAT encourage donc l'ossification de l'Internet vers les seules applications client/serveur. Les Contre notent aussi (RFC 2101) que la division en domaines d'adressage différents font que l'adresse IP cesse d'être unique, et que la résolution d'un nom en adresse donne un résultat qui va dépendre de l'endroit où on pose la question.

Plus fondamentalement, l'Internet repose sur un petit nombre d'excellents principes architecturaux, auxquels il doit son succès, notamment le principe de bout en bout. Ce principe a par exemple pour conséquences qu'il n'y a pas d'état maintenu dans le réseau : un équipement intermédiaire peut redémarrer (et donc tout oublier), un changement de routes peut faire passer par de nouveaux équipements intermédiaires et les extrémités, les machines terminales ne s'apercevront de rien, elles ne connaissaient absolument pas les équipements intermédiaires utilisés. Cela contribue fortement à la résilience du réseau. Le NAT met fin à cela.

J'ai écrit NAT jusqu'à présent mais, en fait, le mécanisme de traduction d'adresse le plus répandu dans l'Internet est plutôt le NAPT (Network Address and Port Translation), c'est à dire qu'il ne traduit pas juste une adresse dans une autre mais un couple {adresse interne, port interne} vers un couple {adresse externe, port externe}. Une grande partie des problèmes qu'on rencontre avec le NAT sont en fait spécifiques au NAPT et n'existeraient pas avec du « vrai » NAT.

Le RFC note que bien des choses qu'on peut dire contre le NAT (cassage du principe de bout en bout, problème pour les applications pair-à-pair) s'appliquent aussi aux pare-feux. La principale différence est que le but explicite d'un pare-feu est de s'insérer sur le trajet et de perturber les communications. En cas de problème, son rôle est donc clair. Au contraire, le NAT est souvent perçu comme transparent, et on oublie plus facilement son rôle, notamment lorsqu'il faut déboguer.

S'appuyant sur le RFC 2663, la section 2 du RFC couvre la terminologie, qui est souvent malmenée lorsqu'il s'agit du NAT :

  • NAT (Network Address Translation) est normalement la traduction d'une adresse IP vers une autre. On parle de static NAT lorsque la correspondance entre les deux adresses est fixe et de dynamic NAT lorsqu'elle change automatiquement. Le static NAT nécessite autant d'adresses internes que d'externes et ne règle donc pas le problème de l'épuisement des adresses IPv4.
  • NAPT (Network Address Port Translation) est ce que font réellement les routeurs abusivement appelés NAT, comme la box typique de M. Michu. Elle utilise un numéro de port de la couche 4 pour démultiplexer les paquets à destination de l'adresse IP publique.

Pour étudier l'impact du NAT sur l'Internet, il faut d'abord définir ce qu'est l'Internet. La définition du RFC est que l'Internet est une concaténation de réseaux utilisant les technologies TCP/IP. Selon cette définition, le réseau privé d'une entreprise fait partie de l'Internet. Une définition plus restrictive serait de dire que l'Internet est l'ensemble des machines ayant une adresse IP publique, et pouvant donc envoyer un paquet à toute autre machine de l'Internet. Selon cette seconde définition, un réseau utilisant des adresses IP privées (RFC 1918) et connecté via un NAT ne fait pas partie de l'Internet. En effet, comme le pare-feu, le NAT isole le réseau privé et ne permet pas d'accéder à tous les services de l'Internet. Dans cette définition stricte, seul le réseau public est l'Internet (avec un grand I puisque c'est un objet unique comme l'Atlantique ou le Kilimandjaro).

La section 4 rappelle le principe de bout en bout décrit plus haut (ou dans les RFC 1958 ou RFC 2775). Le document de référence sur ce principe est l'article de J.H. Saltzer, D.P. Reed et David Clark, « End-To-End Arguments in System Design ». Que dit ce principe ? Que tout état mémorisé par une machine du réseau doit être dans les extrémités. Si une machine à l'extrémité redémarre, la communication est fichue de toute façon. En revanche, il faut éviter que le redémarrage d'une machine intermédiaire ne coupe la communication. En effet, il y a beaucoup de machines intermédiaires (faites un traceroute pour voir) et, si la panne de l'une d'elles perturbait le trafic, l'Internet serait très fragile. Cela illustre la grande différence entre un routeur normal et un routeur NAT : lorsque le routeur normal redémarre (ou change, parce qu'on passe par un autre chemin), la communication continue. Au contraire, le redémarrage d'un routeur NAT fait perdre la table de correspondance entre les tuples {adresse, port} externes et les internes, arrêtant toutes les sessions en cours.

Quelques conséquences importantes du principe de bout en bout sont donc :

  • Pas besoin de synchroniser l'état des différents routeurs dans le réseau : un routeur n'a pas de mémoire. En cas de problème, router par un autre chemin est trivial. (Notez que c'est pour cela que faire du NAT lorsqu'on a plusieurs sorties vers l'Internet est très difficile, car il faut que tous les routeurs NAT se partagent leur table de correspondances externe<->interne.)
  • Le nombre de machines terminales croit plus vite que celui des routeurs. Si les routeurs devaient garder un état proportionnel au nombre de machines terminales, le réseau passerait bien moins à l'échelle.
  • L'absence d'état et, plus généralement d'« intelligence » dans les routeurs, fait que les décisions de sécurité n'ont pas besoin d'être gérées par le réseau. Deux machines qui communiquent s'occupent de leur sécurité et n'ont pas à faire confiance aux équipements intermédiaires. C'est important, par exemple, lorsqu'on voyage, et qu'on ne peut pas être sûr de la confiance à accorder au réseau de l'hôtel ou de l'aéroport.
  • Le point ci-dessus s'applique à tous les services : l'absence d'intelligence dans le réseau (qui est liée d'ailleurs à l'idée plus récente de neutralité du réseau) permet à deux machines consentantes de mettre en œuvre des nouveaux services, sans devoir attendre que quoi que ce soit ait été déployé dans le réseau. Un réseau où une grande partie du travail serait faite dans le réseau lui-même et pas aux extrémités, serait très hostile à l'innovation. Au contraire, le succès de l'Internet est dû en grande partie à la possibilité de déployer de nouvelles applications sans permission. (Et je rajoute que l'un des principaux problèmes de l'Internet d'aujourd'hui est son ossification, due largement au NAT, qui empêche de déployer, par exemple un nouveau protocole de transport comme SCTP.)

Les deux sections suivantes sont consacrées à une mise en comparaison des avantages et inconvénients du NAT (la section 11, en conclusion, les résumera sous forme d'un tableau simple). D'abord, en section 5, ses avantages, dans la résolution de plusieurs problèmes réels :

  • En masquant les adresses IP internes aux observateurs extérieurs, il permet de se dispenser de renumérotation lorsqu'on change d'opérateur (le RFC 5887, par la suite, a analysé la difficulté de la renumérotation).
  • En cas d'usage intermittent, le NAT permet d'économiser les adresses IP globales en ne les attribuant qu'en cas d'usage effectif. (Cet argument n'a plus guère de sens aujourd'hui, avec les accès « always on » comme l'ADSL.)
  • L'usage d'adresses privées, auto-allouées localement par l'utilisateur, dispense de justifier, auprès d'une grosse bureaucratie, l'obtention d'adresses IP uniques.
  • Pour beaucoup d'applications, notamment celles de type client/serveur, aucun changement n'est nécessaire dans les machines terminales lorsqu'on déploie le NAT.

Toutes ces raisons expliquent le succès du NAT.

Et les inconvénients ? La section 6 en dresse une liste :

  • Le NAT casse le principe de bout en bout.
  • Le NAT remplace un modèle simple par un modèle plus complexe, plus fragile et plus difficile à déboguer.
  • Il crée un SPOF (le redémarrage du routeur NAT coupe toutes les sessions de toutes les machines du réseau local). Ce point est détaillé dans la section 7.1.
  • Il perturbe des techniques de sécurité comme le AH d'IPsec (RFC 4302). Pour cette raison, mais aussi pour d'autres, AH n'a guère été déployé et cet argument n'est donc peut-être pas le plus fort (alors que le RFC, à l'époque, le considérait comme « One of the greatest concerns »).
  • Les adresses privées semblent très sympas au début (on se les alloue soi-même sans s'embêter et sans rien demander à personne) mais sont une grosse source d'ennuis lorsque deux réseaux privés communiquent, par exemple suite à une fusion d'entreprises, ou si on se connecte à deux réseaux distants utilisant la même plage d'adresses (la section 7.6 donne un exemple).
  • Le NAT casse les protocoles qui ont une connexion de contrôle séparée de la connexion de données, ce qui est fréquent dans le multimédia (SIP, H.323, et tous les protocoles qui fonctionnent en indiquant une référence à une machine tierce). La connexion de données se fait typiquement en utilisant des adresses IP indiquées par le pair... qui ne marcheront pas car ce sont des adresses privées, le pair ne savait pas qu'il était NATé.
  • Le NAT augmente la complexité de la connexion : c'est un facteur de plus à prendre en compte lorsqu'on débogue.
  • Les connexions entrantes sont impossibles par défaut (ce qui pose problème si on veut héberger un serveur sur le réseau local). On peut sur les routeurs NAT typiques définir une correspondance d'un port bien connu (par exemple 80 pour HTTP) vers une machine interne mais cela ne permet qu'un seul serveur pour chaque port bien connu.
  • Depuis l'écriture de ce RFC 2993, UPnP, puis le PCP (Port Control Protocol) du RFC 6887, ont facilité un peu la vie des applications coincées derrière un routeur NAT, en leur permettant un contrôle limité des correspondances statiques entre {adresse, port} externes et internes.

Il y a aussi des inconvénients plus techniques, comme le fait que le délai d'attente de TCP avant de réutiliser un identificateur de connexion (l'état TCP_TIME_WAIT) peut vite être trop long pour un routeur NAT actif, le soumettant à la tentation d'ignorer ce délai minimum (deux fois la durée de vie d'un segment dans le réseau, normalement).

Par contre, ce RFC oublie un inconvénient important du NAPT (mais pas du NAT) : le partage d'adresses IP publiques, dont les conséquences négatives ont été analysées onze ans plus tard dans le RFC 6269.

La question de la sécurité du NAT occupe la section 9. C'est un point d'autant plus important que certaines personnes prétendent parfois que le NAT améliore la sécurité. En fait, notre RFC note que cela peut être tout le contraire, en créant l'illusion d'une barrière, d'un pare-feu, le NAT peut abaisser le niveau de sécurité. Le RFC critique aussi cette idéologie du pare-feu, qui considère que toutes les menaces sont externes, dans le style du limes romain. Si on pense qu'on est protégé derrière son routeur NAT, c'est qu'on ignore une règle de base de la sécurité, qui est que l'attaque vient souvent de l'intérieur.

Si le NAT, par définition, casse les techniques de sécurité qui protègent l'intégrité du paquet, comme l'AH d'IPsec, d'autres techniques de sécurité peuvent passer malgré le NAT. C'est le cas de TLS ou de SSH. Notez que ces techniques fonctionnent dans la couche 7 et restent donc vulnérables à des attaques qu'IPsec aurait empêchées, comme les resets TCP (cf. RFC 2385).

La section 10 contient quelques conseils de déploiement, pour le cas où on décide de faire du NAT. Le RFC recommande de chercher un mécanisme de résolution de noms qui gère le fait que les adresses soient différentes en interne et en externe, et suggère qu'un serveur DNS intégré au routeur NAT est sans doute dans la meilleure position pour faire cela. Il insiste sur le déploiement d'ALG pour les applications qui ne passent pas à travers le NAT (ou bien l'établissement d'un tunnel au dessus du NAT). Il fait remarquer (c'était une idée novatrice à l'époque) qu'il existe plein de variantes de NAPT, avec des comportements différents. Par exemple, si une application émet un paquet depuis le tuple {adresse interne, port interne} vers une destination extérieure, son tuple interne va être réécrit en {adresse externe, port externe}. Si cette application écrit ensuite à une autre destination extérieure, depuis le même tuple {adresse interne, port interne}, celui-ci sera t-il réécrit dans le même tuple {adresse externe, port externe} ou pas ? Tous les routeurs NAT n'ont pas forcément le même comportement sur ce point, et cela influe beaucoup sur les chances d'une application de passer à travers le NAT (RFC 4787).

Le RFC a aussi des suggestions plus surprenantes comme l'idée d'un registre des adresses privées, pour diminuer les risques de collision dans le cas où un client a des VPN vers deux réseaux privés utilisant la même plage d'adresses. Si cela a un sens au sein d'une même organisation (dont on peut espérer qu'elle a déjà un plan d'adressage cohérent, évitant les collisions), l'idée d'un registre plus large va à l'encontre du principe des adresses privées.

Depuis la sortie de ce RFC, l'IETF a accepté le principe d'un travail pour limiter les dégâts du NAT, le groupe de travail Behave, qui a produit plein d'excellents RFC. L'idée même d'un tel travail gênait certains à l'IETF, car ils pensaient qu'améliorer le NAT allait retarder son démantèlement souhaitable. Mais la prévalence du NAT a conduit à une position de compromis, avec un certain nombre de techniques permettant de vivre avec le NAT.

En résumé, ce RFC est hostile à la généralisation du NAT, non pas en disant qu'il ne marche pas (« it is possible to build a house of cards ») mais en notant qu'il restera toujours un bricolage fragile. Le problème de l'épuisement des adresses IPv4 doit se résoudre par le déploiement d'IPv6, pas par le NAT. On notera que cet avis n'a pas été suivi dans les treize années écoulées depuis la parution de ce RFC : l'IETF peut dire ce qu'elle veut, cela ne change rien en pratique. Les décisions ne sont pas prises par elle.


Téléchargez le RFC 2993


L'article seul

RFC 7012: Information Model for IP Flow Information eXport (IPFIX)

Date de publication du RFC : Unknown month 2013 September
Auteur(s) du RFC : B. Claise (Cisco), B. Trammell (ETH Zurich)
Chemin des normes
Première rédaction de cet article le 16 septembre 2013


Le protocole IPFIX d'envoi par un routeur de résumés statistiques sur le trafic qu'il voit passer (RFC 7011), dépend d'un modèle de données, que décrit notre RFC, qui remplace l'ancien RFC 5102.

Le RFC 7011 qui normalise le protocole IPFIX indique comment transporter les données de l'exporteur (typiquement un routeur) vers le récolteur (typiquement la machine d'administration du réseau) mais n'indique pas quelles données sont transportées. Notre RFC va jouer ce rôle, équivalent à celui du SMI du RFC 2578 pour SNMP.

Notre RFC est assez simple (son prédécesseur, le RFC 5102 était très long, mais c'est parce qu'il intégrait la liste des éléments d'information disponibles, elle est désormais dans un registre IANA). Un élément d'information a un nom (par exemple destinationTransportPort), une description (cet élément indique le port de destination du flot), un type (ici unsigned16, nombre entier sur 16 bits) et d'autres informations utiles comme un ElementID qui identifie de manière unique un élément d'information. Les types sont décrits en détail dans la section 3 mais sont très classiques (entiers de différentes factures, booléens, adresses MAC, chaînes de caractères en Unicode, etc). Plus originaux sont les sémantiques de la section 3.2. Si les éléments ont par défaut la sémantique quantity (ils affichent la valeur actuellement mesurée), d'autres sont différents, par exemple en indiquant un total (sémantique d'odomètre). Ainsi, les éléments ayant une sémantique de totalCounter repartent de zéro lorsqu'ils ont atteint leur valeur maximale. Ceux ayant la sémantique identifier ne sont pas des nombres (même quand leur valeur est numérique, comme les numéros d'AS) et ne doivent donc pas être additionnés.

Voici un exemple complet, tiré du registre. Certains champs sont obligatoires, comme le nom, la description, le type (ici un entier non signé de 64 bits) ou l'ElementID (qui peut être un nombre simple attribué par l'IANA, pour les éléments « officiels » comme le 85 montré ici, ou bien complété par un numéro d'organisation pour les autres). D'autres sont facultatifs comme l'unité (ici, des octets ; une erreur dans les unités a déjà entraîné la perte d'une sonde spatiale). Le nom suit parfois des conventions de nommage (section 2.3). Par exemple, les éléments dont le nom commence par post identifient une mesure faite après un traitement par une middlebox, par exemple une traduction d'adresse. Voici l'élément octetTotalCount :

octetTotalCount
   Description:
      The total number of octets in incoming packets for this Flow at
      the Observation Point since the Metering Process
      (re-)initialization for this Observation Point.  The number of
      octets include IP header(s) and IP payload.
   Abstract Data Type: unsigned64
   Data Type Semantics: totalCounter
   ElementId: 85
   Status: current
   Units: octets

Le vrai format source du registre (regardez https://www.iana.org/assignments/ipfix/ipfix.xml depuis autre chose qu'un navigateur Web) est XML (section 7.3), avec un schéma en Relax NG. La définition ci-dessus est en fait :


<record>
<name>octetTotalCount</name>
<dataType>unsigned64</dataType>
<group>flowCounter</group>
<dataTypeSemantics>totalCounter</dataTypeSemantics>
<elementId>85</elementId>
<applicability>all</applicability>
<status>current</status>
<description>
<paragraph>
The total number of octets in incoming packets
for this Flow at the Observation Point since the Metering
Process (re-)initialization for this Observation Point.  The
number of octets includes IP header(s) and IP payload.
</paragraph>
</description>
<units>octets</units>
<xref type="rfc" data="rfc5102"/>
<revision>0</revision>
<date>2013-02-18</date>
</record>

Les éléments dans le registre IANA sont décrits en XML car cela permet de produire automatiquement du code ou des fichiers de configuration à partir du registre. Mais le protocole IPFIX lui-même n'utilise pas du tout XML.

Les changements depuis le RFC 5102 sont décrits en section 1.1. Le principal est que la liste des éléments d'information, au lieu d'être listée dans le RFC, est désormais dans un registre IANA. D'autre part, le mécanisme pour modifier cette liste a été légèrement changé (section 7.4). Il est décrit en détail dans le RFC 7013. En gros, pour ajouter un nouvel élément d'information, il faut un examen par un expert (le RFC 5226 décrit toutes ces procédures).


Téléchargez le RFC 7012


L'article seul

RFC 7011: Specification of the IP Flow Information eXport (IPFIX) Protocol for the Exchange of Flow Information

Date de publication du RFC : Septembre 2013
Auteur(s) du RFC : B. Claise (Cisco Systems), B. Trammell (ETH Zurich)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF ipfix
Première rédaction de cet article le 16 septembre 2013


Le système IPFIX, successeur désigné de Netflow avait été normalisé dans le RFC 5101, que notre RFC met légèrement à jour. Des routeurs de différentes marques peuvent donc désormais envoyer des informations statistiques à des machines d'administration de différentes origines. L'idée de base, héritée de Netflow, est d'agréger les informations de trafic, pour que le routeur n'ait à envoyer qu'une synthèse, et pas la totalité du trafic. Comme Netflow, IPFIX peut servir à la gestion du réseau, à la supervision mais aussi à l'espionnage.

Un cahier des charges pour IPFIX avait été spécifié dans le RFC 3917. Le système IPFIX lui-même est normalisé depuis le RFC 5101, ce nouveau RFC prenant en charge le protocole d'autres RFC s'occupant du modèle d'informations (RFC 7012 et RFC 5610) ou bien de l'architecture des différents composants d'IPFIX. C'est ainsi qu'IPFIX a des extensions rigolotes comme la technique de compression du RFC 5473, les données complexes du RFC 6313 ou le stockage de donnéees dans des fichiers permanents du RFC 5655.

La terminologie d'IPFIX est en section 2. Il est recommandé de lire le document d'architecture, le RFC 5470. Un point d'observation (Observation Point) est l'endroit du réseau d'où on observe (le port d'un routeur, par exemple). Un domaine d'observation (Observation Domain) est l'ensemble des points d'observation dont les observations vont être agrégées en un seul message IPFIX (un routeur, par exemple). Un flot (flow) est un ensemble de paquets, passant par le même point d'observation, et ayant des caractéristiques communes. la définition est volontairement très ouverte. Un flot ne correspond donc pas forcément à une connexion TCP. Par exemple, un flot peut être défini par :

  • Les en-têtes du paquet : adresses IP de source et de destination, bien sûr, mais aussi les ports, et/ou des champs applicatifs. Donc, « tous les paquets depuis ou vers [2001:db8:1:2]:53 » est un flot, identifiant le trafic DNS de 2001:db8:1:2.
  • Les caractéristiques du traitement du paquet : prochain routeur ou interface de sortie.

Un enregistrement de flot (flow record) est composé de la définition du flot et des valeurs mesurées (nombre total de paquets appartenant à ce flot qui ont été vus, nombre total d'octets). Un gabarit (template) est une structure de données qui décrit ce qui est contenu dans les enregistrements. Un exporteur (exporter), typiquement le routeur, va émettre ces enregistrements, contenant le résultat de ses observations, vers un collecteur (collector) où on fabriquera de jolis graphes.

Notre RFC normalise ensuite le format des paquets (section 3). Comme avec d'autres protocoles, les paquets commencent par un numéro de version, 10 ici (inchangé depuis le RFC 5101), IPFIX marquant sa descendance depuis Netflow, dont la dernière version était la 9. Le RFC décrit aussi l'encodage des données exportées par l'observateur IPFIX (section 6).

Des exemples d'encodage sont fournis dans l'annexe A. Par exemple, A.2.1 utilise des éléments enregistrés à l'IANA (IPFIX permet aussi de définir les siens) :

  • Adresse IP source sourceIPv4Address,
  • Adresse IP destination destinationIPv4Address,
  • Routeur suivant ipNextHopIPv4Address,
  • Nombre de paquets packetDeltaCount,
  • Nombre d'octets octetDeltaCount.

Les trois premiers identifient le flot et les deux derniers sont les mesures par flot. Le gabarit va donc lister ces cinq élements, avec leur taille (quatre octets chacun).

Enfin, notre RFC décrit le mécanisme de transport, au dessus d'UDP, le protocole traditionnel de Netflow, mais aussi de TCP ou bien du protocole recommandé, SCTP. Pour répondre au cahier des charges, qui insistait sur la sécurité, la section 11.1 décrit aussi l'utilisation de TLS. À propos de sécurité, la section 11 se penche aussi sur la confidentialité (IPFIX permet de transporter des informations sur les métadonnées d'une communication, permettant l'analyse de trafic ; même si on n'a pas le contenu des communications, cela peut être très indiscret). Elle attire aussi l'attention du programmeur sur l'importance de s'assurer de l'intégrité des données. IPFIX pouvant être utilisé pour la facturation, un client malhonnête peut avoir une bonne motivation pour modifier ces données.

La section 1.1 décrit les changements depuis le premier RFC, le RFC 5101. Ils sont de peu d'importance et deux logiciels suivant les deux RFC pourront interagir. Il y a eu plusieurs corrections d'erreurs dans la spécification, les définitions d'élements d'information situées dans l'ancien RFC ont toute été sorties, vers le registre IANA, qui fait désormais seul autorité. Une nouvelle section, la 5.2, traite le problème du débordement de certains types temporels, débordement qui se produira en 2032 ou 2038 selon les cas (cela semble loin dans le futur mais les logiciels durent longtemps, rappelez-vous le bogue de l'an 2000).

IPFIX est déjà mis en œuvre dans plusieurs systèmes. Un exemple de mise en œuvre en logiciel libre est Maji. Mais, apparemment Cacti ne sait pas exporter de l'IPFIX, juste du vieux Netflow. Ntop sait faire mais il faut passer à nProbe l'option -V 10 (plein d'exemple dans cet article, merci à Andrew Feren pour les informations). Si vous voulez voir des traces IPFIX, il y en a deux sur pcapr. Wireshark sait analyser de l'IPFIX, il faut lui demander de décoder comme du cflow. Le RFC 5153 donne des conseils aux programmeurs qui veulent créer ou lire de l'IPFIX. Les RFC 5471 et RFC 5472 sont utiles aux administrateurs réseaux qui voudraient déployer IPFIX. Toutefois, aujourd'hui, des années après la sortie du premier RFC, il semble que peu d'opérateurs utilisent IPFIX (v10). La plupart sont restés bloqués sur Netflow (v9). Les « grands » routeurs (Juniper ou Cisco) savent faire de l'IPFIX mais pas forcément les routeurs de bas de gamme.

Deux autres logiciels importants, des collecteurs IPFIX. Il y a bien sûr pmacct mais aussi Vflow. Voici un exemple de fichier de configuration pmacct :

# Les bases de données dans lesquelles on stockera
plugins: memory,sqlite3,pgsql

# La version du schéma de données (7 est la plus récente)
sql_table_version: 7

# Le port UDP où les données IPFIX sont envoyées (cela doit coïncider
# avec la config' du routeur)
nfacctd_port: 2055

# Le ou les critères d'agrégation
aggregate: src_host

Avec une telle configuration, voici ce qui sera enregistré dans la base PostgreSQL :

pmacct=> select ip_src,bytes,packets from acct_v7 ;
    ip_src    | bytes  | packets 
--------------+--------+---------
 10.10.86.133 | 371740 |    2083
 192.0.2.2    | 368576 |    2804
(2 lignes)

Mais, au lieu de PostgreSQL, on aurait pu aussi utiliser le client en ligne de commandes (grâce au plugin memory) :

% pmacct -s
SRC_IP                                         PACKETS               BYTES
192.0.2.2                                      2363                  310176
10.10.86.133                                   1749                  312036

For a total of: 2 entries

Maintenant, si on ajoute au fichier de configuration une agrégation sur d'autres critères :

aggregate: src_host,dst_host,proto,src_port,dst_port

On aura alors bien plus de lignes dans les bases (une par tuple, et le port source du trafic SSH varie à chaque fois) :

% pmacct -s
SRC_IP                                         DST_IP                                         SRC_PORT  DST_PORT  PROTOCOL    PACKETS               BYTES
10.10.86.133                                   192.0.2.2                                      57230     22        tcp         6                     488
10.10.86.133                                   192.0.2.2                                      57250     22        tcp         6                     488
...
192.0.2.2                                      192.0.2.1                                      39802     53        udp         1                     71
192.0.2.2                                      10.10.86.133                                   22        57206     tcp         17                    2539

For a total of: 180 entries

Et idem dans la base PostgreSQL :

pmacct=> select count(*) from acct_v7 ;
 count 
-------
   198
(1 ligne)

On peut utiliser SQL pour faire des sélections, des agrégations... Exemple, tout le trafic depuis une machine, avec la fonction d'agrégation SQL sum et la fonction de sélection SQL where :

pmacct=> select sum(bytes), sum(packets) from acct_v7 where ip_src='192.0.2.2';
  sum   | sum  
--------+------
 326807 | 2492
(1 ligne)

Ou bien tout le trafic UDP :

pmacct=> select sum(bytes), sum(packets) from acct_v7 where ip_proto=17;
  sum   | sum  
--------+------
 111738 | 1574
(1 ligne)

Par défaut, les données sont agrégées, quel que soit leur âge. Si on veut faire des études historiques, il faut demander à garder les données plus anciennes :

aggregate: src_host,dst_host
sql_history: 5m
sql_history_roundoff: m

On voit alors les données « tourner » (notez le order SQL pour classer par ordre rétro-chronologique) :

pmacct=> select ip_src,ip_dst,packets,stamp_inserted,stamp_updated from acct_v7 where ip_dst!='0.0.0.0' order by stamp_updated desc;
    ip_src    |    ip_dst    | packets |   stamp_inserted    |    stamp_updated    
--------------+--------------+---------+---------------------+---------------------
 10.10.86.133 | 192.0.2.2    |    1249 | 2016-05-03 10:25:00 | 2016-05-03 10:28:02
 192.0.2.2    | 10.10.86.133 |    1487 | 2016-05-03 10:25:00 | 2016-05-03 10:28:02
 192.0.2.2    | 192.0.2.1    |     116 | 2016-05-03 10:25:00 | 2016-05-03 10:28:02
 192.0.2.2    | 192.0.2.1    |     252 | 2016-05-03 10:20:00 | 2016-05-03 10:26:02
 192.0.2.2    | 10.10.86.133 |    2906 | 2016-05-03 10:20:00 | 2016-05-03 10:26:02
 10.10.86.133 | 192.0.2.2    |    2354 | 2016-05-03 10:20:00 | 2016-05-03 10:26:02
 10.10.86.133 | 192.0.2.2    |    2364 | 2016-05-03 10:15:00 | 2016-05-03 10:21:02
 192.0.2.2    | 192.0.2.1    |     270 | 2016-05-03 10:15:00 | 2016-05-03 10:21:02
 192.0.2.2    | 10.10.86.133 |    2911 | 2016-05-03 10:15:00 | 2016-05-03 10:21:02
 192.0.2.2    | 10.10.86.133 |    1645 | 2016-05-03 10:10:00 | 2016-05-03 10:16:02
 192.0.2.2    | 192.0.2.1    |     154 | 2016-05-03 10:10:00 | 2016-05-03 10:16:02
 10.10.86.133 | 192.0.2.2    |    1310 | 2016-05-03 10:10:00 | 2016-05-03 10:16:02
(12 lignes)

(Chaque enregistrement dure un peu plus que les cinq minutes configurées car pmacct « bufferise ».)

Voici enfin un exemple de paquet vu par Wireshark. C'est du vrai IPFIX (numéro de version 10).

[Premier paquet, avec les gabarits]

Cisco NetFlow/IPFIX
    Version: 10
    Length: 876
    Timestamp: Jul  8, 2011 21:18:53.000000000 CEST
        ExportTime: 1310152733
    FlowSequence: 0
    Observation Domain Id: 0
    Set 1
        FlowSet Id: Data Template (V10 [IPFIX]) (2)
        FlowSet Length: 248
        Template (Id = 47104, Count = 25)
            Template Id: 47104
            Field Count: 25
            Field (1/25): flowStartMilliseconds
                0... .... .... .... = Pen provided: No
                .000 0000 1001 1000 = Type: flowStartMilliseconds (152)
                Length: 8
            Field (2/25): flowEndMilliseconds
                0... .... .... .... = Pen provided: No
                .000 0000 1001 1001 = Type: flowEndMilliseconds (153)
                Length: 8
            Field (3/25): BYTES_TOTAL
                0... .... .... .... = Pen provided: No
                .000 0000 0101 0101 = Type: BYTES_TOTAL (85)
                Length: 8
            Field (4/25): BYTES_TOTAL [Reverse]
                1... .... .... .... = Pen provided: Yes
                .000 0000 0101 0101 = Type: BYTES_TOTAL (85) [Reverse]
                Length: 8
                PEN: IPFIX Reverse Information Element Private Enterprise (29305)
            Field (5/25): PACKETS_TOTAL
                0... .... .... .... = Pen provided: No
                .000 0000 0101 0110 = Type: PACKETS_TOTAL (86)
                Length: 8
            Field (6/25): PACKETS_TOTAL [Reverse]
                1... .... .... .... = Pen provided: Yes
                .000 0000 0101 0110 = Type: PACKETS_TOTAL (86) [Reverse]
                Length: 8
                PEN: IPFIX Reverse Information Element Private Enterprise (29305)
            Field (7/25): IPV6_SRC_ADDR
                0... .... .... .... = Pen provided: No
                .000 0000 0001 1011 = Type: IPV6_SRC_ADDR (27)
                Length: 16
            Field (8/25): IPV6_DST_ADDR
                0... .... .... .... = Pen provided: No
                .000 0000 0001 1100 = Type: IPV6_DST_ADDR (28)
                Length: 16
            Field (9/25): IP_SRC_ADDR
                0... .... .... .... = Pen provided: No
                .000 0000 0000 1000 = Type: IP_SRC_ADDR (8)
                Length: 4
            Field (10/25): IP_DST_ADDR
                0... .... .... .... = Pen provided: No
                .000 0000 0000 1100 = Type: IP_DST_ADDR (12)
                Length: 4
            Field (11/25): L4_SRC_PORT
                0... .... .... .... = Pen provided: No
                .000 0000 0000 0111 = Type: L4_SRC_PORT (7)
                Length: 2
            Field (12/25): L4_DST_PORT
                0... .... .... .... = Pen provided: No
                .000 0000 0000 1011 = Type: L4_DST_PORT (11)
                Length: 2
            Field (13/25): PROTOCOL
                0... .... .... .... = Pen provided: No
                .000 0000 0000 0100 = Type: PROTOCOL (4)
                Length: 1
            Field (14/25): flowEndReason
                0... .... .... .... = Pen provided: No
                .000 0000 1000 1000 = Type: flowEndReason (136)
                Length: 1
            Field (15/25): paddingOctets
                0... .... .... .... = Pen provided: No
                .000 0000 1101 0010 = Type: paddingOctets (210)
                Length: 6
            Field (16/25):  21 [pen: CERT Coordination Center]
                1... .... .... .... = Pen provided: Yes
                .000 0000 0001 0101 = Type: 21 [pen: CERT Coordination Center]
                Length: 4
                PEN: CERT Coordination Center (6871)
            Field (17/25): TCP_SEQ_NUM
                0... .... .... .... = Pen provided: No
                .000 0000 1011 1000 = Type: TCP_SEQ_NUM (184)
                Length: 4
            Field (18/25): TCP_SEQ_NUM [Reverse]
                1... .... .... .... = Pen provided: Yes
                .000 0000 1011 1000 = Type: TCP_SEQ_NUM (184) [Reverse]
                Length: 4
                PEN: IPFIX Reverse Information Element Private Enterprise (29305)
            Field (19/25):  14 [pen: CERT Coordination Center]
                1... .... .... .... = Pen provided: Yes
                .000 0000 0000 1110 = Type: 14 [pen: CERT Coordination Center]
                Length: 1
                PEN: CERT Coordination Center (6871)
            Field (20/25):  15 [pen: CERT Coordination Center]
                1... .... .... .... = Pen provided: Yes
                .000 0000 0000 1111 = Type: 15 [pen: CERT Coordination Center]
                Length: 1
                PEN: CERT Coordination Center (6871)
            Field (21/25): 16398 [pen: CERT Coordination Center]
                1... .... .... .... = Pen provided: Yes
                .100 0000 0000 1110 = Type: 16398 [pen: CERT Coordination Center]
                Length: 1
                PEN: CERT Coordination Center (6871)
            Field (22/25): 16399 [pen: CERT Coordination Center]
                1... .... .... .... = Pen provided: Yes
                .100 0000 0000 1111 = Type: 16399 [pen: CERT Coordination Center]
                Length: 1
                PEN: CERT Coordination Center (6871)
            Field (23/25): SRC_VLAN
                0... .... .... .... = Pen provided: No
                .000 0000 0011 1010 = Type: SRC_VLAN (58)
                Length: 2
            Field (24/25): SRC_VLAN [Reverse]
                1... .... .... .... = Pen provided: Yes
                .000 0000 0011 1010 = Type: SRC_VLAN (58) [Reverse]
                Length: 2
                PEN: IPFIX Reverse Information Element Private Enterprise (29305)
            Field (25/25): Unknown(32767)
                0... .... .... .... = Pen provided: No
                .111 1111 1111 1111 = Type: Unknown (32767)
                Length: 65535 [i.e.: "Variable Length"]
        Template (Id = 49155, Count = 3)
            Template Id: 49155
            Field Count: 3
            Field (1/3): TCP_SEQ_NUM
                0... .... .... .... = Pen provided: No
                .000 0000 1011 1000 = Type: TCP_SEQ_NUM (184)
                Length: 4
            Field (2/3):  14 [pen: CERT Coordination Center]
                1... .... .... .... = Pen provided: Yes
                .000 0000 0000 1110 = Type: 14 [pen: CERT Coordination Center]
                Length: 1
                PEN: CERT Coordination Center (6871)
            Field (3/3):  15 [pen: CERT Coordination Center]
                1... .... .... .... = Pen provided: Yes
                .000 0000 0000 1111 = Type: 15 [pen: CERT Coordination Center]
                Length: 1
                PEN: CERT Coordination Center (6871)
        Template (Id = 49171, Count = 6)
            Template Id: 49171
            Field Count: 6
            Field (1/6): TCP_SEQ_NUM
                0... .... .... .... = Pen provided: No
                .000 0000 1011 1000 = Type: TCP_SEQ_NUM (184)
                Length: 4
            Field (2/6):  14 [pen: CERT Coordination Center]
                1... .... .... .... = Pen provided: Yes
                .000 0000 0000 1110 = Type: 14 [pen: CERT Coordination Center]
                Length: 1
                PEN: CERT Coordination Center (6871)
            Field (3/6):  15 [pen: CERT Coordination Center]
                1... .... .... .... = Pen provided: Yes
                .000 0000 0000 1111 = Type: 15 [pen: CERT Coordination Center]
                Length: 1
                PEN: CERT Coordination Center (6871)
            Field (4/6): 16398 [pen: CERT Coordination Center]
                1... .... .... .... = Pen provided: Yes
                .100 0000 0000 1110 = Type: 16398 [pen: CERT Coordination Center]
                Length: 1
                PEN: CERT Coordination Center (6871)
            Field (5/6): 16399 [pen: CERT Coordination Center]
                1... .... .... .... = Pen provided: Yes
                .100 0000 0000 1111 = Type: 16399 [pen: CERT Coordination Center]
                Length: 1
                PEN: CERT Coordination Center (6871)
            Field (6/6): TCP_SEQ_NUM [Reverse]
                1... .... .... .... = Pen provided: Yes
                .000 0000 1011 1000 = Type: TCP_SEQ_NUM (184) [Reverse]
                Length: 4
                PEN: IPFIX Reverse Information Element Private Enterprise (29305)
        Template (Id = 49176, Count = 2)
            Template Id: 49176
            Field Count: 2
            Field (1/2):  18 [pen: CERT Coordination Center]
                1... .... .... .... = Pen provided: Yes
                .000 0000 0001 0010 = Type: 18 [pen: CERT Coordination Center]
                Length: 65535 [i.e.: "Variable Length"]
                PEN: CERT Coordination Center (6871)
            Field (2/2): 16402 [pen: CERT Coordination Center]
                1... .... .... .... = Pen provided: Yes
                .100 0000 0001 0010 = Type: 16402 [pen: CERT Coordination Center]
                Length: 65535 [i.e.: "Variable Length"]
                PEN: CERT Coordination Center (6871)
        Template (Id = 49156, Count = 2)
            Template Id: 49156
            Field Count: 2
            Field (1/2): SRC_MAC
                0... .... .... .... = Pen provided: No
                .000 0000 0011 1000 = Type: SRC_MAC (56)
                Length: 6
            Field (2/2): DESTINATION_MAC
                0... .... .... .... = Pen provided: No
                .000 0000 0101 0000 = Type: DESTINATION_MAC (80)
                Length: 6

[Deuxième paquet, avec les données]

Cisco NetFlow/IPFIX
    Version: 10
    Length: 464
    Timestamp: Jul  8, 2011 21:18:53.000000000 CEST
        ExportTime: 1310152733
    FlowSequence: 0
    Observation Domain Id: 0
    Set 1
        FlowSet Id: (Data) (45840)
        FlowSet Length: 448
        Flow 1
            [Duration: 0.274000000 seconds]
                StartTime: Jun  7, 2011 15:22:38.902000000 CEST
                EndTime: Jun  7, 2011 15:22:39.176000000 CEST
            Permanent Octets: 220
            Permanent Octets: 276 (Reverse Type 85 BYTES_TOTAL)
            Permanent Packets: 4
            Permanent Packets: 4 (Reverse Type 86 PACKETS_TOTAL)
            SrcAddr: 77.250.217.161 (77.250.217.161)
            DstAddr: 192.168.5.219 (192.168.5.219)
            SrcPort: 51413
            DstPort: 52026
            Protocol: 6
            Flow End Reason: End of Flow detected (3)
            Enterprise Private entry: (CERT Coordination Center) Type 21: Value (hex bytes): 00 00 00 00
            Vlan Id: 0
            Vlan Id: 0 (Reverse Type 58 SRC_VLAN)
            [Enterprise Private entry: ((null)) Type 32767: Value (hex bytes): 00 c0 13 00 10 14 8d 68 ed 12 11 18 11 ed 4e 7d ... (Variable Length)]
                String_len_short: 255
                String_len_short: 17
        Flow 2
            [Duration: 0.672000000 seconds]
                StartTime: Jun  7, 2011 15:22:40.813000000 CEST
                EndTime: Jun  7, 2011 15:22:41.485000000 CEST
            Permanent Octets: 336
            Permanent Octets: 164 (Reverse Type 85 BYTES_TOTAL)
            Permanent Packets: 5
            Permanent Packets: 3 (Reverse Type 86 PACKETS_TOTAL)
            SrcAddr: 192.168.5.219 (192.168.5.219)
            DstAddr: 84.97.86.239 (84.97.86.239)
            SrcPort: 52035
            DstPort: 43572
            Protocol: 6
            Flow End Reason: End of Flow detected (3)
            Enterprise Private entry: (CERT Coordination Center) Type 21: Value (hex bytes): 00 00 00 dd
            Vlan Id: 0
            Vlan Id: 0 (Reverse Type 58 SRC_VLAN)
            [Enterprise Private entry: ((null)) Type 32767: Value (hex bytes): 00 c0 13 00 10 a3 c6 5c 68 02 19 12 11 8e be b7 ... (Variable Length)]
                String_len_short: 255
                String_len_short: 17
        Flow 3
            [Duration: 2.046000000 seconds]
                StartTime: Jun  7, 2011 15:22:40.813000000 CEST
                EndTime: Jun  7, 2011 15:22:42.859000000 CEST
            Permanent Octets: 336
            Permanent Octets: 164 (Reverse Type 85 BYTES_TOTAL)
            Permanent Packets: 5
            Permanent Packets: 3 (Reverse Type 86 PACKETS_TOTAL)
            SrcAddr: 192.168.5.219 (192.168.5.219)
            DstAddr: 142.68.133.226 (142.68.133.226)
            SrcPort: 52036
            DstPort: 50006
            Protocol: 6
            Flow End Reason: End of Flow detected (3)
            Enterprise Private entry: (CERT Coordination Center) Type 21: Value (hex bytes): 00 00 03 51
            Vlan Id: 0
            Vlan Id: 0 (Reverse Type 58 SRC_VLAN)
            [Enterprise Private entry: ((null)) Type 32767: Value (hex bytes): 00 c0 13 00 10 54 cc ca 16 02 19 12 11 74 3f 5e ... (Variable Length)]
                String_len_short: 255
                String_len_short: 17
        Flow 4
            [Duration: 0.162000000 seconds]
                StartTime: Jun  7, 2011 15:22:43.806000000 CEST
                EndTime: Jun  7, 2011 15:22:43.968000000 CEST
            Permanent Octets: 60
            Permanent Octets: 40 (Reverse Type 85 BYTES_TOTAL)
            Permanent Packets: 1
            Permanent Packets: 1 (Reverse Type 86 PACKETS_TOTAL)
            SrcAddr: 192.168.5.219 (192.168.5.219)
            DstAddr: 84.221.224.151 (84.221.224.151)
            SrcPort: 52047
            DstPort: 44809
            Protocol: 6
            Flow End Reason: End of Flow detected (3)
            Enterprise Private entry: (CERT Coordination Center) Type 21: Value (hex bytes): 00 00 00 a2
            Vlan Id: 0
            Vlan Id: 0 (Reverse Type 58 SRC_VLAN)
            [Enterprise Private entry: ((null)) Type 32767: Value (hex bytes): 00 c0 13 00 10 60 40 f2 6b 02 00 14 00 00 00 00 ... (Variable Length)]
                String_len_short: 255
                String_len_short: 17
        Flow 5
            [Duration: 0.335000000 seconds]
                StartTime: Jun  7, 2011 15:22:43.804000000 CEST
                EndTime: Jun  7, 2011 15:22:44.139000000 CEST
            Permanent Octets: 60
            Permanent Octets: 40 (Reverse Type 85 BYTES_TOTAL)
            Permanent Packets: 1
            Permanent Packets: 1 (Reverse Type 86 PACKETS_TOTAL)
            SrcAddr: 192.168.5.219 (192.168.5.219)
            DstAddr: 113.160.54.234 (113.160.54.234)
            SrcPort: 52044
            DstPort: 39621
            Protocol: 6
            Flow End Reason: End of Flow detected (3)
            Enterprise Private entry: (CERT Coordination Center) Type 21: Value (hex bytes): 00 00 01 4f
            Vlan Id: 0
            Vlan Id: 0 (Reverse Type 58 SRC_VLAN)
            [Enterprise Private entry: ((null)) Type 32767: Value (hex bytes): 00 c0 13 00 10 a0 86 d6 62 02 00 14 00 00 00 00 ... (Variable Length)]
                String_len_short: 255
                String_len_short: 17
...

Questions lectures, vous pouvez regarder cet exposé à FRnog.


Téléchargez le RFC 7011


L'article seul

RFC 5280: Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile

Date de publication du RFC : Mai 2008
Auteur(s) du RFC : D. Cooper, S. Santesson, S. Farrell, S. Boeyen, R. Housley, W. Polk
Chemin des normes
Première rédaction de cet article le 15 septembre 2013


L'une des rares normes de l'UIT encore utilisées sur l'Internet est X.509, une norme décrivant un format de certificats électroniques pour prouver son identité. X.509, comme toutes les normes UIT, est très complexe et probablement impossible à mettre en œuvre correctement et complètement. C'est pourquoi les applications sur l'Internet utilisent en général un sous-ensemble de X.509, décrit par ce RFC.

Ce sous-ensemble de X.509 (ou, plus exactement, de la version 3 de X.509) est souvent nommé PKIX, pour « Public-Key Infrastructure using X.509 ». C'est lui qui est derrière toutes les utilisations des certificats X.509 qu'on voit sur l'Internet, par exemple le fameux petit cadenas de HTTPS. La section 2 décrit les motivations pour avoir créé ce sous-ensemble. Il s'agit notamment de faciliter l'usage des certificats en mettant l'accent sur l'interopérabilité des programmes (n'importe quel certificat PKIX doit être compris par n'importe quel programme PKIX, ce qui n'est pas du tout garanti avec le X.509 original, où deux mises en œuvre de X.509 peuvent être parfaitement conformes au standard... et néanmoins incapables d'interopérer) et le déterminisme (savoir comment le certificat va être compris, ce qui est difficile avec le X.509 original, souvent trop vague). Tous les utilisateurs de X.509 (pas seulement l'IETF avec son PKIX) doivent donc définir un sous-ensemble de X.509, le profile (dans la langue de Whitfield Diffie). L'importance de cette notion de sous-ensemble est bien résumée par le RFC : « unbounded choices greatly complicate the software ». Au contraire, l'UIT travaille autour du principe « satisfaire tout le monde » et toute demande est donc prise en compte dans la norme, la rendant ainsi trop riche pour être programmée correctement.

Le format de certificat X.509 en est à sa troisième version, la première ayant été publiée par l'UIT et l'ISO en 1988. Plusieurs protocoles Internet se servent de ce format, le premier ayant été le projet PEM du RFC 1422 en 1993. C'est entre autres l'expérience de ce projet qui avait mené aux versions 2, puis 3 de X.509.

Ce RFC est uniquement une norme technique : il ne donne aucune règle sur les questions juridiques ou politiques, il ne dit pas, par exemple, comment une AC doit vérifier une demande de certificat, ni ce que doit faire un navigateur Web lorsqu'un certificat est invalide pour une raison ou pour une autre.

La section 3 pose l'architecture et les rôles de la PKIX, notamment les notions d'utilisateurs (end entity), qui demandent des certificats, et d'Autorités de Certification, qui les signent.

En 3.1, elle explique ce qu'est un certificat : lorsqu'on utilise la cryptographie asymétrique, on utilise la clé publique de son correspondant pour chiffrer les messages qu'on lui envoie. Mais comment savoir que c'est bien sa clé publique à lui, et pas celle d'un méchant qui écoute les communications, et pourra les déchiffrer si on utilise la clé qu'il nous a fournie ? Un certificat est l'affirmation, signée par une Autorité de Certification, qu'une clé publique est bien celle d'un utilisateur donné (subject, dans le jargon X.509). On nomme cette affirmation le lien (binding) entre la clé et le sujet.

Le certificat contient aussi diverses informations comme sa date d'expiration. Un certificat est donc juste une structure de données dont les champs sont la clé publique, la signature de l'AC, la date d'expiration, etc. Rendons cela plus concret avec un exemple sur un vrai certificat X.509, celui du site https://app.capitainetrain.com/. Pour simplifier les operations ultérieures, commençons par copier le certificat en local, avec openssl :

% openssl s_client -connect app.capitainetrain.com:443 > capitainetrain.pem < /dev/null
depth=1 C = US, O = "GeoTrust, Inc.", CN = RapidSSL CA
verify error:num=20:unable to get local issuer certificate
verify return:0
DONE

On aurait aussi pu utiliser GnuTLS pour récupérer le certificat :

% gnutls-cli --print-cert app.capitainetrain.com < /dev/null > capitainetrain.pem

On peut maintenant regarder le certificat et y découvrir les informations mentionnées plus haut :

% openssl x509 -text -in capitainetrain.pem
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 555296 (0x87920)
    Signature Algorithm: sha1WithRSAEncryption
        Issuer: C=US, O=GeoTrust, Inc., CN=RapidSSL CA
        Validity
            Not Before: Sep 30 02:22:13 2012 GMT
            Not After : Oct  2 09:04:29 2015 GMT
        Subject: serialNumber=HjJWka0qtZ2MV9EYsbjRf51Mbcd/LYOQ, OU=GT04045327, OU=See www.rapidssl.com/resources/cps (c)12, OU=Domain Control Validated - RapidSSL(R), CN=app.capitainetrain.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:cd:af:c5:f8:ac:db:3b:10:fc:af:05:2f:ec:e5:
                    ...
           X509v3 CRL Distribution Points: 

                Full Name:
                  URI:http://rapidssl-crl.geotrust.com/crls/rapidssl.crl
           ...
   Signature Algorithm: sha1WithRSAEncryption
         95:d4:fe:88:bc:9c:f8:b7:d5:72:52:c1:c8:98:04:ee:82:f7:
    ...

On y trouve le numéro de série du certificat, 555296, le nom de l'AC émettrice (C=US, O=GeoTrust, Inc., CN=RapidSSL CA, à savoir RapidSSL, une AC low-cost), la période de validité (jusqu'au 2 octobre 2015), le titulaire (app.capitainetrain.com), la clé publique, l'endroit où récupérer les CRL, et le tout avec la signature de l'AC.

Il y a aussi d'autres informations qui ne sont pas affichées par défaut par openssl. Par exemple, les usages permis (merci à Laurent Frigault pour son aide à ce sujet). Il faut utiliser l'option -purpose :

% openssl x509 -text -purpose -in capitainetrain.pem
...
Certificate purposes:
SSL client : Yes
SSL client CA : No
SSL server : Yes
SSL server CA : No
...

Ce certificat peut être utilisé pour un serveur TLS (anciennement nommé SSL), l'usage le plus courant des certificats, sur l'Internet.

Dans les normes, cette structure de données est décrite en ASN.1 et encodée en DER, suivant la norme X.690.

La section 4 de notre RFC décrit rigoureusement le sous-ensemble de X.509 utilisé dans l'Internet. Voici une partie de cette description d'un certificat, montrant les champs les plus importants :

   Certificate  ::=  SEQUENCE  {
        tbsCertificate       TBSCertificate,
        signatureAlgorithm   AlgorithmIdentifier,
        signatureValue       BIT STRING  }

   TBSCertificate  ::=  SEQUENCE  {
        version         [0]  EXPLICIT Version DEFAULT v1,
        serialNumber         CertificateSerialNumber,
        issuer               Name,
        validity             Validity,
        subject              Name,
        subjectPublicKeyInfo SubjectPublicKeyInfo,
        ...
        }

Ici, signatureValue est la signature apposée par l'AC. Elle s'applique à un certificat, le tbsCertificate. Celui-ci a un numéro de série unique, un émetteur (l'AC, identifiée par un nom complet - Distinguished Name ou DN), une période de validité (entre telle date et telle date), un titulaire (subject), la clé publique dudit titulaire, etc. Vous pouvez voir tous ces champs dans l'exemple de app.capitainetrain.com montré plus haut.

Comme toujours en bonne cryptographie, plusieurs algorithmes de signature sont possibles, afin de faire face aux progrès de la cryptanalyse. Les RFC 3279, RFC 4055 et RFC 4491 donnent la liste des algorithmes standard dont bien sûr le fameux RSA. Évidemment, il faut utiliser des algorithmes de cryptographie forts, à la sécurité connue et éprouvée. Les AC ne devraient pas, par exemple, accepter de signer des certificats utilisant des algorithmes aux faiblesses identifiées (comme plusieurs l'avaient fait avec le vieil MD5).

Comment identifier un titulaire (champ subject) ? C'est un des points délicats de X.509, qui permet une grande variété de noms. Dans l'Internet, le plus fréquent est d'utiliser un nom de domaine, soit comme spécifié par le RFC 4519 (section 2.4), soit en utilisant l'extension X.509 « noms alternatifs » (section 4.2.1.6 de notre RFC). Cette dernière extension permet aussi d'utiliser comme identificateur une adresse IP, un URI, etc. La grande variété des types de « noms » dans X.509, et la difficulté de la comparaison de ces noms créent d'ailleurs pas mal de risques de sécurité, et compliquent la vie du programmeur.

L'extension « noms alternatifs » sert aussi si, derrière une même adresse IP, on a plusieurs sites. On voit ainsi quatre noms possibles pour www.digicert.com :

% openssl x509 -text -in digicert.pem  
...
X509v3 Subject Alternative Name: 
   DNS:www.digicert.com, DNS:digicert.com, DNS:content.digicert.com, DNS:www.origin.digicert.com

Ce champ subject est évidemment d'une importance vitale. Le but de la signature du certificat est précisément de lier une clé publique à un identificateur (subject). L'AC doit donc vérifier le contenu de ce champ. Par exemple, CAcert n'inclut dans les certificats signés que les champs que cette AC a vérifié. Pour un nom de domaine, CAcert teste qu'il se termine par un des noms dont l'utilisateur a prouvé la possession (preuve typiquement apportée en répondant à un courrier envoyé au titulaire du domaine).

Les noms (subjects) ne sont pas forcément limités à l'ASCII, ils peuvent inclure de l'Unicode et la section 7 de ce RFC décrit les règles spécifiques à suivre dans ce cas. Notamment, les noms doivent être canonicalisés en suivant le RFC 4518. Pour les noms de domaine, le type utilisé par X.509, IA5String, ne permet hélas que l'ASCII et les IDN devront donc être représentés sous forme d'un A-label (www.xn--potamochre-66a.fr au lieu de www.potamochère.fr, par exemple). Même chose pour les IRI du RFC 3987 qui devront être convertis en URI. (Notez que les règles sur l'internationalisation ont été légèrement changées par la suite avec le RFC 8399.)

Une possibilité peu connue de X.509 est l'extension « Name constraints » (section 4.2.1.10) qui permet de signer des certificats d'AC avec une limite : l'AC qui a ainsi reçu une délégation ne peut signer que des certificats obéissant à cette contrainte (si le titulaire du certificat est un URI ou une adresse de courrier, la contrainte s'applique au nom de domaine compris dans l'URI ou l'adresse). On peut ainsi déléguer à une AC qui ne pourra signer que si le nom de domaine du titulaire se termine en .fr, par exemple. Cela résout une faille de sécurité importante de X.509 (celle qui a motivé le RFC 6698) : le fait que n'importe quelle AC puisse signer un nom de n'importe quel domaine, que le titulaire de ce nom de domaine soit le client de l'AC ou pas. Mais, en pratique, cette extension semble peu utilisée.

Enfin, la section 6 du RFC décrit le mécanisme de validation d'un certificat, par exemple lorsqu'un navigateur Web se connecte en HTTPS à un serveur et reçoit un certificat prouvant que ce serveur est bien celui demandé.

La section 8 étudie en détails toutes les questions de sécurité liées à X.509. D'abord, comme tous les éléments décrits dans ce RFC (les certificats et les CRL) sont signés, leur distribution ne nécessite pas de précautions particulières : à l'arrivée, et quel que soit le mécanisme de transport utilisé, le destinataire pourra vérifier l'intégrité de ces éléments.

Plus délicate est la question des procédures que suit l'AC avant de signer un certificat : c'est là que se situent l'essentiel des faiblesses de X.509. Par exemple, est-ce qu'une AC doit vérifier que le nom de domaine n'est pas proche d'un autre ?

Le RFC oublie, semble t-il, de dire que prendre soin de choisir une « bonne » AC n'est pas très utile puisque n'importe quelle AC de confiance peut émettre un certificat pour n'importe quel nom. Si Google est client de GeoTrust, qui signe donc les certificats de gmail.com, rien n'empêche DigiNotar, avec qui Google n'a aucun lien, de signer aussi des certificats pour gmail.com. Le point critique n'est donc pas l'AC qu'on choisit pour signer ses certificats, mais les AC auxquelles nos clients choisissent de faire confiance. Qu'une seule de ces AC trahisse ou soit piratée et tout le système s'écroule. Or, justement, comment sont choisies ces AC de confiance ? Très peu d'utilisateurs examinent la liste (le « magasin ») d'AC de leur logiciel. Ils font une confiance aveugle à l'éditeur du logiciel, qui décide selon ses propres critères, d'inclure telle ou telle AC. Il y a donc des AC qui ne sont que dans certains navigateurs Web (rendant les certificats signés par ces AC difficiles à utiliser). Pour limiter ces difficultés, les éditeurs de navigateurs Web incluent beaucoup d'AC (des centaines, dans un navigateur typique), rendant difficile de valider leur sécurité. Petit exercice : cherchez dans votre navigateur la liste des AC acceptées (sur Firefox, Edit -> Preferences, puis Advanced puis View certificates) et lisez-la. Vous découvrirez plein d'organisations inconnues et lointaines.

Au cas où il faille ajouter ou retirer une AC, on ne peut pas demander à l'utilisateur de le faire. Il faut donc une mise à jour du logiciel, ou bien une distribution, par un autre canal, d'une liste d'AC (distribution sécurisée, par exemple, par une signature avec la clé privée de l'éditeur du logiciel).

L'AC doit évidemment gérer avec le plus grand soin la clé privée de ses propres certificats. Si un méchant copie cette clé, il pourra se faire passer pour l'AC et émettre des faux certificats. À une moins échelle, c'est aussi vrai pour l'utilisateur : si sa clé privée est compromise, il sera possible de se faire passer pour lui, et la signature de la clé publique par l'AC ne changera rien.

Notons que le RFC ne semble pas parler du cas où la clé privée de l'AC est bien gardée et inaccessible mais où le système d'information de l'AC a été piraté, permettant à l'attaquant de faire générer des « vrais/faux certificats ». C'est pourtant la menace principale, comme l'avaient illustrés les cas de Comodo et DigiNotar.

Cela nous amène à un autre point faible de X.509, la révocation. Des clés privées vont forcément tôt ou tard être copiées illégalement par un attaquant, qui va pouvoir alors se faire passer pour le titulaire du certificat. Si une clé privée est copiée à l'extérieur, ou qu'on soupçonne sérieusement qu'elle est copiée, comment empêcher l'attaquant de jouir des fruits de son forfait ? Ou, sans chercher un cas aussi dramatique, on peut aussi imaginer qu'un employé qui avait accès à la clé privée quitte l'organisation et qu'on souhaite, par précaution, qu'il ne puisse pas utiliser cette connaissance. Une solution est d'attendre l'expiration (rappelez-vous que les certificats X.509 ont une période de validité, entre deux dates, celle de début de validité et celle d'expiration). Mais cela peut prendre longtemps. Il faut donc émettre tout de suite une révocation, une annulation du certificat, signée par l'AC. X.509 permet aux AC d'émettre des CRL (Certificate Revocation List), qui sont des listes de certificats révoqués, signées par l'AC qui avait émis le certificat original. Étant signées, les CRL n'ont même pas besoin (comme les certificats, d'ailleurs) d'être distribuées par un canal sûr.

Le problème est de distribuer celles-ci efficacement. Comme l'ont montré plusieurs études, la révocation marche mal car il est difficile de s'assurer que tous les clients ont reçu l'information. Il y a plusieurs raisons à cela, le RFC n'en note qu'une : la révocation n'est pas temps réel. Entre le moment où la CRL est émise et celui où elle est traitée par tous les consommateurs, un certain temps peut s'écouler. (Une solution possible est le protocole OCSP, dans le RFC 6960.)

Voici une CRL de RapidSSL (celle annoncée dans le certificat de app.capitainetrain.com vu plus haut) :

% openssl crl -text -inform DER -in rapidssl.crl
Certificate Revocation List (CRL):
        Version 2 (0x1)
    Signature Algorithm: sha1WithRSAEncryption
        Issuer: /C=US/O=GeoTrust, Inc./CN=RapidSSL CA
        Last Update: Sep 13 12:03:00 2013 GMT
        Next Update: Sep 23 12:03:00 2013 GMT
...
   Serial Number: 070B6B
        Revocation Date: Aug 27 10:56:39 2013 GMT
...

On voit ainsi que le certificat de numéro de série 461675 (070B6B en hexadécimal) a été révoqué le 27 août 2013. Les raisons de la révocation sont également indiquées par certaines AC. Dans ce cas, on verrait :

    Serial Number: 18F...
        Revocation Date: Sep  3 07:58:20 2012 GMT
        CRL entry extensions:
            X509v3 CRL Reason Code: 
                Key Compromise
    Serial Number: 5FD...
        Revocation Date: Aug 12 12:59:20 2012 GMT
        CRL entry extensions:
            X509v3 CRL Reason Code: 
                Key Compromise
...

Enfin, trois annexes du RFC seront particulièrement utiles pour les programmeurs. Ceux-ci doivent d'abord noter que X.509 est très complexe et très difficile à implémenter. La première lecture recommandée, pour avoir une idée du travail, est le « X.509 Style Guide » de Peter Gutmann. L'annexe A liste les structures de données de X.509, en syntaxe ASN.1. On y trouve même des héritages d'un lointain passé comme :

poste-restante-address INTEGER ::= 19

L'annexe B donne des conseils aux programmeurs sur la mise en œuvre de X.509. L'annexe C donne des exemples de certificats et de CRL. Le programme dumpasn1 est utilisé pour les afficher. Attention, cet outil ne lit que le DER, pas le PEM. Si on a un certificat au format PEM, il faut d'abord le convertir :

% openssl x509 -inform pem -outform der -in capitainetrain.pem -out capitainetrain.der

Et on peut alors l'analyser :

% dumpasn1  capitainetrain.der|more

   0 1330: SEQUENCE {
   4 1050:   SEQUENCE {
   8    3:     [0] {
  10    1:       INTEGER 2
         :       }
  13    3:     INTEGER 555296
  18   13:     SEQUENCE {
  20    9:       OBJECT IDENTIFIER sha1WithRSAEncryption (1 2 840 113549 1 1 5)
...
  95   30:     SEQUENCE {
  97   13:       UTCTime 30/09/2012 02:22:13 GMT
 112   13:       UTCTime 02/10/2015 09:04:29 GMT
...
 294   31:       SET {
 296   29:         SEQUENCE {
 298    3:           OBJECT IDENTIFIER commonName (2 5 4 3)
 303   22:           PrintableString 'app.capitainetrain.com'
         :           }
...

Si vous préférez un truc moderne et qui brille, l'outil interactif en ligne ASN.1 JavaScript decoder est remarquable (et, lui, il accepte le PEM).

Ce sous-ensemble (« profile ») de X.509 avait à l'origine été normalisé dans le RFC 3280, que ce RFC met à jour. La liste des changements est décrite en section 1. Rien de crucial, mais on notera que la nouvelle norme fait une part plus grande à l'internationalisation.

Merci à Manuel Pégourié-Gonnard pour la correction d'erreurs.


Téléchargez le RFC 5280


L'article seul

RFC 7010: IPv6 Site Renumbering Gap Analysis

Date de publication du RFC : Septembre 2013
Auteur(s) du RFC : B. Liu, S. Jiang (Huawei Technologies), B. Carpenter (University of Auckland), S. Venaas (Cisco Systems), W. George (Time Warner Cable)
Pour information
Réalisé dans le cadre du groupe de travail IETF 6renum
Première rédaction de cet article le 14 septembre 2013


Si on pouvait facilement renuméroter (changer les adresses IP) d'un réseau, beaucoup de problèmes seraient moins graves. Par exemple, il y aurait moins de demande pour des adresses PI. Mais, comme l'explique bien le RFC 5887, renuméroter, en pratique, est difficile, et les administrateurs réseaux, à juste titre, font tout ce qu'ils peuvent pour l'éviter. Pour essayer de résoudre ce problème, l'IETF a un groupe de travail 6renum, dont voici le troisième RFC. 6renum travaille à faciliter la rénumérotation en IPv6. Ce RFC 7010 est consacré à l'analyse des trous : que manque t-il comme protocole IETF pour faciliter la renumérotation ?

C'est un enjeu important pour l'Internet : sans renumérotation facile, les administrateurs réseaux se tourneront encore plus massivement vers les adresses PI, qui exercent une pression sur la table de routage (RFC 4984). Le RFC 6879, plus pratique, décrivait un certain nombre de scénarios de renumérotation et ce nouveau document, le RFC 7010 va bâtir sur ces scénarios en regardant ce qui gêne leur réalisation (et qui nécessitera un travail à l'IETF). Les machines ayant une adresse IP statique, typiquement les serveurs, sont traitées dans un autre document, le RFC 6866. De même, le cas d'une rénumérotation urgente et non planifiée, par exemple suite à la faillite d'un FAI, n'est pas couvert ici.

Donc, d'abord (section 2), qu'appelle t-on une rénumérotation réussie ? Que voudrait-on comme propriétés ? Une rénumérotation part d'un ancien préfixe et arrive à un nouveau. Pour les moyennes et grandes organisations, on a pu recevoir ce nouveau préfixe par des moyens humains (message électronique, par exemple). Pour les petites, on a pu le recevoir par une délégation, genre DHCPv6-PD (Prefix Delegation, RFC 8415). Dans les deux cas, on voudrait plein de choses :

  • Le nouveau préfixe devrait être reçu automatiquement et correctement,
  • Les adresses IP dans ce nouveau préfixe devraient être acquises automatiquement par les machines, sans intervention humaine,
  • Les endroits où se trouvent configurées ces adresses devraient se mettre à jour,
  • Même si ça se passe tout seul, on souhaiterait être notifié de ce changement et pouvoir le superviser,
  • Enfin, on voudrait que la rénumérotation ne casse pas les sessions applicatives en cours (pensez à SSH...) Comme ce RFC ne regarde que les renumérotations contrôlées (pas celles faites en urgence, à l'arrache), cet objectif peut être atteint en ayant une période de transition qui soit plus longue que la durée de vie de ces sessions applicatives.

Comme le savent les lecteurs du RFC 5887, on en est loin...

Et quels sont les protocoles, les outils et les procédures qui peuvent nous aider à s'approcher de ces beaux objectifs (section 3) ? Les protocoles sont les suivants :

  • Les messages RA (Router Advertisment, RFC 4861) permettent d'annoncer les préfixes IPv6 utilisés sur le lien local,
  • SLAAC (StateLess Address AutoConfiguration, RFC 4862) permet aux machines de se configurer une adresse IPv6 après avoir entendu les RA,
  • RA + SLAAC ne sont pas la seule solution, IPv6 a aussi DHCP (RFC 8415 et RFC 8415 pour la délégation de préfixe),
  • Il y eu aussi un système utilisant ICMP spécifiquement pour la rénumérotation, décrit dans le RFC 2894 et qui ne semble pas avoir jamais été déployé.

Il y a aussi des outils :

  • Les moyens et grands réseaux ne se gèrent pas à la main, ils se servent d'IPAM, qui gardent trace des adresses et de leur allocation,
  • Dès que le réseau a une taille non triviale, il est fréquent que les modifications ne soient pas propagées manuellement mais par un outil comme Chef ou Puppet,
  • Cette propagation des configurations peut aussi se faire avec des outils utilisant NETCONF (RFC 4741) ou d'autres protocoles de transport. Pour des détails pratiques, on peut consulter l'article de Leroy et Bonaventure, « Preparing network configurations for IPv6 renumbering »,

Et des procédures :

  • Le RFC 4192 décrit en détail comment renuméroter un réseau IPv6 sans flag day, sans un jour J où le soleil se coucherait sur un réseau complètement migré,
  • Le RFC 6879, déjà cité, étudie des cas de renumérotation et fait des recommandations opérationnelles.

Mais, en pratique, cela ne suffit pas. La section 5 se penche sur le premier problème, la configuration des adresses dans les machines terminales et les routeurs. D'abord, l'interaction entre SLAAC et DHCP, une source de frustration fréquente pour les administrateurs réseaux IPv6. En gros, ces deux protocoles permettent de faire la renumérotation. S'ils sont présents tous les deux sur un réseau, c'est plus compliqué et il faut bien les coordonner. Le plus simple est quand même de n'en avoir qu'un seul (ce qui est, heureusement, le cas le plus courant). Normalement, il existe des indications dans les messages permettant de coordonner les deux protocoles (options M et O du RA, cf. RFC 4861, section 4.2). Mais ils sont traités comme indicatifs seulement. Résultat, les différents systèmes d'exploitation ne les interprètent pas de la même manière. On n'est donc pas sûr, par exemple, qu'on puisse renuméroter avec les RA des machines qui avaient été configurées en DHCP (ManagedFlag passant de 1 à 0). De même, les RFC 4862 et RFC 3315 ne sont pas clairs sur ce que doit faire une machine cliente DHCP lorsqu'elle voit des nouveaux préfixes être annoncés par des RA. Un problème analogue se pose en sens inverse (transition de DHCP vers SLAAC).

Et pour les routeurs ? Logiquement, tout devrait bien se passer sauf que, contrairement aux machines terminales qui acceptent toutes de changer d'adresse IP en vol, certains routeurs doivent être redémarrés lorsque cela leur arrive.

Comme souvent en renumérotation, on s'épargnerait bien des problèmes en utilisant des noms dans les configurations et pas des adresses IP. Mais le RFC note, à juste titre, que ce n'est pas toujours le cas pour les routeurs.

Une fois machines terminales et routeurs renumérotés, il reste à mettre à jour des tas de configurations et de bases de données qui stockent encore les anciennes adresses. C'est l'objet de la section 6. Premier exemple, les zones DNS. La zone peut être maintenue à la main, avec un éditeur et il faudra alors faire un rechercher/remplacer. Ou bien on peut utiliser les mises à jour dynamiques (RFC 3007). Cette fonction existe depuis longtemps, est mise en œuvre dans plusieurs logiciels serveurs mais, pour que chaque machine puisse individuellement faire la mise à jour, il faut un mécanisme d'autorisation, et gérer une clé dans chaque machine n'est pas pratique. Il est plus commun que la mise à jour du DNS soit faite par le serveur DHCP, pour le compte des machines terminales (RFC 4704). Cela marche très bien si la renumérotation est faite par DHCP. Si on a utilisé SLAAC, il n'existe pas de solution évidente (aujourd'hui : des réflexions sont en cours, par exemple dans draft-ietf-dhc-addr-registration).

Il reste à traiter le cas des adresses IP éparpillées un peu partout, notamment dans des ACL. Il n'existe pas de solution générale pour ce problème. Mais notre RFC recommande que, lorsqu'on utilise des adresses IP dans des configurations, on définisse une variable au début et on l'utilise ensuite, pour limiter la douleur de la renumérotation. Un exemple en shell Unix avec Netfilter, pour un routeur Unix qui transmet vers un serveur HTTP :

# Define the variable
WEBSERVER=2001:db8:cafe::1:34a

# By default, block everything
ip6tables --policy FORWARD DROP

# Allow ICMP. We could be more selective.
ip6tables --append FORWARD --protocol icmp --destination ${WEBSERVER} --jump ACCEPT

# Rate limiting
ip6tables --append FORWARD --protocol tcp --destination ${WEBSERVER} --dport 80 --tcp-flags SYN SYN -m hashlimit \
   --hashlimit-name Web --hashlimit-above 3/second --hashlimit-mode srcip \
   --hashlimit-burst 7 --hashlimit-srcmask 28 --jump DROP

# Allow HTTP and HTTPS
ip6tables --append FORWARD --protocol tcp --destination ${WEBSERVER} \
         --dport 80:443 --jump ACCEPT

Ainsi, le script n'utilise qu'une seule fois l'adresse, au début, et est donc bien plus facile à modifier. Un programme comme ack-grep est très pratique pour trouver tous ces cas où une adresse est stockée dans la configuration :

# ack-grep --all 2001:db8:cafe::1:42   
network/interfaces
14:        address 2001:db8:cafe::1:42   

nsd3/nsd.conf
15:        ip-address: 2001:db8:cafe::1:42   
...

Pour simplifier ce problème des adresses IP dispersées un peu partout, notre RFC recommande l'utilisation d'outils de gestion de configuration comme Chef ou Puppet : on change la configuration à un endroit et elle est ensuite poussée vers tous les serveurs. Il existe aussi des outils non-libres, spécifiques à un vendeur particulier, pour assurer cette tâche et le RFC regrette l'absence d'une norme complète (NETCONF ne règle pas tous les cas) et ouverte pour cette question de mise à jour.

Pour que l'opération de migration vers les nouvelles adresses se passe bien, il faut aussi des mécanismes de gestion des événements, notamment de notification (« Un nouveau préfixe est arrivé »). Ces notifications permettraient, par exemple, d'invalider les caches DNS (pour forcer une mise à jour), ou de changer les configurations de filtrage (le RFC 2827 demande qu'on ne laisse pas sortir de son réseau les paquets ayant une adresse IP source autre que celles du réseau ; mettre ce filtrage en œuvre nécessite de connaître le préfixe du réseau local, et d'en changer si nécessaire). Cette notification n'est pas triviale, notamment si on utilise SLAAC (puisque, dans ce cas, aucun serveur central n'est informé du changement d'adresse d'une machine)

Le DNS pose d'ailleurs d'autres questions. En raison du TTL des enregistrements DNS, les nouvelles informations ne peuvent pas être réjuvénées instantanément. Si la rénumérotation du réseau est prévue suffisemment à l'avance, la bonne pratique est d'abaisser ces TTL avant, de faire le changement, puis de remonter les TTL.

Les sections 9 et 10 résument les trous qu'il y a actuellement dans les protocoles TCP/IP, et dont le comblement rendrait la rénumérotation plus facile :

  • Un mécanisme pour informer le routeur qu'il doit se rénuméroter lui-même, et pour choisir une adresse dans le préfixe délégué. Et une meilleure gestion de sa propre renumérotation par le routeur (ne nécessitant pas de redémarrage).
  • Une meilleure spécification des interactions SLAAC<->DHCP, notamment sur la renumérotation en DHCP de machines numérotées par SLAAC et réciproquement.
  • Le problème de la mise à jour du DNS par les machines SLAAC reste entier.
  • L'usage trop important d'adresse IP « codées en dur », non dérivées d'une unique variable facile à changer. Certains systèmes ne permettent même pas une telle dérivation.
  • Un mécanisme de notification « attention, les adresses vont changer / ont changé ».
  • L'interaction avec les TTL DNS reste compliquée.

La section 10 se spécialise dans les trous considérés comme insolubles, et dont le groupe 6renum ne s'occupera donc pas :

  • La mise à jour des zones DNS pour le cas où elles sont extérieures à l'organisation, par exemple chez un hébergeur DNS qui fournit uniquement une interface Web pour les mettre à jour.
  • La synchronisation des entrées AAAA (nom -> adresse) et PTR (adresse -> nom) dans le DNS. Cette synchronisation est d'autant plus insoluble que les zones « directes » et « inverses » (ip6.arpa) peuvent très bien être gérées par des hébergeurs différents.
  • Créer des types d'enregistrement DNS explicitement pour faciliter la renumérotation a déjà été tenté avec le A6 du RFC 2874. Trop complexe, le A6 a été peu déployé et a officiellement été abandonné avec le RFC 6563. L'idée de séparer le préfixe de l'adresse et son suffixe lors de la résolution DNS reste dans l'air mais le groupe 6renum n'a pas l'intention de s'y attaquer.
  • Les protocoles de transport comme TCP lient une connexion aux adresses IP de source et de destination. Cela a des tas d'inconvénients (en cas de renumérotation, les connexions cassent) mais c'est considéré comme un problème de grande ampleur, loin des capacités du groupe 6renum.
  • Un problème analogue se pose dans certaines applications, qui cassent les sessions lorsqu'une adresse IP d'une des parties change.

Voilà, nous avons fait le tour des problèmes, il reste à lire la section 11, spécialisée dans les questions de sécurité. Par exemple, si on a des ACL sur les adresses IP, et qu'elles interdisent à certains méchants de se connecter à l'adresse IP d'un serveur, la rénumérotation ne doit pas invalider cette liste noire : la règle doit être mise à jour pour pointer vers la nouvelle adresse IP du serveur.

Mais on peut aussi noter que la configuration automatique, souhaitée par le RFC, amène aussi ses propres risques, comme illustré par l'accident de Cloudflare ou comme un cas rigolo avec Ansible.


Téléchargez le RFC 7010


L'article seul

reveal.js, faire des supports de présentation webeux

Première rédaction de cet article le 11 septembre 2013


Récemment, je me suis posé la question de savoir s'il existait des alternatives rigolotes au logiciel de création de présentations que j'utilise d'habitude, LaTeX/Beamer. J'ai découvert qu'il existait notamment tout un tas d'outils fondés sur les techniques Web et j'ai choisi de commencer à utiliser reveal.js. Je documente ici quelques points techniques découverts à cette occasion.

Ces outils Web ont en commun d'utiliser des techniques qui sont maîtrisées par beaucoup de gens (mais pas par moi) comme HTML, CSS ou JavaScript. Si on utilise un des thèmes pré-définis avec reveal.js, l'utilisation de ce logiciel est très simple. Il existe plusieurs tutoriels, voici celui que je recommande.

Mais si on utilise ces outils Web, c'est souvent pour modifier et mettre son propre thème. Pour des modifications simples et limitées, ajouter son code CSS est suffisant. Pour des modifications plus fondamentales, il faut aller plus loin. La procédure d'écriture de son propre thème est documentée mais pas vraiment triviale. D'abord, il faut installer quelques outils, notamment node.js et le gestionnaire de tâches Grunt. Sur une Debian stable (sur la version de développement, surnommée « sid », c'est un peu plus simple, sur une Ubuntu, ça marche pareil), voici comment j'ai fait (en partant des instructions officielles de reveal.js). D'abord, installer node.js. Cela peut se faire de plusieurs façons, mais je tenais à avoir un paquetage Debian installé, pour faciliter les mises à jour ultérieures. (Et merci à l'auteur d'un bon article sur cette procédure.)

% wget -N http://nodejs.org/dist/node-latest.tar.gz
# aptitude install python g++ make checkinstall
% tar xzvf node-latest.tar.gz 
% cd node-v*
% ./configure
# checkinstall

Deux avertissements importants pour la dernière étape : checkinstall doit tourner sous root (à moins qu'il existe une méthode plus astucieuse) et surtout, il faut penser à changer le numéro de version dont la syntaxe par défaut ne plait pas à Debian. Lorsque checkinstall demande :

This package will be built according to these values: 

0 -  Maintainer: [ stephane@tyrion ]
1 -  Summary: [ Node.js ]
2 -  Name:    [ nodejs ]
3 -  Version: [ v0.10.18 ]
4 -  Release: [ 1 ]
5 -  License: [ GPL ]
6 -  Group:   [ checkinstall ]
7 -  Architecture: [ i386 ]
8 -  Source location: [ node-v0.10.18 ]
9 -  Alternate source location: [  ]
10 - Requires: [  ]
11 - Provides: [ node ]
12 - Conflicts: [  ]
13 - Replaces: [  ]

Il faut changer la version :

Enter a number to change any of them or press ENTER to continue: 3
Enter new version: 
>> 0.10.18

Ensuite, on se retrouve avec un paquetage node.js installé :

ii  nodejs    0.10.18-1 i386         Node.js

Maintenant, Grunt. Il n'est pas dans Debian pour un problème de licence. Mais le gestionnaire de paquetages de JavaScript npm l'installe sans problème :

# npm install -g grunt-cli

Ensuite, plus qu'à récupérer reveal.js et à installer les dépendances :

% cd reveal.js
% npm install

Pour créer ou modifier un thèmes, il faut utiliser le langage SASS, le CSS étant trop primitif pour les thèmes compliqués de reveal.js. On installe le programme qui va traduire le SASS en CSS :

# aptitude install ruby-sass

Et on peut alors s'attaquer à la réalisation (ou la modification en partant d'un des thèmes existants) d'un thème en éditant un fichier d'extension .scss. La documentation de reveal.js guide un peu (mais il faut vraiment lire les commentaires dans le fichier template/settings.scss). Voici une partie de mon thème :


$mainColor: #000000;
$headingColor: #000000;
$headingTextShadow: none;
$headingTextTransform: none;
$backgroundColor: #ffffff;
$mainFont: 'arial', sans-serif;
$headingFont: 'arial', sans-serif;

// Custom CSS rules

.reveal em {
   font-style: normal;
   font-weight: bold;
}

.reveal pre {
  font-size: 110%;
}

// Add this element *before* the slides section

.reveal  #decoheader {
   display: block; 
   position: absolute; 
   top: 0%; 
   left: 0%; 
   margin: 0px; 
   height: 12%; 
   width: 100%; 
   background-color: #000099; 
   z-index: 50;
}

Vous voyez que le SASS comprend une bonne partie de CSS normal, comme les trois règles à la fin. Malheureusement, il n'existe pas de guide de création d'un nouveau thème, expliquant les pièges et les problèmes (par exemple, je pense que l'utilisation de position: absolute dans mon code ci-dessus est responsable de certains problèmes avec mon thème mais je ne peux pas en être sûr).

Une fois qu'on a terminé son SASS, on le compile en CSS :

% grunt sass

% find . -name 'bortzmeyer*'
./css/theme/source/bortzmeyer.scss
./css/theme/source/bortzmeyer.scss~
./css/theme/bortzmeyer.css

À chaque modification du .scss, on refera ce grunt sass. Vous pouvez voir le résultat sur mon exposé DNS à la Cantine (et vous rendrez compte ainsi que je ne connais pas grand'chose à CSS).

Autre manipulation technique qu'on peut avoir à faire avec reveal.js, l'impression en PDF. Elle est documentée, n'est pas extrêmement pratique mais marche comme indiquée. (Attention, cela produit un PDF d'une taille ridiculement élevée.)

Enfin, d'autres extensions nécessiteront JavaScript. Par exemple, reveal.js ne permet pas, par défaut, de mettre un compteur affichant la page courante. Ce besoin a déjà été exprimé. Pour moi, la solution de mohikaner marche : on ajoute son code JavaScript à la page HTML (il doit y avoir une solution plus propre, surtout pour partager ce code entre plusieurs exposés, mais je ne me suis pas penché sur la question), et on ajoute un élément de la classe correspondante dans le source HTML :


<div id="decofooter">
    <p><a href="http://www.bortzmeyer.org/">Stéphane Bortzmeyer</a> - 
       <span class="slidenumber"/></p>
</div>


L'article seul

Exposé général sur le DNS à la Cantine

Première rédaction de cet article le 10 septembre 2013
Dernière mise à jour le 27 septembre 2013


Hier, lundi 9 septembre, j'ai eu le plaisir de faire un exposé général sur le DNS (c'est quoi, à quoi ça sert, ça fait mal ?) pour la toute première occurrence des conférences « Il était une fois... Internet ». Ces conférences visent « [...] expliquer et d'aider à comprendre comment fonctionne Internet. Chaque conférence développe un thème précis, regroupant aussi bien le fonctionnement général, des détails techniques, des notions théoriques ou des exemples de configurations. ».

Cette causerie était aussi l'occasion de tordre le cou à quelques idées reçues sur le DNS et les noms de domaine, idées reçues qui semblent assez fréquentes (non, les noms de domaines ne sont pas limités à l'ASCII, non, il ne faut pas confondre résolveur et serveur faisant autorité, non le nombre de composants dans un nom de domaine n'a aucune importance, etc).

En pratique, le public était encore assez geek mais cela pourra changer pour les futures conférences si la formule est maintenue.

Les supports utilisés sont disponibles ici. C'est du reveal.js, un système que j'ai récemment choisi (et sur lequel j'ai testé quelques trucs un peu avancés). Je débute dans toutes ces techniques Web donc la présentation n'est pas parfaite sur tous les navigateurs (ça semble marcher mieux avec Chromium). Bref, vous pouvez regarder, si vous ne connaissez pas reveal.js, c'est la touche F pour passer en plein écran (Esc pour en sortir), et N pour la page suivante. Sinon, pour le papier, une version relativement imprimable est disponible.

Les vidéos sont désormais disponibles sur http://data.confs.fr/dns-bortzmeyer/. Merci beaucoup à Skhaen pour l'idée et l'organisation.


L'article seul

RFC 6986: GOST R 34.11-2012: Hash Function

Date de publication du RFC : Août 2013
Auteur(s) du RFC : V. Dolmatov (Cryptocom), A. Degtyarev (Cryptocom)
Pour information
Première rédaction de cet article le 5 septembre 2013


Ce RFC documente en anglais une norme russe de l'organisme GOST. GOST R 34.11-2012 est une fonction de condensation cryptographique. Elle pourra notamment être utilisée pour DNSSEC.

Les algorithmes GOST (un abus de langage puisque GOST est normalement le nom de l'organisme de normalisation) sont une alternative russe aux algorithmes de cryptographie d'origine états-unienne comme RSA ou ECDSA (qui peuvent être remplacés par GOST R 34.10-2001) ou comme SHA-2 (qui peut être remplacé par GOST R 34.11-2012, qui fait l'objet de ce RFC). Pour être utilisés dans les protocoles IETF, il leut fallait une documentation en anglais. GOST R 34.10-2001 avait été documenté dans le RFC 5832. Notre RFC 6986 documente le petit dernier membre de la famille (son prédécesseur pour la condensation, GOST R 34.11-94, était dans le RFC 5831). Notez que les algorithmes GOST sont normalisés pour un usage dans le cadre de DNSSEC (RFC 5933).

Comme les autres algorithmes GOST, notre R 34.11-2012 est donc un algorithme officiel en Russie. Il a été approuvé par le décret n° 216 de l'agence fédérale chargée de la régulation technique, en août 2012. À terme, il vise à remplacer l'ancien R 34.11-94. C'est un algorithme de condensation cryptographique, qui peut produire des condensats de 256 ou 512 bits.

Je ne vais pas essayer de vous expliquer son principe de fonctionnement (sections 4 à 10), car c'est trop loin de mon domaine de compétence. Si vous êtes plus courageux que moi, notez qu'il y a beaucoup de maths et que, dans le formatage texte brut des RFC, ce n'est pas forcément idéal.

Questions mises en œuvre, notez qu'OpenSSL 1.0.1c n'a apparemment pas d'algorithmes de condensation GOST par défaut. openssl dgst -h pour voir la liste. Il faut apparemment éditer le openssl.cnf pour y avoir accès.


Téléchargez le RFC 6986


L'article seul

RFC 7017: IMAP Access to IETF Email List Archives

Date de publication du RFC : Août 2013
Auteur(s) du RFC : R. Sparks (Oracle)
Pour information
Première rédaction de cet article le 3 septembre 2013


Dans son travail, l'IETF utilise énormément les listes de diffusion. Afin de s'assurer que le travail de normalisation soit ouvert et transparent, ces listes sont publiquement accessibles. Mais il n'existe pas de moyen très pratique de naviguer dans les archives de ces listes, alors qu'il serait tentant de pouvoir le faire en utilisant le protocole normalisé d'accès à des boîtes aux lettres, IMAP. Ce court RFC est le cahier des charges du projet « Accès en IMAP aux archives des listes IETF ».

Les principaux accès à ces listes actuellement se font via le Web (qui fait l'objet d'un travail analogue pour améliorer ce service, cf. RFC 6778) ou en travaillant sur des copies locales des boîtes (pas forcément pratique). Bien des membres de l'IETF réclament un accès IMAP (RFC 9051), chaque liste étant représentée par une boîte IMAP. On pourra ainsi utiliser son client IMAP favori (mutt, Thunderbird, etc) pour accéder à ces archives.

Les exigences les plus importantes de ce cahier des charges (section 2) :

  • Même si l'archive est publique (le cas le plus fréquent) et accessible par tous, il faudra que le système permette de se loguer (avec la base d'identité du datatracker), afin de pouvoir marquer les messages (lu, non lu, etc). Il est souhaitable que d'autres annotations soient possibles, comme décrit dans les RFC 5257 et RFC 5464. Pour l'accès « anonyme », le système devra utiliser le mécanisme SASL du RFC 4505, ou bien un compte spécial (login anonymous / mot de passe anonymous...)
  • À part ces marques et ces annotations, il ne faut évidemment pas que les utilisateurs puissent modifier ou supprimer les messages.
  • Il faut que les fonctions de recherche d'IMAP soient mises en œuvre, avec les fonctions décrites dans le RFC 6778, de préférence en utilisant les extensions à IMAP des RFC 5256 (le tri), RFC 6237 (recherche multi-boîtes, depuis remplacé par le RFC 7377) et RFC 6203 (la recherche floue...)

Si vous êtes programmeur et que vous envisagez de se lancer dans ce travail, attention, la section 3 précise que le système devra prévoir une future extension aux adresses de courrier en Unicode.

Des problèmes de sécurité ? La section 4 en voit quelques uns. La fonction de recherche peut être très gourmande en CPU et en E/S. Un client méchant ou simplement avide pourrait mettre à genoux le serveur en multipliant les requêtes. Le système doit donc être capable de limiter la consommation de ressources par utilisateur. Un problème analogue se pose pour les annotations, dont il faut limiter la consommation d'espace disque.

Je n'ai pas trouvé trace d'un appel d'offres formel de l'IETF correspondant à ce RFC. Plus tard, peut-être ?


Téléchargez le RFC 7017


L'article seul

La cryptographie nous protège t-elle vraiment de l'espionnage par la NSA ou la DGSE ?

Première rédaction de cet article le 1 septembre 2013


Cet article est une exploration, essentiellement théorique, d'un problème technique intéressant : l'utilisation de la cryptographie est-elle utile lorsqu'on veut protéger sa vie privée contre l'espionnage massif auquel se livrent des agences gouvernementales comme la NSA ou la DGSE ? Je vous le dis tout de suite, il n'y a pas de réponse simple.

Notez bien la définition du problème : je ne parle pas des attaques par le pirate du coin (celui qui sniffe votre réseau Wi-fi au cyber-café), car la cryptographie est certainement indispensable contre lui, contre cet attaquant ordinaire. Et je ne parle pas non plus du cas où l'agence d'espionnage vous cible individuellement. Si la NSA a décidé que vous êtes un objectif intéressant et met tous ses moyens à vous espionner, il n'y a pas grand'chose à faire (le plus probable est qu'ils utilisent un spyware dans votre ordinateur, ou bien une écoute électromagnétique, à moins qu'ils ne préfèrent la méthode bien décrite dans xkcd). Dans ce cas, on fait de la gestion de risque, mais on n'espère pas être invulnérable.

Non, je me focalise sur l'espionnage de masse, passant à l'échelle, et visant des tas de gens dont la NSA ou la DGSE ne savent pas a priori s'ils sont une cible intéressante ou pas. C'est cet espionnage qui a fait l'objet récemment d'une prise de conscience, suite aux révélations d'Edward Snowden. Il a parlé de la NSA (et du GCHQ) mais il n'y a aucun doute que d'autres agences font pareil. En France, en raison d'une tradition d'obéissance au monarque qui remonte à longtemps, on n'a pas encore vu de « lanceur d'alerte » héroïque et désobéissant comme Snowden mais cela ne veut pas dire qu'un tel espionnage n'a pas lieu.

Mais comment savoir exactement les capacités de la NSA ? L'adage classique de la sécurité s'applique tout à fait ici : « Ceux qui savent ne parlent pas, ceux qui parlent ne savent pas ». Comme j'écris beaucoup sur ce blog, vous pouvez en déduire que je ne sais pas grand'chose. Il faut donc commencer par un sérieux avertissement : comme les agences secrètes sont... secrètes, on ne peut pas savoir exactement à quoi s'attendre. Cela n'empêche pas les Jean-Kevin de toute sorte d'affirmer bien haut « la crypto, c'est nul, on sait bien que la NSA peut tout casser et tout lire, lol, mdr ». Il faut juste se rappeler que ce genre d'affirmations ne vaut rien.

Est-ce que seuls les Jean-Kevin disent n'importe quoi ? Évidemment non. Les chercheurs en sécurité sont connus pour leur goût pour le sensationnalisme et les annonces spectaculaires, qui seront oubliés trois mois après. Chaque année, à Blackhat ou Defcon, il y a une annonce comme quoi la cryptographie est fichue, l'Internet à poil, et que nous allons tous mourir. En 2011, c'était BEAST, qui devait mettre fin à TLS. En 2013, on a eu la prédiction comme quoi RSA serait cassé dans cinq ans (un article particulièrement grotesque dans le sensationnalisme fut celui de Technology Review).

Bon, maintenant que j'ai critiqué ceux qui disaient n'importe quoi, que peut-on dire de sérieux ? Revenons un peu sur la cryptographie dans son service de confidentialité. Alice et Bob veulent communiquer secrètement. Ils chiffrent leurs communications, empêchant un tiers naïf de comprendre ce qu'ils se disent. Mais pour un tiers plus motivé et ayant davantage de moyens ? Il peut utiliser plusieurs méthodes anti-crypto (je ne cite que celles qui passent à l'échelle par automatisation, sans nécessiter de kidnapper Bob et de le faire parler) :

  • L'espion peut installer du spyware dans les logiciels de tout le monde (le nom de code « GENIE » à la NSA concerne apparemment un tel programme). C'est d'autant plus facile pour la NSA que la majorité des logiciels sont produits par des entreprises états-uniennes. La cryptographie ne protège qu'en transit, pas si une des machines terminales trahit.
  • Puisque, dans mon hypothèse de départ, l'attaquant est un État doté d'importants moyens matériels, il peut aussi utiliser la force brute. Si la clé de chiffrement fait 256 bits, on peut (en théorie) essayer systématiquement les 2^256 valeurs. Aucun algorithme (à part le one-time pad) ne résiste aux attaques par force brute. Mais, avec les tailles de clé utilisées dans les systèmes cryptographiques sérieux, c'est probablement irréaliste en pratique.
  • Il peut trouver une faille dans les logiciels de cryptographie. S'il casse GnuPG et la mise en œuvre de TLS utilisée dans Firefox, il aura déjà accès à bien des choses. Les logiciels de cryptographie sont des logiciels comme les autres et ont des bogues.
  • Il peut casser les protocoles de cryptographie. Il est étonnamment difficile de réaliser un protocole sûr, même quand les algorithmes sous-jacents sont corrects, comme le montrent les différentes failles de TLS (comme celle de renégociation). Sans compter la faille récurrente par laquelle trébuchent tant de mises en œuvre de la cryptographie : le générateur de nombres aléatoires (RFC 4086).
  • Il peut enfin casser les algorithmes de cryptographie eux-mêmes. C'est le plus spectaculaire (et c'est pour cela que les Jean-Kevin du monde entier aiment bien affirmer des choses comme « on sait bien que la NSA a cassé RSA depuis des années - sans doute dans son centre de recherches de la zone 51 ») mais pas le plus facile, loin de là. Les mathématiques résistent longtemps et, surtout, leurs progrès sont imprévisibles (comme le note à juste titre Schneier). Peut-être que, dans cinq ans, un étudiant dans sa chambre va subitement trouver un moyen simple de décomposer en facteurs premiers, cassant ainsi RSA. Peut-être. Et peut-être pas. Les affirmations comme quoi « RSA sera cassé dans cinq ans » sont ridicules : on ne prévoit pas les percées en maths comme les progrès de l'ingénierie (cf. la loi de Moore).
  • L'attaquant peut aussi contourner la cryptographie en se faisant passer pour le correspondant. C'est ce qu'on nomme une attaque de l'homme du milieu et cela a par exemple été utilisé par le gouvernement iranien en 2011. Leur méthode était de détourner le trafic HTTPS vers une machine gouvernementale et de présenter un « vrai/faux » certificat obtenu auprès d'une AC piratée, comme Diginotar. Ainsi, Alice croyait parler avec Bob alors qu'elle parlait à un espion... Le fait que la communication soit chiffrée n'aide pas si on parle au méchant.
  • L'attaquant peut aussi, s'il a l'autorité d'un État derrière lui, ne pas s'embêter et aller prendre les données où elles sont, chez le fournisseur de service. C'est ce que fait le programme PRISM, révélé par Snowden, avec la complicité des gros silos de données comme Facebook ou Gmail. (Dans certains États - mais pas les États-Unis depuis le Patriot Act - il faut normalement l'autorisation d'un juge. Mais il existe des écoutes illégales comme dans l'affaire des gendarmes de l'Élysée.)
  • Une faiblesse souvent oubliée est celle des métadonnées : même quand on n'a pas accès aux communications elles-mêmes, les seules métadonnées peuvent être une mine de renseignements (ce qu'on nomme l'analyse de trafic). Les métadonnées peuvent être le qui (Alice écrit à Bob), le quand et le combien (pour une session HTTP, la taille des données transférées indique si on a lu un fichier ou si on en a envoyé un). C'est d'autant plus vrai que les métadonnées, contrairement à la plupart des contenus, sont structurées, conçues pour être analysées par des programmes informatiques (car elles servent à la facturation ou au routage).

À noter que certaines de ces attaques peuvent se faire dans le temps : la NSA enregistre la conversation à tout hasard... et la lira dans dix ou vingt ans, quand les progrès de la technique ou de la science le lui permettront. Pensez donc aussi à cela : cette conversation sera t-elle toujours « sensible » dans dix ans ?

Maintenant, quelles protections peut fournir la crypto contre ces attaques ? Attention, cela va être plus laborieux que la description des attaques.

  • Contre le malware installé sur la machine de l'utilisateur, rien à faire. La crypto suppose une plate-forme sûre. Il est possible que des machines construites à partir de composants sécurisés (TPM) résolvent le problème mais je ne suis pas optimiste, notamment parce que ces composants sont plus souvent utilisés pour contrôler l'utilisateur que pour l'aider à se protéger.
  • Contre les attaques par force brute, il faut des clés suffisamment longues. Rappelez-vous du pouvoir de l'exponentielle. 2 puissance 256, par exemple, est un nombre qui défie l'imagination humaine. Il ne suffit pas de dépenser beaucoup d'argent et d'acheter des grosses machines pour tester 2^256 possibilités... (Attention, avec certains algorithmes, il existe des attaques appelées « force brute » mais qui intègrent en fait plusieurs astuces pour ne pas tout essayer. C'est ce qui explique que la longueur de la clé ne soit pas le seul paramètre à prendre en compte.) On entend souvent dire que le calcul quantique va tout changer en permettant des bonds colossaux de performance. Mais, malgré les prétentions des commerciaux qui vendent des « ordinateurs quantiques », on en est très loin. Les résultats concrets avec ces ordinateurs restent du domaine du laboratoire. Et, comme le note Schneier, les systèmes cryptographiques ont bien d'autres failles, plus faciles à exploiter que le cassage de la clé par le mythique ordinateur quantique.
  • Et contre les failles dans les logiciels ? Code source disponible, bonnes pratiques de programmation, examen par les pairs... Aucune de ces techniques ne fait de miracle mais, ensemble, elles aident à avoir une assez bonne sécurité. (J'ai lu sur un forum un texte d'un Jean-Kevin proclamant avec assurance que « la NSA a une porte dérobée dans PGP ». Inutile de dire qu'il ne fournissait aucune preuve.)
  • Pour les failles dans les protocoles de cryptographie, c'est à peu près la même approche : protocoles publiés, examinés publiquement par de nombreux experts. Il restera forcément des failles (on en découvre de nouvelles de temps en temps, dont certaines étaient peut-être déjà connues de la NSA) mais c'est mieux que rien. Notez que les protocoles non publiés utilisés dans les produits commerciaux fermés ne valent pas grand'chose. À chaque conférence de sécurité, un chercheur explique comment il en a rétro-ingénieré un. Parfois, un protocole secret chanceux tient le coup plus longtemps (RC4...) mais c'est rare.
  • Pour les algorithmes de cryptographie, c'est un pari sur l'avenir : on espère que l'algorithme ne sera pas cassé. À part l'espérance, la contre-attaque est la même que pour les programmes et les protocoles, à savoir la publication et l'analyse de sécurité au grand jour. On ne sait bien sûr pas où en est la NSA (on dit parfois qu'ils ont dix ou vingt ans d'avance sur la recherche publiée) mais l'ensemble des chercheurs qui travaillent et publient fait néanmoins un bon travail. Si RSA faiblit et devient vraiment trop incertain, on pourra passer aux courbes elliptiques (RFC 6090). Notez quand même qu'une bonne partie des chercheurs compétents ne publie pas, parce qu'ils travaillent pour la NSA, ou parce qu'ils préfèrent vendre leurs découvertes plutôt que d'aider l'humanité (si vous arrivez à trouver une décomposition en facteurs premiers facile, et que vous publiez, vous gagnez les 10 000 euros de la médaille Fields, soit bien moins que si vous vendez l'information à la NSA ou un de ses équivalents en Russie ou en Chine).
  • Contre l'attaque de l'homme du milieu, les solutions envisagées (encore largement expérimentales) tournent autour d'ajouts ou de remplacement du système des AC, comme le système DANE du RFC 6698 ou comme Perspectives.
  • Par contre, contre l'utilisation d'un gros silo de données comme Gmail ou Facebook, qui donne accès à toutes ses données à la NSA, la crypto ne peut rien. Elle ne protège que le voyage des données, mais tout est stocké en clair chez les fournisseurs de PRISM.
  • Enfin, pour la protection des métadonnées, le problème est compliqué. Les intermédiaires ont besoin des métadonnées pour acheminer le trafic et il n'est donc pas évident de les dissimuler (il existe des pistes de recherche mais pas encore de solution applicable). C'est pour cela que PGP ne chiffre pas les en-têtes. Pour sécuriser le courrier électronique, par exemple, il faudrait combiner PGP et SMTP sur TLS (RFC 3207 et attention : en pratique, SMTP sur TLS a des tas de limites, question sécurité).

Tout cela n'était que des solutions techniques car cet article se focalise sur l'aspect technique des choses. Mais, évidemment, le problème de fond est politique et c'est dans des changements politiques profonds qu'il faut chercher les vraies solutions. Il n'est pas normal qu'il faille être expert en crypto pour avoir une vie privée !

Autres bonnes lectures après cet article : l'interview d'un des développeurs de GnuPG ou bien un très bon article de Dan Goodin expliquant comment contourner (et non pas casser) la crypto ou encore celui de Peter Bright sur les vraies capacités de la NSA. Voir aussi l'article de Matthew Green qui fait le tour des techniques connues et inconnues pour déchiffrer le trafic TLS.

Conclusion ? Il faut évidemment de la cryptographie, ne serait-ce que « dans le doute », et à cause des nombreux attaquants moins équipés que la NSA. Snowden lui-même note que cela gêne l'attaquant. Mais ce n'est pas une solution magique et, dans son analyse de sécurité, il faut se demander « et si elle était cassée, quelles seraient les conséquences pour moi ? ».

Merci aux twittériens entre autres (hélas, je n'ai pas pensé à noter tout le monde) Nicolas Caproni, Ollivier Robert (également relecteur de cet article), Marc Levy, Geoffroy Couprie, Gildas Ribot, Damien Clauzel, et les autres. Merci à Gérard Fadrelle pour m'avoir rappelé l'attaque de l'homme du milieu que j'avais bêtement oubliée. Merci surtout au relecteur anonyme qui a fait l'essentiel de la relecture mais ne souhaite pas que son nom apparaisse.


L'article seul

RFC 7020: The Internet Numbers Registry System

Date de publication du RFC : Août 2013
Auteur(s) du RFC : R. Housley (Vigil Security), J. Curran (ARIN), G. Huston (APNIC), D. Conrad (Virtualized, LLC)
Pour information
Première rédaction de cet article le 29 août 2013


Le bon fonctionnement de l'Internet dépend de l'unicité de certains nombres, notamment les adresses IP. Comment ces nombres sont-ils alloués de manière à respecter cette unicité et d'autres propriétés souhaitables ? Ce RFC remplace l'ancien RFC 2050 qui décrivait le système d'allocation des adresses IP en 1996.

Comme son prédécesseur, ce RFC ne propose pas une nouvelle politique : il documente ce qui se fait actuellement. Cette documentation est d'autant plus difficile que la gouvernance des adresses IP est un sujet complexe, à l'intersection de la technique (les limites de taille de l'espace d'adressage, les limites de traitement des routeurs), de la politique et de l'économie. Contrairement à la gouvernance des noms de domaine, celle des adresses IP fait peu de bruit et est surtout traitée dans des cercles fermés. Malgré cela, il n'y a certainement pas de consensus quant à la gestion de ces adresses et ce RFC n'est pas exempt de parti pris. Dans cet article, j'essaie de coller à la description qu'ont choisi les auteurs du RFC mais rappelez-vous que tout le monde ne la trouve pas correcte, loin de là (j'avais un point de vue plus personnel dans mon article sur le RFC 2050).

On notera aussi que le titre du RFC fait référence au système d'allocation des nombres, pas seulement des adresses IP. Il traite en effet également des numéros d'AS, qui étaient absents du RFC 2050.

Donc, commençons par la section 2, les buts. Pourquoi faut-il une gestion des nombres ? On ne peut quand même pas être propriétaire du nombre 3676198671278441090, quand même ? Pourquoi ces organisations et ces règles ? Le premier but de cette gestion est la gestion de la pénurie : les adresses IPv4, notamment, sont en nombre fini et dramatiquement insuffisant. Le bon fonctionnement de l'Internet nécessitant qu'une adresse IP soit unique (ce blog est en 2605:4500:2:245b::42 ; si une autre machine avait cette adresse, à laquelle iraient les paquets ?), il faut un mécanisme pour s'assurer qu'une adresse ne soit allouée qu'une fois. Si l'espace d'adressage était immense, tirer un nombre au hasard dans cet espace assurerait une quasi-unicité (c'est ainsi qu'on fait pour les clés cryptographiques). Mais il ne l'est pas.

Et ce n'est pas le seul but de la gestion des adresses. Le routage dans l'Internet est hiérarchique. Il n'est pas possible qu'un routeur de la DFZ connaisse toutes les adresses du monde, sa mémoire n'y suffirait pas, sans parler du rythme de changement des tables de routage que cela imposerait. On regroupe donc les adresses en préfixes et le routage fonctionne sur ces préfixes, pas sur les adresses individuelles. Mais cela ne marche que si les adresses sont agrégeables, si elles sont suffisamment proches les unes des autres pour être regroupées en préfixes. Si 2001:db8:1:a::/64 est routé par un opérateur et 2001:db8:1:b::/64 par un autre, on ne pourra pas agréger ces annonces en un seul 2001:db8:1::/48. C'est donc le deuxième but de la politique de gestion des adresses IP, permettre l'agrégation. (Par contre, la politique de routage, à savoir ce que les routeurs acceptent en pratique ou pas, est indépendante du système d'enregistrement des nombres. Elle est décidée par chaque opérateur séparément.)

Troisième et dernier but, conserver et publier (typiquement, via whois), des informations fiables sur les titulaires des préfixes, de manière à pouvoir les contacter en cas de problème pratique (par exemple de sécurité, cf. section 7). L'un des rôles des registres est de s'assurer que ces informations soient correctes. En pratique, les données actuellement publiées sont souvent de qualité médiocre (erronées, pas à jour, etc.) D'autre part, rien n'étant parfait en ce monde, on a déjà vu des cas où deux registres avaient alloué le même nombre.

Comme le notait déjà le RFC 2050, ces buts peuvent être contradictoires entre eux. Ainsi, utiliser le mieux possible le nombre limité d'adresses IPv4 nécessiterait des micro-allocations (donner un /29 à celui qui n'a pas besoin de beaucoup d'adresses) alors que le routage demande de l'agrégation et donc d'allouer plutôt les préfixes en grands morceaux. D'autre part, ces trois buts peuvent être en contradiction avec d'autres intérêts. Par exemple, la publication des informations sur les titulaires et responsables techniques des préfixes peut être utilisée par les spammeurs pour collecter des adresses.

La section 3 du RFC décrit les organisations qui mettent en œuvre ce système de registre des nombres, et leurs relations. L'allocation hiérarchique des adresses IP et des numéros d'AS est enracinée à l'IANA qui distribue des ressources aux RIR qui les distribuent à des LIR qui les distribuent à des utilisateurs finaux (en simplifiant un peu). L'IANA est une fonction, pas une organisation (aujourd'hui, la fonction IANA est assurée par l'ICANN, suivant le MoU décrit dans le RFC 2860). Les documents IANA relatifs à ce rôle de registre des nombres sont notamment le ICANN Address Supporting Organization (ASO) MoU, le ICP-2: Criteria for Establishment of New Regional Internet Registries et le Internet Assigned Numbers Authority (IANA) Policy for Allocation of ASN Blocks to Regional Internet Registries. En pratique, les politiques d'allocation sont plutôt du ressort des RIR (décrits à l'origine dans le RFC 1366) et ces politiques doivent plutôt être cherchées sur les sites Web des RIR.

Mais d'autres organisations jouent aussi un rôle comme l'IETF qui édicte les normes techniques (mais, normalement, pas les politiques d'allocation précises, voir le RFC 6177 pour un exemple de débat) et qui réserve certains nombres (RFC 6890). La section 5 revient d'ailleurs sur les rôles respectifs de l'IETF et de l'ICANN.

La section 4 du RFC quitte ces considérations organisationnelles (ou bureaucratiques, si on veut être plus méchant) pour la technique, en notant qu'il est aussi de la responsabilité des registres de nombres de fournir un service de résolution DNS d'adresses IP en noms (via la gestion de domaines en in-addr.arpa et ip6.arpa) et d'assurer un service whois conforme à la norme technique (RFC 3912).

La section 6 décrit les changements depuis le RFC 2050, il y a dix-sept ans (lorsque l'ICANN n'existait même pas). Par exemple, le RFC 2050 décrivait un mécanisme d'appel à l'IANA lorsqu'on était mécontent d'une décision d'un autre acteur. Ce mécanisme a été supprimé (les RIR ont des procédures internes d'appel, par exemple le RIPE-NCC).


Téléchargez le RFC 7020


L'article seul

Attaques de la Syrian Electronic Army contre les noms de domaines

Première rédaction de cet article le 27 août 2013
Dernière mise à jour le 28 août 2013


Mardi 27 août, la « Syrian Electronic Army » a attaqué plusieurs noms de domaines importants, comme ceux du New York Times et de Twitter. Voici mon résumé, ainsi que des éléments concrets que j'avais recueilli sur le moment.

L'attaque a porté sur le bureau d'enregistrement Melbourne IT. Une fois cet intermédiaire piraté, la SEA a pu modifier à sa guise les données et notamment les serveurs de noms des domaines visés.

Ces données ont été récoltées entre 21 et 22 h UTC le 27 août. D'abord, le piratage du domaine nytimes.com. Mon Unbound sur ma machine (qui fait suivre les requêtes aux résolveurs de Free) voit :


% dig SOA nytimes.com.                   

; <<>> DiG 9.9.2-P1 <<>> SOA nytimes.com.
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 8602
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;nytimes.com.			IN	SOA

;; ANSWER SECTION:
nytimes.com.		86308	IN	SOA	ns1.syrianelectronicarmy.com. admin.sea.sy. 2013082701 86400 7200 3600000 86400

;; AUTHORITY SECTION:
nytimes.com.		86374	IN	NS	ns1.syrianelectronicarmy.com.
nytimes.com.		86374	IN	NS	ns2.syrianelectronicarmy.com.

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Tue Aug 27 22:59:11 2013
;; MSG SIZE  rcvd: 145

À ce stade, on ne peut pas encore dire s'il y a empoisonnement DNS ou piratage du registre ou du bureau d'enregistrement ?

Quelques minutes après, en demandant directement au registre :


; <<>> DiG 9.9.2-P1 <<>> @d.gtld-servers.net. NS nytimes.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 2190
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 6, ADDITIONAL: 3
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;nytimes.com.			IN	NS

;; AUTHORITY SECTION:
nytimes.com.		172800	IN	NS	ns27.boxsecured.com.
nytimes.com.		172800	IN	NS	ns28.boxsecured.com.

Ces boxsecured.com (un hébergeur états-unien) sont suspects : l'un répond REFUSED, l'autre donne un SOA étrange :


; <<>> DiG 9.9.2-P1 <<>> @212.1.211.141 SOA nytimes.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 61161
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;nytimes.com.			IN	SOA

;; ANSWER SECTION:
nytimes.com.		86400	IN	SOA	ns5.boxsecured.com. ssuliman.hotmail.co.uk. 2013082703 86400 7200 3600000 86400

;; AUTHORITY SECTION:
nytimes.com.		86400	IN	NS	ns6.boxsecured.com.
nytimes.com.		86400	IN	NS	ns5.boxsecured.com.

   Domain Name: NYTIMES.COM
   Registrar: MELBOURNE IT, LTD. D/B/A INTERNET NAMES WORLDWIDE
   Whois Server: whois.melbourneit.com
   Referral URL: http://www.melbourneit.com
   Name Server: NS27.BOXSECURED.COM
   Name Server: NS28.BOXSECURED.COM
   Status: serverDeleteProhibited
   Status: serverTransferProhibited
   Status: serverUpdateProhibited
   Updated Date: 27-aug-2013
   Creation Date: 18-jan-1994
   Expiration Date: 19-jan-2014

Et Twitter ? twitter.com dans whois montre un piratage (le TLD .sy est la Syrie) :

Admin Name........... SEA SEA
  Admin Address........ 1355 Market Street
  Admin Address........ Suite 900
  Admin Address........ 
  Admin Address. San Francisco
  Admin Address........ 94103
  Admin Address........ CA
  Admin Address........ UNITED STATES
  Admin Email.......... sea@sea.sy
  Admin Phone.......... +1.4152229670
  Admin Fax............ +1.4152220922

Même bureau d'enregistrement que nytimes.com, Melbourne IT. Par contre, les serveurs de noms n'ont pas été changés. Pourquoi ? Manque de temps pour la SEA ? Ou peut-être une protection spéciale, un « super-verrou » contre les modifications, soit au registre, soit au bureau d'enregistrement. Ce qui fait que, dans le cas de Twitter, l'utilisateur ordinaire ne voit rien. Par contre, twimg.com (hébergement d'images pour Twitter) a un whois analogue mais des serveurs de noms changés.

Une heure après, le registre de .com servait à nouveau la bonne information :


% dig @a.gtld-servers.net NS nytimes.com

; <<>> DiG 9.9.2-P1 <<>> @a.gtld-servers.net NS nytimes.com
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 57384
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 6, ADDITIONAL: 3
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;nytimes.com.			IN	NS

;; AUTHORITY SECTION:
nytimes.com.		172800	IN	NS	dns.ewr1.nytimes.com.
nytimes.com.		172800	IN	NS	dns.sea1.nytimes.com.
CK0POJMG874LJREF7EFN8430QVIT8BSM.com. 86400 IN NSEC3 1 1 0 - CK0RFQAOES8CTVNVNH4G6Q85NOQAQ8I9 NS SOA RRSIG DNSKEY NSEC3PARAM
CK0POJMG874LJREF7EFN8430QVIT8BSM.com. 86400 IN RRSIG NSEC3 8 2 86400 20130903044137 20130827033137 8795 com. j5+5FlHHaxax14Oj+MWS+KZAbRb6L9ERQkP6uf/naSfrAbjgWEqW3J3B xp8mCDRkbD0m6/E5Ax/Q8xPB5PqV/KxbaKZb05XxyNlwpN3wFFYlFhW/ Zyn1GbcfWrpHUQH2oTDNDfq7Am+HXbkRU60TwOjICpgkDMZqxHR8hww3 IFk=
O6B9DUFQLHV3BU9UG6OASLHH80ECTS95.com. 86400 IN NSEC3 1 1 0 - O6C0FKNFS7M5TK0HI5HN4O5JKU9PTV22 NS DS RRSIG
O6B9DUFQLHV3BU9UG6OASLHH80ECTS95.com. 86400 IN RRSIG NSEC3 8 2 86400 20130903110913 20130827095913 8795 com. YE2lkYOtVz8iIz31zHReEzQf93S2LAH+ZPMJt5K7vQQoydWJf/dDgqyu 1tDRy4pz+cAXIQYqqodYb/8c0/kMm0dCheUtUUKrhOYH39AqwiN+oMdY 2jxHbS7VPPP3Mj3RNPLj74JeO6pTqfz7a4Ibt5Z6ombsR8H+xbWXI7Li Mks=

;; ADDITIONAL SECTION:
dns.ewr1.nytimes.com.	172800	IN	A	170.149.168.134
dns.sea1.nytimes.com.	172800	IN	A	170.149.173.133

;; Query time: 144 msec
;; SERVER: 192.5.6.30#53(192.5.6.30)
;; WHEN: Tue Aug 27 23:57:25 2013
;; MSG SIZE  rcvd: 603

(Le sea1 dans dns.sea1.nytimes.com n'a rien à voir avec la SEA, il indique la ville, Seattle.) Mais il est amusant de noter que le whois au bureau d'enregistrement indiquait toujours la mauvaise information, ce qui semble indiquer que le registre a modifié l'information directement, en ignorant le bureau d'enregistrement :


% whois nytimes.com

Whois Server Version 2.0

Domain names in the .com and .net domains can now be registered
with many different competing registrars. Go to http://www.internic.net
for detailed information.

   Server Name: NYTIMES.COM
   IP Address: 141.105.64.37
   Registrar: MELBOURNE IT, LTD. D/B/A INTERNET NAMES WORLDWIDE
   Whois Server: whois.melbourneit.com
   Referral URL: http://www.melbourneit.com

   Domain Name: NYTIMES.COM
   Registrar: MELBOURNE IT, LTD. D/B/A INTERNET NAMES WORLDWIDE
   Whois Server: whois.melbourneit.com
   Referral URL: http://www.melbourneit.com
   Name Server: DNS.EWR1.NYTIMES.COM
   Name Server: DNS.SEA1.NYTIMES.COM
   Status: serverDeleteProhibited
   Status: serverTransferProhibited
   Status: serverUpdateProhibited
   Updated Date: 27-aug-2013
   Creation Date: 18-jan-1994
   Expiration Date: 19-jan-2014

>>> Last update of whois database: Tue, 27 Aug 2013 21:58:26 UTC <<<

[...]

Domain Name.......... nytimes.com
  Creation Date........ 1994-01-18
  Registration Date.... 2011-08-31
  Expiry Date.......... 2014-01-20
  Organisation Name.... SEA
  Organisation Address. 620 8th Avenue
  Organisation Address. 
  Organisation Address. 
  Organisation Address. New York
  Organisation Address. 10018
  Organisation Address. NY
  Organisation Address. UNITED STATES

Admin Name........... SEA SEA
  Admin Address........ SEA
  Admin Address........ 620 8th Avenue
  Admin Address........ 
  Admin Address. Syria
  Admin Address........ 10018
  Admin Address........ SY
  Admin Address........ SYRIAN ARAB REPUBLIC
  Admin Email.......... sea@sea.sy
  Admin Phone.......... +1.2125561234
  Admin Fax............ 

Tech Name............ NEW YORK TIMES DIGITAL
  Tech Address......... 229 West 43d Street
  Tech Address......... 
  Tech Address......... 
  Tech Address......... New York
  Tech Address......... 10036
  Tech Address......... NY
  Tech Address......... UNITED STATES
  Tech Email........... hostmaster@NYTIMES.COM
  Tech Phone........... +1.2125561234
  Tech Fax............. +1.1231231234
  Name Server.......... ns27.boxsecured.com
  Name Server.......... ns28.boxsecured.com

À noter que sharethis.com a aussi été attaqué mais qu'il est chez un bureau d'enregistrement différent et qu'il n'est pas sûr que la même méthode ait été employée.

Des rapports fiables signalent également un détournement de huffingtonpost.co.uk (un registre différent mais le même bureau d'enregistrement) mais je n'ai pas pu l'observer moi-même. Mais il est sûr que le problème ne frappait pas que .com. Voici la sortie du whois de twitter.co.uk, vingt minutes après que le .com ait été réparé :


% whois twitter.co.uk

    Domain name:
        twitter.co.uk

    Registrant:
        Twitter Inc

    Registrant type:
        Non-UK Corporation

    Registrant's address:
        1355 Market Street Suite 900
        San Francisco
        CA
        94103
        United States

    Registrar:
        Melbourne IT t/a Internet Names Worldwide [Tag = MELBOURNE-IT]
        URL: http://www.melbourneit.com.au/contacts

    Relevant dates:
        Registered on: 05-Mar-2005
        Expiry date:  05-Mar-2015
        Last updated:  27-Aug-2013

    Registration status:
        Registered until expiry date.

    Name servers:
        ns1.syrianelectronicarmy.com
        ns2.syrianelectronicarmy.com

    WHOIS lookup made at 23:20:51 27-Aug-2013

[...]

Cela plaide donc encore plus pour un piratage du bureau d'enregistrement, Melbourne IT, qui a été confirmé par Melbourne IT quelques heures après.

Quelques articles intéressants sur ce piratage :

Et c'est l'occasion de relire et revoir :


L'article seul

RFC 6998: A Mechanism to Measure the Routing Metrics along a Point-to-point Route in a Low Power and Lossy Network

Date de publication du RFC : Août 2013
Auteur(s) du RFC : M. Goyal (University of Wisconsin, Milwaukee), E. Baccelli (INRIA), A. Brandt (Sigma Designs), J. Martocci (Johnson Controls)
Expérimental
Réalisé dans le cadre du groupe de travail IETF roll
Première rédaction de cet article le 27 août 2013


Le protocole RPL (Routing Protocol for Low power and Lossy Networks), normalisé dans le RFC 6550, est conçu pour des réseaux de machines très bon marché, ayant peu de capacités (mémoire et calcul), étant souvent très limitées en énergie, et étant connectées par des liens de qualité médiocre. Un tel environnement peut par exemple se rencontrer dans des réseaux de capteurs dispersés dans un environnement industriel. Une partie des machines du réseau va se dévouer pour router les paquets des autres. RPL permet de trouver et de diffuser des routes mais celle choisie ne sera pas forcément optimale. D'où ces deux extensions à RPL permettant à un routeur de 1) mesurer une métrique donnée en émettant un paquet de contrôle vers la destination, paquet qui accumulera au fur et à mesure, dans les routeurs intermédiaires, les informations à propos de la route utilisée actuellement et, 2) découvrir à la demande une route meilleure (si tant est qu'il y en a une).

C'est que ce n'est pas une vie que d'être routeur dans un LLN (Low power and Lossy Network, les réseaux difficiles dont je parlais au paragraphe précédent). Le RPL classique du RFC 6550 essaie de faciliter les choses en limitant le réseau à un graphe acyclique dirigé vers un puits de données et en calculant toutes les routes à l'avance (ce qu'on nomme un protocole proactif). Une extension à RPL, nommée P2P-RPL (P2P pour pair-à-pair) et normalisée dans le RFC 6997, permet à RPL de devenir réactif et donc de calculer des routes à la demande. Elle permet aussi de trouver des routes plus courtes, en évitant le passage par le sommet du graphe pré-établi. Le routeur utilise, pour ces calculs, les métriques du RFC 6551 (latence, capacité, qualité, et autres métriques dans le registre IANA). Mais comment connaître leur valeur effective dans un réseau ? Eh bien, en les mesurant, tout simplement.

Le protocole RPL ne transmettant pas cette information pour toutes les routes, c'est au routeur qui en a besoin de demander. Il génère un paquet de contrôle RPL d'un nouveau type, Measurement Request indiquant ce qu'il veut savoir à propos du chemin entre lui-même et la destination. Chaque routeur sur le trajet va mettre à jour ce paquet avec le coût (pour la métrique demandée) du lien effectivement emprunté. Au bout, le destinataire répondra au demandeur, avec un message de contrôle Measurement Reply, contenant toute l'information accumulée. Le demandeur pourra alors agir (changer d'avis pour certaines routes, par exemple).

En fait, les deux messages utilisent le même type de paquets, les Measurement Object de code 0x06 (section 3 et registre IANA). Un bit dans son en-tête, le bit T (pour Type) sert à distinguer si ce Measurement Object est un Measurement Request ou un Measurement Reply. Le paquet contient surtout des options Metric Container (section 6.7.4 du RFC 6550 et section 2.1 du RFC 6551) qui accumuleront au fur et à mesure les valeurs demandées.

Il est intéressant de comparer ce mécanisme à celui de traceroute qui n'accumule pas les mesures mais compte sur une réponse de chaque routeur intermédiaire vers la source ; des options avaient été proposées pour un traceroute « enregistreur » - Record Route du RFC 791 ou option IP du RFC 1393 - mais elles n'ont eu aucun succès.

Notez bien que, dans un réseau ad hoc, rien ne garantit que tous les routeurs accepteront de procéder à cet enregistrement de données. Ils ont parfaitement le droit de refuser de le faire (voir la section 5 de notre RFC), par exemple pour économiser leur batterie ou bien parce qu'ils trouvent une telle demande trop indiscrète (section 8 du RFC).

Il existe déjà plusieurs mises en œuvre de cette extension expérimentale et un test d'interopérabilité a été documenté. Sinon, un bon article consacré aux mesures de P2P-RPL est « The P2P-RPL Routing Protocol for IPv6 Sensor Networks: Testbed Experiments ».

Merci à Emmanuel Baccelli pour sa relecture attentive.


Téléchargez le RFC 6998


L'article seul

RFC 6980: Security Implications of IPv6 Fragmentation with IPv6 Neighbor Discovery

Date de publication du RFC : Août 2013
Auteur(s) du RFC : F. Gont (SI6 Networks / UTN-FRH)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF 6man
Première rédaction de cet article le 26 août 2013


Ce court RFC traite un problème de sécurité lorsqu'on combine la fragmentation avec le protocole NDP d'IPv6. Il interdit désormais cette combinaison, qui pouvait être exploitée pour des attaques sur le réseau local.

NDP est normalisé dans le RFC 4861 (que ce RFC 6980 met à jour). Ce protocole est utilisé pour bien des choses, notamment pour résoudre une adresse IPv6 en adresse MAC et pour découvrir les routeurs du réseau local, ainsi que les préfixes des adresses IP de ce réseau (pour l'auto-configuration). Ses faiblesses de sécurité (très proches de celles d'ARP en IPv4) sont bien connues (RFC 3756). Notamment, n'importe quelle machine peut émettre des paquets NDP et répondre aux questions adressées à une autre machine. Ou bien l'attaquant peut se faire passer pour le routeur et émettre des « RAcailles », ces faux paquets RA (Router Advertisment).

Il existe plusieurs moyens de gérer ces dangers. On peut mettre des ACL statiques dans les commutateurs, n'autorisant les RA que sur le port où se trouve le routeur. Ou bien on peut utiliser la solution un peu plus sophistiquée du RA guard (RFC 6105). On peut aussi surveiller le trafic, avec un IPS ou bien un logiciel comme NDPmon ou ramond, et lever une alarme lorsque quelque chose d'anormal se produit. Mais toutes ces techniques ont un défaut commun : elles reposent sur une analyse du paquet pour détecter si c'était du NDP et il est trop facile de les tromper en fragmentant le paquet. S'il est en deux parties, avec les informations permettant de reconnaître et d'analyser le NDP dans le deuxième paquet, aucun des systèmes existants ne voit ce qui se passe, alors que la machine terminale réassemblera le paquet et se fera donc avoir. À l'heure actuelle, la totalité des mises en œuvre de RA guard est ainsi vulnérable (cf. RFC 7113). Bien sûr, des outils comme les IPS pourraient réassembler les paquets eux-aussi, pour voir le paquet original, mais c'est plus difficile pour les commutateurs Ethernet. Et cela leur fait courir un risque (si l'attaquant génère des quantités de fragments afin d'épuiser la mémoire des réassembleurs, pour faire une attaque par déni de service).

C'est d'autant plus balot que les vrais paquets NDP sont rarement assez grands pour avoir réellement besoin de la fragmentation (section 2). Même si un routeur a besoin d'annoncer de nombreux préfixes dans ses RA, il peut le faire en plusieurs datagrammes IP, il n'est pas nécessaire de tout mettre dans un seul grand datagramme fragmenté. Bref, la fragmentation est quasi-inutile pour NDP alors qu'elle est dangereuse. (Une exception partielle est décrite en section 3, pour SEND, dans le RFC 3971, dans le cas où il y a des gros certificats à transmettre. Je ne la mentionne pas davantage puisque SEND n'est quasiment jamais utilisé. Il résout radicalement presque tous les problèmes de sécurité de NDP mais le manque de mises en œuvre de ce protocole, et la difficulté qu'il y a à distribuer les clés cryptographiques nécessaires font qu'en pratique, SEND n'est pas une approche envisageable. Voir la conférence de l'auteur à DEEPSEC.)

La section 4 résume les raisons d'abandonner la fragmentation pour NDP :

  • Il existe déjà des mises en œuvre d'IPv6 qui ignorent les paquets NDP fragmentés,
  • Dans la vraie vie, comme expliqué en sections 2 et 3, les paquets NDP réels ne sont pas assez grands pour être fragmentés.

Donc, la section 5 du RFC expose la nouvelle règle, qui met à jour le RFC 4861 : une machine qui émet des paquets NDP ne doit pas fragmenter ces paquets. (Une exception partielle est faite pour les messages Certification Path Advertisement utilisés par SEND. Mais, pour tous les messages habituels, la règle est l'interdiction de la fragmentation.) À la réception, les paquets NDP fragmentés doivent être ignorés.

Si vous voulez créer vous-même de tels paquets NDP fragmentés (qui seront ignorés par les systèmes modernes, vous pouvez utiliser la boîte à outils SI6 présenté dans mon article sur le hacking IPv6, avec l'option -y. Par exemple :

# ./ra6 -y 8  -i eth1 -d 2001:db8:8bd9:8bb0:ba27:ebff:feba:9094          

va générer deux fragments, huit octets n'étant pas assez pour mettre le RA. tcpdump les voit ainsi :

08:34:29.122863 IP6 fe80::8609:88f4:14:a635 > 2001:db8:8bd9:8bb0:ba27:ebff:feba:9094: frag (0|8) ICMP6, router advertisement, length 8
08:34:29.122883 IP6 fe80::8609:88f4:14:a635 > 2001:db8:8bd9:8bb0:ba27:ebff:feba:9094: frag (8|8)

Notez que tcpdump ne s'est pas laissé avoir : il a bien identifié le premier fragment comme appartenant à un RA.


Téléchargez le RFC 6980


L'article seul

Latence rigolote chez F-Contact

Première rédaction de cet article le 25 août 2013


Ah, les plaisirs de la fracture numérique. Pas besoin d'aller au fin fond de l'Afrique pour la tester, il suffit de partir en vacances au centre de la France, sur les bords de l'Indre, charmante région, aux excellents fromages de chèvre, mais à la connexion lamentable.

C'est une zone blanche. Très blanche. Au point que le seul opérateur mobile qu'on capte (parfois) est F-contact, opérateur collectif créé pour desservir ces zones blanches. La voix passe dans certains cas. Et les données ? Avec un abonnement Orange 3G, j'obtiens une connexion GPRS et admirez la latence :

% ping -i 30 -c 10 192.134.4.20
PING 192.134.4.20 (192.134.4.20) 56(84) bytes of data.
64 bytes from 192.134.4.20: icmp_req=1 ttl=45 time=12799 ms
64 bytes from 192.134.4.20: icmp_req=2 ttl=45 time=20330 ms
64 bytes from 192.134.4.20: icmp_req=3 ttl=45 time=10799 ms
64 bytes from 192.134.4.20: icmp_req=4 ttl=45 time=13417 ms
64 bytes from 192.134.4.20: icmp_req=5 ttl=45 time=13496 ms
64 bytes from 192.134.4.20: icmp_req=6 ttl=45 time=24128 ms
64 bytes from 192.134.4.20: icmp_req=7 ttl=45 time=34604 ms
64 bytes from 192.134.4.20: icmp_req=8 ttl=45 time=38724 ms
64 bytes from 192.134.4.20: icmp_req=9 ttl=45 time=34504 ms
64 bytes from 192.134.4.20: icmp_req=10 ttl=45 time=21644 ms

--- 192.134.4.20 ping statistics ---
10 packets transmitted, 10 received, 0% packet loss, time 270031ms
rtt min/avg/max/mdev = 10799.256/22445.025/38724.983/9779.967 ms, pipe 2

Dix secondes minimum, vingt-deux en moyenne, soit le temps pour la lumière de faire quinze fois le trajet de la Terre à la Lune. Faire le trajet de l'Indre à l'Internet est bien plus long... Mais pas une seule perte de paquet, par contre.

Pour comparer, dans une région mieux connectée, en UMTS, la même machine et la même clé 3G obtiennent :

% ping -c 10 -i 10 192.134.4.20
...
--- 192.134.4.20 ping statistics ---
10 packets transmitted, 10 received, 0% packet loss, time 90049ms
rtt min/avg/max/mdev = 60.149/289.710/959.800/296.908 ms

Avec une telle latence, quasiment aucun service ne marche (à part ping) comme vu plus haut. Pas TCP, c'est sûr, car il ne patiente jamais assez pour que la connexion puisse être établie. Mais le DNS ne marche pas non plus car le Unbound installé sur ma machine timeoute systématiquement (alors que la réponse arrive, on la voit avec tcpdump, mais horriblement tard). On comprend pourquoi les gens qui ont tenté une mise en œuvre du RFC 1149 n'ont jamais utilisé autre chose que ping. Il faudrait sans doute déployer des applications spécifiques, fondées sur des protocoles adaptés comme celui du RFC 9171.

Pierre Beyssac me fait remarquer que beaucoup d'applications Web auront leurs propres problèmes car elles chargent le code qui va après chercher des données en Ajax, avec leurs propres délais de garde, bien plus courts.

Désolé, je ne peux pas vous montrer un traceroute car les routeurs de l'opérateur trichent et envoient une réponse bidon. Mais si vous aimez la technique, j'ai découvert à cette occasion (merci à MarcBrice) l'excellent site http://www.antennesmobiles.fr/ qui donne accès à la localisation de toutes les antennes de France avec leurs caractéristiques. J'étais situé entre deux antennes Bouygues, distante chacune de six kilomètres.

Comment une telle latence est possible ? Je n'ai pas d'explications. Mais elle peut être volontaire, F-contact servant prioritairement à la voix, introduire une latence est un moyen de décourager son usage pour les données.


L'article seul

RFC 6984: Interoperability Report for Forwarding and Control Element Separation (ForCES)

Date de publication du RFC : Août 2013
Auteur(s) du RFC : W. Wang (Zhejiang Gongshang University), K. Ogawa (NTT Corporation), E.H. Haleplidis (University of Patras), M. Gao (Hangzhou BAUD Networks), J. Hadi Salim (Mojatatu Networks)
Pour information
Réalisé dans le cadre du groupe de travail IETF forces
Première rédaction de cet article le 25 août 2013


Un élément essentiel de la culture IETF est l'importance donnée aux programmes qui marchent : rough consensus and running code. D'où les fréquents tests d'interopérabilité, entre diverses mises en œuvre des protocoles IETF, afin de vérifier que, non seulement le code tourne mais qu'il peut interagir avec d'autres instances. Le groupe de travail ForCES, qui normalise des protocoles de communication internes aux routeurs, a ainsi procédé à deux ateliers de tests d'interopérabilité, ce RFC documentant le second.

Le premier avait eu lieu en 2009 à l'université de Patras et avait été documenté dans le RFC 6053. Le second a eu lieu en février 2011 à l'ITL (Internet Technology Lab) à l'université de Zhejiang Gongshang. (Oui, je sais, c'est long, entre l'atelier et la publication du compte-rendu dans un RFC...)

Rappelons ce que fait ForCES : il normalise la communication entre les éléments d'un routeur (ou autre engin du réseau : la norme parle de NE pour Network Element). Le but est de permettra la construction de routeurs en kit, en assemblant des parties d'origines différentes, mais parlant toutes ForCES. Le système ForCES est riche et complexe et cet atelier d'interopérabilité testait cinq composants : le protocole de communication entre CE (Control Element) et FE (Forwarding Element), normalisé dans le RFC 5810, le protocole de transport sous-jacent (RFC 5811), le modèle des FE (RFC 5812), la bibliothèque standard (RFC 6956) et le mécanisme de haute disponibilité (dont le RFC n'a pas encore été publié). Des CE et FE d'origines diverses ont été connectés entre eux, se sont parlé, la bonne compréhension a été vérifiée et tcpdump et Wireshark ont été utilisés pour un contrôle supplémentaire.

Trois mises en œuvre de ForCES ont été testées, les mêmes qu'à l'atelier précédent (ForCES n'a pas pour l'instant suscité un intérêt massif) : celle de NTT, celle de l'université de Patras, et celle faite en commun entre l'université de Zhejiang Gongshang et la société BAUD Network. Les Grecs n'ayant pu se déplacer, ils ont participé aux tests à distance, connectés via un VPN (dans la réalité, bien sûr, les FE et les CE seront toujours proches, souvent dans le même boîtier physique). Globalement, les tests ont été des succès, à part un problème embêtant avec l'encapsulation des données dans une réponse ForCES (voir les détails plus loin). Comme toujours, ces tests ont permis de découvrir des erreurs ou des approximations dans les RFC.

Les communications utilisaient IPsec, puisque le RFC sur le transport de ForCES, RFC 5811, fait obligation à chaque mise en œuvre de ForCES d'avoir IPsec (mais pas forcément de l'activer par défaut : c'est sa disponibilité qui est obligatoire, pas son usage).

Un exemple d'un des scénarios testés (section 3.4) : deux machines terminales sur deux réseaux locaux différents étaient connectées via deux routeurs OSPF. L'un était un routeur classique, l'autre une machine ForCES dont le CE (Control Element) parlait OSPF avec le routeur classique pendant que le FE (Forwarding Element) transmettait les paquets. Ce scénario nécessitait que le CE communique au FE les règles qu'il avait apprises en OSPF et testait la mise en œuvre correcte de plusieurs fonctions du RFC 6956. Une variante de ce test remplaçait le routeur classique par une autre machine ForCES : les deux CE se parlaient en OSPF et chacun disait ensuite à son FE ce qu'il devait faire des paquets IP.

La section 4 donne les résultats complets des tests. Il y a une très grande majorité de succès mais aussi deux échecs, qui vont nécessiter du travail chez les programmeurs.

Mais le principal problème de l'atelier a été un problème lors de la communication de tableaux (et pas de simples valeurs scalaires) entre deux programmes. Le problème est que ForCES permet plusieurs encodages possibles pour les données complexes (RFC 5810, section 6 et notamment 6.4). La règle est que chaque élément ForCES peut choisir librement parmi ces encodages (pas moins de trois possibilités légales, dans l'exemple discuté dans la section 5 de notre RFC). Mais un programme considérait que la réponse venait forcément dans l'encodage de la question, et plantait si ce n'était pas le cas. Bien qu'il soit clairement en tort, notre RFC considère qu'il vaut mieux en effet générer une réponse en utilisant le même encodage que la question ou la commande. Personnellement, je pense plutôt que c'était très gentil de donner un vaste choix aux CE et FE (par exemple pour optimiser le cas de grands tableaux ayant beaucoup de vide) mais que cela mène forcément à ce genre de problèmes. Traditionnellement, les protocoles IETF préfèrent l'interopérabilité à la liberté et ForCES était peut-être allé trop loin dans les possibilités de choix.


Téléchargez le RFC 6984


L'article seul

RFC 6979: Deterministic Usage of DSA and ECDSA Digital Signature Algorithms

Date de publication du RFC : Août 2013
Auteur(s) du RFC : T. Pornin
Pour information
Première rédaction de cet article le 24 août 2013


Les algorithmes de signature DSA et ECDSA ont une particularité qui est souvent oubliée : chaque signature doit utiliser un nombre imprévisible. On peut, par exemple, générer ce nombre par un processus aléatoire. Mais tous les systèmes qui voudraient utiliser DSA ou ECDSA n'ont pas forcément un tel générateur aléatoire. Ce RFC propose une autre méthode : fabriquer ce nombre par dérivation déterministe d'un certain nombre de paramètres, produisant le même effet, sans pour autant nécessiter de source d'aléa.

Ces deux algorithmes sont très utilisés dans le monde. (À noter qu'ECDSA repose sur les courbes elliptiques, décrites dans le RFC 6090.) Mais cette nécessité de générer un nombre unique et imprévisible par signature n'a pas d'équivalent avec des algorithmes comme RSA. Le pourquoi de cette nécessité est bien expliqué dans un article de Nate Lawson. Si vous l'oubliez, vous serez piraté, comme Sony l'a été. Mais que ce nombre soit aléatoire n'est pas strictement nécessaire. En fait, l'aléatoire a deux défauts :

  • Il rend les tests difficiles puisque deux exécutions successives du même programme ne donneront pas le même résultat. Ces tests ne peuvent pas facilement vérifier si le nombre est bien imprévisible.
  • Et, surtout, toutes les machines n'ont pas forcément un générateur aléatoire de bonne qualité (cf. RFC 4086), notamment les engins spécialisés comme les cartes à puce. Cela peut mener à préférer RSA, pourtant plus consommateur de ressources.

L'algorithme permettant de générer un nombre unique et imprévisible, mais sans générateur aléatoire, est décrit dans les sections 2 et 3 de notre RFC (il est fondé sur l'idée de derandomization, décrite dans « How Risky is the Random-Oracle Model? »). Je ne vais pas résumer cet algorithme ici (la cryptographie, c'est trop fort pour moi) mais ses propriétés importantes sont :

  • Les signatures sont des signatures DSA ou ECDSA traditionnelles. Les vérificateurs de signature n'ont pas besoin de connaître ce nouvel algorithme et n'ont donc pas besoin d'être modifiés.
  • Les clés, elles, doivent, comme avant, être générées aléatoirement (comme avec RSA).

L'annexe A contient un exemple détaillé de calcul du nombre unique pour une signature.

Si vous envisagez de programmer cet algorithme de génération déterministe de signature, faites bien attention à la section 4, qui résume les problèmes de sécurité. Par exemple, comme rappelé plus haut, la procédure de ce RFC ne s'applique pas aux clés qui doivent, comme avant, être générées aléatoirement. Pour des engins sans générateur aléatoire, comme les carte à puce de bas et de milieu de gamme, cela peut par exemple être fait à l'usine, pendant la fabrication de l'engin.

D'autre part, comme la génération de la signature est déterministe, le même messsage aura donc toujours la même signature (tant qu'on garde la même clé privée, bien sûr). Cela n'est pas un problème dans certaines applications (RSA, tel que décrit dans le RFC 3447, fait pareil). Ainsi, TLS (RFC 5246), SSH (RFC 4251) ou CMS (RFC 5652) peuvent utiliser cet algorithme déterministe sans risque pour leur sécurité.

À noter que, de manière surprenante pour un RFC, la section 5 est consacrée aux risque de brevets sur cet algorithme (apparemment assez faibles). C'est surprenant car, comme la situation change tout le temps (nouveaux brevets, brevets reconnus comme futiles, etc), cette information est normalement distribuée en ligne et pas mise dans un RFC stable (c'est expliqué dans le RFC 8179). Les brevets actuellement connus pour ce RFC sont sur le site Web de l'IETF.

L'annexe B contient une mise en œuvre, en Java, de cet algorithme (copiée ici dans le fichier DeterministicDSA.java). On peut l'utiliser, par exemple, ainsi :


import java.math.BigInteger;
import org.ietf.DeterministicDSA;

public class TestDeterministicDSA {
    
    // http://stackoverflow.com/questions/5470219/java-get-md5-string-from-message-digest
    private static String binary2string(byte []bin) {
	StringBuilder binString = new StringBuilder();
	for (int i = 0; i < bin.length; i++) {
	    String hex = Integer.toHexString(bin[i]);
	    if (hex.length() == 1)
		{
		    binString.append('0');
		    binString.append(hex.charAt(hex.length() - 1));
		}
	    else
		binString.append(hex.substring(hex.length() - 2));
	}
	return binString.toString();
    }

    public static void main (String args[]) {
	int i;
        DeterministicDSA dsa = new DeterministicDSA("SHA-256");
	String signature;
        // We use the private key for the appendix A.2.1 of the RFC
	BigInteger p = new BigInteger("86F5CA03DCFEB225063FF830A0C769B9DD9D6153AD91D7CE27F787C43278B447E6533B86B18BED6E8A48B784A14C252C5BE0DBF60B86D6385BD2F12FB763ED8873ABFD3F5BA2E0A8C0A59082EAC056935E529DAF7C610467899C77ADEDFC846C881870B7B19B2B58F9BE0521A17002E3BDD6B86685EE90B3D9A1B02B782B1779", 16);
	BigInteger q = new BigInteger("996F967F6C8E388D9E28D01E205FBA957A5698B1", 16);
	BigInteger g = new BigInteger("07B0F92546150B62514BB771E2A0C0CE387F03BDA6C56B505209FF25FD3C133D89BBCD97E904E09114D9A7DEFDEADFC9078EA544D2E401AEECC40BB9FBBF78FD87995A10A1C27CB7789B594BA7EFB5C4326A9FE59A070E136DB77175464ADCA417BE5DCE2F40D10A46A3A3943F26AB7FD9C0398FF8C76EE0A56826A8A88F1DBD", 16);
	BigInteger x = new BigInteger("411602CB19A6CCC34494D79D98EF1E7ED5AF25F7", 16);
	dsa.setPrivateKey(p, q, g, x);
	for (i=0; i<args.length; i++) {
	    dsa.update(args[i].getBytes());
	    signature = binary2string(dsa.sign());
	    System.out.println(args[i] + " -> " + signature);
	    dsa.reset();
	}
    }
   
}

Et on retrouve les valeurs indiquées dans le RFC (ce qui est logique pour un processus déterministe...) :

 
% java TestDeterministicDSA sample test
sample -> 302d02150081f2f5850be5bc123c43f71a3033e9384611c54502144cdd914b65eb6c66a8aaad27299bee6b035f5e89
test -> 302c021422518c127299b0f6fdc9872b282b9e70d079081202146837ec18f150d55de95b5e29be7af5d01e4fe160

Téléchargez le RFC 6979


L'article seul

RFC 6994: Shared Use of Experimental TCP Options

Date de publication du RFC : Août 2013
Auteur(s) du RFC : J. Touch (USC/ISI)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF tcpm
Première rédaction de cet article le 24 août 2013


Le protocole TCP dispose d'un champ « Options » permettant d'indiquer des fonctions spécifiques. Ce champ commence par un identificateur d'option (sur un octet) et deux valeurs sont réservées pour des options expérimentales, non enregistrées. Deux, c'est trop peu, et, en prime, il y a parfois collision entre deux options expérimentales différentes. Notre RFC propose donc un nouveau mécanisme éliminant ces collisions, en ajoutant un deuxième identificateur, l'ExID, dans les options expérimentales.

Le champ « Options » est décrit dans le RFC 793. Il a deux formes mais la plus courante est composée d'un octet indiquant l'option, d'un octet indiquant la longueur de l'option et de données spécifiques à l'option (un TLV, donc). Les options sont enregistrées à l'IANA et sont aujourd'hui au nombre d'une trentaine. 30 sur 256 possibles, cela justifie de les allouer avec prudence (RFC 2780) et les gens qui veulent juste essayer une idée amusante, sans enregistrer leur option, n'avaient pas de solution simple avant que le RFC 4727 ne réserve les options 253 et 254 pour les expérimentations. Si vous avez une idée qui nécessite une option TCP, et que vous voulez la mettre en œuvre, prenez un de ces deux numéros et mettez-le dans vos paquets TCP, vous serez dans la légalité (le RFC 3692 dit toutefois que cela ne doit pas être activé par défaut).

Mais ces expérimentations risquent de se marcher sur les pieds entre elles. Par exemple, le RFC 6013 s'alloue l'option 253. Si vous voulez tester une option en même temps que celle du RFC 6013, il ne vous reste plus qu'un numéro, ce qui peut être insuffisant (certains systèmes nécessitent plusieurs options). À noter que cet usage d'un numéro d'option expérimental est légal (c'est fait pour) mais qu'il existe aussi des squatteurs, qui utilisent des numéros normalement réservés sans les avoir enregistrés proprement. Les options 31 et 32 avaient ainsi été squattées autoritairement, comme 76 à 78, 33, 69, 70, et 76 à 78 (ces derniers dans des produits commerciaux). Le registre IANA les note comme « known unauthorized use without proper IANA assignment ».

Plusieurs approches ont été suggérées à l'IETF pour régler ce problème. Il a été proposé d'élargir l'espace des numéros d'options (Internet-Draft draft-eddy-tcpm-addl-exp-options) et/ou de libéraliser les règles d'allocation, actuellement très strictes (il faut un RFC sur le chemin des normes pour réserver une option). Ce RFC 6994 utilise une autre approche : il crée un « sous-espace » à l'intérieur des options expérimentales, dans lequel on peut (mais ce n'est pas obligatoire) enregistrer sans trop de formalités une expérimentation et son identificateur. C'est désormais l'approche recommandée pour les nouvelles options expérimentales TCP (et obligatoire si l'option expérimentale est déployée sur l'Internet public).

Le principe (section 3) est de remplacer la structure {numéro d'option, longueur, valeur} par {numéro d'option, longueur, ExID, valeur} où le ExID est l'identificateur d'une expérimentation. La taille des ExID (16 ou 32 bits) permet d'en avoir beaucoup et donc d'avoir une politique d'enregistrement libérale sans craindre d'épuiser une ressource finie. L'IANA les enregistre donc sur une base toute simple : « premier arrivé, premier servi » (RFC 5226 pour les différentes options d'allocation possibles). Le registre de ces ExID est en ligne (il compte actuellement trois expérimentations dont le Fast Open TCP qui a été décrit dans le RFC 7413).

Bon, mais l'ExID fait 16 ou 32 bits, alors ? C'est subtil : les 16 premiers bits doivent être uniques pour identifier une expérimentation. Les 16 bits optionnels suivants servent de nombre magique, pour éviter le risque de collision avec des mises en œuvre de TCP qui ne connaissent pas ce RFC (ou bien l'ignorent) et mettent leurs données juste après l'octet de longueur. Si on veut économiser de la place, on choisit un ExID de 16 bits, si on veut minimiser le risque de collision, on prend 32 bits.

Que va donc faire une mise en œuvre de TCP qui rencontre ces options (section 3.2) ? Si l'option est 253 ou 254, elle doit lire l'ExID et ignorer l'option s'il s'agit d'une expérimentation qui lui est inconnue.

Mais les collisions, alors ? Elles peuvent toujours exister. Si une implémentation ancienne de TCP utilise l'option 253 et met au début des données qu'elle envoie la valeur 0x15df, et que le récepteur TCP, conforme à ce nouveau RFC 6994, croit qu'il s'agit de l'expérimentation 5599, qu'il connait, et se met à analyser l'option comme telle ? Il n'y a pas de solution magique. La section 4 de notre RFC recommande aux receveurs TCP d'être robustes face à de telles collisions, ou bien de mettre en œuvre un mécanisme de contrôle de la cohérence des données, pour rejeter les faux positifs.

Un problème classique (et non spécifique à TCP) avec les options expérimentales est qu'un jour, elles seront peut-être normalisées et qu'il faudra alors gérer une transition depuis l'option expérimentale vers l'option standard. La section 5 couvre ce cas mais ne recommande pas une stratégie particulière. Elle se contente de dire qu'envoyer les deux options (l'expérimentale et la standard) dans le même paquet est une mauvaise idée (l'espace des options est limité en TCP).

La section 6 discute des autres approches qui auraient pu être choisies. Par exemple, au lieu des ExID, on aurait pu marquer les options avec un identificateur de l'organisation qui dirige l'expérience, en utilisant les OUI de l'IEEE ou bien les Enterprise Numbers de l'IANA (RFC 1155). Mais les OUI sont très chers (comme souvent à l'IEEE), plus de 1 800 dollars. Les PEN (Private Enterprise Numbers) sont gratuits mais ne sont normalement pas allouables à un individu. Et, dans les deux cas, ces nombres sont plus grands que l'ExID (les PEN n'ont pas de taille définie actuellement mais ils sont déjà trop nombreux pour 16 bits) alors que l'espace est limité dans le champ Options de TCP, puisque tout octet prend la place d'un octet utile aux données.

Si on regarde les versions de développement de Linux et de FreeBSD, on ne trouve rien dans ce dernier (sys/netinet/tcp_input.c dans tcp_dooptions()), qui ne connait pas, par défaut, les options expérimentales. Pour Linux, seul Fast Open est reconnu. Le code dans net/ipv4/tcp_input.c, tcp_parse_options() dit :


case TCPOPT_EXP:
        /* Fast Open option shares code 254 using a
         * 16 bits magic number. It's valid only in
         * SYN or SYN-ACK with an even size.
         */
        if (opsize < TCPOLEN_EXP_FASTOPEN_BASE ||
            get_unaligned_be16(ptr) != TCPOPT_FASTOPEN_MAGIC ||
            foc == NULL || !th->syn || (opsize & 1))
                break;
        foc->len = opsize - TCPOLEN_EXP_FASTOPEN_BASE;
        if (foc->len >= TCP_FASTOPEN_COOKIE_MIN &&
            foc->len <= TCP_FASTOPEN_COOKIE_MAX)
                memcpy(foc->val, ptr + 2, foc->len);
        ...
}

TCPOPT_FASTOPEN_MAGIC vaut 0xF989 (l'ExID sur 16 bits dans le registre IANA).


Téléchargez le RFC 6994


L'article seul

Nouvelles attaques facilitant l'empoisonnement DNS

Première rédaction de cet article le 2 août 2013


À la réunion de l'IETF à Berlin le premier août, Haya Shulman a présenté le résultat de ses recherches sur des techniques permettant d'améliorer (en parlant avec le point de vue de l'attaquant) les attaques par empoisonnement DNS. Cela illustre un vieil adage de la sécurité : « les attaques ne régressent jamais, au contraire elles deviennent plus efficaces avec le temps ». Concrètement, cela veut dire que des attaques qui semblaient théoriques deviennent pratiques.

Il s'agit de plusieurs attaques différentes, permettant d'empoisonner un cache plus facilement. Ces attaques n'ont pas forcément de rapport entre elles mais, dans certains cas, une des attaques décrites peut faciliter les autres. La principale, de loin, est un mécanisme astucieux pour exploiter la fragmentation. On suscite la création d'une réponse qui sera fragmentée (dig -4 +dnssec @$NAMESERVER ANY $DOMAIN, où $DOMAIN est un domaine contenant suffisamment de données pour dépasser la MTU), et on obtient un paquet normal et un fragment (ici, vus avec tcpdump) :

09:05:06.032332 IP (tos 0x0, ttl 64, id 30286, offset 0, flags [none], proto UDP (17), length 59)
    192.0.2.69.47170 > 198.51.100.1.53: 53344+ [1au] ANY? example. (31)
09:05:06.034638 IP (tos 0x0, ttl 60, id 27730, offset 0, flags [+], proto UDP (17), length 1388)
    198.51.100.1.53 > 192.0.2.69.47170: 53344*- 22/0/1 example. SOA master.nic.example. ... |domain]
09:05:06.034662 IP (tos 0x0, ttl 60, id 27730, offset 1368, flags [none], proto UDP (17), length 1495)
    198.51.100.1 > 192.0.2.69: ip-proto-17

Toutes les techniques anti-spoofing (le Query ID du DNS, le port source UDP, même la casse du nom demandé) sont dans le premier paquet. Le second, le fragment final, peut donc être remplacé par le méchant et il contient un bout de la section réponse plus la section additionnelle, où le méchant peut glisser des fausses informations. L'attaque remplace donc le problème difficile de trouver {Query ID, port} par le problème facile de trouver l'identificateur de fragment (ici 27730), bien plus prévisible, et sur seulement deux octets en IPv4 (d'où le -4 dans ma requête dig : l'attaque ne marche pas en IPv6, où l'identificateur de fragment fait quatre octets). Il reste comme seule protection la somme de contrôle UDP : comme elle n'est pas cryptographiquement forte, il est trivial de la maintenir intacte tout en mettant ses fausses informations.

La seconde attaque détaillée dans cet exposé est la « dé-aléatoirisation » du port source. La technique dite SPR (Source Port Randomization) est la principale technique qui avait été déployée à partir de 2008 contre la faille Kaminsky. Elle consiste à utiliser des ports sources aléatoires par requête DNS. L'étude des auteurs montre que trop de résolveurs font certes de la SPR mais sont trahis par la suite, notamment par un routeur NAT qui dé-aléatoirise (d'autant plus qu'il existe encore des gens qui croient que le NAT améliore la sécurité).

Le risque est réel, l'attaque bien expliquée. DNSSEC est la seule solution. Il ne faut donc pas se rassurer en se disant que les empoisonnements sont trop durs à réaliser, les attaques s'améliorent. D'autant plus que tous les travaux de ces auteurs ne sont pas encore publics et que d'autres améliorations de l'attaque sont en cours.

Les bonnes lectures :


L'article seul

Attaques par réflexion : DNS, SNMP mais aussi...

Première rédaction de cet article le 2 août 2013


Lorsqu'on parle d'attaques par déni de service utilisant la réflexion, on pense souvent uniquement au DNS. Pourtant, d'autres protocoles permettent ces attaques. C'est ainsi qu'un récent message sur la liste NANOG vient de rappeler que le protocole SNMP est couramment employé pour ces attaques.

En quoi consiste une attaque par réflexion ? C'est une attaque où le méchant ment sur son adresse IP : il envoie des paquets avec une adresse IP source qui n'est pas la sienne. Si tout le monde mettait en œuvre la recommandation « BCP 38 » (les RFC 2827 et RFC 3704), ce mensonge ne serait pas possible. Mais BCP 38 est très loin d'être déployé partout, pour de simples raisons économiques (déployer BCP 38, c'est dépenser de l'argent pour protéger ses concurrents...) Les paquets mensongers sont donc possibles et les réponses à ces paquets mensongers seront envoyés à l'adresse IP source indiquée, qui est celle de la victime.

Cela n'est possible que si le protocole de transport n'impose pas l'établissement d'une connexion. Ainsi, UDP est vulnérable mais pas TCP, du moins si on le met en œuvre correctement (RFC 6528).

Le trafic reçu par la victime peut être énorme en raison de l'amplification. Contrairement à certains protocoles comme ICMP echo (celui utilisé par ping), les protocoles comme le DNS ou comme SNMP amplifient l'attaque lors de la réflexion : la réponse est plus grosse que la question. Avec le DNS, on atteint des facteurs d'amplification de 40 ou 50. Avec SNMP, comme l'indique le message NANOG cité plus haut, on atteint plusieurs centaines... Un attaquant peut alors obtenir une attaque de 100 Gb/s en « dépensant » seulement quelques dizaines de Mb/s.

Le risque associé à SNMP est connu depuis un certain temps. Le BITAG a ainsi produit l'année dernière un excellent rapport sur la question (malgré des conclusions qui ne vont pas toujours dans le sens de la neutralité du réseau). Un membre de BITAG, Comcast a annoncé des mesures comme « we will gradually change our default residential Internet device bootfile to restrict SNMP by default ».

Mais quelles sont les parts relatives de DNS ou de SNMP dans ces attaques ? Peut-on dire que l'un est bien plus dangereux, car plus souvent exploité que l'autre ? Et, d'ailleurs, s'agissant du DNS, les attaques par réflexion peuvent se faire avec des résolveurs ouverts ou bien avec des serveurs faisant autorité ; en pratique, quels sont les plus utilisés ? Eh bien, c'est embêtant, mais on ne le sait pas. Il n'y a pas d'étude systématique et indépendante des attaques par déni de service. Lorsqu'une grosse attaque se produit (genre Spamhaus/Cloudflare), on ne sait que ce que contient le communiqué officiel, toujours très court en détails techniques. Et, souvent, il n'y a même pas de communiqué et on n'a que des supputations journalistiques à se mettre sous la dent. Donc, c'est un point important dont il faut se rappeler : on ne connait pas vraiment les attaques par déni de service. Chacun connait celles dont il est victime mais pas celles des autres. Certaines attaques font l'objet de rapports détaillés dans des réunions mais impossible de savoir si elles sont représentatives.

Et il n'y a pas que le DNS et SNMP. NTP a aussi servi à ces attaques. Et les protocoles utilisés par les jeux en réseau ont également été utilisés (un cas fameux a touché Call of Dutyvoir aussi cet article, une étude comparative a montré que Counter-Strike fournissait la meilleure amplification, etc). Comme les développeurs n'ont pas en général de culture historique, la vulnérabilité d'UDP aux attaques par réflexion est régulièrement oubliée et redécouverte. Des protocoles en cours de développement (comme COAP) sont ainsi créés avec cette vulnérabilité.

Sinon, pour mes lecteurs juristes, une discussion intéressante : quelle est la responsabilité juridique du réflecteur, l'entité qui fait l'amplification mais ne participe pas volontairement à l'attaque ? L'article 1382 du Code Civil (qui fait obligation de réparer les dommages qu'on cause) peut-il s'appliquer ?


L'article seul

RFC 6991: Common YANG Data Types

Date de publication du RFC : Juillet 2013
Auteur(s) du RFC : J. Schoenwaelder (Jacobs University)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF netmod
Première rédaction de cet article le 31 juillet 2013


Le langage de modélisation YANG, normalisé dans le RFC 6020, est notamment utilisé dans le protocole de gestion à distance NETCONF (RFC 6241). C'est en YANG que les utilisateurs de NETCONF décrivent les données à manipuler via NETCONF. Ce RFC, successeur du RFC 6021, normalise une bibliothèque de types de données d'usage général, dérivés des types de base de YANG.

Ces types de base sont décrits dans la section 9 du RFC 6020. On y trouve les classiques de l'informatique, boolean, entiers, string, etc. Deux modules YANG sont décrits dans ce nouveau RFC, ietf-yang-types pour des types non limités à l'Internet et ietf-inet-types pour des types spécifiques à TCP/IP.

Je ne vais pas ici reprendre la liste de tous ces nouveaux types, juste donner quelques exemples de ce qu'apporte ce RFC. En section 3, les types généraux, on trouve par exemple, counter32. C'est un compteur, c'est à dire une variable qui ne fait que grimper, jusqu'au moment d'atteindre une valeur maximale (elle repart alors de zéro). Comme son nom l'indique, il est stocké sur 32 bits. Par contre, gauge32 peut monter et descendre.

Le type yang-identifier, un nouveau venu, est une chaîne de caractères ASCII (ne commençant pas par xml). Il est défini en YANG par une expression rationnelle :

typedef yang-identifier {
       type string {
         length "1..max";
         pattern '[a-zA-Z_][a-zA-Z0-9\-_.]*';
         pattern '.|..|[^xX].*|.[^mM].*|..[^lL].*';
         ...

date-and-time, lui, existait déjà dans le RFC 6021. C'est une date au format du RFC 3339 qui est proche du format traditionnel des schémas XML (mais, par contre, est différent de celui utilisé dans le SMI). Au contraire de date-and-time, qui est formaté, timeticks est simplement un nombre de secondes depuis l'epoch (non spécifiée : chaque schéma qui utilisera ce type indiquera quelle est l'epoch).

Il y a aussi des types plus orientés réseau comme mac-address pour les adresses MAC :

typedef mac-address {
       type string {
         pattern '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}';
       }

Et d'autres qui empruntent à des identificateurs existants comme uuid (RFC 4122).

En section 4, les types spécifiques aux protocoles TCP/IP, on a entre autres ip-version qui permet d'indiquer si on parle d'IPv4 ou d'IPv6 :

typedef ip-version {
       type enumeration {
         enum unknown {
           value "0";
           description
            "An unknown or unspecified version of the Internet
             protocol.";
         }
         enum ipv4 {
           value "1";
           description
            "The IPv4 protocol as defined in RFC 791.";
         }
         enum ipv6 {
           value "2";
           description
            "The IPv6 protocol as defined in RFC 2460.";
         }
       }
...

Il y a bien sûr les numéros de port :

typedef port-number {
       type uint16 {
         range "0..65535";
       }
...

Et de système autonome :

typedef as-number {
       type uint32;
...

Et évidemment les adresses IP :

typedef ip-address {
       type union {
         type inet:ipv4-address;
         type inet:ipv6-address;
       }
...
typedef ipv6-address {
       type string {
         pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
               + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
               + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
               + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
               + '(%[\p{N}\p{L}]+)?';
         pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
               + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
               + '(%.+)?';
       }
...

Un exercice amusant : essayez de retrouver dans quel RFC est défini l'expression rationnelle officielle pour les adresses IPv6... (Avertissement : c'est difficile.)

Enfin, ce RFC donne aussi une définition du type domain-name pour les noms de domaine :

typedef domain-name {
       type string {
         pattern
           '((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*'
         + '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)'
         + '|\.';
         length "1..253";
       }
...

C'est une définition très contestable car, limitée à l'ASCII, elle oblige à représenter les IDN par un A-label (café.fr doit être écrit xn--caf-dma.fr, RFC 5890). Pire, le texte d'explication qui accompagne le module est plutôt embrouillé quant à la la définition des noms de domaine par rapport à celle des noms de machines (plus restrictive).

Par rapport au RFC 6021, qui contenait la bibliothèque originale, ce RFC ajoute quelques types (yang-identifier, uuid, etc, la liste complète est dans l'annexe A).


Téléchargez le RFC 6991


L'article seul

RFC 6996: Autonomous System (AS) Reservation for Private Use

Date de publication du RFC : Juillet 2013
Auteur(s) du RFC : J. Mitchell (Microsoft)
Réalisé dans le cadre du groupe de travail IETF idr
Première rédaction de cet article le 29 juillet 2013


Comme pour beaucoup de nombres utilisés dans les protocoles TCP/IP, les numéros de système autonome ont une plage réservée aux usages privés, ne devant pas être transmis à l'extérieur. Ce nouveau RFC élargit la plage existante, qui était jugée trop petite par des gens qui gèrent des gros centres de données (comme Microsoft ou certains acteurs de l'infonuagique).

La section 10 du RFC 1930 réservait la plage allant de 64 512 à 65 535 (soit 1 024 numéros) pour des AS privés. Augmenter la taille de cette plage était délicat tant que les numéros d'AS étaient limités à 16 bits. Mais ils sont désormais sur 32 bits (RFC 6793) et il n'y a donc plus de raison de faire des économies. Une seconde plage, utilisant des numéros sur 32 bits, est donc réservée, allant de 4 200 000 000 à 4 294 967 294 (94 967 295 numéros). Ces deux plages sont documentées dans le registre IANA. (Notez que d'autres plages sont réservées pour la documentation, par le RFC 5398. Les numéros des deux plages de notre RFC sont, eux, conçus pour être utilisés par de vrais routeurs.)

La section 4 de notre RFC met en garde les opérateurs qui utilseraient ces numéros privés : ils ne doivent pas apparaître sur l'Internet public. Lorsqu'une annonce BGP dont le chemin (attributs AS_PATH ou AS4_PATH) sort du domaine privé, ces numéros d'AS doivent être retirés. Les commandes sont neighbor x.x.x.x remove-private-as pour IOS (c'est configuré pour chaque voisin BGP) et neighbor x.x.x.x remove-private pour JunOS mais attention : les anciennes versions de ces logiciels ne connaissaient que la première plage d'AS privés et ne retireront donc pas les numéros de la seconde plage. D'autre part, certains logiciels pour les routeurs ne retirent pas les numéros d'AS privés si le chemin dans l'annonce BGP contient un mélange d'AS privés et publics. Si le routeur en question n'a pas été mis à jour pour connaître la seconde plage de numéros d'AS privés, il va les prendre pour des numéros d'AS publics et ne rien retirer...

À noter que l'idée même d'avoir des nombres pour usage privé (que ce soient les numéros d'AS ou d'autres comme les adresses IP) défrise toujours un certain nombre de gens à l'IETF et que cette minorité s'était fait entendre dans le débat sur cet élargissement.


Téléchargez le RFC 6996


L'article seul

RFC 6973: Privacy Considerations for Internet Protocols

Date de publication du RFC : Juillet 2013
Auteur(s) du RFC : A. Cooper (CDT), H. Tschofenig (Nokia Siemens Networks), B. Aboba (Microsoft Corporation), J. Peterson (NeuStar), J. Morris, M. Hansen (ULD Kiel), R. Smith (Janet)
Pour information
Première rédaction de cet article le 25 juillet 2013


La question de la vie privée est désormais une question de première importance sur l'Internet. La sortie de ce RFC en plein scandale PRISM est une coïncidence mais elle tombe bien. Pendant longtemps, la vie privée avait pourtant été plutôt négligée par les ingénieurs et cette négligence se retrouvait dans les normes techniques, par exemple les RFC, qui ne contenaient pas grand'chose sur la question. Désormais, l'importance du problème est reconnue à l'IETF et ce nouveau RFC vise à expliquer à tous les auteurs de RFC ce qu'il faut connaître de la vie privée et de sa protection, lorsqu'on conçoit un protocole réseau.

Ce n'est donc pas un texte général sur la vie privée (il en existe déjà beaucoup) même s'il explique les principes de base (le membre typique de l'IETF peut être très ignorant à ce sujet). Son objectif est de faire en sorte que les protocoles de la famille TCP/IP prennent en compte les problèmes de vie privée dès leur conception. Cela a été un long chemin. Peu de RFC traitaient explicitement cet aspect (une exception intéressante est le RFC 8981). Mais, petit à petit, entre autre grâce au travail d'Alissa Cooper, une des auteures de ce document, l'IETF est passé de « bof, c'est de la politique, ça ne nous concerne pas, et d'ailleurs la technique est neutre » à un atelier sur la protection de la vie privée (le compte-rendu figure dans le RFC 6462) puis à ce RFC 6973 qui dit en substance que tout nouveau protocole de la famille TCP/IP devrait avoir, lors de sa conception, une réflexion sur les risques qu'il pose pour la vie privée et les moyens de les limiter. S'il reste encore à l'IETF quelques partisans du « on s'en fiche, que toutes les données soient accessibles et que tout le monde soit à poil », ils se font nettement moins entendre désormais. Sans aller jusqu'à imposer une section Privacy considerations dans chaque RFC (sur le modèle de l'obligatoire section Security considerations, cf. RFC 3552), ce RFC l'encourage et aide à sa rédaction.

Le problème n'est pas trivial : la vie privée est quelque chose de complexe. Et tout le monde n'a pas la même opinion sur l'importance de son respect. Sans compter que le cadre légal est très différent d'un pays à l'autre, alors que les RFC sont censés avoir une portée mondiale. Si certains RFC ne semblent pas poser de problème de vie privée (notre RFC cite le RFC 6716...) d'autres sont ou seront entièrement consacrés à ce sujet (RFC 3325) et d'autres nécessiteront un paragraphe ou une section dédiée.

La section 2 détaille les responsabilités des concepteurs de protocoles Internet. Ces protocoles sont souvent utilisés dans une grande variété de cas, parfois non prévus lors de leur conception originelle. Bref, on ne peut pas demander au rédacteur du RFC sur un nouveau protocole de prévoir tous les usages et il y a donc des limites à l'analyse qu'il peut faire sur les conséquences de « son » protocole sur la vie privée. D'autre part, une grande partie, peut-être la majorité des problèmes de vie privée, prennent naissance dans un comportement de l'utilisateur, mal ou peu guidé par des mauvaises interfaces utilisateur. La conception de ces interfaces est typiquement hors-sujet pour l'IETF, qui ne se préoccupe que de protocoles.

Un bon exemple est fourni par HTTP (RFC 7230). Quand on voit la variété des usages de HTTP aujourd'hui, de l'accès à des pages Web statiques à l'échange de données médicales, on se dit qu'une analyse des risques qu'il pose pour la vie privée, faite à l'époque de son développement, aurait été bien limitée.

Le RFC commence vraiment avec la section 3, sur la terminologie. Section bien nécessaire pour ce sujet, où le vocabulaire utilisé est souvent trop flou. Un RFC précédent sur la terminologie de la sécurité avait été le RFC 4949 mais il parlait peu de vie privée. Donc, quelques termes nouveaux (d'autres sont dans le RFC) :

  • Assistant (enabler) : une entité qui n'est pas dans le chemin direct de communication mais qui facilite la communication (et peut donc apprendre des choses). Par exemple, un serveur DNS faisant autorité va être un assistant pour une requête HTTP.
  • Intermédiaire (intermediary) : une entité située, elle, sur le chemin de communication, par exemple un relais SIP.
  • Observateur (observer) : une entité qui est techniquement en mesure d'observer le trafic, du fait de sa position dans le réseau. L'observateur est une entité légitime du réseau, dont l'existence est connue et au moins tacitement autorisée. Par exemple, un serveur de courrier électronique qui relaie les messages est un observateur pour les courriers. L'observateur est, par exemple, un intermédiaire ou un assistant (définitions précédentes) mais il faut se rappeler que les deux extrémités de la communication sont aussi des observateurs..
  • Attaquant (attacker) : toute entité qui va essayer de violer la vie privée, de manière non autorisée.
  • Écoutant (eavesdropper) : un cas particulier d'attaquant, purement passif (il ne fait qu'écouter). Contrairement à l'observateur, il n'est pas autorisé.
  • Corrélation (correlation) : combiner plusieurs informations pour en tirer une information plus complète.
  • Empreinte numérique (fingerprint) : un ensemble de caractéristiques d'une machine ou d'un programme qui permettent de l'identifier. Par exemple, le champ User-Agent:, la liste de polices et quelques autres informations permettent de prendre l'empreinte du navigateur (cf. le Panopticlick).
  • Point intéressant (ou IOI pour Item Of Interest) : toute information que l'attaquant peut avoir envie de connaître. Ainsi, le contenu de la communication est un point intéressant mais aussi, souvent, le seul fait qu'une communication ait lieu entre Alice et Bob est un point intéressant, même si on ne sait pas ce qu'ils se sont dit.
  • Donnée personnelle (personal data) : donnée qui permet d'identifier un individu physique. Ce concept est à la base de beaucoup de lois dans l'Union européenne comme la loi Informatique & Libertés en France. Contrairement à ce que croient beaucoup de gens, une donnée personnelle ne contient pas forcément le nom de l'individu. Par exemple, dans beaucoup de cas, une adresse IP est une donnée personnelle.
  • Analyse de trafic (traffic analysis) : déduire de l'information uniquement à partir de métadonnées sur les communications (qui appelle qui, quand, etc) sans avoir accès au contenu des communications. Par exemple, la simple augmentation du trafic radio d'une armée ennemie peut permettre de prévoir une action de sa part, même si le contenu des communications est chiffré et donc incompréhensible.
  • Anonyme (anonymous) : alors là, c'est un des termes les plus utilisés et les moins bien compris quand on parle de vie privée. On est anonyme si on ne peut pas être distingué des autres membres de l'ensemble d'anonymat (anonymity set). L'anonymat n'est jamais absolu, car on diffuse toujours des informations, l'important est que l'ensemble d'anonymat autour de ces informations soit suffisamment large.
  • Identité (identity) : un ensemble d'attributs qui identifient un individu. On a en général plusieurs identités, selon le contexte. (Voir l'excellent livre d'Olivier Iteanu.)
  • Aujourd'hui, les informations d'identité sur l'Internet sont souvent stockés chez des fournisseurs d'identité spécialisés (si vous vous connectez à un service sur le Web avec votre compte Facebook, alors Facebook est votre fournisseur d'identité). Elles sont ensuite utilisées par des relying parties (le site Web où on se connecte), qui ont donc sous-traité la gestion de l'identité à un tiers.
  • Nom officiel (official name) : celui qui apparait sur les papiers d'identité étatiques. Il n'est en général pas unique. Notez que l'identité, définie plus haut, n'inclut pas forcément le nom officiel (mon identité sur un canal IRC donné peut être mon pseudo canari95). Notez aussi que l'anonymat n'est pas uniquement le fait de garder son nom officiel secret. Cela peut être aussi de vouloir empêcher le rapprochement de deux de ses identités.
  • Nom personnel (personal name) : nom par lequel on désigne un individu. Cela peut être le nom officiel mais pas toujours. Du point de vue technique, un logiciel ne sait pas en général s'il manipule des noms personnels ou des noms officiels.
  • Pseudonyme (pseudonym) : un nom qu'on va utiliser pour ne pas divulguer un nom personnel.

Par exemple, avec IP, le routeur est un intermédiaire, et peut être un observateur (s'il est équipé pour cela, disons que si le routeur est une machine Unix, il devient un observateur dès qu'il lance tcpdump). Quelqu'un qui s'est branché sur le câble sans autorisation est un écoutant.

À noter que l'analyse de sécurité du RFC 3552 supposait que les deux extrémités de la communication étaient sûres et que seuls les intermédiaires représentaient un danger. En matière de vie privée, ce n'est évidemment pas le cas (section 4 de notre RFC). Comme l'a montré l'affaire PRISM, ou comme le montrent les pratiques des gros silos commerciaux du Web 2.0 comme Facebook, le danger est souvent chez l'une des parties en train de communiquer, pas chez un tiers...

Et quelles sont exactement les menaces qui pèsent sur la vie privée ? La section 5 les détaille, suivant en partie le livre de Solove et la recommandation du Conseil de l'Europe. D'abord, leurs conséquences. Les atteintes à la vie privée peuvent provoquer de la gêne mais aussi une perte de dignité, ou des pertes financières. Dans des cas extrêmes (violence conjugale, par exemple), ces atteintes peuvent mettre la vie des victimes en danger. D'autre part, même s'il n'y a pas eu accès à des informations privées, le seul fait d'être sous surveillance peut mettre très mal à l'aise, voir créer un sentiment d'angoisse. Il peut aussi entraîner un changement de comportement (on hésitera à commettre un acte légal, de peur des conséquences s'il était révélé) pouvant aller jusqu'à l'auto-censure. La vie privée est donc une affaire sérieuse, pas un simple détail.

Première attaque contre la vie privée envisagée, la surveillance des communications. Le RFC rappelle qu'elle n'est pas limitée au cas où l'attaquant a accès au contenu des communications. La seule analyse de trafic peut déjà en révéler beaucoup. Le chiffrement n'est pas une protection parfaite : le type de trafic reste visible, via des indicateurs comme la taille des paquets ou leur fréquence. Pour déjouer sérieusement la surveillance, il faudrait des protocoles avec des tailles de paquets variables, n'ayant pas de chaîne de bits prévisibles à un endroit fixe dans le paquet, etc. Pour sérieusement gêner l'analyse de trafic, il faut des systèmes comme Tor. Parmi les entitées présentées plus haut, aussi bien les écoutants que les observateurs peuvent avoir une activité de surveillance.

Une fois les messages arrivés à bon port, tout n'est pas terminé. Les données stockées à destination peuvent faire l'objet d'une compromission, si le serveur qui les stocke n'est pas suffisamment protégé et peut être piraté. Sans compter le cas, traité plus loin, où le serveur de destination est lui-même un attaquant. Ceci dit, ces problèmes ne sont pas du ressort de l'IETF qui s'occupe normalement uniquement des réseaux.

Les risques ci-dessus sont une combinaison de risques pour la vie privée avec les risques plus généraux de sécurité. Mais il y a aussi des risques très spécifiques à la question de la vie privée. Par exemple, la corrélation, qui permet d'acquérir des informations normalement privées en reliant des données qui, séparément, semblaient inoffensives. Par exemple, si des identificateurs stables sont utilisés, les protocoles réseaux facilitent la corrélation. Une adresse IP stable sur le long terme présente un certain nombre d'avantages techniques mais est aussi un danger pour la vie privée (cf. RFC 8981). Autre exemple, le protocole TLS permet de reprendre une session cryptographique existante, pour gagner du temps et éviter de recommencer la négociation de tous les paramètres (cela peut se faire côté serveur, RFC 5246 ou côté client, RFC 5077). Mais comme cette reprise de session se fait avant la négociation de ces paramètres de cryptographie, elle a lieu en clair. Un écoutant peut donc voir que le second client TLS qu'il écoute est en fait le même que le premier, s'il utilise cette fonction.

Autre attaque contre la vie privée, celle passant par l'identification. Savoir que la machine 192.0.2.67 accède au site Web du gouvernement, c'est une chose. Pouvoir accéder à des informations sur la personne qui utilise cette machine, c'est bien mieux, pour l'attaquant. Cela peut se faire facilement avec les protocoles qui identifient une personne (une adresse SIP ou XMPP par exemple) mais aussi de manière indirecte même si le protocole permet l'anonymat. Prenons par exemple un site Web qui n'identifie pas ses utilisateurs. Aucun risque qu'un attaquant qui l'observe retrouve qui a accédé à la page /page-sensible.html, non ? Sauf que, si le même attaquant peut écouter le trafic d'un autre site Web qui authentifie ses utilisateurs, il peut faire une corrélation (via, par exemple, le champ User-Agent:) et ainsi identifier l'utilisateur.

Dans beaucoup de cas, l'utilisateur sait qu'on récolte des données personnelles sur lui. Si je me crée un compte sur amazon.com, il est clair qu'Amazon va savoir des choses sur moi, par exemple mon adresse postale pour me livrer les produits achetés. Il peut aussi y avoir des usages secondaires, des cas où le détenteur des données s'en sert pour autre chose que ce qu'il a annoncé. L'usage secondaire est techniquement indétectable et, comme cela se passe en dehors de la communication standardisée par l'IETF, notre RFC estime que ce problème, si grave qu'il soit en pratique, n'est pas de la responsabilité de l'IETF.

Encore plus sérieux, la révélation de données à des tiers. Comme il est trivial de copier des données numériques, il est techniquement impossible de savoir si les données personnelles qu'on a accepté de confier à l'entreprise X ne vont pas être copiées chez son partenaire Y. Là encore, c'est en dehors de la sphère IETF mais c'est quand même une des menaces les plus sérieuses. Le système PRISM est un exemple d'une telle copie, où les données qu'on avait accepté de confier à Google ou Facebook sont accessibles à la NSA. (Cet exemple n'est pas mentionné dans ce RFC qui, pour ne vexer personne et surtout pas les grosses entreprises états-uniennes qui contribuent beaucoup à l'IETF, passe rapidement sur ce risque, pourtant l'un des plus fréquents.)

Certains protocoles IETF permettent à l'utilisateur d'indiquer ses préférences en matière de protection de la vie privée, et notamment d'interdire la révélation de ces données à un tiers. C'est le cas par exemple du système décrit dans le RFC 6280. Évidemment, il n'existe aucun moyen technique de savoir si ces préférences sont respectées...

Notez aussi que la révélation peut être accidentelle : certains administrateurs systèmes sont assez négligents avec les données personnelles (ou bien ne se rendent pas compte qu'elles sont personnelles) et les laissent parfois accessibles par accident.

Dernière menace envisagée, l'exclusion. C'est le fait d'interdire à l'utilisateur de savoir ce qu'on sait sur lui. (La loi Informatique & Libertés appelle cela le droit d'accès aux données.) C'est une attaque tentante pour les gens qui veulent utiliser vos données personnelles. Cela limite le contrôle que l'individu peut faire.

Maintenant, assez déprimé sur les menaces, place aux solutions. La section 6 envisage les différentes méthodes connues pour limiter les dégâts. Améliorer la protection de la vie privée dans les protocoles réseau n'est pas facile car une protection sérieuse dépend de très nombreux facteurs, qui ne relèvent pas de la seule responsabilité des protocoles (ni même des logiciels). Je pense personnellement (et le RFC a tort de ne pas le rappeler) que le problème requiert avant tout des solutions politiques et juridiques. Mais ce RFC 6973 est un RFC, pas une loi, et se focalise donc surtout sur les aspects techniques : lorsqu'on est membre de l'IETF, que peut-on faire de concret aujourd'hui ?

Première chose évidemment, récolter moins de données (data minimization ou No data, no privacy problem). Les protocoles devraient être conçues de façon à ne transmettre que les données strictement nécessaires à l'accomplissemnt de la tâche. Les choix vont être délicats car les informations envoyées, même pas strictement nécessaires, peuvent avoir une utilité (le User-Agent: en HTTP, énorme risque pour la vie privée, mais si rigolo pour faire des statistiques). Le RFC se focalise donc surtout sur un point, l'identifiabilité. Il faut tout faire pour éviter qu'on identifie un utilisateur. Cela peut passer par l'absence d'identificateurs dans le protocole (ce que permet HTTP mais pas SMTP) ou par l'utilisation d'identificateurs de durée de vie limitée, choisis aléatoirement et changés régulièrement (les adresses IP temporaires du RFC 8981).

La meilleure protection de la vie privée est quand l'utilisateur peut rester anonyme. Cela implique qu'il existe un ensemble d'anonymat assez vaste pour qu'on soit réellement protégé. Un User-Agent: HTTP à lui seul vous place dans un ensemble d'anonymat qui peut être très réduit (j'ai vu une fois dans mes journaux un User-Agent: qui proclamait que le navigateur tournait sur OpenBSD, ce qui diminue considérablement le nombre de « suspects »). Par exemple, pour SIP, le RFC 3325 permet de choisir une adresse anonyme (notez que, comme souvent en matière d'anonymat, l'information sur votre identité peut venir d'ailleurs comme le champ Via:).

Proche de la notion d'anonymat, celle de pseudonymat. Dans ce cas, on a une identité stable et réutilisable, elle n'est simplement pas liée aux identités qu'on veut protéger (comme son nom officiel, par exemple). Dans l'exemple SIP ci-dessus, l'adresse utilisée est toujours anonymous@anonymous.invalid et est la même pour tout le monde. C'est de l'anonymat. Si par contre je me crée un compte aucbbf51n chez un fournisseur SIP example.net qui ne garde pas trace de mes informations personnelles, mon adresse aucbbf51n@example.net est un pseudonyme. Un pseudonyme a l'avantage, par rapport à l'anonymat, de permettre de construire une réputation.

Beaucoup d'identificateurs sur l'Internet vont être des pseudonymes puisque les protocoles Internet n'obligent pas (et heureusement, comparez avec ce que réclame l'UIT qui voudrait obliger à utiliser des « vraies » identités) à se servir d'un nom officiel. Ainsi, mon adresse de courrier pour ce blog est stephane+blog@bortzmeyer.org mais vous ne savez pas si c'est mon nom officiel ou un pseudonyme. Parfois, tout de même, des protocoles ou formats Internet transportent des identités qui peuvent être des noms officiels. Un exemple typique est le format vCard du RFC 6350.

Les pseudonymes ne sont pas parfaits, deux pseudonymes utilisés dans des contextes différents peuvent parfois être reliés par exemple via une information que vous communiquez. Si vous publiez sur l'informatique avec une adresse professionnelle monsieursérieux@example.com et que vous tenez un blog sur la sexualité des hamsters avec l'adresse lol-hamster218@example.net, ne faites pas les mêmes fautes d'orthographe, n'utilisez pas les mêmes tournures de phrase dans les deux contextes ou bien vous serez démasqué. Un exemple de pseudonymes impossibles à lier est fourni par Romain Gary et Émile Ajar : étant donné la différence des styles, personne n'avait jamais suspecté que c'était le même écrivain.

Un problème supplémentaire survient fréquemment de nos jours : beaucoup de services sur l'Internet ne font plus la gestion de l'identité eux-mêmes mais la délèguent à un fournisseur d'identité, utilisant des techniques comme OpenID ou des protocoles privés. Selon le protocole utilisé, les risques pour la vie privée peuvent être plus ou moins grands. Par exemple, si le service voulant authentifier (RP pour relying party, celui qui compte sur le fournisseur d'identité) communique directement avec le fournisseur d'identité (au lieu que tout passe via le client final), le fournisseur d'identité peut apprendre à quels services se connectent ses clients. Autre exemple, le fournisseur d'identité ne devrait pas envoyer au RP la totalité des informations dont il dispose sur un client.

Et, pour clore cette section 6 sur les solutions techniques améliorant la protection de la vie privée, le RFC note que le protocole doit fournir des mécanismes permettant à l'utilisateur de contrôler ses propres données (savoir ce que les autres savent sur lui, et pouvoir exprimer des préférences).

Plus pratique, la section 7 transforme ces bons conseils techniques en une liste de choses à vérifier lorsqu'on conçoit un nouveau protocole réseau. Une fois qu'on a développé un modèle du nouveau protocole (RFC 4101), lire cette liste et se poser les questions qu'elle contient devrait aider à limiter les risques pour la vie privée.

D'abord, minimiser la quantité de données distribuées. La meilleure protection des données est quand il n'y a pas de données. Quels sont les identificateurs utilisés par le protocole ? Est-ce qu'ils permettent la corrélation entre des sessions différentes (c'est souvent le cas s'ils sont stables sur le long terme) ? Ne pourrait-on pas limiter leur utilisation ? Leur mettre une durée de vie limitée ? Permettre aux utilisateurs d'en changer facilement ? Ensuite les données qui ne sont pas officiellement des identificateurs ? Qu'est ce qui est échangé entre les parties qui communiquent ? N'est-ce pas trop de données ? Ces données ne permettraient-elles pas de retrouver les identificateurs (pensez au Panopticlick) ? À qui sont envoyés ces identificateurs et ces données (rappelez-vous qu'il y a typiquement plus que deux parties impliquées dans une communication) ? Par exemple, lors d'une connexion HTTP à http://www.example.com/, la requête DNS est envoyéee à des assistants (cf. le vocabulaire au début), les serveurs de la racine et ceux de .com. La racine apprend donc qu'on se connecte à www.example.com. Et le risque d'empreinte numérique ? Par exemple, si le protocole permet N opérations au début d'une connexion, sans spécifier leur ordre, un observateur peut apprendre quel logiciel vous utilisez en regardant l'ordre choisi. Et enfin est-ce que le protocole permet, voire impose, la conservation de données ou d'identificateurs sur le long terme, en dehors des sessions de communication ?

Ça, c'était pour minimiser les données. Pour le contrôle par l'utilisateur, les questions à se poser sont : quels sont les mécanismes dans le protocole pour contrôler quelles données on diffuse et à qui ? Là encore, il ne faut pas penser qu'au destinataire mais aussi à tous les intermédiaires possibles. Un exemple, HTTP n'impose pas des en-têtes indiscrets comme User-Agent: et Referrer: et cela permet à certains navigateurs ou relais de les supprimer.

Les attaques contre la vie privée ne seront pas menées que par les participants légitimes à une communication. On aura aussi des tiers qui essaieront d'accéder à une information qu'ils ne sont pas censés avoir. Le protocole doit donc prendre en compte la possibilité de surveillance. Qu'est-ce qui est prévu contre l'écoute ? En général, c'est l'utilisation du chiffrement et le RFC contient donc une phrase « utilisez TLS si vous ne voulez pas être écouté ». Mais cela n'empêche pas l'analyse de trafic. Le protocole a-t-il des mécanismes qui facilitent ou au contraire compliquent cette analyse ? Par exemple, avec SSH, on voit facilement si on a affaire à un transfert de fichiers ou à une session interactive, par la quantité de données qui passe et leur cadencement. Lors d'un transfert de fichiers, on a beaucoup d'octets dans un sens et peu dans l'autre, les accusés de réception. Lors d'une connexion à un shell, on a peu d'octets de l'utilisateur vers le shell et une quantité moyenne (les réponses) en sens inverse. Le chiffrement ne dissimule pas cela. SSH a un mécanisme de remplissage de la communication avec des données bidon, pour brouiller les pistes mais je n'ai pas l'impression qu'OpenSSH l'utilise.

Toujours en sécurité classique, comment se comporte le protocole en cas de compromission des données stockées ? Ou contre une attaque active ?

Souvent, les préférences de protection de la vie privée sont réglables. Mais la plupart des utilisateurs ne modifieront jamais le réglage. Le RFC demande donc qu'on prête attention aux réglages par défaut. En l'absence d'intervention explicite, est-on protégé ou, au contraire, faut-il activer cette protection délibérement ? Par exemple, pour le cas des adresses IP temporaires, le RFC 4941 demandait qu'elles ne soient pas utilisées par défaut (sa mise à jour dans le RFC 8981 a changé les choses) alors que le RFC 6724 a demandé le contraire. Écrit quatre ans après, à un moment où les préoccupations de protection de la vie privée sont devenues plus importantes, ce RFC 6724 avait des priorités différentes.

D'ailleurs, la fin de cette section 7 rappelle que, comme Schneier aime le répéter, la sécurité est toujours un compromis. Elle prend du temps, ralentit le réseau, complique les choses (pour les programeurs et pour les utilisateurs), bref a un coût. La protection de la vie privée n'échappe pas à cette nécessité de chercher un compromis.

Pour clore ce RFC, la section 8 fournit un exemple complet d'analyse de sécurité d'un service donné. Les auteurs ont choisi la difficulté, car cette analyse porte sur un service particulièrement indiscret et intrusif, le service de présence (faire connaître à l'extérieur si on est disponible ou pas, par exemple pour être contacté par messagerie instantanée). Ce service permet d'illustrer toute la palette des questions soulevées par la protection de la vie privée. Présentée dans le RFC 2778, la présence (« je suis dispo », « je déjeune », « je suis en réunion ») est un service très dynamique, nécessitant de nombreuses mises à jour. Ses implications pour la vie privée sont évidentes et, dès le début, l'IETF avait prévu un contrôle des utilisateurs sur cette information (RFC 3859). Les protocoles qui utilisent un système de présence comme SIMPLE (RFC 6914) ou XMPP (RFC 3922) s'appuient sur ce contrôle.

Voici la gestion de la présence par l'utilisateur dans le client de messagerie instantanée Pidgin : pidgin-presence.png

Dans l'architecture standard, il y a un tiers, un assistant, le serveur de présence, qui reçoit les informations des clients et les transmet aux lecteurs autorisés. Ce tiers est nécessaire pour les cas où la/les machine(s) du client soient toutes éteintes ou injoignables. Il sert également à agréger de l'information envoyée par les différentes machines de l'utilisateur (son ordinateur peut être éteint mais l'utilisateur être toujours joignable via son smartphone). Mais il complique évidemment beaucoup la sécurité puisqu'il va être au courant de beaucoup de choses. Bien sûr, le serveur ne distribue l'information qu'aux lecteurs autorisés. Mais il n'y a pas de protection technique : il faut faire une confiance totale au serveur, confiance en son honnêteté et ses bonnes pratiques de sécurité. On pirate un serveur de présence et on peut suivre les gens à la trace. Le serveur oublie de rendre TLS obligatoire et les écoutants peuvent tout apprendre (et le client du serveur de présence n'a aucun moyen de vérifier si TLS est activé ou pas). Encore pire, c'est le serveur de présence qui authentifie les lecteurs, pas le client final. L'anonymat n'est ici pas une solution puisque le but d'un service de présence est justement d'obtenir des informations sur des personnes identifiées (« quelqu'un est allé déjeuner » n'est pas une information intéressante).

Pour compléter le tableau, d'autres informations que la présence sont souvent transmises, par exemple les capacités du logiciel utilisé (accepte t-il les appels vidéo, par exemple). Elles peuvent permettre d'identifier l'appareil utilisé. En outre, les extensions ultérieures au service de présence ont permis de publier également la localisation physique. Un groupe de travail a été créé pour travailler sur la protection de la vie privée dans le cas où on distribue cette information, le groupe GEOPRIV, dont le premier RFC fut le RFC 4079 (mais il y en a d'autres).

Avec tellement d'information, l'analyse de sécurité du service de présence doit évidemment commencer par se demander si le jeu en vaut la chandelle. Déjà, on pourrait utiliser une autre architecture, plus pair à pair, où les utilisateurs se préviennent directement de leur présence. Il existe un format standard pour transporter cette information, PIDF (Presence Information Data Format), qu'on peut chiffrer pour empêcher toute écoute. Mais cette solution ne semble pas réaliste aux auteurs du RFC : elle ne fonctionne pas si la machine de publication est éteinte ou injoignable, chaque machine qui publie doit connaître les clés publiques de tous les abonnés, et enfin elle suscite un trafic important (la présence est très dynamique, avec des changements fréquents). Une variante est l'architecture où le serveur de présence ne sert que de redirecteur : il ne connait pas l'information, mais sait rediriger vers la machine actuelle de chaque personne qui publie de l'information de présence. Le serveur peut ainsi prévenir qu'une personne est injoignable et rediriger vers cette personne dans le cas contraire. Mais cette architecture, comme la précédente, a ses propres problèmes de vie privée, puisqu'elle permet à chaque participant d'apprendre les adresses IP des autres (normalement connues du seul serveur de présence). En outre, ces deux solutions, davantage pair à pair, souffrent du difficile problème de la connexion d'une machine à une autre, lorsqu'une des deux, ou les deux, sont derrière un pare-feu ou un routeur NAT. Avec le serveur de présence, il suffit aux clients d'une connexion sortante, ce qui est bien plus souvent possible.

Bref, cette intermédiaire dangereux qu'est le serveur de présence va être difficile à éliminer. D'où l'approche actuelle, qui repose plutôt sur des préférences quant à la divulgation de l'information, préférences (RFC 4745, RFC 5025 et RFC 6772) qui sont envoyées au serveur de présence, et à qui il faut faire confiance pour les respecter. Le RFC note bien que le succès est très limité : peu de logiciels exploitent cette information. Au moins, on peut documenter leurs limites, ce qui est fait ici.

On a donc là un bel exemple d'un compromis entre la protection de la vie privée (qui justifierait qu'on ne publie jamais rien sur sa présence) et le désir de faciliter la vie des utilisateurs en indiquant à l'avance si un appel a des chances d'aboutir ou pas.

Mon commentaire à une version préliminaire de ce RFC est disponible en ligne (notez la note de cloture du ticket). Globalement, mon regret est que ce document (même après les changements) est très axé sur les risques dus aux tierces parties et parle peu des risques du méchant silo qui stocke les données personnelles, ou sur les risques étatiques type PRISM.

Si vous voulez approfondir ces questions, ce RFC cite trois sources : le « FAIR INFORMATION PRACTICES: A Basic History » de Gellman, les directives de l'OCDE et le « Privacy Indexes: A Survey of Westin’s Studies ».


Téléchargez le RFC 6973


L'article seul

Recherche d'un nouveau logiciel de présentation

Première rédaction de cet article le 24 juillet 2013
Dernière mise à jour le 26 juillet 2013


J'ai fait des tas de présentations avec support informatique et, depuis des années, j'utilise Beamer pour faire les diapositives (oui, le terme fait un peu vieux mais aussi bien Wikipédia que Google Translate proposent « diapositive » pour « slide »). Beamer est parfait pour des présentations sérieuses avec beaucoup de texte, de maths et de code source. J'ai sur mon agenda deux ou trois présentations où il serait souhaitable de mettre davantage l'accent sur l'esthétique et j'aimerai bien essayer autre chose que Beamer. Après tout, il faut sortir de sa zone de confort de temps en temps et voir si le monde a évolué en bien. Je recherche donc des suggestions. (J'ai choisi reveal.js pour les prochains exposés et documenté quelques petits trucs techniques sur ce logiciel.)

On pourrait évidemment améliorer Beamer (suggestion de Lucy) plutôt que de changer de logiciel. Mais j'ai vraiment envie de voir d'autres horizons.

D'abord, ce que j'aimerai avoir : un outil évidemment libre, tournant sur mes machines Unix, et permettant de travailler en local, sans accès au Web (pour pouvoir écrire sans être connecté, et pour ne pas dépendre d'un service tiers). J'aimerais bien en plus qu'on puisse écrire les diapositives avec un éditeur ordinaire comme emacs.

J'élimine tout de suite Impress (lent, très consommateur de ressources et surtout, à l'interface incompréhensible, je n'ai jamais réussi à en faire ce que je voulais). Il y a des années, j'avais essayé MagicPoint mais je n'avais pas été convaincu. (Le résultat n'était franchement pas à la hauteur.)

En cherchant un peu, je me rends compte qu'une grande partie des outils modernes de présentation sont écrits en JavaScript et fondés sur HTML et CSS. C'est logique : CSS a évolué au point de permettre des tas d'effets esthétiques et/ou rigolos et sa gestion par les navigateurs modernes s'est nettement améliorée. Et on trouve un navigateur Web partout. Ces systèmes se reconnaissent souvent à leur nom qui se termine en « .js » et je vais surtout me concentrer sur eux.

Autres avantages de ces systèmes, tout le monde connait au moins un peu de HTML et de CSS, et, surtout, on peut réutiliser le travail existant. Si je veux faire une présentation pour mon employeur, j'ai juste à charger la CSS du site Web et j'ai automatiquement mes diapositives qui sont à la charte graphique officielle (bon, en fait, c'est nettement plus compliqué que cela, car la CSS du système de présentation doit obéir à certaines règles).

Donc, pour l'instant, je n'ai pas encore tout testé sérieusement mais voici les outils qu'on m'a recommandé (notamment via Twitter), en commençant par ceux qui n'ont pas de .js dans leur nom (la liste est longue et pourtant je ne les ai pas tous cités !) :

  • Pinpoint colle bien au cahier des charges mais est basé sur une autre technologie que HTML+CSS. On écrit sa présentation dans un format simple qu'il compile en un diaporama.
  • Sozi (recommandé par Plantigrade et Loïc Sevrin). Il ne repose pas sur la logique d'un diaporama (linéaire), mais sur celle d'un espace où on dispose ses éléments. Il ne repose pas sur HTML mais sur SVG et l'éditeur est une extension d'Inkscape.
  • Slide Show (S9) (recommandé par Laurent Vallar et Damien Wyart). Un programme qui prend un fichier marqué et qui génère une présentation en HTML.
  • Hieroglyph (recommandé par Vincent Férotin), une extension de Sphinx, qui fait à peu près la même chose.
  • reveal.js (recommandé par jean burrelier), lui, est complètement JavaScript + HTML + CSS. Il existe un éditeur en ligne mais affreusement lent, sans intérêt. Il a une bonne documentation et écrire la première présentation reveal.js est assez rapide. Une de ses originalités est de pouvoir écrire le contenu du diaporama en Markdown, pas seulement en HTML. Ceux qui utilisent org-mode (ce n'est pas mon cas) ont une passerelle vers reveal.js. Je regrette que créer son propre thème soit une opération si compliquée (il ne suffit pas de charger son CSS). Mais, bon, ça marche, c'est joli, c'est maintenu, et c'est ce que j'ai finalement choisi (après avoir hésité devant le bien plus sage Slidy.) J'ai même utilisé quelques fonctions avancées comme de créer mon propre thème.
  • deck.js (recommandé par jean burrelier). La documentation est son point faible. Intarissable sur les fonctions du logiciel, elle est muette sur les instructions JavaScript à mettre dans l'HTML. Je n'ai jamais réussi à faire un fichier HTML correct.
  • impress.js (recommandé par Unixmail) s'éloigne lui aussi de la logique des diapos organisées linéairement. Écrire une présentation en impress.js est vraiment difficile si on n'est pas un demi-dieu en HTML et CSS (et la documentation insiste sur ce point). impress.js n'est pas pour celui qui veut juste écrire trois diapos simplement, ou alors il faut passer par un environnement auteur comme Strut (recommandé par CM).
  • Shower (recommandé par Grégory Paul et Yannick). Très simple pour la première présentation mais très peu de documentation sur comment aller plus loin (peut-être n'est-ce pas possible ?)
  • Remark.js (recommandé par Bruno Beaufils). Apparemment très simple (tout se fait en Markdown) et donnant un bon résultat.
  • Même le W3C a un tel outil de présentation, Slidy2 (recommandé par Damien Wyart). Très bonne documentation, très clair. Un outil simple avec lequel on a une présentation très rapidement. Par contre, je n'ai pas trouvé facilement comment réaffecter les touches (F11, passage en plein écran est déjà pris par mon window manager). Et c'est clair que ses capacités esthétiques sont moins bonnes que celles de reveal.js. Disons que c'est mon deuxième choix.
  • flowtime.js, dont la présentation officielle rend très bien compte des possibilités du système mais ne dit pas un mot de la création des diapos.
  • Landslide (recommandé par François Lefèvre).
  • dzSlides (recommandé par Clément Delafargue), le dernier de la longue liste des systèmes bâtis sur HTML et CSS. À noter que Pandoc peut produire du dzSlides (il peut aussi faire du Slidy). Ce système me parait plus brut de fonderie, avec peu d'explications. Excellent pour celui qui veut mettre les mains dans le cambouis mais pas pour celaui qui voudrait juste faire des présentations.

Et il y a aussi ceux que je n'ai pas retenus :

  • Please don't show (recommandé par Stéphanie de Vanssay) mais la seule documentation semble être une vidéo, ce que je n'aime pas.
  • Prezi (cité par Éric Cardona) est accessible uniquement en ligne, donc c'est encore un de ces silos Web fermés. Il dépend de la technologie non-libre Flash.
  • Impressive (cité par Éric Cardona) un lecteur de présentations PDF apportant des fonctions supplémentaires à celles des lecteurs traditionnels comme quelques jolies transitions ou la mise en lumière de certains éléments de la page (merci à Johan Grande, Jean-Sébastien Kroll-Rabotin et Damien Wyart pour leurs explications sur ce point). Voir aussi une discussion sur de tels outils.
  • TPP (recommandé par gordontesos) n'est pas pour faire des présentations jolies ou bluffantes mais au contraire pour faire quelque chose d'ultra-Unixien, avec curses.

Bon, maintenant que j'ai une liste, place aux tests (j'en ferai le compte-rendu ici). À moins que quelqu'un ait déjà fait une comparaison ? Notamment des outils *.js, qui sont très nombreux et dont il n'est pas immédiatement évident de voir les différences.

En attendant une telle comparaison complète et détaillée, je recommande la lecture de cet article en français, de la discussion sur LinuxFr et de l'article de Framablog sur reveal.js.


L'article seul

RFC 6970: Universal Plug and Play (UPnP) Internet Gateway Device (IGD)-Port Control Protocol (PCP) Interworking Function

Date de publication du RFC : Juillet 2013
Auteur(s) du RFC : M. Boucadair (France Telecom), R. Penno, D. Wing (Cisco)
Chemin des normes
Première rédaction de cet article le 24 juillet 2013


Le RFC 6887 normalise le protocole PCP (Port Control Protocol) qui permet de contrôler un routeur NAT ou un pare-feu depuis une machine cliente, par exemple pour ouvrir un port en entrée lorsqu'on utilise un logiciel de transfert de fichiers pair-à-pair ou bien un logiciel de téléphonie sur IP. PCP fonctionne également dans le cas des CGN. Mais cela ne sert à rien d'avoir des routeurs PCP si la quasi-totalité des applications sur les postes clients n'utilise toujours que le vieux protocole UPnP, certes très limité mais qui est largement déployé. Ce nouveau RFC décrit donc une solution de transition : une passerelle entre UPnP et PCP, permettant de satisfaire les clients UPnP et les serveurs PCP.

Cette passerelle sera typiquement installée dans le routeur CPE (la box). Ainsi, lorsque, par exemple, l'application qui parle UPnP fera un AddPortMapping, la passerelle le traduira en une requête MAP PCP (avec l'option PREFER_FAILURE puisque cette requête, contrairement à AddAnyPortMapping, réclame un numéro de port spécifique et échoue s'il n'est pas disponible ; cf. section 5.6). Si vous aimez les sigles, vous serez ravis car le nom complet de la passerelle est UPnP IGD-PCP IWF pour UPnP Internet Gateway Device PCP Interworking Function.

La section 4 donne les correspondances complètes entre les méthodes UPnP et les méthodes PCP, ainsi qu'entre leurs codes d'erreur. Ainsi, toute passerelle UPnP<->PCP sait qu'elle doit traduire une erreur 8 de PCP (NO_RESOURCES) en une erreur 501 ActionFailed chez UPnP v1 et 728 NoPortMapsAvailable chez UPnP v2 (qui a des codes d'erreur bien plus détaillés). De la même façon, une erreur 2 de PCP (NOT_AUTHORIZED) devient 718 ConflictInMappingEntry en UPnP v1 et 606 Action not authorized en UPnP v2.

La passerelle UPnP<->PCP n'est pas un simple relais, transférant des requêtes dans un sens et les réponses dans l'autre. Elle doit garder un état, la mémoire de toutes les correspondances demandées (section 5.3). Cela permet, par exemple de faire face au fait que UPnP permet de créer une correspondance {adresse interne, port interne, adresse externe, port externe} de durée illimitée, ce que ne sait pas faire PCP (RFC 6887, section 7.1). Dans ce cas, la passerelle enregistre la correspondance et la renouvelle dans le serveur PCP à chaque fois qu'elle approche de l'expiration (section 5.9). D'autre part, des requêtes UPnP d'information comme GetListOfPortMappings ne sont pas relayés au serveur PCP mais traitées en examinant l'état local (section 5.7).

Autre point important de ce RFC : la passerelle peut être sur un routeur NAT ou pas (par exemple, dans certains cas de CGN, le routeur CPE ne fait pas de NAT). Si elle doit faire du NAT, la réception d'une requête UPnP va se traduire par une mise à jour de la table NAT locale et l'émission d'une requête au serveur PCP.

Ah, et pour trouver le serveur PCP à utiliser, comment fait la passerelle ? Comme un client PCP normal (via DHCP, par exemple).


Téléchargez le RFC 6970


L'article seul

RFC 6972: Problem Statement and Requirements of Peer-to-Peer Streaming Protocol (PPSP)

Date de publication du RFC : Juillet 2013
Auteur(s) du RFC : Y. Zhang, N. Zong (Huawei Technologies)
Pour information
Réalisé dans le cadre du groupe de travail IETF ppsp
Première rédaction de cet article le 20 juillet 2013


Il existe actuellement des tas de logiciels qui font du streaming (audio ou vidéo) en pair à pair mais toujours en utilisant des protocoles privés et fermés. Cela a des tas de conséquences négatives, notamment sur le plan du choix : l'utilisateur est enfermé dans l'offre d'une compagnie particulière. Il est donc urgent de développer un protocole libre et ouvert de streaming pair à pair et c'est la tâche du groupe de travail PPSP de l'IETF. Son premier RFC, ce RFC 6972, est le cahier des charges du protocole (comme toujours à l'IETF, le travail a commencé bien avant la publication du cahier des charges et des mises en œuvre du protocole PPSP - normalisé dans le RFC 7574 - existent déjà).

Le streaming est un usage essentiel de l'Internet (le RFC cite une étude de Cisco à ce sujet). Dans sa version classique, avec un gros serveur ou une batterie de gros serveurs qui distribuent à des millions de clients, le streaming ne passe pas à l'échelle. Si on en était resté à ce mode de distribution, seule une poignée de très grosses entreprises pourraient héberger du contenu vidéo. Heureusement, il existe une meilleure solution, la distribution en pair à pair où chaque client se transforme en distributeur pour une partie du contenu. Le streaming pair à pair permet à n'importe qui de distribuer de la vidéo sur l'Internet, avec seulement des serveurs ordinaires.

Mais, car il y a un mais, ce streaming pair à pair, aujourd'hui, se fait essentiellement avec des protocoles privés d'une entreprise capitaliste particulière. La section 3 décrit les problèmes que cela pose. D'abord, sur le plan technique, cela interdit de développer des mécanismes de cache communs, le cache devant connaître le protocole utilisé (imaginez les caches Web si tout le monde ne parlait pas HTTP). Même chose pour les CDN qui ne peuvent pas être exploités facilement pour aider ce streaming puisqu'ils ne peuvent pas connaître tous les protocoles utilisés.

Enfin, les protocoles existants ne sont pas forcément bien adaptés aux mobiles qui sont pourtant une bonne partie des clients. Il y a eu des recherches à ce sujet (cf. J. Peltotalo et autres, « A real-time Peer-to-Peer streaming system for mobile networking environment » en 2009) mais qui ne se retrouvent pas forcément dans les protocoles existants. PPSP va donc devoir gérer :

  • Le fait que le mobile, contrairement au poste fixe typique, n'est pas allumé et connecté en permanence,
  • Le fait que le mobile ait une batterie de capacité limitée (les protocoles actuels n'indiquent pas si le pair est presque à sec...),
  • La capacité limitée du réseau avec le mobile : certains protocoles sont très bavards, s'envoyant plein d'informations même quand rien n'a changé,
  • L'espace limité sur le mobile, qui rend l'installation de N applications différentes pour la même tâche (le streaming) problématique.

À noter que la section 3 ignore les problèmes plus politiques comme l'excès de pouvoir que ces protocoles fermés donnent à l'entreprise qui les contrôle, et peut ainsi limiter la liberté des clients.

La section 4 décrit à un haut niveau les missions du protocole de streaming pair-à-pair. Pour modéliser ce protocole, elle reprend largement la terminologie de BitTorrent (la section 2 décrit tout le vocabulaire à connaître mais le RFC ne cite jamais BitTorrent), avec notamment la notion de tracker, le mécanisme (pas forcément une machine, cela peut être une DHT) qui garde trace de tous les pairs servant un contenu donné (ce qu'on nomme l'essaim). Il y a en fait deux protocoles, un entre le pair et le tracker et un entre pairs. Lorsqu'il rejoint un essaim, le pair doit pouvoir trouver les autres pairs (avec le premier protocole) et les contacter (avec le second). Il doit pouvoir connaître les caractéristiques des pairs, pour les choisir astucieusement. Le protocole doit bien sûr être efficace (le streaming vidéo fait passer d'énormes quantités de données) et doit être robuste (par exemple en cas de panne du tracker).

Le protocole pair<->tracker va nécessiter un identifiant unique pour les pairs (peer ID). Il va falloir aussi classer les pairs, par exemple selon le fait qu'ils ont une adresse IP publique ou pas, qu'ils sont en IPv4 ou en IPv6, qu'ils ont des ressources importantes ou pas, etc. Ce sera plutôt un protocole requête/réponse (le pair se connecte, transmet ses infos, et reçoit une liste de pairs).

Le protocole pair<->pair devra se colleter avec les problèmes de l'identification du contenu et de son intégrité (un problème important en pair-à-pair). Le contenu envisagé pour ce problème étant souvent de grande taille, il faudra le découper en morceaux (chunks) et il faudra donc un mécanisme d'identification des morceaux et de leur disponibilité. Ce sera plutôt un protocole de bavardage (échange continu d'information).

Avant d'aborder le cahier des charges précis, le RFC pose une dernière question, quels sont les usages envisagés pour ce nouveau protocole de streaming (section 5) ? Il y a la distribution de vidéo en temps réel, par exemple lors d'un événement (cela ressemble fortement à l'usage décrit dans les RFC 6707 et RFC 6770). Il y a aussi la VoD. D'autres usages sont moins évidents à première vue comme la possibilité d'avoir des caches pour le streaming. Même si on est dans une relation client/serveur, un protocole pair-à-pair de streaming permet d'envisager des systèmes de caches automatiques entre le client et le serveur, qui intercepteraient les requêtes et les mémoriseraient pour les futurs utilisateurs. Un exemple proche est l'extension P2Pyoutube du navigateur Opera.

Enfin, le cahier des charges proprement dit. Je ne vais pas reprendre ici toutes les exigences, classées en catégories (REQ : la base, OAM : gestion du protocole, TP : protocole pair<->tracker, PP : protocole pair<->pair) et numérotées. Certaines sont de l'ordre de l'évidence (PPSP.REQ.1 : chaque pair doit avoir un identificateur unique, PPSP.REQ.2 dit la même chose pour l'essaim et PPSP.REQ.4 pour le morceau). D'autres sont toujours bonnes à rappeler (PPSP.OAM.REQ-2 : il doit y avoir des paramètres de configuration, ayant des valeurs par défaut, PPSP.OAM.REQ-7 : on doit pouvoir les changer). Beaucoup sont communes à tout système de distribution de contenu en pair-à-pair et se retrouvent déjà dans BitTorrent. D'autres sont plus spécifiques au streaming. Ainsi PPSP.OAM.REQ-4 parle des mécanismes pour atteindre une qualité suffisante pour le flux audio ou vidéo. Cela implique un délai raisonnable. Le RFC dit par exemple qu'une minute de délai pour la retransmission d'un évenement sportif est inacceptable (imaginez le supporter du PSG ayant encore son verre de bière à la main alors que dans les maisons environnantes, tous les autres hurlent déjà « Buuuuuuuuuuuuuuut ! »).

Souci classique à l'IETF, le protocole doit être gérable. Des exigences comme PPSP.OAM.REQ-5 demandent qu'on puisse accéder à l'information nécessaire pour déboguer et/ou optimiser le protocole et PPSP.OAM.REQ-6 ajoute qu'il faut pouvoir tester un pair, sa connectivité, son bon fonctionnement, etc.

De même, les exigences sur le protocole tracker<->pair sont assez standards et évidentes (PPSP.TP.REQ-1 : le pair doit pouvoir obtenir du tracker une liste de pairs potentiels...). Notez quand même une exigence que l'authentification du pair soit possible, pour les essaims fermés (PPSP.TP.REQ-4). Même chose pour le protocole pair<->pair. Notez toutefois PPSP.PP.REQ-3 (obtenir directement du pair, sans passer par le tracker, d'autres pairs, de préférence vérifiés, ajoute PPSP.PP.REQ-5) et PPSP.PP.REQ-8, la possibilité d'obtenir plein d'informations sur les pairs.

Voilà, le cahier des charges est fini. Une faiblesse traditionnelle des systèmes pair-à-pair, la sécurité, fait l'objet d'une section à part, la 7. Elle analyse les risques dus à des pairs ou des trackers malveillants :

  • Attaque par déni de service en envoyant plein de requêtes,
  • Envoi de fausses informations, par exemple de disponibilité d'un morceau,
  • Violation de la vie privée, en transmettant les informations à un tiers,
  • Et d'autres encore.

Cela entraîne l'ajout de quelques exigences supplémentaires, étiquetées SEC pour SECurity. PPSP.SEC.REQ-1 reprend l'exigence déjà mentionnée de pouvoir faire des essaims fermés, avec pairs authentifiés. PPSP.SEC.REQ-2 rappelle qu'il est indispensable d'avoir un mécanisme de contrôle de l'intégrité du contenu, pour empêcher un pair malveillant d'injecter des morceaux incorrects, et PPSP.SEC.REQ-3 appelle au réalisme en demandant que tout mécanisme de sécurité passe bien à l'échelle, on peut avoir des essaims immenses.

Les auteurs annoncent qu'il y a déjà trois mises en œuvre du protocole mais il ne semble pas y avoir beaucoup de documentation à ce sujet. Le protocole correspondant à ce cahier des charges a été normalisé dans le RFC 7574.


Téléchargez le RFC 6972


L'article seul

RFC 6978: A TCP Authentication Option NAT Extension

Date de publication du RFC : Juillet 2013
Auteur(s) du RFC : J. Touch (USC/ISI)
Expérimental
Première rédaction de cet article le 20 juillet 2013


Le protocole d'authentification des paquets TCP AO (Authentication Option), normalisé dans le RFC 5925, a une limite : il ne fonctionne pas du tout lorsque la session est établie à travers au moins un routeur NAT. Ce nouveau RFC propose une extension qui lui permet d'authentifier quand même les paquets dans ce cas, au prix d'une légère baisse de la sécurité.

En effet, l'authentification AO range et génère ses clés en tenant compte d'un ensemble de paramètres de la session (RFC 5925, sections 3.1 et 3.2), parmi lesquels se trouvent les adresses IP de source et de destination, ainsi que les ports de source et de destination. Un routeur NAT modifie en général l'adresse IP source et les routeurs existants (qui font souvent du NAPT et pas du NAT à proprement parler, cf. RFC 2663) modifie également le port source. AO ne retrouve donc plus ses clés (RFC 5925, section 9.2). Ce n'était pas un gros problème pour le premier client d'AO, le protocole BGP : on met rarement des routeurs BGP derrière du NAT. Mais cette limite est gênante pour généraliser AO à d'autres utilisations, sans compter les futures améliorations de TCP, par exemple le multipath du RFC 6824, où la même connexion TCP utilise plusieurs adresses IP.

Donc, la nouvelle option se nomme TCP-AO-NAT et consiste (section 4 de notre RFC) à ajouter au MKT (Master Key Tuple, cf. RFC 5925, section 3.1) deux booléens, localNAT et remoteNAT indiquant si un routeur NAT est présent en local ou en distant. Si localNAT est vrai, AO va mettre à zéro l'adresse IP source et le port source avant de calculer les clés. Si c'est remoteNAT qui est vrai, ce sera l'adresse et le port de destination qu'on ignorera.

Le MKT n'est pas transmis à la machine distante (et n'apparait donc pas dans l'option TCP AO), il est typiquement configuré à la main des deux côtés. La valeur à donner à localNAT et remoteNAT est déterminée manuellement, mais elle peut aussi être découverte par les méthodes habituelles de détection de NAT. Le client situé immédiatement derrière un routeur NAT (par exemple la machine de M. Michu à la maison) va mettre localNAT à 1. Le serveur en face va mettre remoteNAT à 1. Si les deux partenaires sont derrière un NAT (et utilisent une technique comme celle du RFC 8489), les deux booléens peuvent être à 1.

Notez bien qu'AO ne protège que TCP et ne tient pas compte du contenu des paquets. Si un ALG sur le trajet modifie les adresses contenues, mettons, dans une connexion FTP, TCP-AO-NAT n'y pourra rien.

Attention, rappele la section 6 : TCP-AO-NAT revient à ignorer certaines valeurs qui identifient la connexion et donc à diminuer l'entropie. Si localNAT est vrai, on passe d'une source de hasard pour la KDF qui est composée de deux adresses IP, deux ports et deux ISN (l'Initial Sequence Number de TCP) à une seule adresse, un seul port et les deux ISN. Si les deux booléens localNAT et remoteNAT sont vrais, il ne reste plus que les deux ISN comme source d'entropie. Bref, l'extension normalisée dans ce RFC diminue la sécurité. Toutefois, comme les ports ne sont pas toujours très aléatoires (malgré le RFC 6056) et les adresses encore moins, l'essentiel de l'entropie venait des deux ISN, de toute façon.


Téléchargez le RFC 6978


L'article seul

Problème DNSSEC subtil dans fbi.gov

Première rédaction de cet article le 19 juillet 2013


Le système de sécurité DNSSEC vise à protéger la résolution DNS contre les attaques par empoisonnement (comme l'attaque Kaminsky). Mais, comme toutes les techniques de sécurité, il introduit d'autres risques, notamment celui de casser des choses si on ne fait pas très attention. C'est ce qui arrive en ce moment à fbi.gov, domaine du FBI.

La question a été discutée depuis le 17 juillet sur la liste des utilisateurs de BIND (et n'est pas encore résolue). À première vue, tout se passe bien :


% dig A fbi.gov
...
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 7, ADDITIONAL: 1
...
;; ANSWER SECTION:
fbi.gov.		600	IN	A	72.21.81.85
fbi.gov.		600	IN	RRSIG	A 7 2 600 ...
...

On récupère la donnée qu'on voulait, l'adresse IPv4 (type A) et une signature (type RRSIG). La signature est valide, c'est pour cela que le résolveur DNS a mis le flag AD (Authentic Data). Donc, pourquoi certains parlent d'un problème ? Parce que si on demande quelque chose qui n'existe pas, mettons l'adresse IPv6, le résolveur proteste :


% dig AAAA fbi.gov   
...
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 14748
...

On a cette fois SERVFAIL (Server Failure). Était-ce bien un problème DNSSEC ? Demandons au résolveur de ne pas valider, avec CD (Checking Disabled) :


% dig +cd AAAA fbi.gov   
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 23962
;; flags: qr rd ra cd; QUERY: 1, ANSWER: 0, AUTHORITY: 3, ADDITIONAL: 1
...
;; QUESTION SECTION:
;fbi.gov.			IN	AAAA

;; AUTHORITY SECTION:
...

Cette fois, pas de problème (NOERROR) et pas de réponse (ANSWER: 0, ce qui est normal en l'absence d'une adresse IPv6). Donc, le problème est lié à DNSSEC puisque couper la validation le fait disparaître.

Mais comment se fait-il qu'un excellent service en ligne de vérification des zones DNSSEC, http://dnsviz.net/, ne voie aucun problème et affiche fbi.gov comme normal ? C'est parce que le problème ne se produit que sur les types de données qui n'existent pas dans cette zone. Si on déroule les options de DNSviz et qu'on coche Denial of existence, cette fois, il affiche une erreur RRset is not covered by any RRSIG.

Et cela nous donne une indication sur la cause du problème. Relisons la sortie de la commande dig +cd AAAA fbi.gov tapée plus haut. J'avais omis la section Authority. Voyons-la :

;; AUTHORITY SECTION:
fbi.gov.		525	IN	SOA	ns1.fbi.gov. dns-admin.fbi.gov. 2013071601 7200 3600 2592000 43200
fbi.gov.		525	IN	RRSIG	SOA 7 2 600 20131014154120 20130716154120 32497 fbi.gov. mjg99/NUrrtRn51Ju90FeYyIlF0IITjP/qqk4yWjVsLSDVZIr3uQ9sAn 3e/WrxWeSMteGUMixVDzCBbky5M6/hpO26v2AyKh4IV3I/gIBsy0daS6 MeOMgwhF6EK2HcFoSU24i2Np3GTY05UjpTxlcz1vvoJmBvUOgFbOBJ6d eJM=
97S2G907NEFOJ79P721E4FEQ9LR3IT1S.fbi.gov. 525 IN NSEC3 1 0 10 BBAB A867R4P7R3SHMBUEO5I35R55QH3IEFAI A NS SOA MX RRSIG DNSKEY NSEC3PARAM

L'erreur est dans la dernière ligne. Il y a bien un enregistrement NSEC3 (normalisé dans le RFC 5155), qui sert à prouver que ce type AAAA n'existe pas. Mais ce NSEC3 n'est pas signé... Sur une zone correcte, ici afnic.fr, on trouverait cette signature (je prends le type LOC car afnic.fr a un AAAA) :


% dig LOC afnic.fr
...
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 0, AUTHORITY: 4, ADDITIONAL: 1
...
;; AUTHORITY SECTION:
afnic.fr.		5400	IN	SOA	dnsmaster.nic.fr. hostmaster.nic.fr. 2013071908 7200 1800 2419200 5400
afnic.fr.		5400	IN	RRSIG	SOA 8 2 172800 20130726131527 20130719181913 43854 afnic.fr. IOjRTsqU++CxhlwMW3VAH8j7OPud+zyTbUZ02w44KWwZfLeM8FvYeWDy UfjXA0Mgq2KNUpBXMCKzg9cFaTSvoRXqRKQ24qlDuMOXXZxC5aYtND+x Dax87JNlYycYfsEOLkIP4D6W0VPt8ENFDEdMTrYyLtmXkIrV9RiRg6aM ngs=
4vti9ma10fgk5bpja8qq4phrc4ikk83g.afnic.fr. 5400	IN RRSIG NSEC3 8 3 5400 20130724210757 20130718041857 43854 afnic.fr. myEZi91CVJy8SR6nN2ZarEOMHNMDFCAuynBpSb6HDUqgnYlAzJFo7CuS ZjbB+0SdQzZIiuEdzm7iSUyP47/cnOKYa27ubGDz75fOi5bf0LDNPmRx vC/ZijRFRIQ0NoZVX9oy7kcSPfqOcPpRt6dplGVVy11pRRWfJPd0GqZF ccg=
4vti9ma10fgk5bpja8qq4phrc4ikk83g.afnic.fr. 5400	IN NSEC3 1 1 1 546A5140353A2BE3 68O926N7PINN2OC9URC70JUE5742057E A NS SOA MX AAAA RRSIG DNSKEY NSEC3PARAM

Le NSEC3 est bien signé, comme il doit l'être, permettant ainsi au résolveur de valider la réponse.

Maintenant, pourquoi cette curieuse absence de signature ? Aucun serveur de noms normal ne fait cela. La faute en revient probablement à un pare-feu placé devant le serveur et qui, trop zélé et pratiquant la DPI, élimine uniquement les signatures des NSEC3. C'est difficile à croire, je le sais, mais je ne vois pas d'autre explication.

Je n'ai rien trouvé par moi-même dans ce cas, cet article est entièrement tiré des excellentes analyses de Michael Sinatra, Bill Owens et Casey Deccio. Notez une autre erreur dans la zone : l'enregistrement SOA indique une adresse de contact dns-admin@fbi.gov mais celle-ci génére un avis de non-remise...


L'article seul

RFC 6985: IMIX Genome: Specification of variable packet sizes for additional testing

Date de publication du RFC : Juillet 2013
Auteur(s) du RFC : A. Morton (AT&T Labs)
Pour information
Réalisé dans le cadre du groupe de travail IETF bmwg
Première rédaction de cet article le 19 juillet 2013


Traditionnellement, les mesures des caractéristiques d'un réseau en labo (RFC 2544) se faisaient avec des paquets de taille constante, afin de bien contrôler les conditions de la mesure, de savoir exactement ce qui était mesuré et donc de pouvoir reproduire la mesure à volonté. C'est par exemple ce que fait la commande ping avec son option -s. Mais les réseaux réels sont bien différents : ils font passer des paquets de taille très diverses. Il est donc fréquent aujourd'hui de tester avec un mélange de paquets de différentes tailles, ce qu'on nomme un IMIX (Internet MIXture). De nos jours, les équipements de test ont souvent la possibilité d'utiliser des IMIX. Mais les tests doivent être reproductibles, il faut donc un moyen de caractériser un IMIX, d'indiquer sa composition (autrement que par un vague « on a utilisé un IMIX »). C'est le but du mini-langage présenté dans ce RFC.

En gros, les petits paquets vont tester la capacité du réseau à traiter les en-têtes et les gros vont tester sa capacité à faire circuler des bits. On a donc besoin des deux dans un test. L'IMIX genome est la description, dans un langage formel, de la répartition des tailles de paquets. (Comme un génome décrit une espèce.)

Donc, à quoi ressemble un IMIX (section 3 du RFC) ? À une série de lettres dont chacune code une taille de paquet donnée, en utilisant les tailles « standard » du RFC 2544. Ainsi, avec la table a = 64 octets, b = 128, c = 256, d = 512, e = 1 024, f = 1 280 et g = 1518, l'IMIX aaafg désigne une séquence de cinq paquets, les trois premiers faisant 64 octets, le quatrième 1 280 et le dernier ayant la taille maximale sur Ethernet. Une lettre z est utilisée pour dire « la MTU du lien », donc, ici, on aurait pu utiliser aaafz. Notez bien qu'avec cette notation, les autres tailles ne peuvent pas être représentées (il faut choisir la taille la plus proche) et qu'un test avec des milliers de paquets est décrit par un IMIX assez illisible...

Si on tient à utiliser des tailles non prévues par le RFC 2544, la section 4 prévoit un moyen de définir localement des lettres, notées en majuscule. Avec la table locale A = 98, B = 1 020, l'IMIX BBAA indiquera deux gros paquets puis deux petits.

Ce système manque clairement de souplesse : et si, pour un test long, une séquence de base est répétée ? Ou bien si les tailles sont choisies par un processus pseudo-aléatoire ? La section 5 décrit deux fonctions utiles du mini-langage de description des génomes IMIX. Pour les séquences répétées, on se sert simplement d'un encodage en RLE. Le RFC ne propose pas de syntaxe concrète pour le décrire, l'exemple est juste un tableau « 20 fois abcd puis 5 fois ggga et enfin 10 fois dcba ». Le RFC propose également un autre mécanisme (à nouveau sans syntaxe précise), en indiquant les pourcentages de chaque taille (sans spécifier la séquence) : « 23 % de 64 octets, 67 % de 128 et 10 % de 1 000 ».

Le RFC prévoit aussi le cas où les tailles sont générées par un algorithme. Dans ce cas, pas de langage particulier, il faut le décrire en langage naturel lorsqu'on publie les résultats de la mesure (« on part de paquets de 64 octets et on incrémente leur taille de 1 à chaque paquet, s'arrêtant à la MTU »). Idem si l'algorithme utilisé est un générateur pseudo-aléatoire, qui doit également être décrit (avec la graine utilisée).

Si vous voulez lire des articles sur les IMIX, voir « "Test Methodology Journal: IMIX (Internet Mix) », « Library: Test Plans » ou « The Journal of Internet Test Methodologies ». Pour une discussion sur la normalisation d'IMIX (et pas du langage qui les décrit), voir une discussion terminologique dans le groupe de travail.


Téléchargez le RFC 6985


L'article seul

RFC 6948: Some Measurements on World IPv6 Day from End-User Perspective

Date de publication du RFC : Juillet 2013
Auteur(s) du RFC : A. Keranen, J. Arkko (Ericsson)
Pour information
Première rédaction de cet article le 18 juillet 2013


Le World IPv6 Day le 8 juin 2011 avait pour but de tester le comportement d'IPv6 si de nombreux services sur l'Internet activaient ce protocole. On peut noter que rien de spectaculaire ne s'est produit (tant mieux : comme prévu, cette activation n'a rien cassé) mais les impressions ne suffisent pas, il faut aussi mesurer ce qui s'est passé. C'est une de ces mesures que raconte ce RFC ; ses auteurs ont compté le nombre de sites Web qui activaient IPv6 et le résultat que cela avait sur le temps d'établissement d'une connexion, pour un client qui avait déjà IPv4 et IPv6.

Pourquoi est-ce que, alors qu'IPv6 est normalisé depuis de nombreuses années (RFC 2460), certains gros acteurs de l'Internet hésitent toujours à l'activer ? Les raisons vont de la simple passivité à la crainte que, dans certains cas, l'activation d'IPv6 ne dégrade le vécu de l'utilisateur (RFC 6555). Le but des IPv6 days (il y en avait d'autres avant celui de 2011 et d'autres sont apparus après) est à la fois d'encourager les frileux, et de tester pendant 24 h si les craintes sont justifiées (l'IPv6 Day de 2012, considérant que les tests avaient été suffisants et n'avaient guère montré de problèmes, était au contraire prévu pour qu'IPv6 reste activé). Pendant 24 h, le 8 juin 2011, un certain nombre d'opérateurs de services Internet ont donc configuré leurs services pour répondre en IPv6, leur permettant de tester que tout allait bien, et d'avoir une idée du pourcentage de leurs utilisateurs prêts à faire de l'IPv6. Cette configuration impliquait l'activation du protocole sur les différents équipements : serveurs, bien sûr, mais aussi applications car celles-ci gèrent parfois des adresses IP, par exemple à des fins de statistiques, et également les diverses middleboxes qui sont en général le maillon faible de la connectivité Internet.

Une fois qu'IPv6 était disponible et testé sur le service (normalement, bien avant le grand jour), il n'y avait plus qu'à le faire savoir au reste du monde, ce qui se fait en publiant un enregistrement AAAA dans le DNS.

Les mesures décrites dans ce RFC étaient donc le pourcentage de domaines avec des enregistrements AAAA et le temps pris à établir une connexion avec le serveur (ainsi que le pourcentage d'échecs).

Comme l'Internet est grand, l'étude de ce RFC s'est limitée 10  000 sites Web les mieux placés dans le classement d'Alexa (section 3 du RFC). Pour chaque domaine, le logiciel a fait une requête DNS AAAA pour ledomaine, www.ledomaine, et aussi des noms spécifiques à IPv6 comme www.ipv6.ledomaine (noms peu susceptibles d'être utilisés par le visiteur moyen). Ce logiciel de mesure active était écrit en Perl avec le module Net::DNS. Ensuite, un petit programme en C tentait une connexion TCP vers l'adresse obtenue et mesurait le délai. Les mesures ont commencé une semaine avant l'IPv6 day et se sont terminées trois jours après. Le client était situé dans les locaux d'Ericsson à Helsinki.

Quels ont été les résultats ? La section 4 donne les valeurs obtenues, avec des liens vers des graphiques externes (les RFC ne permettent pas de mettre d'images). Le pourcentage d'enregistrements AAAA est ainsi passé de 2,45 % une semaine avant le grand jour et a culminé à 4,91 % pendant. Il est ensuite redescendu (contrairement à 2012, il n'était pas demandé aux sites de garder leurs AAAA), mais est resté plus élevé qu'avant le jour IPv6. Si on prend seulement les 100 sites les mieux classés par Alexa, on trouve la même courbe mais des pourcentages bien plus élevés (les gros sites sont plus sérieux pour ce qui concerne IPv6).

Ce n'est pas tout de publier des adresses IPv6. Encore faut-il que le serveur HTTP situé derrière réponde effectivement. Si on teste toutes les adresses (v4 et v6) en TCP vers les ports 80 et 443, on trouve entre 1 et 3 % d'échecs. Pour IPv6 seul, le pourcentage d'échec est bien plus élevé. Cela ne recoupe pas les résulats vus par DNSdelve (qui montrent nettement moins d'échecs de connexion) probablement parce qu'il s'agit ici d'une journée exceptionnelle, que tout le monde n'a pas bien préparé. Apparemment, certains ont publié leur AAAA avant de configurer leur serveur, leurs routeurs et leurs pare-feux (notez la baisse du pourcentage d'échecs au fur et à mesure que la journée avance).

Et si TCP marche, OK, mais marche-t-il vite ? La connexion prend t-elle plus ou moins de temps en IPv4 et en IPv6 ? Après tout, autrefois, en raison de l'utilisation de mauvaises technologies comme 6to4 (RFC 3056 et RFC 7526) ou comme des tunnels amateurs, IPv6 avait la réputation d'être lent. Qu'en est-il aujourd'hui ? En prenant la médiane et la moyenne, on voit que la différence est très faible (même pour la moyenne, pourtant plus sensible aux petites variations), et qu'IPv6 est un peu plus rapide en temps normal mais plus lent pendant le jour IPv6 (sans doute parce que l'arrivée de nombreux sites mal configurés a fait baisser les chiffres).

En conclusion, le jour IPv6 de 2011 n'a pas été inutile. Le RFC estime qu'avant celui de 2012, il a été une des journées où l'Internet avait changé le plus. Mais les utilisateurs ordinaires n'ont rien remarqué, ce qui était justement le but. Même ceux qui mesurent les temps de connexion n'auront guère vu de différences. Le principal problème est le nombre trop élevé de sites qui publient un AAAA mais avec qui la connexion IPv6 échoue.

Autres mesures équivalentes :


Téléchargez le RFC 6948


L'article seul

RFC 6982: Improving Awareness of Running Code: the Implementation Status Section

Date de publication du RFC : Juillet 2013
Auteur(s) du RFC : Y. Sheffer (Porticor), A. Farrel (Juniper)
Expérimental
Première rédaction de cet article le 18 juillet 2013


L'IETF se vante souvent de ne pas croire au blabla des marketeux, mais uniquement au code qui tourne. Comme le dit fièrement sa devise, « We believe in rough consensus and running code ». Mais, en pratique, les normes produites et publiées en RFC ne contiennent pas toujours la mention d'une mise en œuvre effective de cette norme. Parfois, c'est parce qu'il n'y en a pas (contrairement à une légende tenace, ce n'est nullement une obligation pour la publication d'un RFC). Parfois, c'est parce qu'elle n'est pas mentionnée. Avant la publication d'un RFC, lorsque le document est encore un simple Internet-Draft, la mention de l'existence de programmes mettant en œuvre le protocole ou le format décrit est complètement facultative. Ce nouveau RFC propose de formaliser et d'encourager cette mention. Il a depuis été remplacé par le RFC 7942.

Cela ne concerne que les Internet-Drafts, pas les RFC. En effet, les RFC sont stables (jamais modifiés) alors que les URL pointant vers un programme ne le sont pas : un programme peut être abandonné, plus maintenu, on peut se retrouver avec des 404, etc. Donc, un RFC n'est pas le bon endroit pour stocker un catalogue de mises en œuvre d'un protocole. L'expérimentation décrite dans ce nouveau RFC 6982 ne vise que les Internet-Drafts, afin d'aider à l'évaluation d'une proposition.

Le concept de running code est décrit dans le Tao (cf. RFC 4677 et RFC 6722). Il synthétise l'approche pragmatique de l'IETF : une norme qui n'est pas mise en œuvre ne sert à rien. Malgré cela, bien des RFC n'ont jamais connu la moindre mise en œuvre. En effet, ce principe général du running code n'a jamais été traduit dans une exigence formalisée et globale pour les auteurs de RFC. Il existe par contre des règles locales. Ainsi, la Routing Area de l'IETF (les groupes de travail qui normalisent les protocoles de routage) a longtemps demandé (RFC 1264) au moins une mise en œuvre avant la publication d'un RFC sur le chemin des normes. Le RFC 4794 a supprimé cette règle, qui reste appliquée par certains groupes de la Routing Area comme IDR.

Notre tout nouveau RFC 6982 est purement expérimental : il ne propose pas de définir une nouvelle règle, juste de formaliser une section dans les Internet-Drafts, facultative, qui permettra de documenter les mises en œuvre connues. L'idée est que les Internet-Drafts ayant cette section seront examinés avec plus de bienveillance, sans toutefois qu'elle soit obligatoire.

La section 4 du RFC fait la liste de tous les avantages qu'il y a à indiquer ces mises en œuvre dans l'Internet-Draft : meilleure information pour la prise de décision (aussi bien sur la publication de l'Internet-Draft que sur le statut du futur RFC), encouragement aux tests d'interopérabilité, possibilité (lorsque le code est publié) de mieux comprendre le protocole (beaucoup de programmeurs préfèrent lire le source plutôt que le RFC), et enfin assurance que telle fonction du RFC peut effectivement être mise en œuvre. C'est en effet souvent le cas (par exemple lors de la discussion qui a mené au RFC 5155) que certaines personnes affirment que la technologie envisagée est tout simplement trop complexe pour être programmée. L'existence d'un programme qu'on peut tester permet de d'assurer que, si, la technologie est réaliste (bien d'autres SDO produisent sans hésiter des technologies impossible à programmer dans des conditions raisonnables).

Cette nouvelle section, « Implementation status » est décrite en section 2 de ce RFC. Elle sera située vers la fin (comme l'actuelle - et obligatoire, elle - « Security considerations ») et pourra comporter les points suivants :

  • Une description du programme,
  • L'organisation qui a développé le programme,
  • Un URL pour le téléchargement du programme, et les conditions de la licence (comme tous les points situés ici, il est facultatif : toutes ces mises en œuvre d'une norme IETF ne seront pas forcément en logiciel libre, ni même publiquemnt accessibles),
  • Le niveau de maturité du programme (une preuve que ça marche, vite faite en un week-end pour tester l'Internet-Draft, n'est pas la même chose qu'une version 1.0 testée et polie),
  • Le taux de couverture de la specification par le programme (des mises en œuvre expérimentales peuvent sauter les parties les plus difficiles de la spécification...).

Cette section peut aussi indiquer l'expérience tirée de cette mise en œuvre, ainsi que des informations sur l'interopérabilité, au cas où plusieurs mises en œuvre existent. Les présidents des groupes de travail sont explicitement chargés de vérifier que cette section ne dégénère pas en simple marketing pour le produit d'un vendeur. Notre RFC propose aussi un texte standard d'avertissement à inclure au debut de cette section « Implementation status ».

D'autres endroits que l'Internet-Draft lui-même auraient pu être utilisés pour informer sur les mises en œuvre existantes. Le RFC suggère (section 3) de passer au wiki de l'IETF lorsque la liste des programmes devient trop longue, lorsqu'il semble préférable que cette liste soit maintenue par les implémenteurs plutôt que par les auteurs de l'Internet-Draft, lorsque le groupe de travail maintient activement un wiki, ou enfin lorsque la liste en question semble utile, même après la publication en RFC (pour indiquer le niveau d'adoption par les programeurs). Dans tous ces cas, il est bon d'indiquer l'URL du Wiki en question dans l'Internet-Draft.

Le RFC se donnait 18 mois pour l'évaluation de l'expérience, ce qui est la durée typique de production d'un RFC). Cette expérimentation est alors devenue la politique officielle de l'IETF (RFC 7942). On a évalué si cette section a été utilisée (par exemple pour trouver du code qu'on va ensuite tester) et si les décisions prises ont effectivement été meilleures. Curieusement, alors que cette nouvelle section n'est nullement obligatoire, ce RFC 6982 ne propose pas parmi les critères de succès de voir tout simplement combien d'auteurs d'Internet-Drafts ont inclus une telle section. Il faut dire qu'un certain nombre le font déjà de façon informelle.

Quelques exemples d'Internet-Drafts qui incluent actuellement cette section : draft-clausen-lln-loadng, draft-wilde-xml-patch ou draft-ietf-mpls-multipath-use.


Téléchargez le RFC 6982


L'article seul

traceroute depuis les sondes Atlas

Première rédaction de cet article le 17 juillet 2013


Lorsqu'on débogue un problème réseau sur l'Internet, on utilise souvent traceroute. Il vous indique jusqu'où vous allez et par quel chemin. Le problème est que cela ne dit pas ce que voit le pair en face, d'autant plus le trafic n'est pas forcément symétrique. Il est souvent utile de pouvoir commander un traceroute depuis le pair vers votre machine. Les sondes Atlas permettent cela.

C'est quand même nettement plus pratique que de demander aux gens d'en face de le faire (d'autant plus qu'ils peuvent n'avoir pas le temps, ou simplement pas la compétence pour le faire corrrectement.) On peut déclencher ce traceroute depuis une sonde donnée, depuis un ensemble de sondes (identifiées par leur pays, par leur numéro de système autonome, etc). Cela peut se faire via l'interface Web des UDM (User-Defined Measurements) ou via un programme (j'utilise traceroute.py). Une fois la mesure faite, on peut, comme avec les autres mesures Atlas, télécharger le résultat en format JSON et l'analyser. Voici un extrait des résultats de la mesure #1013442 montrant les deux premiers sauts :

    "prb_id": 2014, 
    "result": [
      {
        "result": [
          {
            "rtt": 1.6990000000000001, 
            "ttl": 255, 
            "from": "185.12.232.2", 
            "size": 56
          }, 
         ...
        ], 
        "hop": 1
      }, 
      {
        "result": [
          {
            "rtt": 1.601, 
            "ttl": 255, 
            "from": "185.12.232.3", 
            "size": 56
          }, 
         ...
        ], 
        "hop": 2
      }, 

Bon, le JSON, ce n'est pas forcément très agréable à lire (mais c'est documenté). Alors, Jan Hugo Prins a fait un excellent script qui traduit cela en format plus lisible :

% python json2traceroute.py 1013442.json
...
From:  130.79.86.251    2259    FR-U-STRASBOURG OSIRIS - UNIVERSITE DE STRASBOURG
Source address:  130.79.86.251
Probe ID:  2279
1    130.79.86.253    2259    FR-U-STRASBOURG OSIRIS - UNIVERSITE DE STRASBOURG    [2.922, 2.542, 2.686]
2    193.51.183.130    2200    FR-RENATER Reseau National de telecommunications pour la Technologie    [2.666, 2.572, 3.016]
3    193.51.189.85    2200    FR-RENATER Reseau National de telecommunications pour la Technologie    [10.085, 8.778, 9.873]
4    193.51.189.161    2200    FR-RENATER Reseau National de telecommunications pour la Technologie    [11.067, 12.877, 11.121]
5    193.51.180.14    2200    FR-RENATER Reseau National de telecommunications pour la Technologie    [76.381, 68.488, 91.891]
6    194.68.129.118    None    None    [10.383, 10.125, 9.975]
7    217.70.176.214    29169    GANDI-AS Gandi SAS    [11.094, 10.871, 10.186]
8    217.70.176.250    29169    GANDI-AS Gandi SAS    [32.749, 9.386, 10.046]
9    217.70.190.232    29169    GANDI-AS Gandi SAS    [11.058, 10.215, 9.371]
...

On voit, pour chaque saut, l'adresse IP du routeur, le numéro d'AS, le nom de l'opérateur et le RTT pour les trois tests faits par sauts. (Au saut 6, le SFINX n'a pas été reconnu, probablement parce que ce préfixe n'est pas annoncé dans la DFZ.) Ce script nécessite d'installer d'abord la bibliothèque cymruwhois. Elle permet de convertir les adresses IP en numéros de système autonome et en noms d'opérateurs. Pour éviter de charger le serveur whois qui fait ces conversions, elle utilise un cache local. Le délai d'attente de cette bibliothèque est bien trop court et vous aurez donc souvent des erreurs :

socket.timeout: timed out

Dans ce cas, relancez la commande (le cache vous évitera de tout recommencer).

La mesure #1013442, citée plus haut, a été faite vers l'une des machines qui porte ce blog. J'ai utilisé l'option « traceroute avec ICMP » car le pare-feu filtre l'UDP. La commande exacte était :

% python traceroute.py -v -r 100 --protocol ICMP 217.70.190.232

Il existe plusieurs autres paramètres réglables pour lancer les mesures traceroute, n'hésitez pas à consulter la documentation, section « Traceroute-Specific Properties ».

Une des options les plus pratiques, à mon avis, est celle qui permet d'utiliser les mêmes sondes que dans une mesure précédente. Mettons qu'on mesure les performances DNS avec les Atlas. Puis on veut comprendre pourquoi certaines sondes ont des problèmes. On fait un traceroute avec l'option « mêmes sondes que dans la mesure N » et on peut alors analyser par où elles passent.

Un autre mécanisme pour lancer des traceroutes à distance est le RING. Et, bien sûr, il y a traceroute.org mais on a peu d'outils de sélection, on ne peut pas automatiser, beaucoup des services listés sont en panne, etc.


L'article seul

Bitmessage, le courrier enfin sécurisé ?

Première rédaction de cet article le 8 juillet 2013


Le système de messagerie Bitmessage est publié depuis plusieurs mois mais il a acquis une soudaine célébrité avec les révélations sur le programme PRISM. Il y a déjà eu beaucoup d'articles (y compris en français) sur Bitmessage donc je vais ici plutôt me concentrer sur des détails qui n'ont pas toujours été mentionnés.

Un rappel d'abord : Bitmessage est prévu pour faire de la messagerie sécurisée, notamment protégée contre l'espionnage de la NSA ou de la DGSE. Il opère en utilisant des adresses qui sont un condensat d'une clé publique (la mienne est BM-2D8rwZkR1KvUMCnBhH7MGzTwVRXnDvhMC9, vous pouvez m'écrire mais vous pouvez aussi essayer l'auto-répondeur BM-orkCbppXWSqPpAxnz6jnfTZ2djb5pJKDb). Les messages sont transmis au monde entier (Bitmessage n'a pas de préoccupations écologiques et fait travailler toutes les machines du réseau) mais seul le récepteur pourra le lire. Au bout d'une heure trente de fonctionnement de mon logiciel, j'ai traité :

2791 messages person-to-person
700 broadcast
6072 public keys

Autre point pas écologique : Bitmessage dépend de « preuves de travail » (résolution de problèmes nécessitant la force brute comme de trouver une collision dans une fonction de condensation) pour limiter le spam et les attaques Sybil.

Bitmessage est documenté dans un (très court et très elliptique) whitepaper et a une mise en œuvre de référence en Python.

Comme tous les systèmes à preuve de travail, il est très difficile à régler. Si le problème à résoudre est trop difficile, on ne pourra pas envoyer de Bitmessage depuis son smartphone. Et s'il est trop facile, un botnet pourra envoyer autant de spam que ça lui chante.

Les adresses Bitmessage sont une bonne illustration de ma conjecture comme quoi on ne peut pas avoir tout à la fois dans un identificateur. Ici, les concepteurs de Bitmessage ont sacrifié l'utilisabilité à la sécurité.

Notez qu'il existe une autre catégorie d'adresses, dérivée d'une phrase de passe et pas d'une clé publique (la mienne est BM-2DBbqaL9CSi7pVhzfHahy9vPD2hY3aTt5c). Le whitepaper n'en parle pas et je ne trouve pas de documentation sur leur principe. C'est en problème courant avec Bitmessage : la documentation est courte, et en retard sur le code.

Le lien avec Bitcoin, souvent cité, n'est pas clair non plus, à part quelques vagues analogies.

Bitmessage ne semble pas non plus très bien sécurisé contre les attaques par déni de service. Les nœuds de bootstrap, et les relais, sont publics et connus (ils sont même dans le code, en src/defaultKnownNodes.py). Ils peuvent être attaqués.

Attention aussi à la sécurité du poste local. Dans la version actuelle (0.3) du client de référence, la base de données SQLite contenant les messages, le carnet d'adresses, etc, est en clair. Même si on a effacé les messages, ils sont juste marqués détruits mais ils restent dans la boîte. Attention donc en cas de vol ou de perquisition. Il est recommandé d'avoir un disque local chiffré.

Enfin, attention, l'adresse de l'émetteur est vue par tout le réseau (où tout le monde peut s'inscrire). Cela ne donne pas accès au contenu des messages mais cela permet de savoir qui parle avec qui. La solution est de changer d'adresse souvent (ce que permet le client actuel facilement) au prix d'une perte de continuité dans sa réputation.

Je n'ai pas encore vu de comparaison systématique avec des systèmes concurrents comme TorChat, Freemail ou Cryptocat.

Bref, Bitmessage est intéressant et prometteur mais loin d'être fini.

Quelques articles utiles :

Je voulais remercier nominativement les personnes qui m'ont aidé à explorer Bitmessage mais la plupart d'entre elles étaient anonymes... Donc, remerciements aux anonymes et à Changaco.


L'article seul

DNSSEC peut-il aider en cas de piratage du registre de noms de domaines ?

Première rédaction de cet article le 5 juillet 2013


Le piratage du registre du .my le 1er juillet, survenant après des mésaventures analogues subies par d'autres registres de noms de domaine, a remis sur le tapis une vieille question : est-ce que DNSSEC peut aider dans un tel cas ? .my est en effet le premier TLD signé à être piraté.

Le bon sens dit que non : comme répété souvent par Peter Koch, « DNSSEC does not prove that the data is correct, just that it is authentic ». Les signatures DNSSEC sont calculées par le registre, sur ses machines, à partir des données contenues dans sa base. Si le pirate a pris le contrôle du système, il a pu modifier la base et, dans ce cas, DNSSEC signera des données incorrectes. DNSSEC protège contre bien des attaques (dont la fameuse attaque Kaminsky) mais pas contre toutes. Si les données sont fausses, signer prouvera juste que les données fausses étaient bien celles dans la base. GIGO (Garbage In, Garbage Out). C'est un point important lorsqu'on évalue la sécurité des noms de domaine.

Mais, en creusant un peu la question, on voit que c'est plus compliqué que cela. Gardez bien en tête un rappel, un point important du DNS : les données peuvent rester dans les caches (les résolveurs, sur le réseau local ou chez le FAI) pendant un certain temps, borné par le TTL. Par exemple, ici, je demande à mon résolveur la clé de .fr :

% dig DNSKEY fr.
fr.			39110	IN	DNSKEY	256 3 8 AwEAA...
fr.			39110	IN	DNSKEY	257 3 8 AwEAA...
fr.			39110	IN	DNSKEY	257 3 8 AwEAA...
fr.			39110	IN	DNSKEY	257 3 8 AwEAA...

Et je vois qu'elle va encore rester en mémoire du résolveur pendant 39 110 secondes, plus de 10 heures. Comme le note Olivier Auber, avec DNSSEC, il faut toujours avoir une perspective temporelle. (Revoir quelques épisodes de Doctor Who peut aider.)

Or, mettons nous à la place de l'attaquant : il est maître du système du registre, il a l'accès à la base de données, il peut faire des UPDATE ou des INSERT tant qu'il veut. Si le domaine qu'il veut modifier est signé, que peut-il faire ? L'attaquant typique, aujourd'hui, ne connait probablement pas DNSSEC, qui est encore trop peu déployé. Il va donc probablement l'ignorer (comme cela avait été fait pour .my), et changer les enregistements NS pour les domaines visés. Par exemple, dans le cas de .my, DNSdb nous montrait ce changement :

bailiwick	coca-cola.com.my.
count	3
first seen	2013-07-01 04:23:36 -0000
last seen	2013-07-01 07:06:04 -0000
coca-cola.com.my.	NS	ns1.jealousdesigns.com.
coca-cola.com.my.	NS	ns2.jealousdesigns.com.

Pendant quelques heures, ce domaine avait été redirigé vers d'autres serveurs de noms contrôlés par le méchant (les bons serveurs sont en ko.com). Ces serveurs servaient une zone non signée où le nom coca-cola.com.my avait une adresse qui était celle d'une machine du pirate. La zone étant non signée, si un enregistrement DS avait été dans com.my (en fait, com.my est bien signé mais coca-cola.com.my ne l'est pas ; la suite de mon raisonnement est fait en regardant ce qui se serait passé si coca-cola.com.my avait été signé), la zone non signée aurait été considérée comme invalide et les résolveurs validant avec DNSSEC auraient rejeté son contenu. Donc, l'attaquant n'aurait pas atteint son but (qui était de diriger vers une page Web de hameçonnage, ou bien une page Web proclamant ses objectifs politiques ou simplement son ego). À la place, le détournement serait devenu un « simple » déni de service. Donc, dans ce cas (attaquant ignorant), DNSSEC aurait pu aider.

Bon, mais les attaquants vont progresser. Ils vont suivre des cours DNSSEC et faire plus attention la prochaine fois. Quelles sont les possibilités d'un attaquant qui s'y connait ? La première idée est de ne pas seulement modifier les NS mais aussi les DS et de servir, sur les serveurs de noms « pirates », une zone signée (avec les clés indiquées par le nouveau DS). Cela va marcher... sauf que le TTL va s'interposer. Voici le DS de bortzmeyer.fr dans mon cache :

% dig DS bortzmeyer.fr
bortzmeyer.fr.		42507	IN	DS	3445 8 2 7CC...
bortzmeyer.fr.		42507	IN	DS	44461 8 2 56A...

Et on voit qu'il va rester encore 11 heures. L'ancien DS étant dans un certain nombre de caches, la résolution va donc échouer pour ces caches, puisque l'ancien DS pointe vers la zone du pirate, pas signée avec la bonne clé. Ce sera l'équivalent d'un remplacement de clé (key rollover) raté parce qu'on n'a pas bien fait ses calculs de TTL (voir le RFC 6781, mon expérience et l'étude montrant que les erreurs existent.) La seule chose que le pirate ne contrôle pas, c'est le Temps. Et c'est ainsi qu'on peut détecter ses plans diaboliques.

Bon, changement de stratégie. Pourquoi ne pas tout simplement supprimer le DS, attendre que le contenu dans les caches expirent, puis changer les NS ? Cela peut marcher... si le titulaire de la zone fille ne fait pas de surveillance de ses noms de domaine et ne s'aperçoit donc pas que la zone est désormais neutre (non signée). D'où l'importance de la supervision dans tout projet DNSSEC. C'est d'ailleurs également le cas pour l'attaque précédente : si personne ne supervise et ne s'aperçoit du problème avant que les données ne disparaissent des caches, DNSSEC n'aura servi à rien.

Merci à Peter Koch, Antoin Verschuren, Edward Lewis et Klaus Darilion pour une intéressante discussion à ce sujet.

Un autre article sur la sécurité des noms de domaine était celui de Pierre Col.


L'article seul

RFC 6975: Signaling Cryptographic Algorithm Understanding in DNSSEC

Date de publication du RFC : Juillet 2013
Auteur(s) du RFC : S. Crocker (Shinkuro Inc.), S. Rose (NIST)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dnsext
Première rédaction de cet article le 4 juillet 2013


Le système d'authentification du DNS DNSSEC repose sur la signature cryptographique des enregistrements DNS. Cette signature peut se faire par des algorithmes différents. Comment savoir si tel algorithme, récemment spécifié, est désormais d'un usage fréquent ou pas chez les résolveurs validants ? Ce nouveau RFC propose que le résolveur indique, dans sa requête DNS, la liste des algorithmes qu'il comprend. Cela permettra, dans le futur, de mesurer objectivement l'état du déploiement de tel ou tel algorithme.

L'algorithme utilisé dans une signature DNSSEC apparait dans l'enregistrement RRSIG sous forme d'un octet dont la signification est stockée dans un registre IANA. Ainsi, dans cette signature de .fr :

% dig +dnssec SOA fr.
...
;; ANSWER SECTION:
fr.			172800	IN	SOA	nsmaster.nic.fr. hostmaster.nic.fr. 2222283656 3600 1800 3600000 5400
fr.			172800	IN	RRSIG	SOA 8 1 172800 20130814151003 20130615141003 62646 fr. FSSGO0iZ6OBoSUE12Q/NYOU2f3AMNbOf/b4FoC48F8f5gDfSNpJStZF7 zGsN51+zFE3FCucNDw4cQMY8YqBeu6BN5IG4StqAjEp+3FqLYSzyUu4s tZY8GnLa9ZzJCTf6dGT0CE2JbEzc705hc6X6I7DDxqwrzzpj23F/Rg9 PEk=
...

La signature est faite avec l'algorithme 8, RSA + SHA-256. Dans le cas de ecdsa.isc.org :

% dig +dnssec SOA ecdsa.isc.org
...
;; ANSWER SECTION:
ecdsa.isc.org.		3600	IN	SOA	ns-int.isc.org. hostmaster.isc.org. 2013052903 7200 3600 604800 3600
ecdsa.isc.org.		3600	IN	RRSIG	SOA 14 3 3600 20130712033157 20130612023157 30631 ecdsa.isc.org. o+Q1WDDeiCM3z2b793Ni/FtMT223gJ/1Lr+RWOgPJLVxB+AlLKyKvLOs vWRBqUjwYeKE4Dx/ZUSIx8eVzOUt5g6HvBuGaYX/camsYn9ocuTp6J+w J2Fn69Qi6/WbhAa4
...

Elle est fait avec 14, ECDSA avec SHA-384. On trouve également des numéros identifiant un algorithme, celui de condensation cryptographique, dans les enregistrements DS et un autre dans NSEC3 (les valeurs possibles étant dans un autre registre IANA).

Actuellement, les serveurs faisant autorité pour une zone ne savent pas quels algorithmes sont compris par les résolveurs qui les interrogent. Le serveur qui fait autorité envoie toutes les signatures qu'il connait et le résolveur se débrouille. Reprenons le cas de .fr, signé avec RSA. Pourrait-on passer à ECDSA, normalisé dans le RFC 6605, et qui a l'avantage de fournir des clés et des signatures plus courtes ? Le problème est qu'ECDSA dans DNSSEC est très récent et qu'on pense que peu de résolveurs sont capables de valider avec ECDSA. Mais quel pourcentage exactement ? Et, avec le temps, ce pourcentage augmentera. Comment saura-t-on qu'on est arrivé au point où la grande majorité des résolveurs parlent ECDSA ? Si ce nouveau RFC 6975 est déployé, il fournira un moyen de répondre à ces questions.

Le principe est d'utiliser trois nouvelles options EDNS pour signaler les algorithmes connus. Le résolveur mettra ces options dans la requête et le serveur faisant autorité pourra les examiner pour connaître les capacités de ses clients (notez bien que c'est uniquement à des fins d'information : le serveur ne doit pas modifier sa réponse en fonction de ces options). EDNS est normalisé dans le RFC 6891 et l'enregistrement OPT qu'il ajoute contient zéro, une ou plusieurs options (la liste des options possibles est dans un registre IANA). Les trois options ajoutées sont (section 2 de notre RFC) :

  • DAU (code 5) : DNSSEC Algorithm Understood indique quels algorithmes de signature sont acceptés,
  • DHU (code 6) : DS Hash Understood indique quels algorithmes de condensation sont acceptés par le résolveur pour les enregistrements DS,
  • N3U (code 7) : NSEC3 Hash Understood donne la même information pour la condensation dans les enregistrements NSEC3.

L'encodage d'une option EDNS se fait en trois champs, le code sur deux octets (5, 6 ou 7 ici), la longueur des données sur deux octets et les données. Ici, les données consistent en une liste d'algorithmes, un octet pour chacun, dans un ordre quelconque (l'ordre n'exprime pas une préférence). Par exemple, un résolveur validant qui accepte RSA-SHA1, RSA-SHA256 et ECDSA-SHA384 encodera un DAU avec les octets {5, 0, 3, 5, 8, 14}. En pratique, le RFC estime que les trois options toutes ensemble devraient prendre de 22 à 32 octets (en comptant 6 à 10 algorithmes de signature, plus quelques uns pour la condensation).

Bon, et une fois le format défini, on s'en sert comment ? Pour les clients (les résolveurs), c'est en sections 3 et 4 du RFC. Si le client valide, il ajoute une, deux ou trois des nouvelles options dans sa requête. Sinon, il ne doit pas les utiliser.

Si le résolveur valide et qu'il reçoit une requête ayant déjà une de ces options, il doit ajouter ses propres algorithmes. La liste finale sera donc l'union des deux. Un simple relais (forwarder) qui ne valide pas mais qui reçoit une requête ayant une de ces options, doit passer l'option telle quelle car ce qui compte, ce sont les capacités du résolveur qui fera la validation DNSSEC.

Et le serveur faisant autorité ? C'est en section 5. Le point important est qu'il ne doit rien faire. Il suit le même algorithme que d'habitude et, par exemple, il envoie les mêmes signatures quels que soient les algorithmes compris par l'émetteur. Les trois nouvelles options sont là pour information uniquement. D'autres part, les trois options DAU, DHU et N3U sont uniquement dans les requêtes. Le serveur faisant autorité n'en met pas dans les réponses.

Revenons aux administrateurs d'une zone qui voudraient mesurer le déploiement d'un nouvel algorithme cryptographique. Que faire si les clients n'envoient pas cette option ? La section 6 conseille de les considérer comme du vieux logiciel, n'ayant pas les nouvelles options, ni les nouveaux algorithmes. C'est un peu court, à mon avis, car on peut aussi imaginer qu'il y aura des résolveurs récents qui n'enverront pas cette option, peut-être par souci de discrétion (ce point est également couvert dans la section 7, consacrée aux risques de sécurité).

Il ne semble pas exister beaucoup de mises en œuvre de ce RFC. Par exemple, Wireshark, au moment de la publication du RFC, ne savait pas décoder ces options et affichait juste :


    Additional records
        <Root>: type OPT
            Name: <Root>
            Type: OPT (EDNS0 option)
            UDP payload size: 1200
            Higher bits in extended RCODE: 0x0
            EDNS0 version: 0
            Z: 0x0
            Data length: 8
            Data

Depuis r50840, Wireshark a le code nécessaire et on n'a plus qu'à patienter que cela arrive dans une version officielle.

L'examen des requêtes envoyées à un gros serveur de noms ne montrait, au moment de la sortie du RFC, pratiquement pas d'utilisation de cette option.

Trois ans après la publication du RFC, une discussion lors d'une réunion OARC semblait indiquer qu'il n'avait connu aucun déploiement et devait être considéré comme un échec. Mais en juin 2020, OpenDNS l'a activé sur ses serveurs.


Téléchargez le RFC 6975


L'article seul

RFC 6971: Depth-First Forwarding in Unreliable Networks (DFF)

Date de publication du RFC : Juin 2013
Auteur(s) du RFC : U. Herberg (Fujitsu), A. Cardenas (University of Texas at Dallas), T. Iwao (Fujitsu), M. Dow (Freescale), S. Cespedes (U. Icesi)
Expérimental
Première rédaction de cet article le 29 juin 2013


Traditionnellement, l'acheminement à bon port d'un paquet IP nécessitait deux processus distincts : le routage (routing) à proprement parler, où les routeurs calculent des tables de routage indiquant, pour divers préfixes IP, la prochaine étape (next hop) à atteindre, et la transmission (forwarding) où les routeurs choisissent le prochain routeur, et l'interface de sortie, pour un paquet donné. Le premier processus, le routage, est fait à l'avance, indépendemment d'un paquet précis, et nécessite des protocoles complexes comme OSPF. Le second processus, la transmission, nécessite de faire tourner l'algorithme de plus long préfixe, et se fait par contre en temps réel, pour chaque paquet entrant. Pourquoi cette séparation en deux ? Car ces deux processus ont des caractéristiques très différentes. Le premier, nécessitant des protocoles et des algorithmes élaborés, est mieux réalisé sur un processeur classique. Le second est typiquement le domaine d'ASIC spécialisés. Les routeurs haut de gamme utilisent d'ailleurs les deux types de matériel, selon la tâche. Mais cette séparation a aussi des inconvénients. Ainsi, la détection qu'un lien ne marche plus est typiquement du ressort des algorithmes de routage, qui ajusteront alors leurs routes. Pourtant, certains réseaux physiques permettent la détection, lors de la transmission d'un paquet, d'une panne et d'une impossibilité d'envoi. Pourquoi ne pas utiliser cette information pour que les paquets suivants aillent essayer une autre étape suivante ? C'est ce que propose ce RFC.

Notez que, comme souvent en matière de réseaux informatiques, le vocabulaire est flou et incohérent. Ainsi, le terme de routage est souvent utilisé pour désigner les deux processus qui concourent à l'acheminement, le routage à proprement parler et la transmission. Par exemple, j'ai parlé de table de routage alors que le sigle FIB (Forwarding Information Base) aurait été plus correct. Et le terme routeur désigne une boîte qui fait de la transmission et parfois (sur le moyen et haut de gamme) le routage. On lit ainsi des phrases fausses comme « Quagga permet de transformer un PC Unix en routeur » alors que le noyau Unix a toujours été capable de faire de la transmission de paquets (Quagga met en œuvre les protocoles de routage, qui ne sont pas nécessaires à un routeur).

Mais passons. Il faut bien faire avec le vocabulaire que nous avons. Revenons à la proposition expérimentale de notre RFC 6971. Elle ne cherche pas à couvrir tous les cas de transmission de paquets. Ce RFC s'applique aux paquets IPv6, lors de leur transmission sur des liens peu fiables, avec une topologie sans cesse changeante, un trafic assez faible, et où le protocole de couche 2 permet de savoir si un paquet a été transmis avec succès ou pas. C'est typiquement le monde des MANET et des LowPAN, des réseaux de petites machines connectées en radio. L'idée centrale de ce protocole DFF est d'avoir, dans le processus de transmission, certaines techniques utilisées d'habitude uniquement dans le routage, pour chercher un chemin alternatif. DFF va transmettre un paquet au premier routeur, s'il ne reçoit pas de nouvelles, il va essayer le second et ainsi de suite. Par contre, si la transmission vers la première étape se fait avec succès, DFF va laisser le paquet continuer, passer au routeur suivant, etc. Il fonctionne donc en profondeur d'abord (on essaie d'aller le plus loin possible, avant de tester d'autres « frères »). Les essais successifs se font séquentiellement (et non pas en parallèle comme dans les protocoles d'inondation) pour éviter qu'un destinataire ne reçoive plusieurs copies du même message. Cela peut donc prendre pas mal de temps s'il y a beaucoup de routeurs potentiels. À noter que le tout fonctionne de manière répartie, sans composant central.

N'est-ce pas un peu bizarre que de refaire une partie du travail du processus de routage dans celui de transmission ? Mais c'est lié à la façon dont fonctionnent les protocoles de routage. Travaillant à l'avance, ils ne peuvent pas s'adapter assez vite à tous les changements de topologie, qu'on ne découvrira qu'en envoyant réellement des paquets. Les protocoles de routage fonctionnent typiquement en envoyant de temps en temps des messages d'information. L'information peut donc être dépassée au moment de la transmission. Pour avoir une information plus à jour (section 1.1), il faudrait augmenter le rythme des messages d'information et cela se ferait au détriment de la consommation d'énergie des machines (rappelez-vous que DFF est prévu pour des réseaux de petites machines, souvent sans autre source d'énergie que leur batterie). Se placer sur le dos du processus de transmission (qui doit avoir lieu de toute façon) permettra donc, si ce protocole DFF tient ses promesses (ce RFC est expérimental), d'augmenter le pourcentage de paquets effectivement transmis, sans augmenter les coûts.

DFF va donc récolter de l'information sur le fonctionnement effectif du réseau, information qui peut être utile au processus de routage. DFF peut donc la réinjecter dans ce dernier, pour l'aider à calculer de meilleures routes, mais ce point n'est pas détaillé dans ce RFC.

La section 3 du RFC revient sur l'applicabilité limitée de ce protocole DFF. On l'a dit, il ne s'agit pas de remplacer tous les mécanismes de routage existants par ce mécanisme utilisant le succès de la transmission comme indication. D'abord, tous les réseaux n'offrent pas de possibilité de détecter cet échec. 802.15.4 ou 802.11 le permettent mais pas Ethernet, par exemple. D'autre part, DFF n'est utile que si la topologie change souvent. Dans un réseau filaire stable et fiable, les mécanismes de routage actuels marchent très bien et n'ont pas besoin de DFF. Et DFF nécessite un réseau ayant une topologie dense, avec plusieurs liens possibles entre deux points. S'il n'existe qu'un seul lien, DFF ne servira à rien puisque, en cas de perte d'un paquet, il n'y aura pas d'alternative. Enfin, DFF, contrairement à la transmission IP traditionnelle, nécessite un état dans le routeur. Il faut se souvenir de chaque paquet envoyé, le temps qu'on soit sûr de son bon acheminement. DFF ne peut donc être utilisé qu'en cas de faible trafic.

DFF peut fonctionner aussi bien dans les réseaux route-over (réseaux routés par les méthodes IP classiques) que dans les réseaux mesh-under (réseaux utilisant un mécanisme de « routage » dans la couche 2, cette terminologie est empruntée au RFC 6775).

La section 4 résume le fonctionnement du protocole : pour chaque paquet qu'il a reçu et qu'il doit transmettre, le routeur construit une liste des prochaines étapes possibles. Il tente d'envoyer le paquet en essayant successivement ces étapes. Si toutes échouent, le routeur renvoie le paquet à l'expéditeur, qui va alors essayer l'étape suivante dans sa liste à lui (rappelez-vous qu'on est en profondeur d'abord). On voit donc que, pour chaque paquet pas encore transmis avec succès, le routeur doit garder cette information en mémoire : routeur précédent (qui a envoyé le paquet), numéro et prochaines étapes possibles en indiquant lesquelles ont déjà été essayées. C'est quoi, ce numéro ? C'est un identifiant unique par routeur et permettant de distinguer un paquet des autres (section 12). La liste des paquets en cours de transmission, avec les métadonnées, est nommée le Processed Set (section 6.2).

DFF doit connaître la liste des prochaines étapes possibles. Il a pu utiliser un protocole de découverte des voisins (comme le NHDP du RFC 6130), ou bien il a pu trouver cette information dans la RIB (Routing Information Base), la base de données construite par le processus de routage (voir la section 5 pour les détails).

Les informations dont a besoin DFF peuvent être représentées de deux manières différentes dans le paquet. En route-over, on utilise un en-tête d'extension IPv6 standard, le hop-by-hop options (et pas un destination options, malgré les recommandations du RFC 6564 car cet en-tête doit être examiné par tous les routeurs sur le trajet). Le type de l'option DFF est 0xEE. Comme il commence par deux bits à Un, le paquet sera rejeté par les routeurs non-DFF (RFC 2460, section 4.2). La section 13.1 de notre RFC fournit les détails sur cette adaptation à IPv6. En mesh-under, on se sert des en-têtes 6LoWPAN, avec les adresses du RFC 4944 (section 13.2 pour les précisions). Outre le numéro, il faut mettre dans chaque paquet deux booléens : RET indique un paquet renvoyé à l'expéditeur car non distribuable, et DUP indique une retransmission, au moins un essai ayant apparemment échoué. Comme le paquet a pu être distribué quand même (même si le routeur émetteur n'a pas été notifié), DUP sert à indiquer la possibilité de duplication d'un paquet, avec laquelle les couches hautes vont devoir se débrouiller.

Rien ne garantit que le réseau soit un arbre pur. Des boucles sont parfaitement possibles et DFF doit les détecter. Ces booléens RET et DUP permettent notamment de distinguer un paquet délibérement renvoyé à l'émetteur d'un paquet qui boucle dans le réseau. Si le routeur reçoit un paquet qu'il a déjà transmis (il le sait d'après le numéro), avec DUP et RET tous les deux à Zéro, c'est que le paquet est en train de boucler. Si RET est à Un, c'est un retour délibéré car le routeur suivant n'a pas pu transmettre le paquet.

Le format exact des paquets figure en section 7. Le traitement des paquets par les routeurs est détaillé en sections 10 et 11 du RFC. Des examples de fonctionnement de DFF dans diverses topologies, et pour divers cas de figure, se trouvent dans l'annexe A.

Notez que, comme la plupart des protocoles conçus pour ce type de réseau (sans administrateur réseaux, et où il y a beaucoup de machines, qu'il n'est pas question de configurer une par une), DFF ne présente guère de sécurité. Par exemple, en envoyant beaucoup de paquets à une adresse inexistante, on force les routeurs à retenir ces paquets en mémoire le temps de détecter la non-délivrabilité, réalisant ainsi facilement une attaque par déni de service (section 16.3.1).

Maintenant, il reste à tester DFF en vrai, et à récolter de l'information sur les points détaillés en section 1.2 : quelles sont les bonnes valeurs pour le délai d'attente P_HOLD_TIME (trop long, et on consomme de la mémoire sur les routeurs, qui doivent se souvenir du paquet, trop court, on risque d'oublier un paquet et de le croire nouveau lorsqu'il revient après un échec, cf. section 8) ? Et les valeurs idéales pour le nombre de sauts maximum MAX_HOP_LIMIT ? Et l'interaction idéale entre DFF et les protocoles de routage ? Tous ces points vont devoir être étudiés en pratique.

L'annexe B du RFC rassemble un certain nombre d'informations sur le déploiement effectif de DFF et ses mises en œuvre (au moins deux à l'heure actuelle, une sur 802.11 et une sur 802.15.4). Par exemple, les compteurs électriques de la smart grid au Japon utilisent apparemment DFF mais les détails n'ont pas été publiés. Un autre distributeur d'électricité qui utilise DFF est la Kit Carson Electric Cooperative au Nouveau-Mexique, qui en a http://www.kitcarson.com/index.php?option=com_content&view=article&id=45&Itemid=1fait état publiquement. Une mise en œuvre en logiciel libre de DFF en Java a été annoncée par Fujitsu mais apparemment pas encore publiée (en tout cas, je ne l'ai pas trouvée).

Merci à Laurent Toutain pour sa relecture et ses remarques pertinentes sur l'algorithme DFF.


Téléchargez le RFC 6971


L'article seul

RFC 6956: ForCES Logical Function Block (LFB) Library

Date de publication du RFC : Juin 2013
Auteur(s) du RFC : W. Wang (Zhejiang Gongshang University), E. Haleplidis (University of Patras), K. Ogawa (NTT Corporation), C. Li (Hangzhou DPtech), J. Halpern (Ericsson)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF forces
Première rédaction de cet article le 29 juin 2013


Le protocole ForCES vise à permettre la création d'équipements réseaux (par exemple des routeurs) en assemblant des pièces d'origines diverses, parlant un protocole commun et pouvant donc interagir. Ce RFC marque l'achèvement de la première (et très longue) phase de ForCES, la normalisation complète de ce protocole. Notre RFC 6956 décrit la bibliothèque standard de ForCES, les parties d'un routeur qu'on trouvera partout et qui assurent les fonctions indispensables comme faire suivre un paquet IP.

ForCES peut servir à bien d'autres choses et il y aura aussi des bibliothèques pour d'autres équipements que les routeurs, et aussi des bibliothèques non-standard, développées par tel ou tel projet. Mais pour atteindre l'objectif premier de ForCES, créer un routeur par assemblage de pièces standards, cette bibliothèque « routeur » était le dernier élement manquant.

Avant de lire ce RFC 6956, il faut bien se pénétrer du cadre général (RFC 3746), du protocole (RFC 5810) et du modèle de données (RFC 5812). J'en extrais quelques termes qu'il faut connaître :

  • NE ou Network Element, l'engin complet (un routeur, un commutateur, etc).
  • CE ou Control Element, la partie du NE qui fait tourner les protocoles de contrôle et de signalisation (pour un routeur, OSPF, BGP, etc).
  • FE ou Forwarding Element, la partie de l'engin qui traite les paquets (pour un routeur, qui les fait suivre d'une interface à l'autre). CE et FE se parlent en suivant le protocole ForCES. Un NE comprend au moins un CE et un FE.
  • LFB ou Logical Function Block, c'est le concept qui fait l'objet de ce RFC. Un LFB est une fonction d'un FE, contrôlée par le CE. Un FE typique met en œuvre plusieurs fonctions (par exemple : faire suivre les paquets, filtrer les paquets, compter les paquets et chacune de ces trois fonctions est représentée par un LFB). Un CE typique va donc utiliser le protocole ForCES pour configurer les LFB (« arrête de faire suivre les paquets », « coupe l'interface Ethernet/0/2 », etc). Un LFB est une fonction logique : dans la matériel, on ne retrouve pas forcément ce concept.
  • Classe de LFB et instance de LFB sont des concepts empruntés à la programmation objet. L'idée est qu'on définit des classes de LFB et que le LFB dans un FE donné est une instance d'une de ces classes.
  • Un « port » dans ce RFC est une interface physique du routeur.

La bibliothèque composée des classes définies dans ce RFC 6956 permet de réaliser un routeur complet, mettant en œuvre toutes les fonctions obligatoires du RFC 1812, notamment :

  • Encapsuler et décapsuler les paquets pour la couche 2 (Ethernet, par exemple),
  • Envoyer et recevoir des paquets de taille allant jusqu'à la MTU du lien, fragmenter les autres (pour IPv4),
  • Traduire les adresses IP en adresses de la couche 2 (par exemple avec ARP),
  • Gérer ICMP, et notamment créer et envoyer les messages d'erreur ICMP en réponse à des problèmes, ou bien lorsque le TTL tombe à zéro,
  • Gérer les tampons d'entrée/sortie, la congestion, un juste traitement des différents paquets,
  • Trouver le routeur suivant (next hop) lorsqu'il faut transmettre un paquet,
  • Être capable de faire tourner un IGP comme OSPF, dans certains cas un EGP comme BGP, et accepter évidemment de simples routes statiques,
  • Avoir toutes les fonctions de gestion du réseau qu'on attend : statistiques, débogage, journalisation...

Place maintenant au cœur de ce RFC, les classes qui y sont définies. Le choix du groupe de travail forces (section 3.2) a été de privilégier la souplesse en définissant plutôt trop de classes que pas assez. Chaque classe ne va donc effectuer qu'un minimum de fonctions, être logiquement séparée des autres classes et notre routeur devra donc mettre en œuvre beaucoup de classes. Cela rend donc le RFC très long et je ne vais donc pas parler de toutes les classes, seulement de quelques unes choisies comme exemples. Pour la totalité des classes, vous devez lire le RFC.

Les définitions des classes s'appuient sur un certain nombre de types définis en section 4. Le RFC 5812 avait normalisé les types de base comme uint32, char ou boolean. Notre RFC y ajoute quelques types atomiques comme IPv4Addr, IPv6Addr, IEEEMAC (une adresse MAC), PortStatusType (permettant d'indiquer si le port est activé ou non et s'il fonctionne), VlanIDType pour le numéro de VLAN, etc. Il définit également des types composés comme MACInStatsType (une entrée dans le tableau de statistiques pour les paquets entrants, analysés à la couche 2), IPv6PrefixInfoType (un préfixe IPv6), IPv4UcastLPMStatsType (une entrée dans le tableau de statistiques pour les paquets IPv4), etc. Logiquement, les tableaux qui utilisent ces types sont également définis comme IPv6PrefixTableType (un tableau de préfixes IPv6) ou VlanInputTableType (un tableau de VLAN).

Un NE manipule des paquets donc il y a évidemment des types de paquets parmi lesquels EthernetII, IPv4, IPv6, et même Arbitrary pour des paquets quelconques.

Le tout est formellement décrit en XML dans la section 4.4. Ainsi, une adresse IPv4 est :


<dataTypeDef>
         <name>IPv4Addr</name>
         <synopsis>IPv4 address</synopsis>
         <typeRef>byte[4]</typeRef>
</dataTypeDef>

et une IPv6 est :


<dataTypeDef>
         <name>IPv6Addr</name>
         <synopsis>IPv6 address</synopsis>
         <typeRef>byte[16]</typeRef>
</dataTypeDef>

Un type atomique comme la capacité du lien est définie par :


<dataTypeDef>
        <name>LANSpeedType</name>
        <synopsis>LAN speed type</synopsis>
        <atomic>
         <baseType>uint32</baseType>
         <specialValues>
           <specialValue value="0x00000001">
            <name>LAN_SPEED_10M</name>
            <synopsis>10M Ethernet</synopsis>
           </specialValue>
           <specialValue value="0x00000002">
            <name>LAN_SPEED_100M</name>
            <synopsis>100M Ethernet</synopsis>
           </specialValue>
...

Même chose pour le PortStatusType mentionné plus haut :


<dataTypeDef>
        <name>PortStatusType</name>
        <synopsis>
          Type for port status, used for both administrative and
          operative status.
        </synopsis>
        <atomic>
         <baseType>uchar</baseType>
         <specialValues>
           <specialValue value="0">
            <name>Disabled</name>
            <synopsis>Port disabled</synopsis>
           </specialValue>
           <specialValue value="1">
            <name>Up</name>
            <synopsis>Port up</synopsis>
           </specialValue>
           <specialValue value="2">
            <name>Down</name>
            <synopsis>Port down</synopsis>
           </specialValue>
         </specialValues>
        </atomic>
      </dataTypeDef>
<dataTypeDef>

Et les types structurés ? Un exemple est celui des statistiques sur les paquets sortants, qui a deux composants (les champs des objets), un pour les paquets transmis et un pour les paquets jetés :


<dataTypeDef>
         <name>MACOutStatsType</name>
         <synopsis>
           Data type defined for statistics in EtherMACOut LFB.
         </synopsis>
         <struct>
            <component componentID="1">
               <name>NumPacketsTransmitted</name>
               <synopsis>Number of packets transmitted</synopsis>
               <typeRef>uint64</typeRef>
            </component>
            <component componentID="2">
               <name>NumPacketsDropped</name>
               <synopsis>Number of packets dropped</synopsis>
               <typeRef>uint64</typeRef>
            </component>
         </struct>
</dataTypeDef>

Un autre exemple est le préfixe IPv6, qui réutilise le type atomique IPv6Addr :


<dataTypeDef>
         <name>IPv6PrefixInfoType</name>
         <synopsis>Data type for entry of IPv6 longest prefix match
          table in IPv6UcastLPM LFB. The destination IPv6 address
          of every input packet is used as a search key to look up
          the table to find out a next hop selector.</synopsis>
         <struct>
            <component componentID="1">
               <name>IPv6Address</name>
               <synopsis>The destination IPv6 address</synopsis>
               <typeRef>IPv6Addr</typeRef>
            </component>
            <component componentID="2">
               <name>Prefixlen</name>
               <synopsis>The prefix length</synopsis>
               <atomic>
                  <baseType>uchar</baseType>
                  <rangeRestriction>
                     <allowedRange min="0" max="32"/>
                  </rangeRestriction>
               </atomic>
            </component>
...

Une fois tous ces types définis (et cela prend un bon bout du RFC), on peut les utiliser pour bâtir les classes (section 5). Chaque classe va être un gabarit dont on tirera les instances. Premier exemple : notre routeur ForCES va évidemment avoir besoin de connaître Ethernet et de traiter des paquets Ethernet, en envoi et en réception. Ethernet étant très varié, commençons par un LFB (Logical Function Block) qui représente le niveau physique, EtherPHYCop. Ce LFB (cette partie logique d'un routeur) a des composants pour indiquer l'état du port (AdminStatus et OperStatus), composants qui peuvent être lus et modifiés via le protocole ForCES. Ce LFB peut aussi générer des événements comme par exemple le changement d'état d'un port (PHYPortStatusChanged).

Au niveau au dessus (couche 2), il y a le LFB EtherMACIn. C'est par exemple là que se trouve le composant LocalMACAddresses qui indique l'adresse MAC. ou bien le composant PromiscuousMode qui dit si on veut recevoir (ou pas) tous les paquets, même adressés à une autre machine.

Rappelez-vous : cette bibliothèque standard de ForCES privilégie la souplesse, et crée donc beaucoup de LFB, pour pouvoir les arranger comme souhaité. Rien que pour Ethernet, il y en a encore plusieurs comme EtherEncap qui modélise les fonctions d'encapsulation et de décapsulation des trames (ajout ou retrait des en-têtes Ethernet).

Mais on ne peut pas passer toute la journée sur les couches basses. Pour « construire » un routeur par assemblage de LFB, il nous faut maintenant des fonctions de manipulation d'IP. C'est le cas du LFB IPv6Validator qui représente les fonctions de validation d'un paquet (avant qu'on décide de le traiter, ou de le jeter s'il est invalide). On suit le RFC 2460 et on considère comme invalide (ne devant pas être transmis) les paquets ayant une taile inférieure à la taille minimale, les paquets ayant une adresse source ou destination inacceptable, etc. Il y a aussi des paquets nommés « exceptionnels » qui, sans être à proprement parler invalides, ne pourront pas être transmis normalement (par exemple ceux avec un hop limit descendu à zéro).

Et, ensuite, le travail sera fait par les LFB de transmission. Oui, ils sont plusieurs. Pour IPv6, au moins IPv6UcastLPM (trouver le LPM, Longest Prefix Match, dans la table) et IPv6NextHop (sélection du routeur suivant), sans compter des futurs LFB optionnels, par exemple pour mettre en œuvre RPF.

Les LFB sont eux aussi formalisés en XML (section 6). Par exemple, le dernier que nous avons vu, IPv6NextHop, sera :


      <LFBClassDef LFBClassID="13">
         <name>IPv6NextHop</name>
         <synopsis>
           The LFB abstracts the process of next hop information
           application to IPv6 packets. It receives an IPv6 packet
           with an associated next hop identifier (HopSelector),
           uses the identifier as a table index to look up a next hop
           table to find an appropriate output port.
         </synopsis>
         <inputPorts>
            <inputPort group="false">
               <name>PktsIn</name>
               <synopsis>
                 A port for input of unicast IPv6 packets, along with
                 a HopSelector metadata.
                </synopsis>
              ...
            </inputPort>
         </inputPorts>
         <outputPorts>
            ...
         </outputPorts>
         <components>
            <component componentID="1">
               <name>IPv6NextHopTable</name>
               <synopsis>
                 The IPv6NextHopTable component. A HopSelector is used
                 to match the table index to find out a row which
                 contains the next hop information result.
               </synopsis>
               <typeRef>IPv6NextHopTableType</typeRef>
            </component>
         </components>
      </LFBClassDef>

Si la tête commence à vous tourner sérieusement, c'est sans doute normal et prévu. Les auteurs du RFC ont pensé à vous et inclus une section 7 qui décrit comment on crée une fonction de haut niveau à partir des LFB de cette bibiothèque standard. Leur premier exemple est la transmission de paquets IPv4 et le dessin ne compte pas moins de treize LFB... (Dont, il est vrai, neuf juste pour Ethernet.) Pour ajouter ARP, cela prend sept LFB (certains sont communs par exemple EtherEncap est utilisé à la fois par la transmission de paquets IPv4 et par ARP).

Les classes des LFB sont désormais dans un registre IANA, ce qui permettra d'en ajouter plus facilement d'autres.

Voilà, arrivé à ce stade, on a de quoi « fabriquer » un routeur ou plus exactement de quoi le modéliser. En pratique, les vrais routeurs seront bien différents mais ils exporteront aux clients ForCES des fonctions représentées par ces LFB standards, fonctions qu'on pourra configurer avec Forces.


Téléchargez le RFC 6956


L'article seul

Un routeur de cœur de réseau peut-il espionner le trafic ?

Première rédaction de cet article le 26 juin 2013


Dans son médiatique rapport, le sénateur Bockel affirmait que « Rien n'empêcherait, en effet, un pays producteur de ce type d'équipements [les routeurs de cœur de réseau] d'y placer un dispositif de surveillance, d'interception, [..] ». Est-ce réaliste ?

Si c'est possible, alors, comme la totalité des routeurs de cœur de réseau utilise du logiciel privateur sur lequel l'utilisateur n'a aucun contrôle, on peut en effet imaginer que le gentil routeur qu'on a installé nous trahit et envoit une copie de nos messages à Pékin (Bockel, qui est un nationaliste de mauvaise foi, ne cite que les routeurs Huawei comme si les Cisco, les Juniper ou même les Alcatel tricolores n'avaient pas exactement les mêmes possibilités. Cisco va jusqu'à les documenter publiquement.) Un routeur étant un engin très complexe, une fonction supplémentaire dans son logiciel pourrait être difficile à voir.

Mais, franchement, je ne pense pas, pour des raisons de limites physiques, que ce soit réaliste. Il y a deux façons d'espionner le trafic : analyser sur le routeur et envoyer au maître espion une synthèse. Ou bien transmettre la totalité du trafic au maître qui pourra alors l'analyser.

Le premier nécessite des processeurs puissants puisqu'il faut analyser un trafic cumulé qui peut être de plusieurs Tb/s. Les routeurs typiques ont, curieusement (vu leur prix), des processeurs plutôt petits, l'essentiel du travail étant fait par des ASIC. On ne peut pas espérer faire une recherche de mots-clés avec ces processeurs. Il faudrait donc dissimuler dans le routeur des processeurs spécialisés, et espérer qu'ils ne seront jamais repérés. Or, les gens qui installent de tels routeurs les ouvrent souvent, ne serait-ce que pour installer de nouvelles cartes, et sont souvent curieux et compétents techniquement. Un tel dispositif matériel ne resterait sans doute pas longtemps secret (lisez un récit de découverte d'un tel dispositif). Et ce serait la fin des ambitions commerciales du constructeur qui serait ainsi attrapé la main dans le sac.

Notez que les fonctions d'espionnage pourraient en théorie être dans les ASIC, sur lesquels on n'a aucune information (même si tout le logiciel standard du routeur était libre). Cela affecterait toutefois leur taille et leur consommation électrique donc cela semble peu vraisemblable.

Enfin, l'arrivée de routeurs programmables (OpenFlow et autres SDN) introduit de nouvelles possibilités d'attaques : on pourrait reprogrammer le routeur pour lui faire écouter.

Je parlais ici d'une analyse complète du paquet, genre recherche plein texte, ou bien genre DPI. Mais on peut aller plus vite si on se contente d'analyser les métadonnées (comme les adresses IP de source et de destination). C'est moins riche mais, dans certains cas, cela peut être mieux que rien pour l'espion (analyse de trafic). Les routeurs savent déjà faire, avec leur matériel actuel, ce genre de travail, nécessaire pour les statistiques NetFlow (IPFIX aujourd'hui, cf. RFC 7011). Autre hypothèse, si on veut filtrer très vite le trafic, le routeur peut n'envoyer à l'espion que le trafic de/vers une adresse IP spécifique.

Dans tous les cas, une fois la synthèse faite, il faut l'envoyer au maître espion, ce qui peut être détecté (ce qui serait très gênant pour la firme qui fournit les routeurs). Une solution possible pour l'espion serait de ne pas transmettre directement les données mais indirectement, par exemple en faisant passer certains paquets envoyés par le maître et en en bloquant d'autres, selon la valeur des données qu'on veut faire sortir du routeur.

Bref, c'est peut-être possible mais avec des capacités d'espionnage plutôt limitées (officiellement, les dispositifs d'écoute légale ne sont pas prévus pour de l'écoute en masse). Est-ce de cela que parlait le rapport Bockel ? Pour les consultants en cyberpeur, cela serait certainement moins efficace de ne parler que de surveillance ciblée.

Bon, si analyser un tel trafic total en temps réel sur le routeur n'est pas possible, peut-on le transmettre en vrac afin de l'analyser tranquillement dans des centres de données où le maître espion aurait tous les moyens matériels nécessaires ? Là, on se heurte aux limites de la physique. Si un routeur a quinze interfaces à 10 Gb/s (c'est petit, pour un routeur de cœur, songez aussi que les interfaces à 100 Gb/s commencent à apparaître), il faudrait pouvoir faire passer 150 Gb/s de trafic vers Pékin ! Non seulement c'est physiquement impossible avec les interfaces réseau dont dispose le routeur, mais cela se remarquerait (tous les opérateurs regardent leur données NetFlow, c'est le cœur de leur métier).

Enfin, notons aussi que les routeurs de cœur sont chers et viennent souvent avec une offre de maintenance, voire un technicien à demeure. L'humain a certainement des possibilités d'espionnage plus élevées que le routeur...

Surtout, ce qu'oublie de dire le rapport Bockel (mais ce n'est pas un oubli : son vrai but est le protectionnisme, pas la sécurité) est que le vrai espionnage ne se fait pas par des astuces techniques sophistiquées sur les routeurs. Il se fait surtout aux extrémités, où le trafic est facilement écoutable (et pas uniquement par les Chinois, cf. PRISM, une attaque extrêmement low-tech).

Ceci dit, dans tous les cas, il est prudent, lorsqu'on fait une analyse de sécurité, de supposer que le trafic est écouté (après tout, mon analyse peut avoir des failles, ne basez pas votre sécurité uniquement sur cet article). Si ce n'est par le routeur, cela peut être par d'autres biais (on trouve même des SFP qui savent espionner). Et, donc, pensez à chiffrer tout votre trafic. C'est le B. A. BA de la confidentialité, que ce soit contre l'APL ou contre d'autres espions. Attention, cela ne protège que le voyage, la sécurité des extrémités est une autre question.

Dans un article récent d'Andréa Fradin, un autre risque est discuté, celui où une porte dérobée dans le routeur permettrait l'arrêt soudain de celui-ci, faisant ainsi une attaque par déni de service. Ce point est également mentionné dans le rapport Bockel (« voire un système permettant d'interrompre à tout moment l'ensemble des flux de communication »). Là, on ne peut rien dire. Une telle porte dérobée est techniquement possible quoique non triviale (les routeurs de cœur sont en général configurés de manière à ne pas recevoir de trafic de l'extérieur ; il faudrait donc que l'ordre vienne dans un des paquets qui transite par le routeur). Elle serait difficile à détecter puisque, comme indiqué plus haut, le logiciel des routeurs n'est pas du logiciel libre (notez que le rapport Bockel, tout occupé à voir des Chinois partout, ne mentionne pas du tout cette possibilité évidente d'améliorer la sécurité).

Il est rigolo de se dire que, compte tenu du nombre de bogues accidentelles dans les routeurs (un routeur, cela ressemble à une grosse boîte bruyante, mais en fait c'est plein de logiciel), une telle porte dérobée pourrait facilement passer pour une bogue. Cela permettrait au fabricant de nier toute action malveillante. Moins drôle, comme des mécanismes d'espionnage existent déjà dans les routeurs (cf. la documentation de Cisco citée plus haut), on pourrait imaginer un espion qui, sans avoir besoin d'instrumenter le routeur lui-même, se contente d'exploiter une fonction d'espionnage existante (celles-ci ne sont pas forcément bien protégées).

Notez qu'une telle porte dérobée pourrait être utilisée pour bien d'autres choses que d'arrêter le routeur brutalement. Elle pourrait permettre par exemple de détourner ou de jeter une partie du trafic, par exemple en tripotant les tables de routage.

Merci à Olivier Laurelli, Ollivier Robert et Jean-Baptiste Favre pour les intéressantes discussions sur « comment, lorsqu'on est Empire du Mal, mettre une porte dérobée dans un routeur ». Merci à Frédéric Gander, Emmanuel Thierry, Alex Archambault, Thomas Mangin, Julien Rabier, Alexandre Dulaunoy, Phil Regnauld et Jérôme Nicolle pour d'utiles critiques et ajouts à cet article. À noter que j'ai eu aussi des messages privés de gens travaillant pour des fabricants de routeurs ou des opérateurs de télécommunications ne souhaitant pas que leur nom soit publié. Donc, merci aux anonymes.


L'article seul

La fracture numérique en Afrique, supervision de l'Université de Yaoundé

Première rédaction de cet article le 25 juin 2013


Lorsqu'on parle de fracture numérique en Afrique, on pense souvent à l'absence de connectivité Internet dans certains endroits. Mais, une fois que le réseau marche, la fracture n'est pas réparée. Il reste le problème de la qualité et notamment de la fiabilité de ce réseau. Une supervision automatique de la connectivité de l'Université de Yaoundé montre l'ampleur du problème.

Le phénomène n'est pas forcément bien connu car il y a peu de supervision réseau en Afrique (encore un effet de la fracture numérique). C'est ainsi qu'il n'y a que 17 sondes Atlas opérationnelles en Afrique (sur 3 358 aujourd'hui). L'une d'elles est située à l'Université de Yaoundé et est supervisée automatiquement depuis une sonde Icinga en France. La dite sonde est bien connectée et ne voit pas de problème avec d'autres destinations. (Détail technique : la sonde a une adresse IP privée et c'est en fait le routeur NAT qu'on supervise.)

Pour éviter des alarmes permanentes (la plaie des systèmes de supervision, qui fait qu'on en vient souvent à ne plus prêter attention aux alarmes), j'ai dû mettre des paramètres extrêmement laxistes. La configuration Icinga est :

define service{
        use                             generic-service        
        host_name                       yaounde
        service_description             PING4
         # L'Afrique est loin...
        check_command                   check_ping4!400.0,50%!700.0,65%
        }

C'est à dire qu'on ne passe en état WARNING que si le RTT dépasse 400 ms ou si le taux de pertes dépasse 50 %. Et en état CRITICAL uniquement si on a > 700 ms de RTT ou > 65 % de pertes... Malgré ces valeurs fort tolérantes, le journal d'Icinga montre plein de problèmes :

[1372069221] SERVICE ALERT: yaounde;PING4;CRITICAL;SOFT;1;PING CRITICAL - Packet loss = 70%, RTA = 165.12 ms
[1372074141] SERVICE ALERT: yaounde;PING4;WARNING;SOFT;1;PING WARNING - Packet loss = 60%, RTA = 164.65 ms
[1372076061] SERVICE ALERT: yaounde;PING4;WARNING;SOFT;1;PING WARNING - Packet loss = 60%, RTA = 164.53 ms

Et le joli graphique des tendances d'Icinga (sur le dernier mois) contient bien trop de rouge : yaounde-icinga.png

J'ai donc dû arrêter la supervision de cette machine : trop d'alarmes tue l'alarme. Mais, la prochaine fois que vous entendrez parler de fracture numérique en Afrique, pensez aux conditions d'accès réelles (et dans la capitale, pas au fin fond de la brousse), et pas aux jolies images publicitaires d'un Africain heureux avec son nouveau téléphone portable.


L'article seul

Exposé sur les réseaux sociaux « alternatifs » à Pas Sage en Seine

Première rédaction de cet article le 24 juin 2013


Le 23 juin, au festival Pas Sage en Seine, j'ai eu le plaisir de parler sur les projets de réseaux sociaux alternatifs (vous savez, les trucs comme Diaspora ou status.net). Pourquoi sont-ils des échecs ? Comment faire mieux la prochaine fois ?

Mon résumé était : « Une critique des innombrables projets d'un Twitter libre, d'un DNS pair-à-pair ou d'un Facebook éthique, en pointant du doigt la distance entre l'intérêt que suscitent ces projets et la réalité du travail effectué. Souvent, le projet n'a pas dépassé le stade « dos de l'enveloppe » qu'il a déjà une page Web drôlement sophistiquée, et qu'il suscite d'innombrables discussions sur les rézosocios®. Bref, du vaporware. Parfois, le projet est plus sérieux (Diaspora) mais ne tient aucun compte de l'existant (il existe des tas de systèmes fédérés, comme SMTP et XMPP, mais les diasporistes les ignoraient systématiquement) et produit finalement quelque chose de très insuffisant par rapport à l'ampleur de la tâche (être sans scrupule ne suffit pas pour devenir Zuckerberg, il faut aussi bosser). Enfin, dans certains cas, le projet tourne (status.net) mais ne rencontre aucun succès en partie par refus de considérer les problèmes vraiment durs (dans le cas de status.net, la question des identifiants). »

Voici les supports de l'exposé :

Pour une vidéo de la causerie, c'est par ici. Il y a eu une longue discussion sur LinuxFr (avec pas mal de gros mots, dommage). Pour des jolies photos de cette édition de Pas Sage en Seine, allez ici.

Je ne connaissais pas à l'époque l'article « A Critical Look at Decentralized Personal Data Architectures » qui explore les mêmes thèmes et est, sur certains points, plus approfondi. Mon résumé et mes critiques de cet article sont sur Seenthis.


L'article seul

Le cours « Hacking IPv6 »

Première rédaction de cet article le 20 juin 2013


Cette semaine, j'ai eu le plaisir de suivre le cours « Hacking IPv6 » de Fernando Gont lors de Hack in Paris à Disneyland. C'est l'occasion de partager quelques-unes de mes notes de cours. (Les supports de cours ne sont pas encore publiquement disponibles.)

Gont est l'auteur de plusieurs excellents RFC sur la sécurité. La tonalité générale de son cours était plutôt méfiante vis-à-vis d'IPv6, il s'est notamment attaqué à des mythes comme celui selon lequel IPv6 serait plus sûr car IPsec y est obligatoire (cela n'a jamais été vrai en pratique et cela n'est même plus le cas en théorie depuis le RFC 6434). Il a également noté la faiblesse en ressources humaines (peu de compétences disponibles) mais il a oublié de dire que c'était pareil chez les attaquants. Faites l'expérience (comme moi), mettez un pot de miel accessible uniquement en IPv6 et vous verrez que personne ne l'attaque (alors que les mouches affluent immédiatement sur tout pot de miel IPv4). Dans le monde réel (pas dans les conférences de hackers), les attaques via IPv6 sont en quantité négligeable et, à mon avis, ne représentent pas une raison sérieuse de retarder la migration. Gont a un point de vue différent, comme quoi il faudrait avoir un bon niveau de sécurité avant de migrer. Il note que les HOWTO « comment migrer vers IPv6 en cinq minutes » sont dangereux car ils laissent le réseau migré vulnérable. Selon moi, avec un tel argument, on n'aurait jamais déployé IPv4...

Mais Gont note aussi que, non seulement la migration est inévitable, mais qu'elle a déjà commencé. Ainsi, beaucoup de systèmes d'exploitation ayant IPv6 activé par défaut, bien des réseaux ont déjà IPv6 sans le savoir et, grâce à Teredo, ont même parfois une connectivité externe (« There are no IPv4-only networks »). Donc, qu'on veuille migrer ou pas, il faut se préoccuper de la sécurité sur IPv6.

L'essentiel de la partie pratique du cours se faisait avec deux boîtes à outils :

  • La plus ancienne, THC-IPv6, qui ne marche que sur Linux et que sur Ethernet et dont Gont trouve la documentation plutôt limitée,
  • Celle du formateur, SI6 toolkit, distribuée sous GPL.

Les exemples ci-dessous utilisent en général les outils d'une de ces deux boîtes.

Le cours suit classiquement le modèle en couches. On part de la couche 2. Normalement, dans Ethernet, le type de protocole utilisé figure dans l'en-tête Ethernet mais, en théorie, on pourrait imaginer un attaquant mettant des paquets IPv6 avec un en-tête Ethernet indiquant ces paquets comme étant IPv4, pour essayer de passer outre un filtrage dans les commutateurs. En pratique, cette attaque ne marche pas, tous les systèmes testés vérifient que les deux types correspondent. Premier hack raté.

Ensuite, la couche 3, le gros morceau du cours. Chaque champ de l'en-tête IPv6 est examiné. Par exemple, le peu connu Flow label avait été conçu pour ne pas avoir à suivre la chaîne des en-têtes (opération très complexe) pour découvrir les paquets du même flot. En pratique, peu de systèmes s'en servent (il est souvent à zéro et, dans ce cas, tcpdump ne l'affiche pas) mais il peut être utilisé par l'attaquant, par exemple pour découvrir le rythme de création de nouvelles connexions par une machine. L'outil flow6 dans la boîte SI6 permet de connaître la politique utilisée (ici, contre un système Linux) :

# flow6 -i eth1 -v --flow-label-policy -d 2001:db8:8ad9:84b1:ba27:ebff:feba:9094                                                                    
...
Identifying the 'Flow ID' generation policy of the target node....
Flow Label policy: Global (predictable) constant labels, set to 00000

On voit que ce système met toujours le flow label à zéro. Contre un système FreeBSD :

# flow6 -i eth0 -v --flow-label-policy -d 2001:1900:2254:206a::50:0
...
Identifying the 'Flow ID' generation policy of the target node....
Flow Label policy: Global (predictable) labels with increments of 2202551761 (sdev: 0.500000)

Cette fois, le flow label est mis et est prévisible, donnant accès à des informations utiles. Avec tcpdump, on voit ce champ, s'il n'est pas nul (il vaut ici 0xaa187) :

12:28:58.432511 IP6 (flowlabel 0xaa187, hlim 57, next-header TCP (6) payload length: 40) 
     2001:41d0:1:ea44::1. 42700 > 2001:4b98:dc0:41:216:3eff:fece:1902.80: 
     Flags [S], cksum 0x9850 (correct), seq 1485994586, win 65535,
      options [mss 1440,nop,wscale 3,sackOK,TS val 181079131 ecr 0], length 0

Cet outil, sur certains réseaux (peut-être ceux ayant plus d'un routeur), dit parfois Couldn't find local router mais cette bogue n'est pas encore résolue.

Autre chose amusante dans IPv6 : au lieu d'avoir un en-tête de taille variable, comme IPv4 (avec un champ qui indique la taille de l'en-tête, qui change selon les options IP incluses), IPv6 a un en-tête de taille fixe, puis zéro, un ou davantage d'en-têtes d'extension. Par exemple, si le paquet est fragmenté, un en-tête d'extension Fragment header va être mis. L'un des problèmes que posent ces en-têtes d'extension est que les paquets qui les portent sont souvent jetés sans cérémonie par des routeurs ou des pare-feux violents. Si ce n'est pas le cas, comme leur présence décale tous les champs suivants (comme l'en-tête TCP, avec ses numéros de port), ils peuvent être utilisés pour échapper à des IDS naïfs, qui attendent ces numéros de port à un décalage fixe. (Par exemple, si on utilise le module u32 de Netfilter.)

Une attaque en IPv4 commence souvent par un balayage (scan) du réseau visé pour trouver des machines intéressantes. En IPv4, il y a au maximum 2^32 adresses et balayer tout le réseau est très court (on peut même balayer tout l'Internet IPv4 relativement facilement). Les outils de hack habituels savent faire cela sans mal (par exemple nmap qui peut prendre comme cible une adresse mais aussi un préfixe entier). En IPv6, 2^128 adresses est un nombre énorme qui défie l'imagination. Est-ce que cela rend le balayage impossible ? Non, comme l'a montré un article fameux de David Malone et les RFC 5157 et RFC 7707. Malone a vu que les adresses IPv6 ne sont pas réparties au hasard dans l'espace de 128 bits. Pour reprendre son vocabulaire, certaines adresses sont low-byte (2001:db8:67a::1), certaines wordy (2001:db8:67a::dead:beef), certaines port-based (un serveur HTTP en 2001:db8:67a::80). Si nmap ne met pas en œuvre les techniques suggérées par le RFC 7707, l'outil scan6 de la boîte SI6 le fait. Mais d'abord, un truc simple, pinguer l'adresse multicast de toutes les machines du réseau local :

% ping6 -I eth0 ff02::1
PING ff02::1(ff02::1) from fe80::ba27:ebff:feba:9094 eth0: 56 data bytes
64 bytes from fe80::ba27:ebff:feba:9094: icmp_seq=1 ttl=64 time=0.232 ms
64 bytes from fe80::f6ca:e5ff:fe4d:1f41: icmp_seq=1 ttl=64 time=0.809 ms (DUP!)
64 bytes from fe80::a2f3:c1ff:fec4:5b6e: icmp_seq=1 ttl=64 time=1.77 ms (DUP!)
64 bytes from fe80::f6ec:38ff:fef0:d6f9: icmp_seq=1 ttl=64 time=8.21 ms (DUP!)
64 bytes from fe80::223:8bff:fec9:48f2: icmp_seq=1 ttl=64 time=13.0 ms (DUP!)
64 bytes from fe80::215:afff:fe7d:3de5: icmp_seq=1 ttl=64 time=172 ms (DUP!)

On découvre ainsi bien des machines, sans dépendre de la façon dont leurs adresses sont affectées. Windows ne répond pas à ces paquets donc, ensuite, il faut passer à scan6 qui utilise une combinaison de trucs (par exemple d'envoyer des paquets avec une option IP inconnue, Windows, suivant la norme, répond alors qu'il ne connait pas) :

# scan6 -i eth1 -L
fe80::1a03:73ff:fe66:e568
fe80::f6ec:38ff:fef0:d6f9
fe80::a2f3:c1ff:fec4:5b6e
fe80::f6ca:e5ff:fe4d:1f41
fe80::ba27:ebff:feba:9094
fe80::223:8bff:fec9:48f2
fe80::215:afff:fe7d:3de5

(Vous avez noté la nouvelle, la fe80::1a03:73ff:fe66:e568 ?) scan6 a plein d'options utiles, par exemple d'afficher les adresses globales (et non plus locales au lien), et les adresses MAC :

# scan6 -i eth1 -L -e --print-type global
2001:db8:8ad9:84b1:7111:869b:5081:e0ed @ 18:03:73:66:e5:68
2001:db8:8ad9:84b1:: @ f4:ca:e5:4d:1f:41
2001:db8:8ad9:84b1:f6ec:38ff:fef0:d6f8 @ f4:ec:38:f0:d6:f8
2001:db8:8ad9:84b1:a2f3:c1ff:fec4:5b6e @ a0:f3:c1:c4:5b:6e
2001:db8:8ad9:84b1:ba27:ebff:feba:9094 @ b8:27:eb:ba:90:94
2001:db8:8ad9:84b1:223:8bff:fec9:48f2 @ 00:23:8b:c9:48:f2
2001:db8:8ad9:84b1:e4:323a:3c73:c537 @ 00:15:af:7d:3d:e5

Cette technique ne marche que sur le réseau local. Mais scan6 peut faire mieux. Revenons à la classification de Malone un instant. Dans la même boîte à outils, address6 prend une adresse IP et détermine son type :

% address6 -a  2001:7fe::80
unicast=global=global=embedded-port=unspecified

% address6 -a  2001:7fe::1
unicast=global=global=low-byte=unspecified

% address6 -a   2001:db8:2:25e::bad:dcaf
unicast=global=global=embedded-ipv4=unspecified

% address6 -a  2001:db8:8ad9:84b1:ba27:ebff:feba:9094
unicast=global=global=ieee-derived=b8-27-eb

% address6 -a  2001:db8:8ad9:84b1:7111:869b:5081:e0ed
unicast=global=global=randomized=unspecified

(Notez l'erreur de classification dans la troisième, qui aurait dû être marquée wordy.) Pour les adresses IP dérivées de l'adresse MAC, on n'a plus qu'à chercher dans les bases de préfixes MAC pour savoir que la quatrième adresse appartient à un Raspberry Pi. Enfin, la cinquième adresse est une adresse temporaire (pour préserver la vie privée) du RFC 8981.

address6 peut aussi travailler sur un ensemble d'adresses, pour en tirer des statistiques. Ainsi, si je regarde les lecteurs IPv6 de ce blog (une population dont je ne prétends pas qu'elle soit représentative de tout l'Internet) :

% zgrep -h -E  '^[0-9]+:' /var/log/apache2/access.log.2.gz /var/log/apache2/access.log.3.gz \
       /var/log/apache2/access.log.1 /var/log/apache2/access.log |\
   awk '{print $1}' | sort | uniq | address6 -i -s
...
** IPv6 Interface IDs **

Total IIDs analyzed: 172
IEEE-based:      27 (15.70%)            Low-byte:             46 (26.74%)
Embed-IPv4:      10 (5.81%)             Embed-IPv4 (64):       7 (4.07%)
Embed-port:       2 (1.16%)             Embed-port (r):        0 (0.00%)
ISATAP:           0 (0.00%)             Byte-pattern:          2 (1.16%)
Randomized:      78 (45.35%)

Contrairement aux résultats de Malone en 2008, on voit une majorité d'adresses temporaires pseudo-aléatoires (RFC 8981). La sécurité progresse donc (une étude analogue sur les clients du site Web de l'ISOC a montré la même chose). Ici, il s'agit de clients HTTP donc probablement des machines individuelles. Si on teste sur un tout autre échantillon, les serveurs de noms des TLD, on a un résultat bien différent :

% grep : root.zone | awk '{print $5}' | sort | uniq | address6 -i -s
...
** IPv6 Interface IDs **

Total IIDs analyzed: 486
IEEE-based:       2 (0.41%)             Low-byte:            350 (72.02%)
Embed-IPv4:       7 (1.44%)             Embed-IPv4 (64):      56 (11.52%)
Embed-port:      62 (12.76%)            Embed-port (r):        0 (0.00%)
ISATAP:           0 (0.00%)             Byte-pattern:          6 (1.23%)
Randomized:       3 (0.62%)

On a cette fois une grande majorité de low byte et de embedded port (beaucoup de ces serveurs ont une adresse IPv6 se terminant par ::53). C'est normal, ces serveurs sont publics, ils n'ont pas à se cacher. Même chose lorsqu'on fait tourner address6 sur des listes comme celle des serveurs Alexa. Et sur des machines qui sont parfois des clients finaux et parfois des serveurs, les résolveurs DNS qui interrogent d.nic.fr, un serveur de .fr ? Le résultat est logiquement entre les deux :

** IPv6 Interface IDs **

Total IIDs analyzed: 8756
IEEE-based:    1825 (20.84%)            Low-byte:           4570 (52.19%)
Embed-IPv4:      79 (0.90%)             Embed-IPv4 (64):     211 (2.41%)
Embed-port:     135 (1.54%)             Embed-port (r):       28 (0.32%)
ISATAP:           0 (0.00%)             Byte-pattern:         82 (0.94%)
Randomized:    1826 (20.85%)

Armé de cette connaissance, on peut revenir au problème du balayage. En IPv4, l'espace est tellement petit que l'algorithme le plus simple (la force brute) est le meilleur. En IPv6, il faut être plus subtil. À la bataille navale, on n'essaie pas toutes les cases séquentiellement. On ne le fait pas non plus aléatoirement. On frappe en fonction des règles qu'on connait sur les bateaux et leurs positions. C'est ce que fait scan6, qui peut balayer un réseau distant avec plus d'intelligence que les balayeurs IPv4. Un avertissement toutefois : en pratique, je trouve les résultats décevants. Comme l'explique le RFC 7707, le balayage est possible en IPv6. Mais il est lent, laborieux, et pas toujours réussi. Voici un exemple qui a marché :

# scan6 -v -i eth1 -d 2001:db8:2:25e::/64 
Target address ranges (1)
2001:db8:2:25e:0-ffff:0-ffff:0-ffff:0-ffff

Alive nodes:
2001:db8:2:25e::42
...

Mais, en pratique, outre une patience d'ange, vous aurez souvent besoin d'aider l'outil. Par exemple, si vous connaissez le type de cartes Ethernet utilisé (beaucoup d'entreprises utilisent un seul modèle d'ordinateurs et donc peu de modèles de cartes), vous pouvez guider l'outil avec cette information (-K Apple pour se limiter aux ordinateurs Apple, -k 52:54:00 pour une plate-forme de virtualisation, où on connait le préfixe utilisé pour numéroter les cartes). Vous pouvez également guider scan6 avec des options comme --tgt-low-byte (ne chercher que les adresses de type low byte) :

# scan6 -i eth1 -v -d fc00:675:ab4:2::/64 --tgt-low-byte -r 200pps                                                
Target address ranges (1)
fc00:675:ab4:2:0:0:0-100:0-1500

Alive nodes:
fc00:675:ab4:2::1
fc00:675:ab4:2::4:1
fc00:675:ab4:2::4:5
...

Notez que les adresses ayant les deux derniers octets non nuls sont également trouvées (mais plus lentement : scan6 commence par ce qui est facile). Notez l'intervalle testé (affiché par -v), syntaxe que vous pouvez aussi utiliser en entrée pour indiquer quelles adresses doivent être essayées. Notez aussi l'option de limitation de trafic -r 200pps. Ce n'est pas seulement pour éviter d'être détecté, c'est aussi parce qu'un trafic trop important peut dépasser les capacités du réseau en face et donc vous ralentir. Enfin, rappelez-vous qu'un balayage peut vous conduire dans un réseau taquin comme le 2404:6800:4004:802::/64toutes les adresses répondent (il n'y a certainement pas 2^64 machines, plutôt un routeur qui répond pour tout le monde).

Le code source de scan6 est également instructif. Lorsqu'on balaye, tous les paquets n'atteignent pas leur destination. Un balayeur typique va donc stocker toutes les adresses en cours de test dans un tableau, notant au fur et à mesure lesquelles ont marché. Une telle mise en œuvre serait catastrophique en IPv6 (un tableau de 2^64 entrées...). scan6 balaye donc sans redondance (un seul paquet, ne garde que les résultats positifs en mémoire), balaye une seconde fois et fusionne les résultats, et ainsi de suite.

Autre méthode pour découvrir les machines dans un réseau, par l'énumération DNS. Il « suffit » de faire des requêtes PTR pour les adresses vraisemblables (rappelez-vous bien que les adresses ne sont pas attribuées au hasard). Un outil dans la boîte THC permet cela facilement. On lui donne un résolveur DNS et un préfixe :

% dnsrevenum6 127.0.0.1 fc00:675:ab4:2::/64        
Starting DNS reverse enumeration of fc00:675:ab4:2:: on server 127.0.0.1
...
Found: fc00:675:ab4:2::4:1 is ns1.foobar.example.
...
Found: fc00:675:ab4:2::4:12 is mx4.foobar.example.
Found: fc00:675:ab4:2::4:13 is mx5.foobar.example.
...
Found: fc00:675:ab4:2::4:20 is web.foobar.example.
...

Autre problème de sécurité, le suivi d'une machine. Dès qu'on a une adresse IP stable (ou dont une partie est stable), elle peut être utilisée pour vous suivre à la trace. La solution évidente (et recommandée par le RFC 8981) est d'avoir des adresses qui ne sont pas stables, mais qui sont regenérées au hasard de temps en temps. Parfois, c'est trop radical. On peut avoir envie d'adresses stables dans le temps mais par destination (toujours la même adresse quand on parle à Google, toujours la même quand on parle à Amazon mais différente de celle utilisée pour Google, pour ne pas permettre des rapprochements). Cela peut se faire en condensant un secret local avec le préfixe de la destination (RFC 7217).

Bien, passons maintenant à un sujet toujours rigolo et qui offre plein de perspectives de bogues, la fragmentation. On peut la déclencher facilement en tenant d'envoyer 2 000 octets sur un Ethernet où la MTU est à 1 500 :

% ping6 -c 1 -s 2000  2001:5c0:1400:a::56d

% tcpdump ...
08:07:30.906552 ip: (hlim 54, next-header Fragment (44) payload length: 1240) \
        2001:db8:8ad9:84b1:ba27:ebff:feba:9094 > 2001:5c0:1400:a::56d: \
        frag (0x2fe73a49:0|1232) ICMP6, echo request, length 1232, seq 1
08:07:30.913604 ip: (hlim 54, next-header Fragment (44) payload length: 784) \
        2001:db8:8ad9:84b1:ba27:ebff:feba:9094 > 2001:5c0:1400:a::56d: \
	frag (0x2fe73a49:1232|776)

On voit les deux fragments, de 1 240 et 784 octets. Le premier contenait l'en-tête ICMP, autorisant tcpdump à afficher de l'information. Quelles sont les conséquences en sécurité ? Exactement les mêmes qu'en IPv4. Comme souvent, IPv6 étant juste une nouvelle version d'IP, les problèmes de sécurité sont très proches entre les deux versions :

  • Un attaquant peut envoyer des fragments d'un datagramme incomplet. La cible va les stocker en attendant d'avoir tout et on peut ainsi l'empêcher de recevoir les vrais paquets (le réassemblage après fragmentation ne peut pas être sans état).
  • Chaque fragment indique sa position dans le datagramme original et sa longueur (0|1232 pour le premier fragment ci-dessus et 1232|776 pour le second). Des fragments qui se recouvrent sont possibles.

Certaines attaques sont plus faciles si on peut prédire l'identificateur de fragment utilisé (0x2fe73a49 dans l'exemple ci-dessus). Cette prévisibilité permet par exemple l'idle scan où une machine fait un balayage des ports ouverts sans se révéler à la cible : le balayeur usurpe l'adresse IP source d'une tierce machine et lui demande ses identificateurs de fragment pour voir quelles réponses elle a reçu. L'outil frag6 de la boîte SI6 permet de voir si ces identificateurs sont prévisibles :

# frag6   --frag-id-policy  -i eth1 -d  2001:db8:8ad9:84b1:1a03:73ff:fe66:e568                                    
Identifying the 'Fragment ID' generation policy of the target node....
Fragment ID policy: Per-destination IDs with increments of 1 (sdev: 0.000000)

Ici (la cible est un noyau Linux 3.2), les identificateurs sont prévisibles mais pour un même pair (PDC : Per Destination Counter). frag6 teste avec deux adresses IP source différentes pour voir cela (utilisez -vv pour voir les identificateurs reçus en mono-adresse et en multi-adresses). La sécurité n'est donc pas menacée, un attaquant aveugle (non situé sur le chemin des paquets) ne peut donc pas prévoir quel sera l'identificateur du prochain fragment. Avec une machine FreeBSD, les identificateurs sont aléatoires, ce qui va aussi :

Fragment ID policy: Randomized IDs (Avg. inc.: 2497753097, sdev: 1449618001.141603)

Par contre, les anciens noyaux Linux avaient des identificateurs complètement prévisibles (compteur global et pas par destination) :

Fragment ID policy: Global IDs with increments of 1 (sdev: 0.500000)

(Attention, dès qu'il y a un routeur sur le trajet, frag6 a du mal à choisir correctement sa propre adresse IP source et vous avez intérêt à utiliser l'option -s pour l'aider).

Et les autres attaques utilisant la fragmentation ? Par exemple, pour tenter un déni de service en remplissant la table des fragments en attente de réassemblage, on peut injecter autant de fragments incomplets qu'on veut avec --flood-frags :

# frag6 -v  --flood-frags 10000  -i eth0 -l -v -d  fc00:1::a00:27ff:fef7:5cd2

Mais, désolé de vous décevoir, cela ne marche plus avec les systèmes modernes, qui gèrent leur table proprement.

Bon, maintenant, passons aux attaques contre NDP, le protocole de découverte des voisins en IPv6, normalisé dans le RFC 4861. Comme avec ARP en IPv4, rien n'est authentifié (ce qui est normal : on ne peut pas avoir à la fois sécurité et simplicité d'usage). On peut donc en théorie, lorsqu'on voit une requête neighbor solicitation, répondre à la place de la machine légitime par un neighbor advertisement avec sa propre adresse MAC (et capter ainsi tout le trafic) ou avec une adresse bidon (et faire ainsi un déni de service). Je dis « en théorie » car Fernando Gont note qu'une telle attaque marche mal. Il suggère de faire plutôt du neighbor advertisement gratuit (émis spontanément, pas en réponse à un neighbor solicitation). Attention, cela ne marche que sur le réseau local car les machines refusent les paquets NDP dont le hop limit est inférieur à 255 (cf. RFC 5082). L'outil na6 permet cela (ici, l'adresse MAC bidon 1:2:3:4:5:6) :

# na6 -i eth0 -t 2001:db8:8ad9:84b1:ba27::1 -d ff02::1 -o -E 1:2:3:4:5:6 -v -l

Notez qu'on a envoyé ce paquet NDP à toutes les machines du réseau local (-d ff02::1). Sur une machine Linux, l'entrée n'apparait pas immédiatement lors d'un ip -6 neighbor show mais, si on tente de joindre cette machine, on verra bien l'adresse MAC empoisonnée :

% ip -6 neighbor show
2001:db8:8ad9:84b1:ba27::1 dev eth0 lladdr 01:02:03:04:05:06 DELAY

(Sur un BSD, cela serait ndp -an.) Ironiquement, l'attaque par déni de service peut quand même échouer, si le commutateur relaie tous les paquets et que la machine cible a mis ses interfaces en mode promiscuous. Un attaquant qui veut lire le trafic d'une machine sans être détecté peut aussi indiquer comme adresse MAC une adresse de diffusion...

Comment combat-on cette attaque ? Une solution est de mettre des entrées statiques dans la table des voisins. (Cette technique est conseillée dans les documents remis aux participants à des conférences de sécurité comme NoSuchCon ou comme celle du CCC, documents qui indiquent l'adresse MAC du routeur officiel. Certes, c'est pour IPv4 mais rappelez-vous que le problème est exactement le même pour IPv4 et IPv6.) Sur un BSD, cela se fait avec ndp -s IPV6ADDR MACADDR et sur un Linux avec ip -6 neighbor add IPV6ADDR lladdr MACADDR dev NETWORKIFACE.

Passons maintenant à un autre protocole utilisant ICMP v6 : Router Discovery. C'est grâce à lui qu'une machine apprend le préfixe d'adresses utilisé sur le réseau, ainsi que le ou les routeurs en usage. rdisc6 (qui fait partie du paquetage ndisc6 qu'on trouve déjà fait pour tous les bons Unix) permet de voir ces informations (ici, le routeur est une Freebox) :

% rdisc6 eth0
Soliciting ff02::2 (ff02::2) on eth0...

Hop limit                 :           64 (      0x40)
Stateful address conf.    :           No
Stateful other conf.      :           No
Mobile home agent         :           No
Router preference         :       medium
Neighbor discovery proxy  :           No
Router lifetime           :         1800 (0x00000708) seconds
Reachable time            :  unspecified (0x00000000)
Retransmit time           :  unspecified (0x00000000)
 Prefix                   : 2001:db8:8ad9:84b1::/64
  On-link                 :          Yes
  Autonomous address conf.:          Yes
  Valid time              :        86400 (0x00015180) seconds
  Pref. time              :        86400 (0x00015180) seconds
 Recursive DNS server     : 2a01:e00::2
 Recursive DNS server     : 2a01:e00::1
  DNS servers lifetime    :          600 (0x00000258) seconds
 MTU                      :         1480 bytes (valid)
 Source link-layer address: F4:CA:E5:4D:1F:41
 from fe80::f6ca:e5ff:fe4d:1f41

La Freebox a donc indiqué que le préfixe de ce réseau est 2001:db8:8ad9:84b1::/64, que le routeur est elle-même, fe80::f6ca:e5ff:fe4d:1f41, qu'il y a deux résolveurs DNS (cette option est décrite dans le RFC 8106) et que la MTU est de seulement 1 480 octets (Free utilise le 6rd du RFC 5969, une technique de tunnel, qui diminue donc la MTU).

L'outil ra6 permet de générer des router advertisement de tous les genres, y compris pour une attaque (cf. RFC 6104). Par exemple, un router advertisement donnant une hop limit maximale de 1 (-s est l'adresse du routeur, qu'on va usurper) :

# ra6 -i eth1 -s fe80::f6ca:e5ff:fe4d:1f41 -d fe80::ba27:ebff:feba:9094 -c 1 -v

Lorsque fe80::ba27:ebff:feba:9094 reçoit ce paquet :

15:28:35.732604 IP6 (hlim 255, next-header ICMPv6 (58) payload length: 16) \
        fe80::f6ca:e5ff:fe4d:1f41 > fe80::ba27:ebff:feba:9094: \
        [icmp6 sum ok] ICMP6, router advertisement, length 16 \
        hop limit 1, Flags [none], pref high, router lifetime 9000s, \
        reachable time 4294967295s, retrans time 4000s

Il ne peut plus joindre les machine situées à plus d'une étape de distance :

% ping6 -n www.dns-oarc.net
...
64 bytes from 2001:4f8:3:2bc:1::8: icmp_seq=10 ttl=58 time=175 ms
64 bytes from 2001:4f8:3:2bc:1::8: icmp_seq=11 ttl=58 time=302 ms
64 bytes from 2001:4f8:3:2bc:1::8: icmp_seq=12 ttl=58 time=181 ms
From 2001:db8:8ad9:84b1:: icmp_seq=13 Time exceeded: Hop limit
From 2001:db8:8ad9:84b1:: icmp_seq=14 Time exceeded: Hop limit
From 2001:db8:8ad9:84b1:: icmp_seq=15 Time exceeded: Hop limit

ra6 permet aussi d'envoyer de faux RA (router advertisement) ayant une MTU ridiculement basse (la plupart des systèmes refuseront les valeurs trop faibles, toutefois).

Comment empêcher ces attaques neighbor discovery et router discovery ? Outre des logiciels de supervision comme NDPmon, la meilleure solution est équivalente à ce qui se fait en IPv4 : que le commutateur Ethernet refuse les paquets RA venant sur un port où il n'est pas censé y avoir de routeur. Cette solution est décrite plus en détail, sous le nom de RA Guard, dans le RFC 6105.

L'atelier de Fernando Gont couvrait également les attaques en couche 4 ou couche 7 où il y a évidemment peu ou pas de différences avec IPv4. Il y a eu aussi une discussion sur l'importance des pare-feux en IPv6 et la question de savoir si le NAT apporte de la sécurité du NAT ou pas, point sur lequel Gont conseille de ne pas tenter le diable : comme on n'est pas sûr des machines du réseau local, il vaut mieux mettre un pare-feu à état qui bloque, par défaut, les connexions entrantes. (Le RFC 6092 a un point de vue différent.)

J'ai fait moi-même un exposé (bien plus court et sans travaux pratiques) sur la sécurité d'IPv6.


L'article seul

RFC 6967: Analysis of Solution Candidates to Reveal a Host Identifier (HOST_ID) in Shared Address Deployments

Date de publication du RFC : Juin 2013
Auteur(s) du RFC : M. Boucadair (France Telecom), J. Touch (USC/ISI), P. Levis (France Telecom), R. Penno (Cisco)
Pour information
Réalisé dans le cadre du groupe de travail IETF intarea
Première rédaction de cet article le 19 juin 2013


Lorsque plusieurs machines sont situées derrière un routeur NAT, leurs pairs sur l'Internet ne peuvent pas facilement les distinguer. Tout le trafic vient de la même adresse IP, l'adresse publique allouée au routeur NAT, et c'est gênant pour certaines applications. Par contre, cela est positif d'un autre point de vue : cela fournit un certain niveau de masquage des machines individuelles, qui peut aider à protéger sa vie privée. Pris entre ces deux exigences contradictoires, l'IETF propose dans ce RFC une analyse des techniques permettant de révéler la machine individuelle derrière le routeur NAT, sans prendre position sur le fait de savoir si cette révélation est une bonne ou une mauvaise chose.

L'idée est que chaque machine a une identité unique (notée HOST_ID) et que les techniques étudiées ici doivent permettre de communiquer ce HOST_ID au pair avec qui on parle sur l'Internet. Autrefois, l'adresse IPv4 pouvait servir de HOST_ID mais cela ne marche plus désormais en raison de la prévalence du NAT. Le cas du petit routeur NAT à la maison n'est pas forcément le plus intéressant (toutes les machines appartiennent au même foyer) mais le problème est plus crucial avec les CGN, où des machines n'ayant aucun lien entre elles se partagent la même adresse IP, ce qui a des tas d'effets néfastes (RFC 6269) : impossible de mettre en liste noire la machine coupable, par exemple, sans risquer de gêner des utilisateurs n'ayant commis d'autre délit que de partager l'adresse IP d'un méchant. Même problème avec des techniques comme l'A+P du RFC 6346.

J'ai dit plus haut que le but était d'avoir des HOST_ID uniques. En fait, il doivent être uniques par adresse IP publique. Deux routeurs NAT qui utilisent des adresses IPv4 publiques différentes peuvent générer des HOST_ID identiques, seul le couple {adresse IPv4 publique, HOST_ID} a besoin d'être unique au niveau mondial (section 2 du RFC).

À ce stade, rappelez-vous que ce RFC présente un problème en terme très général et expose des solutions possibles. Par exemple, le HOST_ID peut figurer dans chaque paquet IP ou bien uniquement au début d'une session. Et il peut être ajouté par l'engin qui gère le partage d'adresse (le routeur NAT ou CGN) ou bien par la machine originale (qui pourra donc mentir, mais c'est pareil avec l'adresse IP source). Enfin, bien des identificateurs peuvent être utilisés comme HOST_ID (l'adresse IP à la source, les seize bits de poids le plus faible de l'adresse IP, un identifiant opaque compris uniquement par le FAI de départ, un VLAN ID, etc).

Une telle fonction de révélation des identités soulève évidemment des problèmes liés à la protection de la vie privée. Certains voient en effet dans le NAT des avantages en terme de sécurité comme, via le partage d'adresses, le fait que l'observateur extérieur ne puisse pas savoir quelle machine exactement, parmi toutes les machines situées derrière le routeur NAT, il est en train d'observer. En fournissant un HOST_ID à l'extérieur, on perdrait cette intimité. Notez qu'HOST__ID ramènerait juste au cas où on utilise une adresse IP publique sur sa machine, ni plus, ni moins. Notamment, un HOST_ID, comme une adresse IP publique, ne serait pas forcément permanent (lisez le RFC 8981 pour un exemple d'adresses publiques temporaires préservant la vie privée). Ainsi, une machine en redémarrant pourrait acquérir un nouvel HOST_ID.

Pour limiter les risques, ce RFC suggère deux règles : que les HOST_ID ne soient uniques que localement, pas globalement. Et qu'ils soient toujours temporaires. Cette question de la vie privée avait été la plus chaude lors des discussions à l'IETF sur le futur RFC, et le document a beaucoup évolué vers davantage de prise en compte du problème de la protection de la vie privée. Alissa Cooper, du CDT et auteure du RFC 6462 avait été particulièrement critique sur les premières versions de ce document, réclamant des modifications comme le fait que le HOST_ID ne soit pas forcément unique mondialement.

D'autre part, les logiciels qui visent à mettre en œuvre des mécanismes de dissimulation, afin de protéger la vie privée, comme Tor, supprimeront évidemment le HOST_ID, comme ils suppriment aujourd'hui d'autres informations bien plus révélatrices. Regardez le Panopticlick pour voir qu'on est facilement identifié de manière unique lorsqu'on navigue sur le Web, même derrière un routeur NAT.

La section 4 de notre RFC présente ensuite toutes les solutions étudiées pour transmettre l'HOST_ID. Certaines sont clairement mauvaises et ne sont mentionnées que pour documenter les raisons de leur rejet. D'autres méritent davantage d'étude.

D'abord, utiliser le champ Identification des paquets IP. Ce champ est surtout connu pour servir lors du réassemblage des datagrammes mais on peut théoriquement s'en servir pour « exfiltrer » de l'information sur une machine. Ce champ fait seize bits, ce qui est suffisant pour identifier une machine. Cela empêche évidemment de s'en servir pour le réassemblage après fragmentation (voir l'excellent RFC 6864 si vous voulez tout comprendre sur ce champ). Comme il n'est pas toujours facile pour le routeur NAT de garantir que les datagrammes ne seront jamais fragmentés, ni avant, ni après, cette solution est déconseillée par notre RFC.

On peut alors imaginer de définir une nouvelle option IP, conçue uniquement pour notre but d'identification, et dont l'usage n'entrerait pas en conflit avec des usages existants. Elle permettrait de transporter l'information qu'on veut. (Cela avait été documenté dans l'Internet-Draft draft-chen-intarea-v4-uid-header-option, abandonné depuis.) Cette solution, comme la précédente, a l'avantage d'être indépendante du protocole de transport. Elle pose quelques problèmes techniques (que faire si le paquet a une taille proche de la MTU et qu'on veut y ajouter cette option ? que faire si l'espace pour les options, qui a une taille maximale en IPv4, est plein ?) Mais elle a surtout comme défaut que les options IP sont souvent bloquées sur l'Internet (voir aussi « Measuring interactions between transport protocols and middleboxes » par Alberto Medina, Mark Allman et Sally Floyd). Le RFC la regarde donc comme non viable.

On peut alors monter d'une couche et choisir une nouvelle option TCP, qui indiquerait le HOST_ID. (Documenté dans l'Internet-Draft draft-wing-nat-reveal-option qui a été abandonné par la suite.) Cela aurait l'avantage qu'on n'aurait pas à la répéter dans chaque paquet mais uniquement dans le paquet SYN. Cela aiderait à résoudre les problèmes de MTU (le paquet SYN est petit). Et les mesures indiquent que les options TCP sont bien mieux respectées que les options IP sur l'Internet (voir l'article de Medina, Allman et Floyd cité plus haut, ainsi que l'Internet-Draft draft-abdo-hostid-tcpopt-implementation). Mais cette solution ne marcherait évidemment pas pour les autres protocoles de transport. Et il y a quelques problèmes techniques (une vision générale est dans l'article de Honda, M., Nishida, Y., Raiciu, C., Greenhalgh, A., Handley, M. et H. Tokuda, « Is it still possible to extend TCP? »). Par exemple, l'espace pour les options a une taille maximum dans TCP.

Si on n'a pas trouvé son bonheur dans la couche 3 (champ ID d'IP ou option IP), ni dans la couche 4 (option TCP), les couches supérieures seront-elles plus accueillantes ? Pourquoi ne pas transmettre l'information dans les applications ? Par exemple, pour HTTP, l'en-tête Forwarded: (RFC 7239) pourrait être l'endroit idéal pour cela. L'engin qui fait le partage d'adresses pourrait ainsi ajouter à la requête HTTP :

Forwarded: for=192.168.13.1

Il existait avant un en-tête non-standard, X-Forwarded-For:, dit aussi XFF, qui faisait quelque chose de ce genre. Comme les autres solutions au problème de la révélation du HOST_ID, elle permet la triche. C'est pour cela que Wikipédia maintient une liste des FAI à qui on peut faire confiance pour mettre de l'information XFF correcte. Wikipédia peut alors utiliser l'information dans ce champ pour attribuer les responsabilités (de vandalisme, par exemple, ou d'introduction délibérée d'informations fausses) à la bonne adresse IP. La principale limite de cette solution est qu'elle ne marche que pour certains protocoles, comme HTTP. Pour les autres, il faudrait au fur et à mesure concevoir une extension permettant de diffuser cette information. Même pour HTTP, elle nécessite de modifier les requêtes en cours de route, ce qui est impossible avec HTTPS.

Pour éviter de devoir développer une extension ou un en-tête spécifique par protocole applicatif, la solution PROXY a été proposée. Elle consiste à ajouter l'information juste avant les données de la couche Application. L'information a cette allure (au moment du partage d'adresses, 192.168.13.1:56324 voulait parler à 192.0.2.15:443) :

PROXY TCP4 192.168.13.1 192.0.2.15 56324 443\r\n

En la recevant, le serveur a juste à retirer cette ligne et à passer ce qui suit à l'application. En pratique, cette solution n'est pas réaliste car elle casse la compatibilité : un client qui a PROXY ne peut pas parler à un serveur qui ne l'a pas (l'opposé est vrai, par contre). Sans même parler des pare-feux qui n'accepteront pas ce qui leur semblera une requête invalide. Bref, elle n'est envisageable que dans des environnements fermés.

Le NAT tel que déployé aujourd'hui dans le monde IPv4 ne mérite pas réellement son nom. Il ne traduit pas une adresse pour une autre mais un couple {adresse, port} pour un autre. Il devrait plutôt être qualifié de NAPT (Network Address and Port Translation). Peut-on utiliser les ports alloués pour transporter l'information sur le HOST_ID ? L'idée est d'allouer un jeu de ports à chaque machine située derrière le routeur NAPT. Par exemple, imaginons trois machines derrière le routeur, celui-ci utilise les ports publics de 1 024 à 20 000 pour la première machine, de 20 001 à 40 000 pour la seconde et de 40 001 à 65 535 pour la troisième (voir l'Internet-Draft draft-donley-behave-deterministic-cgn). Il ne reste plus ensuite qu'à publier cette information à l'extérieur (le RFC est muet sur ce point). Le RFC 6346 propose une solution de ce genre. Malheureusement, cela contredit partiellement les exigences de sécurité des RFC 6056 et RFC 6269 qui demandent des ports sources imprévisibles.

Plus disruptive est la solution qui consiste à utiliser un protocole nouveau, au dessus d'IP, le protocole HIP. HIP a déjà cette notion de HOST_ID (l'identité d'une machine est une clé cryptographique, ce qui résout bien des problèmes de sécurité). Mais cela nécessite que le client et le serveur parlent HIP tous les deux, ce qui parait irréaliste. À la rigueur, si tous les serveurs parlaient HIP, le routeur NAT pourrait se contenter de prendre des requêtes non-HIP et de les traduire en HIP. Mais tous les serveurs ne parlent pas HIP, loin de là.

Bon, si on n'arrive pas à mettre le HOST_ID dans le canal normal de communication, peut-on le mettre à l'extérieur ? Par exemple, peut-on utiliser ICMP pour signaler l'adresse originale d'une communication en cours ? Dans cette idée, le routeur NAT, en même temps que le paquet TCP initial vers le serveur, enverrait une requête ICMP contenant l'information utile. Cela avait été documenté dans l'Internet-Draft draft-yourtchenko-nat-reveal-ping, qui a expiré depuis. Cela marcherait pour tous les protocoles ayant la notion de port (puisque c'est ce qu'on mettrait dans le paquet ICMP pour indiquer de quelle session on parle). Et un problème éventuel sur cette fonction de révélation de l'HOST_ID (par exemple de l'ICMP bloqué) ne gênerait pas la session normale (contrairement aux options IP ou TCP). Par contre, on n'est pas sûr que ce soit la même machine qui reçoive l'ICMP et qui reçoive les autres paquets (en cas d'utilisation de répartiteurs de charge). Et cette technique rend plus difficile l'examen de l'HOST_ID par des intermédiaires, genre IDS.

Toujours dans la série « communications hors bande », l'idée de ressortir le vieux protocole IDENT (RFC 1413), qui récupérerait le HOST_ID par une connexion TCP vers la source d'une session. Il faudra donc un serveur IDENT dans la machine faisant le partage d'adresses et publier cette information (dans le DNS ?) pour éviter que les serveurs ne bombardent les pauvres CPE de requêtes IDENT. Il y a aussi des craintes quant aux performances de cette solution. Et quant à sa sécurité la requête IDENT pourrait être émise par un méchant.

Voilà, on a fait le tour de toutes les solutions envisageables. La section 5 de notre RFC présente une synthèse sous forme d'un tableau dont les lignes sont les solutions présentées plus haut et les colonnes sont les critères d'évaluation (« nécessite une modification de TCP/IP dans les machines », « a un impact sur les performances », « déployable aujourd'hui (sans refaire l'Internet de zéro) », etc).


Téléchargez le RFC 6967


L'article seul

DNS man-in-the-middle at the Krasnapolsky hotel in Amsterdam

First publication of this article on 11 June 2013


Hotel networks are famous for their brokenness. It seems their network managers are fond of always finding some new and clever ways to break things. The famous Krasnapolsky hotel in Amsterdam, home of many RIPE meetings, decided to attack the DNS.

I discovered the problem during a CENTR meeting. The DNSSEC-validating resolver on my laptop did not work (SERVFAIL for every query). But dig apparently did. Checking with tcpdump :

10:47:24.578004 IP (tos 0x0, ttl 64, id 36388, offset 0, flags [none], proto UDP (17), length 56)
    192.168.48.71.38053 > 192.58.128.30.53: [udp sum ok] 17756% [1au] NS? . ar: . OPT UDPsize=4096 OK (28)
10:47:25.567816 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto UDP (17), length 269)
    192.58.128.30.53 > 192.168.48.71.38053: [udp sum ok] 17756 FormErr q: NS? . 13/0/0  [2d1h59m18s] NS j.root-servers.net.,  [2d1h59m18s] NS h.root-servers.net.,  [2d1h59m18s] NS g.root-servers.net.,  [2d1h59m18s] NS c.root-servers.net.,  [2d1h59m18s] NS e.root-servers.net.,  [2d1h59m18s] NS a.root-servers.net.,  [2d1h59m18s] NS m.root-servers.net.,  [2d1h59m18s] NS k.root-servers.net.,  [2d1h59m18s] NS b.root-servers.net.,  [2d1h59m18s] NS l.root-servers.net.,  [2d1h59m18s] NS f.root-servers.net.,  [2d1h59m18s] NS i.root-servers.net.,  [2d1h59m18s] NS d.root-servers.net. (241)

The first packet is a priming request from the resolver, trying to check the list of the root name servers. The replies is complete (full list of these servers) but with an abnormal status: FormErr (Format Error). From RFC 1035, it means "The name server was unable to interpret the query".

But if I try with dig? Here, I request the DNSKEY of the root, from the server K.root-servers.net, with the EDNS options a real resolver would use:


% dig +bufsize=4096 +dnssec @193.0.14.129 DNSKEY .

; <<>> DiG 9.8.1-P1 <<>> +bufsize=4096 +dnssec @193.0.14.129 DNSKEY .
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 41313
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;.				IN	DNSKEY

;; ANSWER SECTION:
.			30672	IN	DNSKEY	256 3 8 AwEAAc5byZvwmHUlCQt7WSeAr3OZ2ao4x0Yj/3UcbtFzQ0T67N7CpYmN qFmfvXxksS1/E+mtT0axFVDjiJjtklUsyqIm9ZlWGZKU3GZqI9Sfp1Bj Qkhi+yLa4m4y4z2N28rxWXsWHCY740PREnmUtgXRdthwABYaB2WPum3y RGxNCP1/
...

Everything goes fine, it seems. No, there are three problems. I let you check, I will explain later. But, first, why do I get a NOERROR from dig and a FORMERR when it's done by the resolver? That's because dig sets the RD bit in the request (again, from the RFC: "Recursion Desired - this bit may be set in a query and is copied into the response. If RD is set, it directs the name server to pursue the query recursively. Recursive query support is optional."). Typical resolvers, unlike stub resolvers like dig, do not set this bit. Let's try with +norec which will disable this bit:


% dig +bufsize=4096 +dnssec +norec @193.0.14.129 DNSKEY .

; <<>> DiG 9.8.1-P1 <<>> +bufsize=4096 +dnssec +norec @193.0.14.129 DNSKEY .
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: FORMERR, id: 7135
;; flags: qr ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;.				IN	DNSKEY

;; ANSWER SECTION:
.			158539	IN	DNSKEY	256 3 8 AwEAAc5byZvwmHUlCQt7WSeAr3OZ2ao4x0Yj/3UcbtFzQ0T67N7CpYmN qFmfvXxksS1/E+mtT0axFVDjiJjtklUsyqIm9ZlWGZKU3GZqI9Sfp1Bj Qkhi+yLa4m4y4z2N28rxWXsWHCY740PREnmUtgXRdthwABYaB2WPum3y RGxNCP1/
...

OK, this is consistent: dig and my local resolver gets the same result, a Format Error. The network provider (Swisscom) did that to prevent people from running their own resolvers (or may be simply out of incompetence).

Do note the brokenness is not in the DHCP-provided resolver (which is almost always broken in hotel and airport networks). I queried directly the root name server. So, it's a real man-in-the-middle. As in China, the network intercepts the request (or the response) and rewrites it.

Anything else? I said there were three problems in the reply with the RD bit set. Did you find them? One is conspicuous: the DNSSEC signatures were stripped from the reply, preventing any local validation (the only safe way to do DNSSEC validation). The second is more subtle: the reply should have the AA bit set (from the RFC: "Authoritative Answer - this bit is valid in responses, and specifies that the responding name server is an authority for the domain name in question section.") since I queried directly a root name server. But it has not. Yet another information erased from the reply. And the third was noticed in this paper by Sebastian Castro: "RA [Recursion Available] is bit set when you are talking to a non-recursive server".

Of course, this sort of man-in-the-middle is very common. What's ironic here is that it takes place at the Krasnapolsky, which is an important place of the Internet in Europe. And that it happens in the Netherlands, which was the first country in the world to protect network neutrality by the law, law which is here blatantly violated.

So, it seems the only solution to have a proper DNS service on your laptop when travelling is to tunnel everything through some VPN.


L'article seul

Journée ordinaire sur l'Internet, une nouvelle attaque par déni de service

Première rédaction de cet article le 11 juin 2013


C'est tous les jours qu'il y a des problèmes sur l'Internet. Par exemple, hier soir, mon système de surveillance me prévient qu'une des machines qui porte ce blog n'est plus joignable (les requêtes HTTP échouent).

Plus joignable en IPv4 mais, en IPv6, la même machine répond bien en HTTP (je teste les deux protocoles séparément). En prime, l'examen du journal d'Apache montre que le serveur HTTP continue à recevoir de nombreuses requêtes en IPv4 avec succès.

Quelques coups de mtr donnent plus de détails. Depuis la machine qui fait la surveillance, 90 % de perte de paquets (cf. RFC 6673) dans les deux dernières étapes (le dernier routeur et le serveur Web lui-même). Depuis une machine sur un tout autre réseau, tout va bien, 0 % de pertes. Dans le premier cas, on passe par Level 3, dans le second par AboveNet. Donc, un problème sur la liaison entre Level 3 et l'hébergeur de cette machine, 6sync. Cet hébergeur explique rapidement le problème. C'était simplement encore une banale attaque par déni de service, qui visait un autre client de 6sync (aucun rapport avec moi, je vous rassure) et avait réussi à saturer le lien entre Level 3 et 6sync.

Un peu plus d'une heure de perturbation en tout, comme le montre le joli graphique : ddos-6sync-2013.png .


L'article seul

RFC 6962: Certificate Transparency

Date de publication du RFC : Juin 2013
Auteur(s) du RFC : B. Laurie, A. Langley, E. Kasper (Google)
Expérimental
Première rédaction de cet article le 7 juin 2013


Plusieurs attaques spectaculaires, notamment celle contre DigiNotar, ont montré la fragilité de l'actuel système de gestion de certificats X.509. Comme n'importe quelle AC peut émettre un certificat pour n'importe quel nom de domaine, il ne suffit pas d'évaluer la sécurité de son AC, il faudrait idéalement évaluer toutes les AC. Ce RFC propose une approche différente : encourager/obliger les AC à publier « au grand jour » les certificats qu'elles émettent. Un titulaire d'un certificat qui craint qu'une AC n'émette un certificat à son nom sans son autorisation n'a alors qu'à surveiller ces publications. (Il peut aussi découvrir à cette occasion que sa propre AC s'est fait pirater ou bien est devenue méchante et émet des certificats qu'on ne lui a pas demandés.) À noter qu'une deuxième version du système décrit ici a été publiée en décembre 2021, dans le RFC 9162 mais elle reste, fin 2021, peu déployée.

Ce n'est pas par hasard que les auteurs de ce RFC sont trois employés de Google. Dans l'affaire DigiNotar, comme dans d'autres affaires analogues, le premier vrai/faux certificat émis par celui qui a piraté une AC est souvent un certificat pour gmail.com, de façon à permettre d'espionner le trafic vers Gmail. La proposition de ce RFC (qui est encore expérimental) est d'empêcher l'émission « discrète » de vrais/faux certificats qui seraient ensuite utilisés uniquement à certains endroits (l'Iran dans le cas de DigiNotar mais cela peut aussi concerner des entreprises qui font des attaques de l'homme du milieu contre leurs propres employés).

Le principe est donc de créer un (ou plusieurs) journal des certificats émis. Le journal doit être public, pour que Google ou n'importe qui d'autre puisse l'auditer. Il doit être en mode « ajout seulement » pour éviter qu'on puisse réécrire l'histoire. Les certificats sont déjà signés mais le journal a ses propres signatures, pour prouver son intégrité. Conceptuellement, ce journal est une liste de certificats dans l'ordre de leur création. Toute AC peut y ajouter des certificats (la liste ne peut pas être ouverte en écriture à tous, de crainte qu'elle ne soit remplie rapidement de certificats bidons). En pratique, le RFC estime que la liste des AC autorisées à écrire dans le journal sera l'union des listes des AC acceptées dans les principaux navigateurs Web (voir aussi la section 4.7).

À chaque insertion, le journal renvoie à l'AC une estampille temporelle signée, permettant à l'AC de prouver qu'elle a bien enregistré le certificat. Si une AC peut présenter cette signature mais que le certificat est absent du journal, l'observateur aura la preuve que le journal ne marche pas correctement. Le format exact de cette estampille temporelle est décrit en section 3.2. Elle devra être envoyée au client par les serveurs TLS, comme preuve de la bonne foi de l'AC (cf. sections 3.3 et 5.2).

Les titulaires de certificats importants, comme Google, mais aussi des chercheurs, des agences de sécurité, etc, pourront alors suivre l'activité de ce(s) journal (journaux) public(s) (section 5.3 du RFC). Ce qu'ils feront en cas de détection d'un certificat anormal (portant sur leur nom de domaine, mais qu'ils n'ont pas demandé) n'est pas spécifié dans le RFC : cela dépend de la politique de l'organisation concernée. Ce RFC fournit un mécanisme, son usage n'est pas de son ressort. Ce journal n'empêchera donc pas l'émission de vrais/faux certificats, ni leur usage, mais il les rendra visibles plus facilement et sans doute plus vite.

Pour que cela fonctionne, il faudra que les clients TLS vérifient que le certificat présenté est bien dans le journal (autrement, le méchant n'aurait qu'à ne pas enregistrer son vrai/faux certificat, cf. section 5.4 du RFC).

En pratique, la réalisation de ce journal utilise un arbre de Merkle, une structure de données qui permet de mettre en œuvre un système où l'ajout de certificats est possible, mais pas leur retrait. La section 2 du RFC détaille l'utilisation de ces arbres et la cryptographie utilisée.

Le protocole utilisé entre les AC et le journal, comme celui utilisé entre les clients TLD et le journal, sera HTTP et le format des données sera JSON (section 4). Ainsi, pour ajouter un certificat nouvellement émis au journal géré sur sunlight-log.example.net, l'AC fera :

POST https://sunlight-log.example.net/ct/v1/add-chain

et le corps de la requête HTTP sera un tableau JSON de certificats encodés en Base64. La réponse contiendra notamment l'estampille temporelle (SCT pour Signed Certificate Timestamp). Pour récupérer des certificats, le programme de surveillance fera par exemple :

GET https://sunlight-log.example.net/ct/v1/get-entries

D'autres URL permettront de récupérer les condensats cryptographiques contenus dans l'arbre de Merkle, pour s'assurer qu'il est cohérent.

Notez que Google a produit une mise en œuvre de ce RFC, qui semble activement développée. Et il existe un pilote écrit en Go. Il y a aussi une liste de diffusion sur ce projet et un site officiel du projet par Google. Sinon, si vous voulez en savoir plus sur cette idée de vérification publique, consultez « Efficient Data Structures for Tamper-Evident Logging » de Scott A. Crosby et Dan S. Wallach. Autres lectures sur la certificate transparency, un article de promotion de Ben Laurie et un article violemment critique.

Quelles sont les chances de succès de cette idée ? Tant que peu d'AC participent, ces journaux ne serviront pas à grand'chose (le méchant attaquera uniquement les AC non participantes). L'idée est qu'à moyen terme, la pression sur les AC (directement ou bien via les navigateurs Web qui ne feraient plus confiance aux AC non participantes) pourra faire que tous les certificats devront être dans le journal et que l'examen de celui-ci suffira à détecter les « vrais/faux certificats ».

Merci à Florian Maury pour sa relecture très détaillée.


Téléchargez le RFC 6962


L'article seul

RFC 6960: X.509 Internet Public Key Infrastructure Online Certificate Status Protocol - OCSP

Date de publication du RFC : Juin 2013
Auteur(s) du RFC : S. Santesson (3xA Security), M. Myers (TraceRoute Security), R. Ankney, A. Malpani (CA Technologies), S. Galperin (A9), C. Adams (University of Ottawa)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF pkix
Première rédaction de cet article le 7 juin 2013


Le protocole OCSP permet à un client X.509 (par exemple un navigateur Web engagé dans une connexion HTTPS) de s'informer en temps réel sur l'état d'un certificat, notamment afin de savoir s'il est révoqué ou pas. Ce nouveau RFC remplace (avec de légers changements) l'ancienne norme OCSP qui était dans le RFC 2560.

Normalement, le destinataire d'un certificat X.509 (par exemple le navigateur Web cité plus haut), authentifie ce dernier en utilisant les clés publiques des AC qu'il a dans son magasin, et en vérifiant dans une liste de CRL, mise à jour périodiquement, que le certificat est toujours d'actualité, qu'il n'a pas été révoqué par l'AC émettrice (section 3.3 du RFC 5280). En complément, ou à la place de ces CRL, le destinataire peut utiliser le protocole OCSP normalisé dans ce RFC. OCSP est un protocole synchrone : le destinataire du certificat émet une requête à un serveur OCSP et attend sa réponse avant de valider le certificat. Il peut ainsi obtenir des informations plus à jour qu'avec des CRL.

La requête OCSP contient (un survol du protocole figure en section 2 de ce RFC) le numéro de série du certificat qu'on veut authentifier. La réponse dépend de si le répondeur (le serveur OCSP) a l'information sur ce certificat. Si oui, il répond positivement (good, le certificat est valable) ou négativement (revoked, le certificat ne doit pas être accepté), en indiquant l'heure (un certificat valable à un moment peut être révoqué par la suite) et sa réponse est signée (typiquement avec le certificat de l'AC). Si non, si le répondeur n'a pas l'information, il répond unknown.

Les réponses possibles sont donc good, revoked et unknown. Notez que, de manière surprenante, good ne dit pas que le certificat existe, simplement qu'il n'a pas été révoqué. (Cette question a fait l'objet de chauds débats dans le groupe de travail : que doit faire un répondeur OCSP lorsqu'il reçoit une requête pour un certificat qu'il est censé connaître mais qu'il n'a pas émis ?)

Le répondeur peut aussi être dans l'incapacité de fournir une réponse et, dans ce cas, le message d'erreur résultant n'est pas signé. Parmi les causes possibles d'erreur, une requête incorrecte, une erreur dans le répondeur (équivalent du 500 Internal server error de HTTP), un problème temporaire qui nécessite que le client réessaie plus tard, un client non autorisé, etc.

La réponse inclut souvent des temps : dernier moment où l'information retournée était correcte, moment de la prochaine mise à jour de l'information, moment de la signature de l'information (les réponses peuvent être pré-produites) ou moment où la révocation a eu lieu.

Mais comment un destinataire de certificat sait-il où trouver le serveur OCSP ? Il est typiquement indiqué dans le certificat qu'on teste, dans l'extension Authority Information Access (section 4.2.2.1 du RFC 5280). Si la méthode d'accès est id-ad-ocsp, le contenu de cette extension est un URL pointant vers le serveur OCSP. Voici un exemple dans un certificat récupéré sur l'Internet :

% openssl x509 -text -in /tmp/site.pem
...
            Authority Information Access: 
                OCSP - URI:http://rapidssl-ocsp.geotrust.com
                CA Issuers - URI:http://rapidssl-aia.geotrust.com/rapidssl.crt

Mais cette information peut aussi être codée en dur dans le client.

La plupart du temps, l'URL en question sera un URL HTTP, et OCSP tournera donc au dessus de ce protocole (parfois en HTTPS). L'annexe A décrit en détail ce mécanisme. OCSP peut utiliser GET ou POST. Dans ce dernier cas, la requête HTTP aura le type application/ocsp-request et la requête OCSP forme le corps de la requête POST, après son encodage en DER. Même chose pour la réponse, type application/ocsp-response, et du DER dans le corps HTTP.

Voilà, vous savez l'essentiel, la section 4 décrit tout le protocole, en ASN.1 (en s'appuyant sur les modules de l'annexe B). Par exemple, une requête est une TBSRequest qui contient plusieurs Request, chacune concernant un certificat :

OCSPRequest     ::=     SEQUENCE {
       tbsRequest                  TBSRequest,
       optionalSignature   [0]     EXPLICIT Signature OPTIONAL }

   TBSRequest      ::=     SEQUENCE {
       version             [0]     EXPLICIT Version DEFAULT v1,
       requestorName       [1]     EXPLICIT GeneralName OPTIONAL,
       requestList                 SEQUENCE OF Request,
       requestExtensions   [2]     EXPLICIT Extensions OPTIONAL }

 ...

  Request         ::=     SEQUENCE {
       reqCert                     CertID,
       singleRequestExtensions     [0] EXPLICIT Extensions OPTIONAL }

   CertID          ::=     SEQUENCE {
       hashAlgorithm       AlgorithmIdentifier,
       issuerNameHash      OCTET STRING, -- Hash of Issuer's DN
       issuerKeyHash       OCTET STRING, -- Hash of Issuers public key
       serialNumber        CertificateSerialNumber }

Et la réponse est un code de retour et la réponse elle-même :

OCSPResponse ::= SEQUENCE {
      responseStatus         OCSPResponseStatus,
      responseBytes          [0] EXPLICIT ResponseBytes OPTIONAL }

   OCSPResponseStatus ::= ENUMERATED {
       successful            (0),  --Response has valid confirmations
       malformedRequest      (1),  --Illegal confirmation request
       internalError         (2),  --Internal error in issuer
       tryLater              (3),  --Try again later
                                   --(4) is not used
       sigRequired           (5),  --Must sign the request
       unauthorized          (6)   --Request unauthorized
   }

   ResponseBytes ::=       SEQUENCE {
       responseType   OBJECT IDENTIFIER,
       response       OCTET STRING }

Avec response comportant à son tour des structures ASN.1 arrivant finalement à :

  SingleResponse ::= SEQUENCE {
      certID                       CertID,
      certStatus                   CertStatus,
      thisUpdate                   GeneralizedTime,
      nextUpdate         [0]       EXPLICIT GeneralizedTime OPTIONAL,
      singleExtensions   [1]       EXPLICIT Extensions OPTIONAL }

   CertStatus ::= CHOICE {
       good        [0]     IMPLICIT NULL,
       revoked     [1]     IMPLICIT RevokedInfo,
       unknown     [2]     IMPLICIT UnknownInfo }

   RevokedInfo ::= SEQUENCE {
       revocationTime              GeneralizedTime,
       revocationReason    [0]     EXPLICIT CRLReason OPTIONAL }

On note que la raison de la révocation est indiquée. Elle n'est pas toujours indiquée par le répondeur OCSP (cela peut être une information sensible). La présence de cette information dans les CRL a permis à l'EFF de réaliser une intéressante étude sur les raisons des révocations (la section « How often are these attacks occurring? »).

La section 5 revient sur l'analyse de sécurité d'OCSP. On notera que les problèmes de vie privée n'y sont pas mentionnés. Pourtant, la requête OCSP indique au répondeur (en général l'AC) quels sites Web ont été visités. C'est d'ailleurs ainsi qu'il a été possible de prouver l'utilisation en Iran des vrais/faux certificats de DigiNotar, en regardant les requêtes OCSP de leurs navigateurs vers l'AC.

Un autre problème de sécurité n'est pas mentionné : que doit faire le navigateur Web qui tente d'authentifier un certificat lorsque la requête OCSP n'aboutit pas (peut-être parce qu'un Homme du Milieu bloque l'accès au serveur OCSP) ? S'il refuse d'authentifier le certificat, la connexion échoue. Mais s'il accepte, OCSP ne protège plus tellement.

Les changements depuis le RFC 2560 sont mineurs, et sont résumés dans la section 1.

Merci à Erwann Abalea pour sa relecture précise.


Téléchargez le RFC 6960


L'article seul

RFC 6951: UDP Encapsulation of SCTP Packets for End-Host to End-Host Communication

Date de publication du RFC : Mai 2013
Auteur(s) du RFC : M. Tuexen (Muenster Univ. of Appl. Sciences), R. R. Stewart (Adara Networks)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF tsvwg
Première rédaction de cet article le 30 mai 2013


Normalement, un nouveau protocole de transport comme SCTP ne devrait avoir besoin de l'autorisation de personne pour être déployé entre deux machines majeures et consentantes. Le modèle de l'Internet, fondé sur le protocole IP, permet aux machines terminales, sans autorisation d'un intermédiaire, de communiquer en mettant ce qu'elles veulent dans les paquets IP. Cela, c'est la théorie. En pratique, par incompétence, sécurité ultra-rigide ou paresse, des tas d'intermédiaires se permettent de se placer sur le chemin entre deux machines et ne laissent passer qu'un petit nombre de protocoles de transport (typiquement uniquement TCP et UDP). Un nouvel arrivé (SCTP a quand même été normalisé dans le RFC 2960 en 2000 donc, « nouveau » est relatif ; la norme actuelle est le RFC 4960) a donc le plus grand mal à se faire une place au soleil. On en est donc réduit à des astuces plus ou moins propres comme celle décrite dans ce RFC : encapsuler SCTP dans de l'UDP.

La principale cible visée est donc le grand nombre de machines coincées derrière un routeur NAT. Mais cette encapsulation peut aussi servir pour mettre en œuvre SCTP sans avoir accès au noyau, entièrement dans une application, sans avoir de privilèges particulier (ce qui est souvent nécessaire pour implémenter un protocole de transport). Attention, il ne s'agit pas de faire un tunnel pour mettre en relation deux réseaux, mais de faire communiquer deux machines terminales qui voudraient faire du SCTP et qui en sont empêchées par une middlebox (cf. section 4).

Pourquoi UDP, au fait, et pas TCP ? Parce que SCTP fournit tous les services de TCP (notamment le contrôle de congestion et la fiabilité) et qu'il ferait donc double emploi avec TCP.

Notez que rien n'empêcherait de faire un routeur NAT qui permettrait SCTP, comme ils permettent aujourd'hui de faire du TCP et de l'UDP. C'est juste que de tels routeurs, s'ils existent, sont très rares.

Bon, et comment SCTP sur UDP fonctionne (section 5) ? On utilise par défaut le port de destination et de source 9899. Toutefois, celui-ci aura pu être modifié en route par un routeur NAT et le port à l'arrivée sera donc peut-être différent. D'autre part, certaines machines peuvent se trouver dans l'obigation d'écouter sur un autre port et il faut donc qu'une mise en œuvre de ce RFC soit capable d'utiliser un port différent par correspondant (cf. l'API plus loin), et de se souvenir de ces ports. On met le paquet SCTP dans un paquet UDP qui sera lui-même transporté dans IP (peut-être avec des en-têtes d'extension, dans le cas d'IPv6). La somme de contrôle UDP doit être mise (même en IPv4 où elle est normalement facultative ; et, pour IPv6, on n'a pas le droit d'utiliser l'exception du RFC 6935).

C'est simple mais il y a quelques petits pièges. D'abord, avec les messages ICMP (section 5.5) : lors de leur réception, il n'y aura pas forcément assez d'octets du message original pour trouver l'association SCTP à qui envoyer le message ICMP. Il faudra alors jeter ce dernier sans remords. La mise en œuvre de SCTP doit donc être capable de se débrouiller sans les messages ICMP, dont la réception ne peut pas être garantie.

Deuxième piège, commun à toutes les techniques d'encapsulation, la MTU (section 5.6). SCTP doit penser à diminuer la MTU de la taille de l'en-tête UDP. Et se souvenir qu'ICMP est encore moins garanti lorsqu'on utilise l'encapsulation UDP donc les procédures de découverte de la MTU du chemin (RFC 4820, RFC 4821 et surtout RFC 8899) doivent fonctionner même si on ne reçoit pas les messages ICMP.

Dernier piège, mais crucial, le contrôle des adresses IP source des paquets UDP. Pour les associations SCTP à une seule adresse IP, il ne faut pas indiquer l'adresse IP de la machine dans les sous-paquets (chunks) de type INIT (section 3.3.2 du RFC 4960) mais la mettre dans le paquet UDP (ce que fait UDP par défaut). Et si la machine a plusieurs adresses IP, il faut se servir des mécanismes des RFC 5061 et RFC 4895 pour les faire connaître au correspondant, et non pas mettre les adresses IP dans les sous-paquets SCTP car l'intervention d'un routeur NAT modifierait l'adresse source, rendant ces sous-paquets invalides.

Et pour les applications, quels mécanismes sont nécessaires pour faire fonctionner cette encapsulation ? La section 6 propose des changements à l'API du RFC 6458, avec l'ajout d'une option SCTP_REMOTE_UDP_ENCAPS_PORT qui prendra en paramètre une structure :

struct sctp_udpencaps {
     sctp_assoc_t sue_assoc_id;
     struct sockaddr_storage sue_address;
     uint16_t sue_port;
   };

Ce qui permettra de définir/connaître les adresses IP et les ports utilisés par l'encapsulation UDP.

Depuis sa version 9.1, FreeBSD a la capacité d'utiliser cette encapsulation pour envoyer des paquets SCTP. Un portage a été fait vers Mac OS X, disponible en http://sctp.fh-muenster.de.


Téléchargez le RFC 6951


L'article seul

RFC 6959: SAVI Threat Scope

Date de publication du RFC : Mai 2013
Auteur(s) du RFC : D. McPherson (VeriSign), F.J. Baker (Cisco Systems), J.M. Halpern (Ericsson)
Pour information
Réalisé dans le cadre du groupe de travail IETF savi
Première rédaction de cet article le 30 mai 2013


On sait que, sur l'Internet, il est possible et même facile d'usurper une adresse IP , c'est-à-dire d'émettre un paquet IP avec une adresse source allouée à quelq'un d'autre (ou pas allouée du tout). Le projet SAVI (Source Address Validation Improvement) vise à améliorer la validation de l'adresse source, de manière à rendre l'usurpation plus rare et plus difficile. Ce RFC décrit la menace à laquelle SAVI répondra et étudie les contre-mesures existantes.

L'Internet emploie un protocole de réseau sans connexion (que ce soit en IPv4 ou en IPv6). Lorsqu'une machine veut communiquer avec une autre, elle met son adresse IP comme source d'un paquet, celle de son correspondant en destination et elle envoie le paquet. Substituer l'adresse IP d'une autre machine à la sienne est donc aussi simple que d'écrire une autre chaîne de bits à la place de l'adresse authentique. Le réseau n'essaie pas d'empêcher cela. Certes, le fraudeur ne pourra pas forcément recevoir les réponses (elles arriveront à celui dont l'adresse a été usurpée) mais ce n'est pas forcément un problème dans un réseau sans connexion. Il existe des mécanismes pour empêcher cette usurpation, le plus connu étant BCP 38 (les RFC 2827 et RFC 3704) mais ils sont insuffisamment déployés, car ils n'apportent pas de bénéfices à celui qui les déploie, uniquement aux autres acteurs de l'Internet. En outre, BCP 38 ne protège pas toujours suffisamment. Par exemple, s'il est mis en œuvre dans le premier routeur, il n'empêchera pas les machines du LAN d'usurper les adresses de leurs voisines.

L'une des idées de SAVI est donc de compléter BCP 38 avec des validations locales, apportant un bénéfice local, et qui permettraient une meilleure traçabilité.

Quelques termes à apprendre pour bien suivre les documents sur SAVI :

  • Bind anchor : l'information sur laquelle on se base pour valider une adresse IP source. Par exemple, sur un commutateur, cela pourra être l'adresse MAC ou bien le port physique du commutateur.
  • Routeur NNI (Network to Network Interface) : un routeur qui fait face à un routeur d'un autre opérateur.
  • Routeur PE (Provider Edge) : un routeur qui fait face au client d'un opérateur.
  • RPF (Reverse Path Forwarding) : valider une adresse source en regardant si la réponse au paquet entrant partirait ou non par l'interface sur laquelle il est entré (détails dans le RFC 3704).

La section 3 détaille ensuite les attaques rendues possibles, ou facilitées par l'usurpation d'adresses IP source (la section 4 couvrira les contre-mesures). D'abord, les attaques en aveugle : l'assaillant, qui a usurpé l'adresse IP source, ne peut pas recevoir les réponses à ses paquets. Il peut les envoyer, ces paquets, mais c'est tout. Cela lui complique évidemment sérieusement la vie. Certaines attaques restent possibles. Il y a celles ne nécessitant qu'un seul paquet (et donc pas de réponse). Par exemple, si un paquet spécialement construit plante le logiciel du routeur qui le traite, un attaquant peut monter une attaque par déni de service en envoyant un unique packet of death. Un autre cas est celui où, en envoyant un paquet où l'adresse source et destination sont identiques, le destinataire se réponde à lui-même, puis à la réponse de la réponse, et entretienne ainsi lui-même la boucle sans fin (une bogue de cette famille avait frappé PowerDNS).

Une autre attaque en aveugle est le RST (ReSeT) TCP usurpé (section 2.3 du RFC 4953). Un seul paquet TCP accepté (l'attaquant doit deviner un numéro de séquence contenu dans la fenêtre en cours) va couper la connexion (notez que les protocoles applicatifs comme TLS et SSH ne sont d'aucune utilité contre cette attaque). Cela peut être très gênant pour les connexions censées durer longtemps (sessions BGP par exemple). Il existe des contre-mesures (voir le RFC 5961) mais empêcher l'usurpation d'adresse IP empêcherait complètement cette attaque.

Après les attaques en aveugle formées d'un seul paquet, place aux attaques volumétriques, reposant sur l'envoi d'un grand nombre de paquets. L'idée est de remplir certaines tables de taille fixe (par exemple la table des connexions entrantes) ou, encore plus simplement, de saturer le réseau de la victime. L'attaquant n'ayant pas besoin de réponse, il a tout intérêt, dans ces paquets, à usurper l'adresse IP source pour déguiser son identité. On constate que beaucoup de gens n'ont pas encore compris la facilité avec laquelle cette usurpation est possible, et croient réellement que l'adresse IP source qu'ils observent dans les paquets entrants est réellement celle de leur attaquant (pensez à cela la prochaine fois que vous lirez dans les médias quelque chose du genre « attaque par déni de service contre tel organisme, l'examen de l'attaque montrait que l'attaquant venait de Russie/Chine/Moyen-Orient »). Pire, la victime bloque parfois les paquets IP entrants en fonction de cette adresse source, réalisant ainsi une autre attaque par déni de service, contre la victime de l'usurpation d'adresse. Certaines attaques peuvent d'ailleurs être montées dans ce seul but.

Une autre raison pour l'attaquant d'usurper l'adresse IP source est la possibilité d'attaque par réflexion : comme au billard, on va viser une autre boule que celle qu'on veut vraiment toucher. L'attaquant envoie un paquet UDP au réflecteur (qui n'est pas sa vraie victime, juste un complice involontaire) en usurpant l'adresse IP source de la victime. Le réflecteur va alors répondre à ce qu'il croit être l'émetteur et qui est en fait la victime, qui sera ainsi bombardée par le ou les réflecteurs. La réflexion sert à l'attaquant à dissimuler ses traces (le paquet va suivre un tout autre chemin dans le réseau) mais elle est surtout intéressante couplée avec l'amplification. Avec certains protocoles, la réponse va être plus grande, voire beaucoup plus grande, que la requête. Avec une amplification de 20, l'attaquant pourra ainsi obtenir un bombardement de 1 Gb/s en ne dépensant lui-même que 50 Mb/s. Plusieurs protocoles permettent l'amplification, comme NTP, SNMP et surtout le DNS comme ce fut le cas lors de l'attaque de 2006 (le RFC ne les cite pas mais des attaques plus violentes ont eu lieu en 2012 et 2013).

Le RFC classe aussi dans les attaques volumétriques les actions visant à empoisonner les données d'un serveur distant. Le cas le plus courant est celui des empoisonnements DNS où le méchant va tenter de répondre avant le serveur légitime (cas, par exemple, des attaques Kaminsky). Ici, le volume élevé des requêtes n'est pas dû au désir de saturer la victime, mais à la nécessité de faire beaucoup d'essais pour en voir un accepté. (Dans le cas du DNS, il s'agit d'essayer beaucoup de Query ID et de ports source UDP.) À noter qu'il existe aussi des attaques par empoisonnement contre les caches ARP.

Cela, c'était les attaques en aveugle. Mais, parfois, un attaquant qui usurpe une adresse IP peut observer les réponses, par exemple parce qu'il est sur le même réseau local à diffusion que la victime de l'usurpation ou bien, si le réseau local ne diffuse pas à tous, parce qu'il a empoisonné les caches ARP. L'attaquant a alors bien plus de possibilités comme le détournement d'une connexion TCP à son profit, les tests de vulnérabilité d'un objectif sans se trahir, la subversion des protocoles de routage en se faisant passer pour un des routeurs participants, etc.

La section 4 décrit ensuite les contre-mesures qui peuvent être adoptées aujourd'hui et qui sont effectivement déployées, au moins partiellement. Par exemple, un commutateur peut (en violant légèrement le modèle en couches), refuser les paquets dont l'adresse IP source ne correspond pas à l'adresse MAC du paquet (que le commutateur a pu apprendre en examinant les requêtes et réponses ARP). Ou bien ceux qui viennent d'un autre port physique que d'habitude. Si les paquets de 192.168.7.64 venaient toujours du port 3 et que, tout à coup, ils viennent du port 4, le commutateur peut soupçonner une usurpation (ou tout simplement une machine qui a été déplacée : la sécurité peut se tromper).

On peut donc jeter un paquet lorsque son adresse IP source ne correspond pas aux informations qu'on possède. Notez bien que, plus on s'éloigne de la source des paquets, plus il est difficile d'être sûr que c'est bien une usurpation. Néanmoins, le RFC identifie cinq endroits où peut se faire cet examen de validité, du plus proche de la source au plus éloigné :

  • Sur le lien où est attachée la machine, comme dans l'exemple du commutateur ci-dessus. On dispose au moins de l'adresse MAC, ce qui facilite le test. Si le médium est complètement partagé (lien Wi-Fi, Ethernet classique...), cela s'arrête là. Mais, dans la cas contraire, on a aussi souvent une information physique, comme le port du commutateur. C'est donc clairement le meilleur endroit pour valider et c'est là que porteront l'essentiel des efforts du projet SAVI (voir par exemple un des premiers RFC, le RFC 6620). Le RFC traite aussi les cas spécifiques des accès Internet par câble (technologie DOCSIS) ou par ADSL. Pour ce dernier, le premier équipement du FAI dans le réseau a en général largement assez d'informations pour empêcher qu'un abonné n'usurpe l'adresse d'un autre (mais pas pour empêcher qu'une machine chez un abonné n'usurpe l'adresse d'une autre chez le même abonné ; il n'est pas évident que ce soit un problème sérieux en pratique puisque c'est le même foyer).
  • Les commutateurs suivants, auxquels la machine n'est pas directement connectée, peuvent aussi valider, mais de manière moins fiable. Si le spanning tree ou un autre protocole comme VRRP change la topologie, les paquets émis par une adresse IP donnée apparaîtront, et légitimement, sur un autre port. Les commutateurs pourraient donc avoir besoin de se transmettre leur état SAVI (liste des adresses valides et leurs ports, autrement dit les bind anchors).
  • Les routeurs peuvent ensuite être utilisés. À part le premier, ils n'ont pas l'adresse MAC à leur disposition. Le principal test qu'ils peuvent faire est de s'assurer que l'adresse IP source est dans un préfixe qui existe sur ce réseau. Par exemple, un routeur qui sait qu'il connecte 2001:db8:32:a17::/64 à l'Internet peut raisonnablement jeter un paquet venant du réseau local et prétendant avoir comme source 2001:db8:cafe::666. Notez que le routeur ne peut en général rien faire contre une machine qui usurperait une adresse du même réseau local (ici, 2001:db8:32:a17::b00c qui se ferait passer pour 2001:db8:32:a17::babe). Dans des cas moins triviaux (routeurs avec beaucoup d'interfaces et ayant de nombreux préfixes derrière eux), pour savoir quels préfixes sont acceptables, le routeur peut simplement consulter une ACL maintenue manuellement ou alors utiliser RPF (RFC 3704).
  • Un cas intéressant est le premier routeur du FAI, le routeur PE : le RFC 2827 demande explicitement que tous ces routeurs filtrent les paquets ayant une adresse IP qui n'est pas dans le préfixe alloué au client (voir aussi la section 4.2.1 de notre RFC). À noter qu'il ne peut pas aller plus loin et valider chaque adresse : cela nécessiterait que le client fasse ce filtrage (cf. les cas plus haut).
  • Enfin, au niveau des routeurs NNI, on est très loin de la source et tout filtrage devient difficile. Qui plus est, on ne sait pas si l'opérateur en place filtre dans son propre réseau ou pas. L'ancien projet SAVA (précuseur de SAVI, mais beaucoup plus ambitieux) espérait monter une infrastructure de transmission d'informations sur la validation, permettant d'indiquer aux autres opérateurs l'étendue du filtrage qu'on avait fait sur son réseau. Le projet ayant été abandonné, il ne reste que les solutions non techniques comme de tenter de faire signer des engagements de validation d'adresse IP source à ses pairs BGP, en mettant ceux qui ne signent pas dans dans un « enfer » par exemple en étiquetant leurs annonces de préfixes avec une communauté BGP ad hoc (RFC 1997) et en la transmettant aux autres pairs (idée qui me semble personnellement très peu réaliste).

En pratique, il y a des tas de détails qui compliquent la validation d'adresse IP source. Par exemple, pour un commutateur réseau, le cas simple est celui où il y a une et une seule machine derrière chaque port physique et où chaque adresse MAC ne correspond qu'à une seule adresse IP. Si ce n'est pas le cas, le problème devient plus difficile. Pensez par exemple à une machine physique, connectée par le port d'un commutateur mais portant plusieurs machines virtuelles, chacune avec sa propre adresse IP et sans doute sa propre adresse MAC. Ce cas est en fait un commutateur interne, le commutateur physique n'étant que le deuxième commutateur sur le trajet et n'ayant donc que des capacités de validtaion limitées. Idéalement, c'est le commutateur virtuel dans le système de virtualisation qui devrait faire respecter les règles SAVI, mais l'administrateur réseaux n'en a pas forcément le contrôle et ne lui fait pas forcément confiance.

Pour apprendre le lien entre une adresse MAC et une adresse IPv4, la meilleure solution pour un commutateur est d'écouter les requêtes et les réponses DHCP et de considérer qu'elles font autorité au sujet de ce lien (cf. RFC 7513). Par exemple, en voyant passer cette réponse (vue avec tcpdump) :

09:49:23.191187 00:10:db:ff:40:70 > 18:03:73:66:e5:68, ethertype IPv4 (0x0800), length 368: (tos 0x0, ttl 64, id 16537, offset 0, flags [none], proto UDP (17), length 354)
    192.0.2.20.67 > 192.0.2.54.68: BOOTP/DHCP, Reply, length 326, hops 1, xid 0x903b4b00, Flags [none]
	  Your-IP 192.0.2.54
	  Client-Ethernet-Address 18:03:73:66:e5:68
          ...

Le commutateur sait alors que l'adresse IP 192.0.2.54 a été allouée à 18:03:73:66:e5:68 et qu'un paquet IP dont l'adresse MAC source serait 18:03:73:66:e5:68 et l'adresse IP source serait autre chose que 192.0.2.54 est probablement une usurpation et doit être jeté.

Pour IPv6, outre le trafic DHCP, le commutateur doit écouter les paquets DAD (Duplicate Address Detection) du protocole d'auto-configuration (RFC 4862). Le commutateur sera alors au courant des adresses IP légitimement enregistrées, et de l'adresse MAC correspondante, et pourra se servir de cette information pour valider. Par contre, contrairement à ce qu'on pourrait penser, le protocole d'authentification 802.1x n'aide pas : il authentifie un utilisateur mais ne limite pas les adresses IP qu'il peut utiliser. Enfin, il existe des techniques cryptographiques qui pourraient être utiles pour SAVI comme le SEND du RFC 3971 mais qui sont tellement peu déployées qu'on ne peut pas réellement compter dessus.

Certaines topologies de réseau, quoique parfaitement légales, peuvent sérieusement handicaper SAVI (section 5). Par exemple, si toutes les adresses sont statiques et stables, le problème est relativement bien circonscrit. Mais dans beaucoup de réseaux, ce n'est pas le cas et des adresses sont attribuées dynamiquement. Une même adresse IP sera, dans le temps, allouée à plusieurs adresses MAC et une même adresse MAC n'aura pas forcément la même adresse IP à chaque visite de ce réseau. (Ceux qui utilisent arpwatch sur un tel réseau savent le nombre d'« alarmes » que cela génère. SAVI a exactement le même problème.) D'autre part, si certaines machines sont simples (une adresses MAC, une adresse IP), d'autres sont plus complexes pour le validateur. Un exemple typique est un routeur. Par définition, il émet sur le réseau local des paquets avec sa propre adresse MAC mais des adresses IP source qui ne sont pas la sienne. Il est donc difficile de valider ces paquets.

Autre cas rigolo, notamment en cas de virtualisation : si une machine se déplace dans le data center mais garde son adresse IP. Les commutateurs vont devoir oublier la vieille information sur le port où est connecté cette machine et apprendre la nouvelle. (On appelle cela « mettre à jour son état SAVI ».)

La mobilité entraîne aussi des problèmes. Dans IP, elle peut se réaliser de plusieurs façons. Dans l'une, dite « en jambe de chien », la machine mobile émet des paquets avec son adresse IP source stable (home address), quel que soit le réseau physique où elle est attachée. Un tel mécanisme est évidemment incompatible avec toute solution de validation. Il faut donc que tous les paquets du mobile, aussi bien en émission qu'en réception, soient relayés par la station de base située sur son réseau d'attachement habituel.

Un petit mot aussi sur IPv6 : il crée des difficultés supplémentaires en raison de l'auto-configuration, très pratique mais, par son caractère local, non contrôlé centralement, pas forcément très sûre. Et son espace d'adressage très large (une bonne chose, et la principale raison pour laquelle il est important de déployer IPv6) a comme effet de bord la facilité à utiliser beaucoup d'adresses usurpées. En IPv4, un usurpateur a en théorie 2^32 adresses à usurper et, en pratique, plutôt moins de 2^24 (uniquement celles de son réseau local). En IPv6, même si on arrive à limiter l'usurpateur à son réseau local, il aura 2^64 adresses, ce qui permet de court-circuiter certains mécanismes de sécurité.

La section 6 revient en détail sur la question de la granularité de la validation. Aujourd'hui, il est relativement facile d'empêcher les usurpations inter-sites (où un attaquant prend l'adresse IP d'une machine sur un autre site). Mais empêcher les usurpations intra-sites est plus complexe or, justement, la plupart des attaques viennent de l'intérieur.

Notez que SAVI se limite aux couches basses : il n'est pas prévu de vérifier les adresses IP qui apparaissent dans les applications (par exemple dans le champ Received: des messages formatés suivant le RFC 5322).

Enfin, la section 7 revient sur les questions de sécurité à un haut niveau. Elle rappelle que SAVI n'a pas pour but de produire des preuves, au sens judiciaire du terme (dans le meilleur cas, la validation permet de s'assurer de l'adresse IP, mais certaines machines sont multi-utilisateurs). Elle rappelle aussi que SAVI est une technique relativement légère et que, même si elle était massivement déployé, il ne faudrait pas utiliser les adresses IP source comme authentiques. La seule solution fiable pour être certain de l'identité de son correspondant est la cryptographie.

Cette section 7 revient aussi en détail sur les conséquences de SAVI pour la vie privée. Une adresse IP peut être vue, dans certains cas, comme une donnée identifiant une personne et le fait de la valider a donc des implications. Le RFC note bien que la validation SAVI ne nécessite pas d'enregistrer de l'information et que, si on réalise cet enregistrement avec des adresses IP, on peut engager sa responsabilité morale et/ou légale.

Aujourd'hui, des fonctions de type SAVI sont présentes dans pas mal de systèmes (par exemple les commutateurs haut de gamme) mais pas forcément toujours activées. Le RFC 5210 contient un compte-rendu d'expériences à ce sujet.


Téléchargez le RFC 6959


L'article seul

RFC 6955: Diffie-Hellman Proof-of-Possession Algorithms

Date de publication du RFC : Mai 2013
Auteur(s) du RFC : J. Schaad (Soaring Hawk Consulting), H. Prafullchandra (Hy-Trust)
Chemin des normes
Première rédaction de cet article le 30 mai 2013


Lorsqu'on détient une clé cryptographique privée et qu'on veut le prouver à un correspondant, la méthode la plus simple et la plus standard est de signer un message avec cette clé et de l'envoyer audit correspondant, qui, en vérifiant la signature, s'assurera qu'on était bien en possession de la clé privée. Mais dans certains cas, signer n'est pas possible. Ce RFC décrit trois algorithmes qui permettent de prouver qu'on connait une clé, sans signer. Il remplace le RFC 2875.

Ce test de POP (Proof Of Possession) est un de ceux que doit faire, par exemple, une autorité de certification, avant de signer un certificat. (Le RFC 4211, annexe C, explique pourquoi c'est important.) Ainsi, une CSR (demande de signature d'un certificat) faite par OpenSSL est signée et cela peut se vérifier :

% openssl req  -verify -in server.csr -noout       
verify OK

Le format CRMF du RFC 4211 et le format PKCS#10 permettent tous les deux d'envoyer une demande de signature de certificat à une AC mais seul CRMF a un moyen d'inclure une POP pour les algorithmes ne permettant pas de signature. PKCS#10 (RFC 2986) n'a rien. Cela existe, de tels algorithmes, ne permettant pas de signature ? Oui, c'est le cas de Diffie-Hellman et de ECDH.

Les trois algorithmes de POP de notre RFC sont le Diffie-Hellman statique en section 4, le logarithme discret en section 6 et l'ECDH statique en section 6. Ne me demandez pas de vous les expliquer, cela dépasse largement mes compétences en cryptographie. Lisez le RFC pour cela. (Et révisez le RFC 6090 pour le troisième, qui utilise les courbes elliptiques.) Notre RFC 6955 fournit les algorithmes et les modules ASN.1 qui les décrivent.

La section 1.1 décrit les changements depuis le RFC 2875. Les deux algorithmes du précédent RFC ont été réécrits pour permettra leur paramétrisation par rapport à la fonction de condensation (obligatoirement SHA-1 dans l'ancien RFC, alors que plusieurs fonctions sont désormais possibles, notamment la famille SHA-2). Et un troisième algorithme a été ajouté, pour ECDH.


Téléchargez le RFC 6955


L'article seul

MinimaLT, un remplaçant réaliste pour TCP, TLS et IPsec ?

Première rédaction de cet article le 26 mai 2013


Il y a des chercheurs ambitieux. En voici qui proposent un protocole qui veut remplacer à la fois TCP et TLS et IPsec. Ils exagèrent ? Pas complètement. Le projet est prometteur (mais encore à ses tout débuts) mais il y a quelques points noirs qu'ils « oublient » de mentionner.

Le projet MinimaLT (à ne pas confondre avec l'application Apple qui s'écrit minimALT) ne semble pas avoir encore publié de code. Il y un article assez détaillé (lien alternatif), un joli poster publicitaire et c'est tout. Donc, pour l'instant, tout est à étudier avec prudence.

À quel problème s'attaque MinimaLT ? Les auteurs estiment que du TCP sans chiffrement est vraiment trop dangereux dans l'Internet d'aujourd'hui et qu'il faudrait du chiffrement partout. Des protocoles comme TLS (RFC 6347) ou IPsec (RFC 4301) visent à fournir de la cryptographie mais souffrent de différentes faiblesses, soit de performance (ce qui amène certains à ne pas imposer TLS, de peur des conséquences sur les délais pour l'utilisateur) ou de complexité (qui utilise réellement IPsec, à part des tunnels point-à-point entre deux sites de la même organisation ?).

MinimaLT vise donc à rendre le chiffrement moins coûteux et plus simple. Le principe de base est de créer à la demande un tunnel chiffré dès que deux machines communiquent. Ensuite, tout le trafic MinimaLT entre ces deux machines (même s'il provient de deux applications sans aucun rapport entre elles) passe par ce tunnel. On ne paiera donc qu'une fois certains coûts cryptographiques, alors qu'avec TLS on les paie à chaque connexion.

Et pour authentifier la machine en face, afin d'être sûr qu'on n'est pas en train de parler au vilain Homme du Milieu ? MinimaLT utilise pour cela des certificats X.509 trouvés dans le DNS. J'en parlerai plus longuement plus loin car c'est le principal point noir de MinimaLT.

Quel est l'intérêt de ces tunnels ? C'est que l'établissement d'un contexte cryptographique (les clés utilisées, notamment) nécessite pas mal d'échanges entre les deux machines et introduit donc une latence importante. MinimaLT (dont le nom veut dire Minimal Latency Tunneling) ne peut pas complètement faire disparaître ces échanges mais il les amortit sur un plus grand nombre de connexions. La première fois qu'Alice parle à Bob, il faudra attendre. Mais le tunnel reste ouvert ensuite et pourra servir aux communications suivantes. L'établissement de ces connexions dans le tunnel pourra être très rapide puisque l'essentiel du boulot a déjà été fait.

Cela a des conséquences dont l'article parle peu : en cas de communications intermittentes, il faut maintenir un état entre deux sessions, et en cas de communications intensives (pensez à Gmail utilisant MinimaLT), il y a beaucoup d'état à maintenir. Mais, surtout, cela rend les comparaisons de performances plus délicates : lorsqu'on mesure le nombre de connexions qu'on peut ouvrir par seconde et qu'on compare MinimaLT avec TCP ou TCP+TLS, on compare des pommes et des oranges... Les résultats présentés dans l'article sont d'autant plus difficiles à lire que les auteurs ne disent pas à chaque fois clairement s'ils mesurent en partant d'un état « froid » (rigoureusement aucun état) ou « chaud » (tunnel déjà établi).

On notera que le tunnel fonctionne sur UDP, afin de réussir à passer les middleboxes qui infestent l'Internet. C'est dommage mais c'est réaliste : la solution architecturalement propre (créer un nouveau protocole de transport) ne serait pas déployable, avec toutes les machines sur le trajet qui se croient autorisées à bloquer tous les protocoles qu'elles ne connaissent pas (SCTP avait le même problème et a fait le même choix, cf. RFC 6951.). MinimaLT doit ensuite réinventer toutes les fonctions de TCP (délivrance des messages garantie, et dans l'ordre, contrôle de congestion) ce qui est beaucoup de travail et offre beaucoup de possibilités d'erreur.

Un gros problème de toute solution de chiffrement est d'établir l'authenticité du pair situé en face. Si Alice croit parler à Bob mais qu'elle parle en fait à Mallory, le chiffrement ne servira à rien. Il faut donc s'assurer de l'identité du pair. Ce point, pourtant crucial, est très vite traité dans l'article. On comprend qu'il existe un annuaire des caractéristiques des machines, comprenant leurs clés cryptographiques et des certificats qui lient ces clés aux noms des machines. Le DNS est utilisé pour réaliser cet annuaire. DNSSEC n'est pas mentionné car la sécurité repose sur la signature des certificats récupérés dans le DNS. MinimaLT reprend donc tous les problèmes de sécurité de X.509, notamment l'absence de lien entre une AC et un domaine (n'importe quelle AC peut signer pour n'importe quel domaine, sans que le titulaire du domaine ne puisse s'y opposer, cf. RFC 6394). À noter que l'idée de mettre des certificats dans le DNS est ancienne mais que l'article ne cite pas un seul des travaux antérieurs (par exemple, DANERFC 6698 - n'est même pas mentionné en passant).

(Un expert en sécurité anonyme me fait aussi remarquer que MinimalLT ne permet apparemment que d'authentifier le répondant, pas l'initiateur de la connexion, contrairement à TLS et IPsec.)

Enfin, il faut préciser que l'interface de MinimaLT avec les applications n'est guère discutée. L'article note à juste titre que les mises en œuvre de TLS sont typiquement trop difficiles à utiliser par les applications, avec trop de possibilités d'erreur entraînant des failles de sécurité (voir l'article « The most dangerous code »). Mais utiliser une autre API veut dire qu'il faudra adapter toutes les applications. MinimaLT est conçu pour un nouveau système d'exploitation, sans base installée, Ethos, donc ce cas ne sera peut-être pas trop un problème. Mais il y a aussi un portage sur Linux où la question se posera.

L'article originel est riche et je n'ai pas parlé de tout, je vous encourage donc à le lire. Une discussion a lieu sur Reddit mais pour l'instant avec peu de contenu. Merci à l'expert sécurité anonyme pour sa relecture de cet article.


L'article seul

RFC 6952: Analysis of BGP, LDP, PCEP and MSDP Issues According to KARP Design Guide

Date de publication du RFC : Mai 2013
Auteur(s) du RFC : M. Jethanandani (Ciena Corporation), K. Patel (Cisco Systems), L. Zheng (Huawei Technologies)
Pour information
Réalisé dans le cadre du groupe de travail IETF karp
Première rédaction de cet article le 25 mai 2013


Dans le cadre du travail du groupe KARP de l'IETF, consacré à la sécurisation des protocoles de routage de l'Internet, ce RFC est consacré à l'analyse de la sécurité des protocoles de routage utilisant TCP, notamment BGP.

Deux petits rappels : KARP travaille sur les protocoles eux-mêmes, ni sur le contenu des informations transmises (c'est le rôle de SIDR, qui a produit le système RPKI+ROA), ni sur les pratiques quotidiennes d'administration des routeurs. Son rôle est d'améliorer la sécurité des protocoles, et pour cela il commence par des analyses de la sécurité des protocoles existants, suivant une méthode décrite dans le RFC 6518. Il y avait déjà eu une analyse d'OSPF (RFC 6863) et ce nouveau RFC s'attaque à des protocoles très différents mais qui ont en commun d'utiliser TCP comme transport : BGP (RFC 4271) et LDP (RFC 5036), ainsi que les moins connus PCEP (Path Computation Element Communication Protocol, RFC 5440) et MSDP (RFC 3618). Ils appartiennent tous à la catégorie un-vers-un du RFC 6518 (les messages d'un routeur sont transmis à un seul autre routeur).

Donc, aujourd'hui, quels sont les risques de sécurité pour ces protocoles et les défenses existantes ? D'abord, ceux et celles spécifiques à la couche transport. Il y a les attaques par déni de service et les attaques où l'ennemi va tenter d'établir une session avec sa victime, sans en avoir normalement le droit. Parmi les contre-mesures (RFC 4732 pour un point de vue plus général), il y a des ACL par adresse IP (tous ces protocoles utilisant TCP, il n'y a normalement pas de possibilité pour un attaquant en dehors du chemin d'usurper une adresse IP, si tout le monde suit bien le RFC 4953 et le RFC 5961) et le fait d'écouter les connexions entrantes uniquement sur les interfaces où on s'attend à avoir des pairs. Pour éviter les attaques de méchants lointains, il y a la technique GTSM du RFC 5082, qui consiste à n'accepter des paquets que s'ils ont un TTL maximal (ou proche du maximum).

Cela ne suffit pas contre des assaillants situés sur le chemin (par exemple parce qu'ils sont sur le réseau local). Ceux-ci peuvent établir une connexion avec une fausse adresse IP, ou bien simplement envoyer des resets TCP pour couper les sessions existantes (notez que TLS ou SSH ne protégeraient pas contre ce dernier risque car ils fonctionnent au-dessus de TCP). Pour assurer l'authentification et l'intégrité de la connexion TCP, on a l'« authentification MD5 » du RFC 2385, normalement remplacée par l'AO du RFC 5925. AO est très supérieur, fournissant notamment l'agilité cryptographique (la possibilité de changer d'algorithme si la cryptanalyse en a trop affaibli un, ce qui est le cas de MD5). Mais AO est loin d'avoir remplacé MD5.

Et puis il y a les problèmes qui ne dépendent pas du transport utilisé, comme l'absence d'un protocole de gestion des clés (KMP pour Key Management Protocol). Actuellement, la gestion des clés dans tous ces protocoles est purement manuelle et, résultat, les clés cryptographiques des routeurs ne sont quasiment jamais changées, même lorsqu'un administrateur quitte la société.

Maintenant, place à chaque protocole individuellement. Le RFC fait une présentation de chaque protocole (section 2), puis de l'état de sécurité idéal qu'on souhaite atteindre (section 3), puis de la différence entre l'état actuel et cet idéal (section 4). Enfin, la section 5 étudie les questions de transition vers une meilleure solution de sécurité (tous ces protocoles étant pair-à-pair, il faut que les deux pairs soient d'accord pour la nouvelle technique de sécurité). Ici, je procède différemment en traitant tous les aspects de chaque protocole successivement (enfin, pas chacun, je ne couvre que BGP et LDP, ne connaissant pas vraiment PCEP et MSDP). Donc, honneur à BGP pour commencer, puisque c'est sans doute le protocole de routage le plus important pour l'Internet (section 2.3). Comme il ne fonctionne que sur TCP, sa sécurité est en bonne partie celle de ce protocole de transport. Autrement, il devra attendre le déploiement d'AO, puis d'un KMP pour que sa sécurité s'améliore.

LDP, lui, est utilisé par MPLS et le RFC général de sécurité sur MPLS, le RFC 5920 est donc une utile lecture, ainsi que la section 5 du RFC 5036. LDP (sections 2.4, 3.1 et 4.1 de notre RFC) peut, lui, fonctionner sur TCP ou sur UDP. Ce dernier sert notamment aux messages Hello d'établissement d'une session. Cet établissement n'est donc pas protégé par les mesures de sécurité de TCP. En fait, il n'existe même quasiment aucune protection pour ces messages. Et pour TCP ? LDP peut utiliser l'authentification MD5 du RFC 2385 mais on a vu que MD5 n'était pas conseillé (RFC 6151 et section 2.9 du RFC 5036) et LDP ne permet pas encore d'utiliser AO (RFC 5925).

L'état de sécurité idéal pour LDP serait clairement un état où les messages Hello seraient authentifiés. En attendant, les contre-mesures minimales sont de n'accepter des Hello que sur les interfaces réseau qui en ont réellement besoin, et d'utiliser GSTM. Cela ne supprime pas toutes les attaques, mais un travail est déjà en cours pour l'authentification des Hello (Internet-Draft draft-zheng-mpls-ldp-hello-crypto-auth).


Téléchargez le RFC 6952


L'article seul

RFC 6963: A Uniform Resource Name (URN) Namespace for Examples

Date de publication du RFC : Mai 2013
Auteur(s) du RFC : P. Saint-Andre (Cisco Systems)
Première rédaction de cet article le 24 mai 2013


Voici un nouvel espace de nommage pour les URN, urn:example, qui servira pour les exemples et la documentation.

Les URN sont normalisés dans le RFC 8141 et offrent un moyen de construire des URI stables et indépendants de toute notion de localisation. L'URN commence par urn: puis par un NID (namespace identifier). Le RFC 3406 définissait trois genres de NID, formel, informel et expérimental (nom commençant par x-, et supprimé depuis par le RFC 8141). Lorsqu'on a besoin d'URN pour une documentation ou un cours, on utilisait en général ces NID expérimentaux. Mais les identificateurs commençant par x- sont désormais mal vus dans le monde IETF (cf. RFC 6648) et ce nouveau RFC propose donc d'abandonner ces NID expérimentaux et, pour les exemples, d'utiliser le NID example. De tels noms réservés pour les exemples sont courants dans les RFC (par exemple le RFC 2606 pour les noms de domaine ou le RFC 5612 pour les numéros d'organisations).

Ainsi, on peut désormais créer comme ça, gratuitement, l'URN urn:example:foo:bar et être sûr qu'il n'entrera jamais en collision avec un « vrai » URN. (Par contre, deux URN example peuvent être accidentellement identiques puisqu'aucune autorité ne les attribue.) Ces URN ne doivent être utilisés qu'à des fins d'exemple et pas pour court-circuiter les mécanismes normaux d'allocation des URN formels et informels, décrits dans le RFC 8141.


Téléchargez le RFC 6963


L'article seul

Le bitsquatting menace-t-il les utilisateurs de l'Internet ?

Première rédaction de cet article le 23 mai 2013


Vous avez confiance dans les composants électroniques de votre ordinateur ? Vous croyez que, lorsque vous tapez ou sélectionnez http://www.impots.gouv.fr/, vous vous retrouverez bien là où vous pouvez déclarer vos revenus ? Vous avez tort. L'électronique, c'est fragile. Un bit 1 peut se changer en 0 subitement (ou le contraire) et, à partir de là, le http://kremlin.ru/ se change en http://kremlin.re/... C'est le bit flipping (le changement de la valeur d'un bit), qui permet le bitsquatting (l'enregistrement par un méchant d'un domaine proche d'un bit du domaine dont on veut détourner le trafic).

Mais pourquoi un 0 se transformerait-il en 1 subitement ? Il existe des tas de raisons physiques possibles, d'un rayon cosmique (la Terre en reçoit en permanence) à la radioactivité en passant par la simple agitation thermique. Moins il y a d'atomes pour faire un bit (avec les progrès de la miniaturisation) et plus le risque est important. Mais les ordinateurs n'ont pas de moyen de se défendre, de la redondance, des contrôles ? Si, cela existe, cela se nomme les mémoires ECC mais elles sont plus chères et n'équipent pas les engins de bas de gamme. Ceux-ci, bon marché mais connectés à l'Internet, sont de plus en plus nombreux.

Quels sont les changements possibles ? En regardant la table ASCII, on voit que e est représenté par 01100101 et u par 01110101. Un changement du quatrième bit suffit donc à passer de la Russie à l'île de la Réunion comme dans l'exemple ci-dessus. Mais le bit flipping ne change pas que des lettres en lettres. Par exemple, n est représenté par 01101110 et le point par 00101110. En changeant le deuxième bit, on change tout dans le nom de domaine. windowsupdate.com peut devenir wi.dowsupdate.com en modifiant un seul bit. Même chose entre o (01101111) et la barre oblique (00101111). Un https://ecampus.phoenix.edu tapé dans un navigateur peut devenir https://ecampus.ph/enix.edu, qui est dans un tout autre TLD.

Mais les protocoles de sécurité comme X.509 ou DNSSEC ne vont pas s'y opposer ? Si le bit flipping avait lieu dans le réseau, sans doute. Mais il a souvent lieu dans la machine originale. Auquel cas, ces protocoles ne peuvent pas aider, le problème étant dès le début. S'il a lieu dans le réseau, notons que les simples mécanismes de contrôle existants comme la somme de contrôle UDP suffisent à l'attraper.

Bon, le bit flipping est possible. Est-il fréquent ? Pose-t-il un vrai problème en pratique ? La première question est délicate car on ne connait pas le nombre de fois où un nom de domaine est manipulé et copié dans une machine. Même si le pourcentage de bit flipping est très faible, il faut le multiplier par le nombre de machines existantes et par le nombre de fois qu'elles tripotent des noms de domaine. En fait, personne ne sait vraiment.

Et le risque de sécurité ? C'est que quelqu'un de mal intentionné n'enregistre le nom avec un bit changé et n'intercepte alors du trafic légitime, comme dans l'exemple du Kremlin ci-dessus. L'expérience (voir la bibliographie) montre que ces noms bitsquattés attirent effectivement du trafic, même s'il n'est pas toujours facile d'être certain de son origine. À la dernière réunion OARC à Dublin, Jaeson Schultz a présenté une entreprise de bitsquatting de grande envergure, afin d'étudier le phénomène, et ses mesures semblent indiquer que le bit flipping est plus répandu qu'on en le pensait.

Il a aussi étudié le passé et montré que wwwnfacebook.com, bitsquatting de www.facebook.com, avait été enregistré deux ans avant la publication du premier papier sur le bitsquatting. Cela ne veut pas dire que celui qui a fait l'enregistrement connaissait le phénomène du bit flipping, peut-être le domainer a-t-il essayé beaucoup de noms et constaté empiriquement que celui-ci recevait du trafic.

Mais il est difficile de faire la part de ce qui est du vrai bit flipping. Il peut s'agir de fautes de frappe (Schultz note que des domaines très éloignés sur le clavier mais proches en bits reçoivent eux aussi du trafic, donc les fautes de frappe n'expliquent pas tout) ou d'un simple bruit de fond (enregistrez n'importe quel nom de domaine, vous aurez du trafic).

L'article de Schultz contient aussi des suggestions de techniques pour limiter le bitsquatting mais aucune ne me semble réaliste. J'en ai quand même déployé une dans le source de cet article : les noms de domaine dans les URL sont en majuscules (il y a moins de possibilités de bit flipping en majuscule).

Un peu de bibliographie :

Enfin, un script Python pour afficher les variantes bit-flipées d'un nom, bitflip.py :

% python bitflip.py  labanquepostale
mabanquepostale
nabanquepostale
habanquepostale
dabanquepostale
lcbanquepostale
lebanquepostale
libanquepostale
lqbanquepostale
lacanquepostale
...

L'article seul

Le DNS va t-il utiliser de plus en plus souvent TCP ?

Première rédaction de cet article le 20 mai 2013


Le DNS utilise traditionnellement surtout UDP comme protocole de transport. TCP est parfaitement légal mais, en pratique, il a été cantonné aux transferts de zone et à quelques requêtes où la réponse était trop grosse pour passer en UDP. La montée des attaques utilisant le DNS avec réflexion et amplification a changé les choses et de plus en plus de gens se demandent si le DNS ne va pas utiliser TCP plus fréquemment.

Écartons d'abord un mythe encore propagé par certains ignorants : non, le DNS n'utilise pas que UDP. Outre les transferts de zone (cf. RFC 5936), le DNS utilise TCP dès que la réponse est de taille trop importante pour être transmise en UDP. C'est combien d'octets, « trop importante » ? Cela dépend. Autrefois, il y avait une limite en dur à 512 octets. Elle a été remplacée depuis longtemps par l'extension EDNS (aujourd'hui décrite par le RFC 6891) qui permet d'indiquer la taille des réponses qu'on peut recevoir. Le serveur répondeur ayant également sa propre limite, la taille maximale pratique est le minimum de la taille annoncée que le demandeur et de la taille configurée dans le serveur répondeur. Pour la plupart des logiciels DNS, ces deux tailles valent par défaut 4 096 octets, mais peuvent être modifiées. Vous verrez ainsi que les serveurs de noms de .com ont une limite configurée à 1 460 octets. Même si le demandeur propose d'avantage (8 192 octets dans l'exemple suivant), le serveur enverra une réponse tronquée (bit TC mis à un) et le demandeur réessaiera alors en TCP. Voyons avec dig :


% dig +bufsize=8192 @a.gtld-servers.net ANY com.
;; Truncated, retrying in TCP mode.
...
;; flags: qr aa rd; QUERY: 1, ANSWER: 21, AUTHORITY: 0, ADDITIONAL: 16
...
;; SERVER: 192.5.6.30#53(192.5.6.30)
;; WHEN: Mon May 20 17:21:15 2013
;; MSG SIZE  rcvd: 1792

dig a automatiquement réessayé en TCP. Si on lui dit de ne pas le faire :


% dig +bufsize=8192 +noignore @a.gtld-servers.net ANY com.
;; flags: qr aa tc rd; QUERY: 1, ANSWER: 20, AUTHORITY: 0, ADDITIONAL: 1
...
;; SERVER: 192.5.6.30#53(192.5.6.30)
;; WHEN: Mon May 20 17:23:24 2013
;; MSG SIZE  rcvd: 1365

Le tc dans la réponse indique qu'elle a été tronquée (regardez le compteur ANSWER et la taille de la réponse).

Cette possibilité de se rabattre en TCP est cruciale si la réponse est de trop grande taille (ce qui est plus fréquent aujourd'hui, avec IPv6, les IDN et surtout DNSSEC). C'est pour cela qu'il est essentiel de s'assurer que la configuration du réseau permette les requêtes et les réponses TCP, comme exigé par le RFC 7766. C'est aussi pour cela que l'outil Zonecheck a, par défaut, une politique de tests qui impose que le serveur réponde en TCP. (Un point qui a toujours fait l'objet d'un consensus chez les experts à chaque discussion.)

Au fait, pourquoi le serveur a t-il une limite de taille en UDP et pas en TCP ? Car, en UDP, on n'a aucun moyen de garantir la véracité de l'adresse IP source utilisée. Cela permet des attaques par réflexion + amplification, qui ne sont pas possibles en TCP. Limiter la taille des réponses, comme le fait .com, limite donc les dégâts.

OK, bon, on a le droit d'utiliser TCP si on veut. Si un employé ou un consultant en sécurité dit qu'il faut débrayer / bloquer TCP, on sait qu'on peut muter l'employé et virer le consultant, ils ne connaissent pas leur métier. Mais le fait qu'on puisse utiliser TCP veut-il dire qu'il le faut ? Notons qu'un client DNS peut toujours utiliser TCP dès le début, sans attendre une réponse tronquée :


% dig +tcp @a.gtld-servers.net ANY com.
...
;; flags: qr aa rd; QUERY: 1, ANSWER: 21, AUTHORITY: 0, ADDITIONAL: 16
...
;; SERVER: 192.5.6.30#53(192.5.6.30)
;; WHEN: Mon May 20 17:51:26 2013
;; MSG SIZE  rcvd: 1792

Mais quels sont les problèmes si tous les clients DNS faisaient ainsi ? Il y en a deux : bien des réseaux bloquent stupidement les requêtes DNS TCP (cf. le cas du consultant en sécurité incompétent, ainsi que les excellents tests TCP de Zonecheck, cités plus haut). Ensuite, UDP est bien plus léger pour le serveur. Il peut être mis en œuvre sans état (notez que ce n'est pas toujours fait ainsi sur les systèmes modernes) et la même machine peut donc servir bien plus de requêtes par seconde en UDP.

Au dernier atelier OARC à Dublin, le 12 mai, deux excellents exposés étaient revenus sur cette question. Celui de Francis Dupont présentait le problème des performances TCP, les réglages souhaitables sur les serveurs et les clients (ceux par défaut conviennent rarement) et les résultats de ses mesures (après réglages, 30 kr/s en TCP sur une machine qui en fait 130 kr/s en UDP). Cela indique que TCP reste plus lent (ce qui est logique) mais que l'écart est peut-être supportable (le DNS va de toute façon nécessiter des investissements, entre autre en raison des attaques par réflexion). Et des optimisations sont possibles, comme de laisser les connexions TCP ouvertes (c'est l'établissement de la connexion TCP qui est coûteux, et on peut faire passer plusieurs requêtes DNS sur une seule connexion).

Autre exposé très intéressant, celui d'Ed Lewis, exposé très provoquant sur la sécurité du DNS, le genre d'exposé qui remet tout à plat et où personne n'est d'accord à 100 % mais qui disait plein de choses justes, comme le fait que nous serons probablement amenés à dépendre de plus en plus de TCP dans le futur.

Et mon opinion ? Je pense qu'en effet, les défauts d'UDP (notamment en cas d'attaques par réflexion) deviendront de plus en plus insupportables avec le temps et que les problèmes de performance de TCP doivent être relativisés : aujourd'hui, avec l'expérience des serveurs HTTP, faire des serveurs qui encaissent des dizaines de milliers de connexion par seconde n'est plus de la magie noire... Experts TCP, il y aura donc peut-être bientôt du travail pour vous dans le monde DNS.

Vous pouvez aussi lire une bonne étude sur TCP pour le DNS, un exemple de ce qui se passe si on bloque TCP et l'exposé de Huston sur le pourcentage de résolveurs DNS qui savent faire du TCP.


L'article seul

La panne de la RATP et le DNS

Première rédaction de cet article le 16 mai 2013


Aujourd'hui, le site Web de la RATP, http://www.ratp.fr/ a été en panne de 11h à 16h environ (la reprise a été cahotique, avec de nombreuses rechutes jusqu'en soirée). Que s'est-il passé ? Comme pour chaque panne d'un service Internet, c'est l'occasion d'en tirer des leçons pour améliorer la résilience.

Sur les réseaux sociaux, les utilisateurs mécontents ont signalé le problème en disant que « le site Web ne marche pas » ou que « l'appli (pour mobile) ne marche pas ». Mais la vraie cause n'étant pas là. Regardons pendant la panne avec wget :

% wget http://www.ratp.fr/
--2013-05-16 11:52:21--  http://www.ratp.fr/
Resolving www.ratp.fr... failed: Name or service not known.
wget: unable to resolve host address `www.ratp.fr'

Le message d'erreur est clair : le client HTTP wget n'a pas réussi à charger le site car il n'a pas pu résoudre le nom en adresse IP. C'était donc un problème DNS, apparemment. Regardons le DNS pendant la panne avec dig. Quels sont les serveurs de noms de ratp.fr ?

% dig NS ratp.fr
...
;; ANSWER SECTION:
ratp.fr.                3600    IN      NS      indom10.indomco.com.
ratp.fr.                3600    IN      NS      ns1.ratp.fr.
ratp.fr.                3600    IN      NS      indom30.indomco.fr.
ratp.fr.                3600    IN      NS      ns0.ratp.fr.
...

Et demandons à l'un d'eux l'adresse de www.ratp.fr :


% dig @ns0.ratp.fr. A www.ratp.fr
...
;; AUTHORITY SECTION:
www.ratp.fr.            3600    IN      NS      altns1.ratp.fr.
www.ratp.fr.            3600    IN      NS      altns2.ratp.fr.

;; ADDITIONAL SECTION:
altns1.ratp.fr.         3600    IN      A       195.200.228.2
altns2.ratp.fr.         3600    IN      A       195.200.228.130

;; Query time: 4 msec
;; SERVER: 193.104.162.15#53(193.104.162.15)
;; WHEN: Thu May 16 11:53:02 2013
;; MSG SIZE  rcvd: 114

Ah, on n'a pas directement l'adresse mais une délégation. Le DNS repose sur un système arborescent de délégations depuis la racine jusqu'à la machine qui connait la réponse. Dans .fr, il n'y a en général pas de délégation entre le deuxième et le troisième composant du nom de domaine mais, ici, c'est le cas : www.ratp.fr n'est pas dans la même zone que ratp.fr.

Avant de revenir sur les raisons de cette délégation inhabituelle (mais parfaitement légale), continuons la recherche de l'adresse IP de www.ratp.fr :


% dig @altns1.ratp.fr. A www.ratp.fr
; <<>> DiG 9.7.3 <<>> @altns1.ratp.fr. A www.ratp.fr
; (1 server found)
;; global options: +cmd
;; connection timed out; no servers could be reached

Et c'est pareil pour altns2.ratp.fr. La zone n'a que deux serveurs de noms, ce qui est peu, et les deux sont en panne en même temps. Pas étonnant que le nom ne puisse pas être résolu.

Pourquoi ces deux serveurs sont en panne simultanément ? La proximité de leurs adresses IP fait penser qu'ils sont sans doute au même endroit, et qu'ils ont été victimes de la même panne de courant ou de réseau ou de la même attaque par déni de service. La RATP n'a pas suivi un principe de base de la résilience : éloigner les serveurs de noms, pour que la même panne ne les coupe pas tous en même temps. On note que la zone ratp.fr suit les bons principes (quatre serveurs, bien éloignés). Mais www.ratp.fr ne le fait hélas pas.

Mais pourquoi cette délégation relativement inhabituelle du nom www ? Le plus probable est que le site Web se trouve derrière un équipement de répartition de charge et que cet équipement prend également en charge le DNS, changeant les réponses suivant la demande. Une fois le service réparé, on peut d'ailleurs constater que ces engins envoient des réponses avec une durée de vie très courte (300 secondes). Ces équipements conçus pour les gens du Web (qui ne connaissent pas forcément le DNS) sont souvent bogués jusqu'au trognon. Ainsi, un des serveurs répond parfois FORMERR (Format Error) et renvoie une réponse syntaxiquement incorrecte (le Messages has 11 extra bytes at end) :

% dig @altns1.ratp.fr A www.ratp.fr

...
;; ->>HEADER<<- opcode: QUERY, status: FORMERR, id: 12599
;; flags: qr aa rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available
;; WARNING: Messages has 11 extra bytes at end

;; QUESTION SECTION:
;www.ratp.fr.			IN	A

;; Query time: 37 msec
;; SERVER: 195.200.228.2#53(195.200.228.2)
;; WHEN: Thu May 16 22:17:06 2013
;; MSG SIZE  rcvd: 40

Ce comportement disparait si on coupe EDNS.

Merci à Jean-Baptiste Favre pour le premier signalement.


L'article seul

RFC 6949: RFC Series Format Requirements and Future Development

Date de publication du RFC : Mai 2013
Auteur(s) du RFC : H. Flanagan (RFC Series Editor), N. Brownlee (Independent Submissions Editor)
Pour information
Première rédaction de cet article le 15 mai 2013


Cela fait longtemps que le format des RFC est critiqué, à l'IETF ou ailleurs. Pour d'excellentes raisons (détaillées plus loin), ce format est très ancien et très rigide, sans concessions aux gadgets modernes. Il n'a pas encore été possible de le modifier, à la fois en raison des difficultés de prise de décision au sein de la communauté, et aussi parce que le problème est réellement difficile. Contrairement à ce que prétendent certains yakafokon, trouver un format idéal n'est pas trivial. Ce RFC est la première étape d'une tentative de réforme, commençant par un cahier des charges sur les changements souhaitables. Les règles rigides de formatage (longueur des pages et des lignes) disparaissent, l'Unicode fait son entrée dans les RFC, et la possibilité d'inclure des images apparait.

Une des raisons de la stagnation du projet de changement depuis des années était la réorganisation de la fonction de RFC Editor. Désormais, les nouvelles règles sur cette fonction sont écrites (RFC 6635), une nouvelle RFC Editor a pris ses fonctions, jeune et dynamique (Heather Flanagan, un des auteurs de ce RFC), et il va peut être être enfin possible de faire évoluer le format traditionnel. (Depuis cet article, le nouveau format des RFC a été adopté, cf. RFC 7990.)

Le format actuel est documenté dans le RFC 7322 mais à l'époque de notre RFC, c'était le RFC 2223 qui s'appliquait : texte brut sans enrichissement, en ASCII, pages de 58 lignes, lignes de 72 caractères au maximum, pas de notes de base de page, références croisées par numéro de section et pas de page, etc. PostScript était autorisé et quelques RFC ont été publiés ainsi. Une tentative de mise à jour de ce RFC, avec écriture d'une proposition de nouvelle version, avait eu lieu en 2004 mais avait été abandonné. J'avais déjà écrit un article détaillé expliquant le pourquoi du format traditionnel et les raisons pour lesquelles il est difficile à changer.

La section 1 de ce RFC commence par rappeler la longue histoire des RFC. Ils ont commencé il y a plus de quarante ans, et dans les débuts, certains étaient écrits à la main (!), d'autres tapés à la machine, d'autres encore produits par les outils de formatage invraisemblables qu'on trouvait sur les mainframes de l'époque. Résultat, certains sont devenus illisibles avec le temps, les outils tombant en désuétude. Ce problème de permanence est un des problèmes les plus cruciaux pour les RFC et explique pourquoi le RFC Editor n'a jamais été très chaud à l'idée d'utiliser le logiciel à la mode du moment : l'informatique en a déjà enterré beaucoup.

Au bout d'un moment, un format standard a émergé, fondé sur du texte brut et un encodage en ASCII. À partir de là, la série des RFC a vécu une longue période de calme et de stabilité et cette permanence (songez aux formats à la mode vite disparus comme WordPerfect) a beaucoup contribué à son succès. On peut relire aujourd'hui sans problème un RFC de 1980 comme le RFC 768. Ce n'est pas que le format ait été jugé parfaitement satisfaisant par tout le monde, ni qu'aucune proposition de changement n'ait été faite, bien au contraire. Mais aucun des ces propositions n'a connu de consensus : toutes résolvaient un problème précis... en en créant plusieurs autres.

Avant de regarder les propositions actuellement sur la table, il faut bien comprendre qu'il y a plusieurs endroits dans le cycle de vie d'un RFC où un format standard est nécessaire ou utile. Cette terminologie est très importante car l'incompréhension de ces étapes du cycle de vie est l'une des causes principales de la confusion des débats sur la réforme des RFC :

  • Un format de soumission, celui dans lequel le futur RFC est remis par l'auteur au RFC Editor. Aujourd'hui, c'est obligatoirement du texte brut, que l'auteur peut accompagner de XML (RFC 7749) s'il le souhaite.
  • Un format de révision, celui avec lequel travaille le RFC Editor. C'est actuellement du nroff, pour lequel il est de plus en plus dur de trouver des outils.
  • Un format de publication dans lequel le RFC va être distribué au monde. Cette fois, il n'est pas obligé d'être unique. Le même RFC peut être distribué sous plusieurs formats, automatiquement produits. Aujourd'hui, le RFC Editor publie le texte brut et du PDF, d'autres publient du HTML (sur l'excellent http://tools.ietf.org par exemple voici ce RFC), du PDF formaté différemment, etc.
  • Un format canonique qui fait référence en cas de désaccord (rappelez-vous que pas mal de RFC sont des documents normatifs). Actuellement, c'est la version en texte brut.

Évidemment, les choses ont changé depuis (le RFC 2223 date de seize ans...) Quels sont les points qui suscitent le plus de protestations ? D'abord, l'utilisation d'art ASCII et lui seul pour les graphiques. Elle a l'avantage d'encourager les auteurs à écrire des descriptions textuelles claires, plutôt que de passer du temps à faire de jolis dessins. Sans les limitations de l'art ASCII, les diagrammes seraient probablement moins concis. D'un autre côté, des choses comme les automates finis sont vite illisibles en art ASCII et les protocoles où il y a plus de trois acteurs qui interagissent sont difficiles à dessiner. Des graphiques plus élaborés que l'art ASCII permettraient également de représenter des équations mathématiques complexes.

Après les images, le sujet le plus chaud est évidemment l'encodage. ASCII a des tas d'avantages : standard, très répandu, facile à manipuler (outils de recherche, par exemple), plus pratique lorsqu'il faut renumériser un document (oui, le cas s'est déjà produit dans le passé)... Et la langue des RFC étant de toute façon l'anglais, les limites d'ASCII ne sont pas trop graves.

Mais il y a quand même des limites : lorsqu'un RFC parle d'internationalisation (comme le RFC 5890 ou le RFC 6530, ou comme de plus en plus de normes), c'est bien dommage de ne pas pouvoir donner d'exemple lisible dans ce RFC. Devoir écrire U+00c9 pour parler de É est pénible... Des exemples comme ceux de XMPP (RFC 6121, section 5.2.3) bénéficieraient de l'acceptation d'Unicode dans les RFC.

Et certains auteurs de RFC ont des noms qui ne peuvent pas s'écrire correctement en ASCII et ils regrettent de devoir les modifier.

Autres points sur lesquels des gens ont souvent râlé contre le format actuel : la pagination et l'ajustement du texte. La pagination en unités fixes fait vraiment rétro : elle avait un sens quand les RFC étaient souvent imprimés pour être lus mais à l'ère des tablettes, cela semble bien dépassé. Plus compliqué est le cas de l'ajustement du texte. La largeur de colonne fixe qui est la norme actuelle convenait aux VT100 mais pas aux écrans modernes, avec leurs tailles très variables.

Enfin, ce n'est pas tout de définir des formats, il faut aussi des outils qui rendent la production de RFC conforme à ces formats facile (pour avoir une idée des difficultés, lire le RFC 5385). Ces outils doivent-ils être développés à l'IETF ou bien doit-on utiliser des outils standard ? Les exigences de l'IETF sont-elles tellement spécifiques qu'on ne puisse pas utiliser des outils existants ? D'un autre côté, les outils spécifiques donnent plus de souplesse et de pouvoir et, aujourd'hui, il en existe déjà beaucoup (par exemple, la version 2 de xml2rfc - une réécriture complète, abandonnant TCL pour Python, pour produire des RFC suivant le schéma du RFC 7749, est bien meilleure que la précédente) donc on peut dire que le modèle « faisons tout nous-même » marche bien (il y a beaucoup d'informaticiens à l'IETF).

Enfin, s'il y a des réclamations des lecteurs et des auteurs, il y en a aussi du RFC Editor : il voudrait pouvoir abandonner nroff (65 % des RFC aujourd'hui sont soumis au format XML, qu'il faut traduire en nroff au lieu de l'utiliser directement comme format d'entrée pour les différentes publications).

Après les contraintes et les réclamations, les décisions (section 3). D'abord, ce qui ne change pas :

  • Stabilité du RFC une fois publié (jamais de correction mais des errata),
  • Format canonique stable et standard (pas question d'utiliser Word),
  • Le texte brut reste la meilleure solution dans bien des cas donc au moins un des formats de publication doit être le texte brut,
  • Le contenu, par exemple les avertissements juridiques reste comme spécifié dans le RFC 7841.

Ensuite, les nouvelles exigences effectivement retenues, notamment :

  • Documents accessibles même aux personnes en situation de handicap (notez que certaines personnes réclamaient de la couleur dans les RFC, ce qui peut être un problème pour l'accessibilité),
  • Possibilité d'utiliser l'Unicode d'une manière très encadrée, notamment l'ASCII est obligatoire pour le texte normatif (pas de passage global d'ASCII vers UTF-8, mais possibilité d'utiliser UTF-8 par exemple pour les... exemples),
  • Possibilité d'inclure des graphiques en SVG (sous une forme qui reste à déterminer) mais uniquement en noir & blanc,
  • Nécessité de garder un mécanisme permettant des polices de chasse fixe et du texte qui ne s'ajuste pas, pour l'art ASCII et pour les exemples de code source,
  • Format canonique permettant de marquer clairement le code ou assimilé (MIB, ABNF...).
  • Autant que possible, le RFC en cours de révision devrait tenir dans un petit nombre de fichiers (pas une tarball avec des tas de trucs),
  • Le nombre de formats publiés directement par le RFC Editor restera faible, pour que ledit éditeur puisse se concentrer sur le contenu et pas sur la génération de fichiers dans des formats divers.

Et il y a aussi des exigences qui ont été supprimées :

  • La limite de longueur des pages disparait (plus de pages de taille fixe),
  • Même chose pour celle de la longueur des lignes. Ces deux exigences du RFC 2223 ayant disparue, cela ouvre la voie à du texte ajustable,
  • Le contenu ne sera plus obligé d'être à 100 % en ASCII.

Voilà, le cahier des charges est posé, il reste à définir le nouveau format, développer les outils, et déployer le tout... Ce sera pour le prochain épisode. À la réunion IETF 86 a été annoncé le choix de s'appuyer sur le format XML comme format canonique, avec comme formats de publication le texte brut, HTML, PDF et EPUB (voir la FAQ sur ces décisions.) Deux Internet-Drafts sont en cours, un sur le format, draft-rfc-format-flanagan, et un sur le style, draft-flanagan-style. (Depuis, le premier draft a été publié, RFC 7990.)


Téléchargez le RFC 6949


L'article seul

RFC 6946: Processing of IPv6 "atomic" fragments

Date de publication du RFC : Mai 2013
Auteur(s) du RFC : F. Gont (Huawei)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF 6man
Première rédaction de cet article le 15 mai 2013
Dernière mise à jour le 20 juin 2013


Une particularité amusante de la gestion de la fragmentation dans IPv6 est qu'un paquet peut très bien avoir un en-tête de fragmentation sans être fragmenté du tout. Cela se nomme un « fragment atomique » (le terme est très malheureux car il n'a rien à voir avec les « datagrammes atomiques » du RFC 6864). Ils n'ont aucun intérêt pratique mais sont engendrés par certains systèmes lorsqu'ils reçoivent un message ICMP Packet too big indiquant une MTU inférieure à 1280 octets (la taille miminale pour une MTU IPv6). Le problème est que ces fragments atomiques sont ensuite traités par bien des systèmes comme des vrais fragments, permettant ainsi certaines attaques subtiles. Ce nouveau RFC demande donc que les fragments atomiques soient gérés à part, compte tenu de leurs particularités. (Depuis, le RFC 8021 a carrément rendu ces fragments atomiques obsolètes.)

Si vous voulez réviser les règles de la fragmentation dans IPv6, c'est dans le RFC 2460 (depuis remplacé par le RFC 8200, qui a changé ces règles). Contrairement à IPv4, seules les machines de départ (pas les routeurs intermédiaires) peuvent fragmenter. Si une machine de départ doit envoyer un paquet qui est trop grand pour la MTU, elle le fragmente en plusieurs morceaux, chaque morceau indiquant son décalage par rapport au début du paquet original. Même si ce n'est pas explicite dans ce RFC, le recouvrement des fragments était autorisé, ce qui complique sérieusement le réassemblage et pouvait permettre d'échapper à certains IDS. Il n'est donc pas étonnant que le RFC 5722 ait finalement interdit ces fragments recouvrants. Bon, et les fragments atomiques, ils sont fabriqués pourquoi ? La section 5 du RFC 2460 ne laissait pas le choix aux mises en œuvre d'IPv6 : normalement, elles devaient fabriquer un fragment atomique (un paquet qui a l'en-tête de fragmentation, sans pour autant être fragmenté) si la taille indiquée par le paquet ICMP est inférieure aux 1280 octets minimaux d'IPv6 (c'est pour aider certains mécanismes de traduction IPv4<->IPv6). Dans un fragment atomique, le décalage (fragment offset) sera de zéro (puisque ce fragment est le premier) et le bit M sera à Zéro (puisque ce fragment est le dernier du datagramme). Comme ces paquets ICMP Packet too big ne sont pas authentifiés, même quand c'est possible (section 5.3 du RFC 4443 et RFC 5927), un attaquant peut donc faire fabriquer des fragments atomiques assez facilement. Notez que le RFC 8200 a changé cette règle et donc interdit les fragments atomiques.

Ensuite, comme bien des systèmes traitent ces fragments atomiques en même temps que les fragments normaux, ils peuvent, par exemple, être fusionnés avec d'autres fragments prétendant venir de la même source.

Les problèmes de sécurité liés aux fragments sont bien connus : voir notamment le RFC 5722 mais aussi le RFC 6274 qui décrit ces attaques pour IPv4 (beaucoup sont communes aux deux versions). Ce problème est encore aggravé par le fait que certains systèmes génèrent des identificateurs de fragment trop prévisibles, permettant à l'attaquant de savoir où il devra frapper.

La section 4 décrit ensuite les nouvelles règles, visant à résoudre ce problème. En deux mots, en recevant un fragment atomique (que l'on reconnait à la combinaison décalage=0 et bit M =0), on doit le traiter différemment des autres fragments et il ne peut être réassemblé qu'à partir du fragment unique.

L'annexe A contient un tableau listant un certain nombre de systèmes d'exploitation actuels en indiquant s'ils génèrent des fragments atomiques, et s'ils mettent en œuvre ce RFC (les traitent différemment des autres fragments). La plupart des systèmes génèrent ces fragments atomiques lorsqu'ils reçoivent le faux paquet ICMP Too big (une exception est NetBSD). Et plusieurs d'entre eux (Linux récent, NetBSD, OpenBSD) suivent déjà la recommandation de ce RFC et ne sont donc normalement pas vulnérables aux attaques décrites ici.

Si vous voulez tester vous-même, l'outil frag6 dans la boîte à outils SI6 permet de le faire facilement. D'abord, on envoie un fragment incomplet qui est le premier du datagramme :

# frag6 -v -i em0 --frag-type first --frag-id 1234 -d $MACHINE_UNDER_TEST

Dans une autre fenêtre, et avant l'expiration du délai de garde pour le réassemblage (60 secondes par défaut), on envoie un fragment atomique de même identificateur (1234 ici) :

# frag6 -v -i em0 --frag-type atomic --frag-id 1234 -d $MACHINE_UNDER_TEST

Si les fragments atomiques sont réellement traités à part (ce que notre RFC exige), ce qui est le cas sur un FreeBSD >= 9 ou un Linux >=> 3), le fragment atomique est « réassemblé » avec lui-même et on obtient une réponse :

ICMPv6 echo Reply from $MACHINE_UNDER_TEST (RTT: 5 seconds)

Si on n'a pas cette réponse, c'est que le système en face traite incorrectement les fragments atomiques avec les autres. Dans les deux cas, système correct ou non, le premier fragment ne sera jamais réassemblé et, au bout des 60 secondes, on aura :

Response from $MACHINE_UNDER_TEST: ICMPv6 Time Exceeded error message (Reassembly timeout: 60 seconds)

Et rappelez-vous que, normalement, les mises en œuvre d'IPv6 ne doivent plus générer de fragments atomiques depuis le RFC 8021.


Téléchargez le RFC 6946


L'article seul

RFC 6943: Issues in Identifier Comparison for Security Purposes

Date de publication du RFC : Mai 2013
Auteur(s) du RFC : D. Thaler (Microsoft)
Pour information
Première rédaction de cet article le 10 mai 2013


Utiliser des identificateurs (noms de domaine, URI, noms d'utilisateur, adresses de courrier, etc) comme clés d'accès à des informations de sécurité est courant. Par exemple, on autorise machin@truc.example et lui seul à accéder à certains contenus. Cela implique une comparaison entre l'identificateur présenté et ceux stockés dans une base. En apparence, rien de plus simple que de comparer deux chaînes de caractères. En réalité, il existe plein de pièges, que documente ce RFC de l'IAB. Si tout le monde n'utilise pas exactement le même algorithme de comparaison (et certains sont mal spécifiés ou mal connus et permettent donc des variations), alors on peut avoir aussi bien des dénis de service (utilisateur légitime refusé) que des augmentations de privilèges (utilisateur illégitime accepté).

L'informaticien naïf peut croire que comparer deux identificateurs, c'est simplement faire une comparaison bit à bit de leur représentation mais non, c'est plus compliqué que cela.

Pour comprendre le problème, la section 1 du RFC commence par parler du cycle de vie d'un identificateur. Il est d'abord généré, par exemple par une autorité centrale. Il est ensuite souvent stocké en deux endroits, chez l'utilisateur qui va s'en servir et dans une base des identificateurs enregistrés. Par exemple, si c'est une autorité centrale qui a fabriqué l'identificateur, elle le met dans sa base de données (cas, par exemple, d'un registre de noms de domaine). Naturellement, il y a des tas de possibilités différentes. Par exemple, un identificateur peut être une clé publique cryptographique, générée localement et stockée de même.

L'identificateur est ensuite distribué à ceux et celles qui en auront besoin. Cela peut se faire par des moyens numériques mais aussi par des moyens traditionnels comme une carte de visite ou une communication téléphonique. Pensez à un URL que l'on utilise dans des publicités, dans l'espoir que des gens tapent ensuite cet URL dans la barre d'adresse de leur navigateur. Ce passage par des moyens de communication non numériques est une des sources de problèmes car taper correctement un identificateur lu en vitesse sur le flanc d'un autobus n'est pas trivial.

Enfin, quelqu'un va utiliser cet identificateur. Par exemple, il va essayer d'envoyer un message à barack@whitehouse.gov et espère que cela atteindra la boîte aux lettres de quelqu'un de l'équipe du Président. Ou bien un utilisateur va récupérer un identificateur et essayer de le comparer avec celui qu'il connait. C'est le cas d'un navigateur Web voulant valider un certificat X.509 (RFC 6125).

À noter qu'il existe plein d'autres complications possibles. Par exemple, une entité peut être désignée par plusieurs identificateurs (ce RFC est à la fois http://www.ietf.org/rfc/rfc6943.txt et http://www.rfc-editor.org/rfc/rfc6943.txt, un être humain peut être référencé par son numéro de passeport ou bien par son numéro de Sécu). Notre RFC ne se préoccupe pas de ce cas, se limitant à celui, déjà assez difficile, de la comparaison de deux identificateurs pour voir s'ils sont identiques.

Cela peut se faire de trois façons (section 1.1, et voir aussi le RFC 6885 qui avait introduit ces trois cas) :

  • Identificateurs absolus : ce sont les cas idéaux, ceux où une comparaison bit à bit convient. Les adresses IP sous forme binaire sont dans ce cas : si vous mettez 2001:db8:1::1317 dans une ACL, il n'y a aucune ambiguité pour déterminer si l'adresse présentée est égale ou non à celle-ci. (Attention, ce n'est vrai que pour la forme binaire des adresses IP, pas pour leur représentation textuelle.)
  • Identificateurs définis : il existe un algorithme bien défini pour comparer deux identificateurs. Un cas typique est celui d'une comparaison insensible à la casse, par exemple pour les noms de domaine. (Au fait, la section 9.2.1 du RFC 4790 contient d'utiles conseils.)
  • Identificateurs indéfinis : il n'existe pas vraiment d'algorithme pour les comparer. Les noms humains sont dans ce cas (est-ce que George Martin est la même personne que George R. R. Martin ?)

Une technique courante pour faciliter les comparaisons des identificateurs définis est la canonicalisation. On réduit d'abord l'identificateur à une forme canonique et on fait ensuite une comparaison absolue (bit à bit). Pour des noms de domaines, on peut par exemple toujours les passer en minuscules avant de comparer. Dans le cas d'identificateurs Unicode, c'est évidemment plus complexe mais il existe plusieurs algorithmes de canonicalisation Unicode. L'important est que toutes les parties impliquées utilisent le même.

On peut bien sûr comparer sans canonicaliser mais avoir une forme canonique est tellement pratique (par exemple pour l'affichage) que cela vaut toujours la peine d'en définir une. Ce faisant, on définit aussi un algorithme de comparaison.

La section 2 cite des exemples d'utilisation d'identificateurs dans des contextes de sécurité. Par exemple, trouver une clé en échange d'un nom (a principal, dit-on en sécurité), chercher dans une ACL si une entité est autorisée, compter l'activité d'une entité donnée (et il faut donc ajouter son activité dans la bonne ligne du tableau). Le point important est qu'il faut que tout le monde utilise le même algorithme. Si on stocke l'activité d'adresses de courrier électronique sans les canonicaliser, et que quelqu'un change son adresse de jean@durand.example à jean@Durand.EXAMPLE (pourtant la même adresse), il pourra apparaître comme vierge, comme n'ayant pas d'activité précédente.

Les cas réels peuvent être très compliqués. Par exemple, en HTTPS, on compare ce qu'a tapé un utilisateur dans la barre d'adresses du navigateur avec ce que contient le certificat (RFC 6125). Plusieurs protocoles différents sont en jeu (de la définition des URL à celle de X.509) et plusieurs acteurs (des utilisateurs qui tapent plus ou moins bien, sur des systèmes très variés, et tout le monde des AC), chacun de ces acteurs pouvant avoir ses propres règles.

En cas d'algorithmes différents utilisés par des parties différentes, on peut avoir aussi bien des faux positifs que des faux négatifs. Les faux positifs, c'est quand deux identificateurs sont considérés comme identiques alors qu'ils ne devraient pas. (Je me souviens d'un vieux système Unix où le nom de login était silencieusement tronqué à huit caractères, donc bortzmeyer et bortzmeye étaient considérés identiques.) Si les privilèges sont attribués en fonction de cette égalité, on a un gain en privilèges. Si, par contre, les privilèges sont refusés en fonction de cette égalité (cas d'une liste noire), on a un refus d'un service légitime. Le faux négatif, c'est le contraire : deux identificateurs considérés comme différents alors qu'ils sont équivalents (cas de jean@durand.example et jean@Durand.EXAMPLE plus haut, si on oublie que le nom de domaine est insensible à la casse). Les conséquences sont opposées : si les privilèges sont attribués en fonction de cette égalité, on a un refus de service. Si, par contre, les privilèges sont refusés en fonction de cette égalité, on a un gain de privilèges, à tort.

Évidemment, le gain de privilèges est plus grave que le refus de service et c'est pour cela qu'on trouve, par exemple, dans la section 6.1 du RFC 3986 « comparison methods are designed to minimize false negatives while strictly avoiding false positives ». (Cet exemple suppose que les privilèges sont accordés en fonction de l'égalité et que les faux positifs sont bien plus graves.)

Le RFC donne un exemple où les identificateurs sont des URI. La société Foo paie example.com pour accéder à un service nommé Stuff. Alice, employée de Foo, a un compte identifié par http://example.com/Stuff/FooCorp/alice. En comparant des URI, Foo tient compte du fragment (la partie après le #, section 3.5 du RFC 3986) ce qu'example.com ne fait pas. Et Foo permet les # dans les noms de compte. Un autre employé de Foo, le malhonnête Chuck, se fait créer un compte avec l'identificateur http://example.com/Stuff/FooCorp/alice#stuff. Foo ne voit pas le problème puisque cet identificateur n'existe pas. Chuck va donc pouvoir obtenir des autorisations d'accès de Foo. Il peut ensuite se connecter auprès d'example.com comme étant http://example.com/Stuff/FooCorp/alice, l'identificateur d'Alice. Certes, l'autorisation de Chuck n'était valable que pour http://example.com/Stuff/FooCorp/alice#stuff mais rappelez-vous qu'example.com compare les URI en ignorant les fragments... Voici un cas où les différences entre les mécanismes de comparaison d'identificateurs ont permis un accroissement illégitime de privilèges.

Après cet exemple, la section 3 fait le tour des identificateurs les plus courants et de leurs pièges spécifiques. D'abord, les noms de machines. Ce sont normalement un sous-ensemble des noms de domaines (RFC 6055) mais notre RFC utilise ce terme dans un sens plus large, pour parler de tous les fois où un identificateur ou composant d'identificateur est appelé Host. Ils sont souvent utilisés comme identificateurs, soit directement (par exemple dans le RFC 5280), soit indirectement, comme partie d'un identificateur (le RFC cite l'exemple des URI et des adresses de courrier). Le RFC note bien que ce terme de nom de machine (hostname) est ambigu. Ainsi, dans tyrion.lannister.got, le nom de machine est-il tyrion ou bien tyrion.lannister.got (section 3.1 du RFC 1034) ? Cela peut entraîner des problèmes lorsqu'on veut décider si la machine tyrion a accès aux privilèges de la machine tyrion.lannister.got...

Dans le sens large qu'il a ici « nom de machine » peut aussi être une adresse IP littérale. Cela entraîne d'autres confusions possibles. Par exemple, si le TLD .42 existe et qu'un nom 103.2.1.42 est enregistré, comment le distinguer de l'adresse IPv4 103.2.1.42 ? Normalement, la section 2.1 du RFC 1123 règle la question : on doit tester l'adresse IP d'abord et 103.2.1.42 n'est donc jamais un nom. Mais il n'est pas sûr que tous les programmes appliquent le RFC 1123... Certaines personnes pensent donc qu'il y a un risque à accepter des TLD numériques, même si le RFC 1123 est clair.

Autre source d'ambiguité : la norme POSIX 1003.1 de l'IEEE admet pour une adresse IPv4 plusieurs formes, pas seulement la forme classique en quatre composants séparés par des points. Ainsi, 10.0.258, 0xA000201 et 012.0x102 sont des représentations légales de la même adresse, 10.0.1.2. Certaines normes se tirent d'affaire en imposant la forme stricte, celle avec les quatre composants décimaux séparés par des points. C'est le cas des URI, par exemple (« an IPv4 address in dotted- decimal form »). Même chose avec inet_pton qui n'accepte que la forme stricte. Si les différentes formes sont acceptées, on peut avoir un problème d'ambiguité.

Et avec IPv6 ? Il y a également plusieurs représentations texte possibles (mais, à mon avis, moins susceptibles de poser des problèmes en pratique), par exemple 2001:db8::1 et 2001:DB8:0:0:0:0:0:1 pour la même adresse, sans compter des cas plus tordus comme les identificateurs de zone dans les URL (RFC 6874). Contrairement à IPv4, il existe une représentation canonique, normalisée dans le RFC 5952 mais elle n'est pas forcément utilisée par tous.

L'internationalisation (RFC 2277) ajoute évidemment quelques questions. Par exemple, la section 3.2.2 du RFC 3986 autorise un nom de domaine Unicode à être écrit en encodage pour-cent ou en punycode (le second étant recommandé mais pas imposé). Comment comparer caf%C3%A9.fr et xn--caf-dma.fr ? Comme souvent en matière d'internationalisation (qui n'a jamais été complètement acceptée par certains), le RFC pinaille même plus loin en imaginant le cas (purement hypothétique) d'un registre qui accepterait l'enregistrement de noms commençant par xn--, entrainant ainsi une confusion avec des IDN.

Autre façon de comparer des noms : les résoudre en adresses IP et comparer les adresses. C'est ce que fait la bibliothèque standard Java par défaut (classe URL). Cette méthode a évidemment toujours été dangereuse, mais c'est encore pire maintenant, avec les adresses IP privées, les trucs du DNS pour avoir une réponse dépendant de la source, les mobiles, etc. Elle était conçue pour lutter contre des failles de sécurité comme le changement DNS mais le jeu en vaut-il la chandelle ? Sans compter qu'il est contestable d'attendre le DNS juste pour comparer deux identificateurs.

Après les noms de machines, les ports. L'URL http://www.example.com:443/ est-il égal à http://www.example.com:https, https ayant été enregistré (RFC 6335) comme équivalent de 443 ? (Cet exemple est facile : la seconde forme est illégale dans un URL HTTP. Mais, dans d'autres cas, cela peut être ambigu.)

On a souvent vu les URI dans les deux sections précédentes, consacrées aux noms de machines et aux ports. Le principal problème de la comparaison d'URI est qu'un URI est formé de plusieurs composants, chacun suivant des règles de comparaison différentes. Second problème, il existe plusieurs mécanismes standard de comparaison d'URI (RFC 3986, section 6.2, qui décrit l'échelle des comparaisons, de la plus simple à la plus complète). Le but de cette variété est de permettre aux diverses applications des URI d'optimiser pour les performances ou pour la sécurité. L'inconvénient est que deux comparateurs d'URI peuvent donner des résultats différents sans même qu'on puisse accuser l'un d'eux d'être bogué ou non standard.

Certains composants de l'URI posent des problèmes particuliers : les plans définissent la syntaxe spécifique d'un type d'URI et il ne faut donc jamais essayer de comparer deux URI de plans différents (http et ftp par exemple, même si, dans ce cas, la syntaxe est la même). Un autre cas souvent oublié dans les URI est la partie nommée userinfo avant le @, par exemple dans ftp://alice:bob@example.com/bar. Doit-elle être considérée significative en comparant des URI ? Le RFC ne fournit pas de règles à ce sujet.

Le chemin après le nom de machine pose un autre problème, celui des caractères . et .. qui, normalement, indiquent un chemin relatif. Mais la section 5.2.4 du RFC 3986 fournit un algorithme pour les retirer, transformant http://example.com/a/b/c/./../../g en http://example.com/a/g. Un nouveau piège pour la comparaison ?

Continuons vers la fin de l'URI. Après le ? il y a une requête. Doit-elle être prise en compte dans la comparaison ? Là encore, pas de réponse simple, c'est à l'application de décider si http://www.example.org/foo/bar?ref=323 est identique à http://www.example.org/foo/bar. Un exemple où cette question se pose est celle d'un site de référencement d'URI, avec les nombreux cas où la requête ne stocke en fait qu'une variable de suivi de la circulation de l'URI (lu sur Twitter, lu sur Facebook, etc).

Reste le fragment, la dernière partie d'un URI, après le #. En général, lorsqu'on utilise un URI comme identificateur dans un contexte de sécurité, on ignore le fragment (voir l'exemple plus haut avec Chuck et Alice...) Mais ce n'est pas une règle qui marche dans tous les cas. Là encore, l'important est la cohérence : que toutes les applications qui gèrent cet URI fassent pareil.

Comme pour les noms de machine, dans l'exemple Java plus haut, on pourrait se dire qu'une façon simple de comparer deux URI est de les déréférencer et de voir s'ils pointent vers des contenus identiques. Mais tous les URI ne sont pas déréférençables, on n'a pas forcément envie d'imposer une connexion Internet en état de marche juste pour comparer deux identificateurs et, de toute façon, un tel algorithme serait très fragile (que faire si on trouve le même document XML mais avec des encodages différents ?) En outre, toute démarche active comme celle-ci est dangereuse pour la vie privée (elle informe les gérants des serveurs Web de ce que l'on est en train de faire, comme le font les Web bugs).

Après les URI, place à une catégorie d'identificateurs très souvent utilisés pour identifier une entité, les adresses de courrier (RFC 5322 pour leur syntaxe, et RFC 6532 pour le cas où elles sont internationalisées). Une adresse de courrier, comme un URI, a plusieurs parties, qui suivent des règles différentes pour la comparaison. La partie à droite du @ est un nom de domaine et ce cas a été traité plus haut. La partie gauche, dite partie locale, est un identificateur indéfini : ses règles ne sont pas connues à l'extérieur et on ne peut donc pas savoir, par exemple, si rms@gnu.org et RMS@gnu.org sont le même utilisateur, ou si stephane+ps@bortzmeyer.org est le même que stephane+ump@bortzmeyer.org. Dans le cas où des adresses de courrier sont utilisées dans un certificat, on choisit souvent une comparaison bit à bit... qui peut donner plein de faux négatifs.

Après cette liste à la Prévert de problèmes, la section 4 de notre RFC tente une synthèse. Elle identifie quatre problèmes. Le premier est la confusion. Un identificateur est utilisé sans que son type soit clair. Par exemple, si je tape telnet 1000, est-ce l'adresse IPv4 0.0.3.232 ou bien l'adresse IPv6 ::3:e8 ? Et si je tape ping 10.1.2.42, est-ce que 10.1.2.42 est un nom ou une adresse (le TLD .42 peut exister) ?

Résoudre la confusion nécessite un algorithme clair. Dans le premier exemple ci-dessus, il n'y a pas de confusion. 100 ne peut pas être une adresse IPv6 légale (la présence ou l'absence d'un : suffit à les reconnaître). Le second exemple est normalement clair : l'adresse IP a priorité donc 10.1.2.42 ne peut pas être un nom même si le TLD .42 existe. Si cette règle de précédence est respectée par les implémentations, il n'y aura pas de problèmes (identificateurs définis). Mon avis personnel est que ce RFC pinaille quand même très fort sur ce point, en s'interrogeant gravement sur des problèmes théoriquement intéressants mais extrêmement tordus et donc rares en pratique.

Deuxième problème, l'internationalisation. Un logiciel n'a aucun problème à comparer google.com et goog1e.com et à dire qu'ils sont différents. C'est plus difficile pour un humain (vous aviez repéré le L qui était en fait un 1 ?) Toutes les fois où un humain est impliqué, dans la saisie ou la reconnaissance d'un identificateur, ce genre d'erreur peut se produire. Comme le montre cet exemple, cela n'a d'ailleurs rien de spécifique aux chaînes de caractères Unicode. Mais ce problème est souvent cité comme argument contre l'internationalisation. Bref, le point important : la sécurité ne devrait pas dépendre d'une vérification visuelle faite par un humain. (Cf. l'article de Weber et le RFC 6885.)

Problème suivant, la portée. Certains identificateurs ne sont pas uniques au niveau mondial. localhost est un bon exemple. C'est également le cas des adresses du RFC 1918. On peut aussi citer l'adresse de courrier alice qui, utilisée depuis une machine d'example.com arrivera à une Alice et, depuis une machine d'un autre domaine, à une autre. Dans ce dernier cas, la bonne solution est de toujours utiliser une adresse unique (par exemple alice@example.com) même dans un contexte local : l'expérience prouve que les identificateurs fuient souvent d'un domaine local vers un autre.

Enfin, dernier problème identifié par cette section 4, la durée. Certains identificateurs ne sont pas éternels et peuvent disparaître, ou désigner une autre entité. Par exemple, bob@example.com peut désigner un Bob aujourd'hui et, s'il quitte l'entreprise et qu'un autre est embauché, un Bob complètement différent dans quelques mois. C'est la même chose pour les adresses IP et des tas d'utilisateurs ont déjà souffert de se voir attribuer une adresse IP qui avait une mauvaise réputation.

La section 5 résume les conseils les plus importants : se méfier des identifcateurs indéfinis, prévoir une comparaison absolue ou définie pour tous les identificateurs futurs, penser aux mécanismes pour valider les identificateurs (RFC 3696). Le gros risque restera toujours le cas où plus d'un protocole utilise un identificateur donné, car les différents protocoles n'auront pas forcément les mêmes règles de comparaison des identificateurs.


Téléchargez le RFC 6943


L'article seul

RFC 6927: Variants in Second-Level Names Registered in Top Level Domains

Date de publication du RFC : Mai 2013
Auteur(s) du RFC : J. Levine (Taughannock Networks), P. Hoffman (VPN Consortium)
Pour information
Première rédaction de cet article le 7 mai 2013


Beaucoup d'utilisateurs des noms de domaine pensent que deux noms qui, pour eux, sont « le même », devraient être traitées d'un bloc par le DNS et/ou par les systèmes d'enregistrement de noms. Tout le problème est évidemment de définir « le même » : il n'y a en général pas d'accord entre les utilisateurs sur ce point. Ainsi, des anglophones peuvent penser que meter.example et metre.example sont « le même nom » et devraient donc se comporter ainsi. D'autres pensent que pizzeria-napoli.example et pizzerianapoli.example sont « le même nom ». Et, évidemment, depuis l'arrivée des IDN, le potentiel pour des noms « identiques » a encore augmenté. Il a donc été proposé que ces variantes d'un « même » nom soient explicitement reconnues. Ce RFC ne suggère pas de mécanisme en ce genre (je pense personnellement que le problème est bien trop flou et subjectif pour cela). Il se contente de regarder les pratiques actuellement déployées par les registres en matière de « variantes ».

Des exemples de caractères qui sont une « variante » d'un autre ne manquent pas dans les écritures du monde. Ainsi, la Chine a connu sous Mao une réforme orthographique, passant des sinogrammes « traditionnels » aux « simplifiés ». La plupart des sinophones considèrent que et sont des variantes du même mot. Dans les langues utilisant l'alphabet latin avec des accents, certains considèrent que le mot avec et sans accent sont des variantes l'un de l'autre. Le RFC note qu'en français certains omettent les accents sur les majuscules (c'est incorrect, mais cela se fait parfois) et que donc INTERNÉ et INTERNE sont considérés comme « équivalents ». Ce qui est sûr, c'est qu'historiquement, les difficultés à manier les caractères non-ASCII dans beaucoup d'environnements informatiques avaient mené bien des utilisateurs à considérer les accents comme purement décoratifs, et pouvant être omis.

Est-ce que ce vague sentiment que deux groupes de caractères sont « la même chose » peut être formalisé dans une définition rigoureuse des « variantes » ? Il y a eu quelques tentatives comme à l'ICANN, ou à l'IETF dans le RFC 3743 (non standard). Mais un autre document de la même ICANN concluait qu'il n'existait pas de définition utilisable. Ensuite, sur le comportement attendu de deux noms identiques ne fait pas non plus l'objet d'un consensus. Par exemple, si on veut, non pas seulement une réponse identique dans le DNS, mais un vécu de l'utilisateur identique, par exemple sur le Web, il n'y a aucune solution purement DNS (en raison du comportement de HTTP avec le champ Host:). Si vous voulez lire davantage sur cette question, je vous renvoie à mon article « Que veut dire synchroniser deux domaines ? ».

Ce RFC n'essaie donc pas de régler ce problème (très ancien et sans doute insoluble). Il fait un tour d'horizon des pratiques des gTLD (qui sont contractuellement obligés par l'ICANN de rédiger leurs pratiques IDN et de les déposer à l'ICANN, et qui rendent accessibles le contenu de leurs zones, permettant aux chercheurs de l'étudier) et d'un certain nombre de ccTLD. Ces obligations de l'ICANN sont décrites dans « Guidelines for the Implementation of Internationalized Domain Names ». Le RFC note que ces règles ne sont guère respectées, les politiques déposées à l'ICANN étant souvent dépassées et plus à jour (URL cassés, personnes désormais parties, etc). (Mon opinion personnelle est que ces « IDN Guidelines » n'ont aucun sens et sont motivées par des frayeurs bureaucratiques plutôt que par des considérations pratiques.)

Pensez à réviser la terminologie en section 2. Un lot (bundle, on dit aussi IDL package) est un ensemble de noms qui sont tous des variantes les uns des autres (RFC 3743). Un nom est alloué (allocated) ou enregistré s'il est attribué à un titulaire. Il est actif (active) s'il apparait dans le DNS. Il est bloqué (blocked) s'il ne peut pas être alloué du tout et réservé (witheld) s'il ne peut être alloué que dans certaines conditions.

La section 4 décrit les politiques des gTLD (avec vérification dans les fichiers de zone de la réalité de ces politiques). Certains sont faciles : .aero, .coop ou .pro n'ont pas d'IDN (même chose pour .xxx). D'autres ont un grand intérêt pour les IDN. Ainsi, .asia a évidemment une politique IDN détaillée, avec gestion de lots, via les enregistrements NS (les variantes ont le même jeu de NS). .cat a un cas plus simple que .asia puisqu'il ne reconnait qu'une seule langue, le catalan. La liste des caractères autorisés est publiée et elle comprend des caractères comme le l·l (considéré comme un caractère en catalan mais représenté par trois caractères Unicode). Lorsqu'on enregistre un nom IDN, l'ASCII « équivalent » est aussi enregistré et un DNAME (RFC 6672) est mis dans le fichier de zones (il semble que cela soit le seul gTLD à procéder ainsi). Par exemple :

xn--caball-gva.cat.	43200	IN	DNAME	caballe.cat.

Le nom IDN caballé.cat pointant vers l'ASCII caballe.cat (et merci à DNSDB pour permettre l'exploration facile du DNS à la recherche d'exemples).

Contrairement à .asia et a fortiori à .cat, .com doit gérer toutes les écritures du monde. VeriSign a transmis à l'ICANN des tables pour des écritures hiéroglyphiques et pour l'araméen... Les politiques suivies sont décrites en détail dans plusieurs documents (voir la liste dans la bibliographie du RFC). Pour l'écriture chinoise, et pour elle seule, les variantes d'un nom alloué sont bloquées. (.net et .name suivent la même politique que .com.)

.org publie une liste des langues gérées (notez que c'est absurde puisque IDN gère des écritures, pas des langues, mais cette confusion est fréquente dans les cercles ICANN, où il est toujours mal admis que des gens osent utiliser d'autres écritures que celle des États-Unis). Les tables déposées à l'ICANN sont un sous-ensemble de ces tables publiées par le registre (pas de mise à jour ?) Les documentations officielles de .org font allusion à une politique de gestion des variantes mais apparemment sans dire en quoi consiste cette politique.

.tel a beaucoup d'IDN et une politique publique. Les noms avec l'écriture japonaise utilisent un système de blocage (le premier arrivé empêche l'allocation des variantes) alors que pour l'écriture chinoise, les variantes sont publiées (avec des enregistrements NS identiques).

La section 5 passe aux ccTLD. Je ne vais pas tous les citer mais ils ont souvent des politiques intéressantes. .cl publie sa politique, qui ne tient pas compte d'éventuelles variantes.

.cn a évidemment plus de travail : leur politique est publiée sous forme d'un RFC, le RFC 4713. Les variantes sont publiées, avec des enregistrements NS. Par contre, .ir n'a pas d'IDN. Comme un certain nombre de registres des pays utilisant l'écriture arabe (qui va de droite à gauche), ils considèrent que le mélange d'un nom en écriture arabe avec un TLD en écriture latine (allant de gauche à droite) n'est pas souhaitable. (Mais il y a des IDN dans le TLD équivalent en écriture arabe, ایران.)

Bien que TLD d'un pays majoritairement anglophone, .nz a une politique IDN (qui ne parle pas des variantes) pour le maori. On notera que le domaine compte des DNAME par exemple māori.dns.net.nz qui pointe vers l'équivalent ASCII :

xn--mori-qsa.dns.net.nz. 86400	IN	DNAME	maori.dns.net.nz.

Contrairement aux autres ccTLD, il semble que .ru ne publie pas sa politique directement, uniquement via la table déposée à l'ICANN.

La politique utilisée par .fr n'est pas étudiée dans ce RFC. Elle est disponible en ligne. La liste des caractères acceptés figure en section 2 (ce sont les caractères utilisés pour les langues d'Europe de l'Ouest). S'il y a eu un système de variantes pendant la période d'ouverture (section 4), il a ensuite disparu.

Voilà, si vous voulez approfondir la question et voir la politique des autres TLD, consulter ce RFC. J'espère en tout cas avoir donné une bonne idée de la variété des écritures du monde et des solutions pour les gérer dans les noms de domaine.


Téléchargez le RFC 6927


L'article seul

RFC 6944: Applicability Statement: DNS Security (DNSSEC) DNSKEY Algorithm Implementation Status

Date de publication du RFC : Avril 2013
Auteur(s) du RFC : S. Rose (NIST)
Réalisé dans le cadre du groupe de travail IETF dnsext
Première rédaction de cet article le 2 mai 2013


Mais quel algorithme de cryptographie choisir pour mes signatures DNSSEC, se demande l'ingénieur système ? Il y a bien un registre IANA des algorithmes normalisés mais c'est juste une liste non qualifiée, qui mêle des algorithmes de caractéristiques très différentes. Ce nouveau RFC vise à répondre à cette question en disant quels sont les algorithmes recommandés. (Il a depuis été remplacé par le RFC 8624.)

La première liste d'algorithmes possibles avait été faite dans le RFC 4034. D'autres algorithmes avaient été ajoutés par la suite. Certains sont devenus populaires. Par exemple, RSA avec SHA-2 est utilisé pour presque tous les TLD importants et est donc difficilement contournable pour un résolveur validant. D'autres ont été peu à peu abandonnés, parfois parce que les progrès de la cryptanalyse les menaçaient trop, parfois simplement parce qu'ils n'avaient pas un bon marketing.

Aujourd'hui, le développeur qui écrit ou modifie un logiciel résolveur validant (comme Unbound ou BIND) doit donc se taper pas mal de RFC mais aussi pas mal de sagesse collective distillée dans plusieurs listes de diffusion pour se faire une bonne idée des algorithmes que son logiciel devrait gérer et de ceux qu'il peut laisser tomber sans trop gêner ses utilisateurs.

Ce RFC 6944 détermine pour chaque algorithme s'il est indispensable (on n'a pas le droit de faire l'impasse), recommandé (ce serait vraiment bien de l'avoir, sauf raison contraire impérieuse), facultatif (si vous n'avez rien d'autre à faire de vos soirées que de programmer) ou tout simplement à éviter (pour le cas de faiblesses cryptographiques graves et avérées). La liste se trouve dans la section 2.3 : RSA avec SHA-1 est le seul indispensable. RSA avec SHA-1 plus NSEC3 (voir plus loin l'explication de ce cas particulier), RSA SHA-256 ou SHA-512 (connus collectivement comme SHA-2), ECDSA avec SHA-256 ou SHA-384 sont recommandés. Tous les autres sont facultatifs (c'est par exemple le cas de GOST dans le RFC 5933) sauf RSA avec MD5 qui est à éviter (RFC 6151).

La section 2.2 justifie ces choix : RSA+SHA-1 est l'algorithme de référence, celui qui assure l'interopérabilité (tout logiciel compatible DNSSEC doit le mettre en œuvre). Normalisé pour DNSSEC avant l'apparition de NSEC3 dans le RFC 5155, il existe en deux variantes, une sans NSEC3 (celle qui est indispensable) et une avec (qui est recommandée car la plupart des TLD utilisent NSEC3). RSA+SHA-2 est recommandé car, comme indiqué plus haut, la racine et la plupart des TLD l'utilisent. Un résolveur qui ne comprendrait pas ces algorithmes ne servirait pas à grand'chose.

Au contraire, ECDSA est très peu utilisé en pratique. Mais les courbes elliptiques suscitent beaucoup d'intérêt, et sont une alternative au cas où il y aurait un gros problème avec RSA. D'où le statut « Recommandé ».

Des nouveaux algorithmes vont certainement apparaître dans le registre (cf. RFC 6014). Ils seront automatiquement considérés comme facultatifs, jusqu'à la sortie d'un nouveau RFC (qui a été le RFC 8624, qui privilégie désormais les algorithmes utilisant les courbes elliptiques).

Et si vous parlez plutôt la langue de Manuel Puig, ce RFC est également commenté en espagnol.


Téléchargez le RFC 6944


L'article seul

RFC 6929: Remote Authentication Dial In User Service (RADIUS) Protocol Extensions

Date de publication du RFC : Avril 2013
Auteur(s) du RFC : Alan DeKok (Network RADIUS), Avi Lior
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF radext
Première rédaction de cet article le 1 mai 2013


RADIUS, un protocole utilisé pour l'authentification (et la configuration) d'accès à l'Internet, est ancien et marche toujours. Lorsque vous accédez à l'Internet depuis chez vous, sans vous en rendre compte, vous avez probablement indirectement utilisé RADIUS. Il marche toujours très bien mais, rançon du succès, il a été tellement étendu qu'un certain nombre de champs du message RADIUS sont désormais pleins : toutes les options possibles seront allouées très bientôt. Ce nouveau RFC décrit un mécanisme d'extension de RADIUS, permettant de continuer l'enregistrement de nouvelles options, au prix de quelques bricolages.

Il y a peu de gens qui manipulent RADIUS (RFC 2865) explicitement. Ce protocole se trouve en effet caché dans le réseau du FAI, entre la machine qui contrôle l'accès (le NAS) et un serveur RADIUS qui contient les données sur les utilisateurs. RADIUS permet de ne pas avoir à copier les informations d'authentification, ou les paramètres d'un utilisateur donné, directement dans tous les NAS, mais de les centraliser dans un petit nombre de serveurs RADIUS.

La requête, et surtout la réponse RADIUS peuvent contenir un certain nombre d'attributs (RFC 2865, section 5) comme « nom de l'utilisateur », « mot de passe », « adresse IP à attribuer », etc. Le champ « Attribute » est en TLV et le type (User-Name = 1, User-Password = 2, Framed-IP-Address = 8, etc) est encodé sur un seul octet. La liste (un registre IANA) est aujourd'hui bien remplie et devrait l'être complètement en 2014 ou 2015. C'est le principal problème de RADIUS aujourd'hui (section 1 de notre RFC). Mais il y en a d'autres comme le fait que la longueur d'un attribut soit codé sur un octet seulement (donc 253 octets maximum pour la valeur d'un attribut, puisqu'il faut retirer le type et la longueur).

Notre RFC fait donc les changements suivants :

  • Définition du format Extended Type : certains types d'attributs ont désormais ce format, qui inclut un second champ Type d'un octet dans la partie Valeur de l'attribut. Le nouveau type sera donc indiqué par la combinaison du Type et du nouveau champ (donc, deux octets, et le type sera noté N.M où N et M sont les valeurs des deux octets). Ça fait un peu bricolage, mais cela permet l'interopérabilité entre les nouvelles implémentations et les anciennes. Ce format est utilisé par quatre nouveaux attributs (de 241 à 244) et permet donc environ 1000 types nouveaux. La taille maximale des attributs a donc diminué d'un octet mais le deuxième changement, ci-dessous, résoud cela.
  • Définition du format Long Extended Type qui ajoute un octet (après le type) dans le champ Valeur, pour pouvoir ajouter des nouvelles fonctions au protocole. Deux attributs (245 et 246) utiliseront ce format, soit environ 500 possibilités.
  • En utilisant ce format, définition d'un mécanisme permettant de dire que la valeur est stockée sur plusieurs attributs consécutifs. Cette « fragmentation » permettra d'utiliser des attributs de plus de 253 octets. Elle est indiquée par un bit (nommé M pour More, s'il est à Un, cela indique que d'autres attributs suivent) dans le nouvel octet réservé.
  • Les types de données disponibles dans le champ Valeur étaient au nombre de cinq (les classiques, nombre entier, adresse IP, temps, texte et suite de bits). Notre RFC 6929 en ajoute deux, TLV (qui va donc permettre de structurer les données puisqu'un TLV pourra en contenir d'autres, et récursivement) et entier de 64 bits (certaines valeurs, par exemple le nombre d'octets transmis, dans les messages de comptabilité, ne tenaient plus toujours en 32 bits).

Voilà, c'est l'essentiel du RFC. Ceux qui étendent le protocole RADIUS vont sans doute migrer vers les nouveaux types, dès aujourd'hui, ou bien lorsque les anciens seront épuisés.

Des exemples d'encodage figurent en section 9. Par exemple, un attribut utilisant un type étendu (ici, 241.1) et ayant une valeur de type texte (la chaîne "bob") se représentera f1 06 01 62 6f 62 (f1, le type, 241, 06 la longueur totale, 01 le sous-type du type étendu, 1 (à la place du premier octet de la valeur), 62 6f 62 la vraie valeur, la chaîne de caractères). Plus compliqué, un attribut 241.2 contenant un TLV dont le type est 1, la longueur 4 et la valeur 23 45, sera représenté f1 07 02 01 04 23 45.

Avec les étendus longs (Long Extended Type), un attribut 245.1 contenant le même "bob" sera f5 07 01 00 62 6f 62 (f5 est le type, la longueur est de sept octets, 01 est la suite du type, l'octet supplémentaire est à 0 (donc le bit M aussi : pas d'autres attributs à attendre) et la valeur est la chaîne "bob" (62 6f 62 en ASCII). Si un type 245.4 encode plus de 251 octets (ici, 260 octets de valeur), on aura le premier attribut qui commencera par f5 ff 04 80 (longueur totale à 256 octets, l'octet supplémentaire vaut 80, indiquant que le bit M est à Un) et un deuxième attribut qui commencera par f5 13 04 00 (octet supplémenaire à 0 donc bit M à Zéro, ce second attribut est le dernier). La longueur totale est ff + 13 soit 260 octets pour la valeur.

Si vous voulez tester vous-même ces nouveaux types et leur encodage, l'annexe A du RFC contient un programme en C qui permet exactement cela (copie locale du source). Il s'utilise ainsi :

% echo '241.1 "bob"' | ./radius-attr-generator
241.1 "bob" -> f1 06 01 62 6f 62 

% echo '243.2 42' | ./radius-attr-generator
243.2 42 -> f3 04 02 42

# Plus drôle, un TLV dans un TLV :
% echo '241.4 { 1 23 45 } { 3 { 1 ab cd } }' | ./radius-attr-generator
241.4 { 1 23 45 } { 3 { 1 ab cd } } -> f1 0d 04 01 04 23 45 03 06 01 04 ab cd 

Parmi les autres nouveautés du RFC, il y a la formalisation de la convention de nommage informel des attributs : mots séparés par des tirets (par exemple Framed-MTU), attributs spécifiques à un vendeur préfixés par le nom du vendeur (par exemple Starbucks-Latte-Size pour un vendeur nommé Starbucks).

Le changement apporté au protocole n'est pas trivial, mais soigneusement conçu pour maintenir la compatibilité. La section 5 du RFC note toutefois quelques problèmes potentiels. D'abord, certains vendeurs se sont approprié des numéros de types qui étaient marqués comme réservés (et qui sont désormais utilisés pour les types étendus). Comme le notait le RFC 6158, c'est un comportement anti-social. Maintenant que ces numéros réservés sont utilisés, ces attributs spécifiques au vendeur anti-social ne marcheront plus (bien fait).

Autre problème potentiel, il est fréquent que les messages RADIUS soient relayés par un serveur intermédiaire (RFC 2865, section 2.3), notamment en cas d'itinérance. Idéalement, le relais devrait ignorer les attributs qu'il ne comprennent pas. Si, par contre, il rejette les messages contenant ces attributs nouveaux, un client et un serveur conformes au nouveau format ne pourront pas communiquer à travers un tel relais. Notre RFC rappelle bien qu'un relais devrait être transparent et relayer même ce qu'il ne comprend pas.

Les sections 6.6 et 10.3 fournissent les règles d'enregistrement des nouveaux types. Il est recommandé d'y aller mollo : les nouveaux espaces sont plus grands mais pas infinis. Le registre IANA stocke désormais des attributs des nouveaux types.

Devoir ajuster a posteriori un protocole, qui avait été conçu d'une certaine manière, et qui esr assez rigide, est toujours une opération délicate, spécialement lorsqu'il faut maintenir la compatibilité avec l'existant. Des tas de propositions ont été faites depuis des années, pour étendre RADIUS. La section 7 du RFC documente pourquoi celle-ci a été choisie. D'abord, elle est relativement simple, avec peu de modifications du format. Son principal inconvénient est que le format des Long Extended Type est assez baroque.

Quant au mécanisme pour agrandir la taille possible des valeurs, il a d'abord été conçu pour ne pas changer les attributs dont la valeur restait petite. D'après une étude de 2010 (citée en section 7.1) portant sur tous les dictionnaires Radius connus, les entiers représentent près de la moitié des valeurs d'attributs RADIUS publics. En ajoutant les autres types de taille fixe (adresses IP, par exemple), on arrive à plus de la moitié. Il fallait donc éviter de faire payer ces types peu consommateurs en octets.

Plusieurs des mises en œuvre de Radius gèrent déjà ces extensions, par exemple FreeRADIUS. Il faut dire qu'il n'y a guère le choix, vue l'imminence de l'épuisement.


Téléchargez le RFC 6929


L'article seul

RFC 6887: Port Control Protocol (PCP)

Date de publication du RFC : Avril 2013
Auteur(s) du RFC : D. Wing (Cisco), S. Cheshire (Apple), M. Boucadair (France Telecom), R. Penno (Cisco), P. Selkirk (ISC)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF pcp
Première rédaction de cet article le 1 mai 2013


Aujourd'hui, l'utilisateur de l'Internet ne bénéficie que rarement d'une connexion neutre, d'un simple tuyau le connectant à toutes les autres machines de l'Internet. La plupart du temps, il est au contraire bloqué derrière des engins comme les routeurs NAT ou les pare-feux. Par défaut, ces engins bloquent les connexions entrantes, limitant l'utilisateur à un usage type Minitel. Dans ce cas, on a souvent besoin de dire à l'engin sur le trajet « laisse entrer des connexions vers tel port » (par exemple pour le pair à pair). Cela se fait aujourd'hui en général par une interface spécifique (par exemple une page Web d'administration du routeur NAT) ou par le protocole privé UPnP. Il y avait donc une demande pour un protocole standard, adapté aux mécanismes d'aujourd'hui comme les CGN : c'est ce nouveau protocole, PCP (Port Control Protocol).

Voici un exemple de configuration manuelle comme on fait souvent aujourd'hui, via une interface Web, ici celle d'une Freebox : freebox-config-ports.jpg Avec PCP, ces interfaces vont-elles disparaître complètement ?

Le principe est simple : un serveur PCP tourne sur l'engin bloquant (routeur NAT ou pare-feu) et autorise des clients PCP à lui parler et à demander des services comme l'ouverture d'un port entrant, ou comme une durée de vie plus longue pour les sessions en cours. Redonnant du contrôle à la machine de l'utilisateur, il rétablit un peu de neutralité dans le réseau. Avec PCP, on a un moyen propre de gérer un serveur (acceptant des connexions entrantes) derrière un routeur NAT et même derrière un CGN. Rappelez-vous qu'accepter des connexions entrantes n'est pas seulement utile si on a un serveur Web à la maison, c'est également une fonction demandée par les protocoles de voix sur IP comme SIP ou bien par le pair-à-pair.

Une fois que le client PCP a obtenu une réponse positive du serveur PCP (« OK, j'envoie les connexions entrantes sur le port 8080 à 172.19.1.1, port 80, comme tu me l'as demandé »), il peut alors prévenir le reste du monde. Cette information sur le rendez-vous n'est pas gérée par PCP : on se sert de fonctions spécifiques au protocole (SIP REGISTER auprès du mandataire, pour SIP, par exemple), ou bien du DNS (éventuellement avec mise à jour dynamique du RFC 2136 pour cela). Les enregistrements SRV du DNS (RFC 2782) sont la solution idéale, puisqu'ils permettent d'indiquer le numéro de port.

On notera que PCP diminue le besoin d'ALG dans les engins intermédiaires. Une nouvelle application n'aura pas besoin d'attendre que des ALG apparaissent, elle pourra contrôler les connexions dont elle a besoin elle-même, via PCP.

Même si on n'accepte pas de connexions entrantes, qu'on est un pur client, PCP peut être utile. Les routeurs NAT et les pare-feux coupent typiquement la session au bout de N minutes d'inactivité. Pour empêcher cela, les applications qui doivent rester connectées longtemps (SSH, par exemple), envoient régulièrement des paquets keepalive. Avec PCP, ce n'est plus nécessaire, l'application peut dire au serveur PCP « augmente N, s'il te plait ».

PCP est conçu, au contraire d'UPnP, pour une large gamme de besoins : du NAT traditionnel (RFC 3022), au NAPT commun aujourd'hui dans les boxes (cf. RFC 3022, section 2.2), en passant par le CGN (RFC 6888) et des choses plus exotiques comme DS-Lite (RFC 6333 et RFC 6619), NAT64 (RFC 6146), et même NAT66/NPT (RFC 6296).

PCP est prévu pour fonctionner avec les protocoles de transport qui ont la notion de port (UDP, TCP, SCTP, DCCP, etc). Pour les autres (ICMP, RSVP, ESP...), PCP ne fournit que des services partiels.

Autre limitation : PCP suppose que la machine de M. Toutlemonde n'a qu'une seule connexion à l'Internet, passant par l'équipement qui héberge le serveur PCP. Le but est de garantir que l'équipement qui répond en PCP verra bien passer tous les paquets. Ce modèle convient à la maison ou à la petite entreprise actuelle, avec son réseau local connecté via une unique box. Le dessin 1 en section 4 du RFC illustre ce modèle.

Les sections suivantes fournissent les détails du protocole. Celui-ci manipulant souvent des adresses IP, la représentation de celles-ci (section 5) va servir souvent : PCP utilise systématiquement un champ de taille fixe de 128 bits (même pour des adresses IPv4, qui sont alors représentées préfixées du ::ffff:0:0/96), car c'est plus simple.

Une description de haut niveau du protocole est en section 6. À première vue, PCP pourrait être traité comme un protocole requête/réponse (un peu comme le DNS) mais, en fait, comme il n'est pas synchrone (on peut envoyer plusieurs requêtes à la suite et lire ensuite plusieurs réponses), il vaut peut-être mieux le considérer comme un protocole suggestion/notification. Le client PCP fait des suggestions au routeur ou au pare-feu (qui sont donc libres de refuser) et le serveur PCP (le routeur ou pare-feu) envoie des notifications indiquant son état. Dans ce modèle, il y a donc deux flux de données indépendants, un du client PCP vers le serveur et un du serveur PCP vers le client. Bien sûr, l'envoi d'une notification est en général corrélé à une suggestion (elle indique indirectement l'acceptation de la suggestion) mais, je le répète, ce n'est pas synchrone. (Une des raisons de ce choix est de permettre au serveur de résister aux attaques par déni de service en ignorant les suggestions lorsque la charge est trop élevée, laissant le client ré-émettre si nécessaire.) PCP tourne sur UDP (ports 5350 et 5351) et n'a pas de notion de transaction (les messages ne portent pas d'identificateur de transaction.) La notification donne l'état actuel du routeur ou pare-feu. Si le client tient à savoir à quelle suggestion est liée telle notification, il doit examiner le contenu du message et le corréler aux suggestions qu'il a envoyées.

La section 7 indique le format standard de tous les paquets : un numéro de version (aujourd'hui 2), un bit indiquant s'il s'agit d'une question ou d'une réponse, un code indiquant l'opération (la plus importante est sans doute MAP, décrite en section 11), l'adresse IP du client PCP, la durée de vie demandée ou obtenue (pour certaines opérations) et quelques autres informations, qui dépendent de l'opération. Parmi elles, les options, encodées en TLV et enregistrées dans un registre IANA.

Les réponses ont un champ indiquant le code de retour d'une requête. 0 est un succès, tous les autres codes indiquent une erreur. Par exemple, 2 est la réponse à une requête non autorisée (rappelez-vous que le serveur PCP a sa propre politique et n'obéit pas aveuglément à tout ce que demande le client), 3 la réponse à une requête syntaxiquement incorrecte, etc. Ces deux erreurs sont permanentes (renvoyer le même paquet PCP ne changera rien). Mais il existe aussi des erreurs temporaires comme 8 qui indique que le serveur PCP aurait bien voulu répondre favorablement mais qu'il manque de ressources (par exemple de ports libres) pour cela. Ré-essayer automatiquement, après un délai raisonnable, peut donc être une bonne solution.

Le fonctionnement de base de PCP figure en section 8. Le client PCP doit d'abord trouver le serveur. Il a pu le connaître par configuration statique, ou tout simplement l'apprendre via une option DHCP (RFC 7291). Sinon, il tente le routeur par défaut, qui sera en général le serveur PCP. Le client va ensuite générer un message, où l'adresse IP du client est sa propre adresse IP (qui sera souvent une adresse privée, du RFC 1918). La section 16.4 explique comment connaître cette adresse grâce à getsockname(). Le client doit être prêt à retransmettre (section 8.1.1 pour les détails) : UDP ne garantit pas l'acheminement.

Le serveur reçoit la requête, vérifie qu'elle arrive sur la bonne interface (le CPE typique de M. Toutlemonde, par exemple, n'acceptera pas les requêtes PCP venant de l'Internet, uniquement celles venant du réseau local), vérifie que l'adresse du client dans le paquet correspond à l'adresse IP source (autrement, c'est qu'un NAT supplémentaire se trouvait accidentellement sur le chemin) et répond. Il inclus dans la réponse un champ Epoch qui est un compteur s'incrémentant une fois par seconde. Si le client voit ce compteur diminuer, cela indiquera que le routeur a probablement redémarré, et donc perdu toutes les correspondances enregistrées, qu'il va falloir re-créer.

C'est quoi, ces « correspondances » (mappings dans la langue de George Martin) ? Le routeur NAT maintient une table des correspondances entre un couple {adresse IP interne, port interne} et un couple {adresse IP externe, port externe}. Cette table est en partie remplie automatiquement lors des connexions sortantes mais peut aussi être partiellement gérée par PCP. Par exemple, le fonctionnement classique du NAT d'un petit routeur à la maison, lorsqu'un paquet venant de {192.168.10.10, 5623} sort, est de réserver un port pour cette session (mettons le port 7891) et de mémoriser une correspondance {203.0.113.254, 7891} <=> {192.168.10.10, 5623} (on suppose que l'adresse IPv4 externe du routeur est 203.0.113.254). Avec cette correspondance en tête, le paquet de réponse destiné à {203.0.113.254, 7891} sera automatiquement NATé et dirigé vers {192.168.10.10, 5623}. PCP permet de manipuler de telles correspondances et, par exemple, pour reprendre un exemple donné plus haut, de dire « envoie les connexions entrantes sur le port 8080 à 192.168.10.1, port 80 », ce qui se traduira par la création d'une correspondance (mapping) {203.0.113.254, 8080} <=> {192.168.10.11, 80}. On notera que le client PCP n'a pas indiqué l'adresse externe 203.0.113.254. PCP permet de le faire mais, dans le cas le plus courant, le client PCP ne connait pas cette adresse et laisse le serveur la choisir.

La section 10 résume les opérations les plus importantes de PCP, MAP (détaillée en section 11) et PEER (détaillée en section 12). MAP permet de créer les correspondances statiques, pour gérer un serveur, PEER permet notamment de manipuler les correspondances dynamiques, celles crées automatiquement par le routeur NAT. La liste de toutes les opérations est dans un registre IANA (cf. section 19.2, sur la politique d'affectation des codes numériques correspondants.)

Prenons l'exemple d'un serveur du réseau local (comme {192.168.10.11, 80} dans mon exemple), qui va appeler MAP pour « ouvrir » le routeur ou pare-feu aux connexions entrantes. En pseudo-code :

/* Les variables précédées de & sont des pointeurs, pour pouvoir
écrire un résultat dans la variable. */
externalport = 80;
pcp_send_map_request(myport, myaddr, &externalport, &externaladdr,
                requestedlifetime, &assignedlifetime);

if (!pcp_response_received())
      panic("No answer"); 
}
else {
    /* Éventuellement mettre à jour le DNS, un serveur de rendez-vous,
    pour dire au reste du monde qu'il peut y aller */
}

/* La suite est le code habituel, sans PCP */
if (received_incoming_connection_or_packet())
            process_it(s);

Si l'application se moque du port externe attribué, il suffit de ne pas l'indiquer dans la requête et de regarder dans la réponse quel port a été alloué. De toute façon, le routeur ne lui allouera pas forcément le port demandé. Par exemple, pour un CGN, tout le monde voudra sans doute s'allouer le port 80, ce qui n'est pas possible. Soit le CGN le refusera à tous, soit il le donnera au premier arrivé et allouera un autre port pour les suivants. Un client PCP bien fait doit donc être préparé : il doit lire le port effectivement attribué et réagir intelligemment s'il n'a pas eu le port souhaité (ce n'est pas fait dans le programme d'exemple ci-dessus). Bien sûr, le client PCP doit aussi être prêt à ce que sa requête soit complètement rejetée, par exemple parce que la table des correspondances a une taille fixe et que ladite table est pleine.

La lecture de la réponse permet aussi au client PCP de savoir quelle est l'adresse externe allouée, ce qui peut être pratique. (Si on n'est intéressé que par cela, il suffit donc de créer une correspondance avec une très courte durée de vie et de lire la réponse.)

La réponse PCP inclut la durée de vie de la correspondance (champ Lifetime du paquet, variable assignedlifetime du programme plus haut). C'est la responsabilité du client de renouveller la correspondance avant qu'elle n'expire (cf. section 15).

Si l'application ne sait pas si elle est derrière un routeur NAT ou un pare-feu, ce qui est fréquent, la solution recommandée est quand même d'essayer PCP. S'il n'y a pas de réponse, cela peut vouloir dire que la machine a une connectivité complète (sans NAT) ou malheureusement que le routeur ne gère pas PCP. (Le code plus haut suppose que l'absence de réponse indique qu'on n'a pas de connectivité en tant que serveur, donc panic().)

Le routeur doit créer des correspondances ayant la sémantique Endpoint Independent Filtering, ce qui veut dire que cette correspondance sera la même quelle que soit l'adresse IP de la machine distante. Il va devoir aussi se débrouiller pour que les messages ICMP correspondant à cette correspondance soient bien acheminés à la machine.

Outre les champs génériques communs à tous les paquets PCP, MAP a quelques champs qui lui sont propres notamment le port interne (la variable myport dans le pseudo-code), le port externe suggéré (la variable externalport dans le programme en pseudo-code) et l'adresse IP externe suggérée (rappelez-vous que le petit routeur NAT de la maison n'a pas le choix : il n'a en général qu'une seule adresse IPv4 externe, donc il ignorera ce paramètre). Dans la réponse à un MAP, la valeur de ces champs indiquera au client ce que le serveur PCP a finalement choisi (pas forcément ce qui était demandé). Une option de la requête permet de dire si les adresses et ports suggérés sont impératifs (on préfère un échec plutôt qu'une correspondance avec d'autres valeurs que celles demandées) ou pas (cf. section 13.2).

MAP permet aussi de contrôler un pare-feu, avec son option FILTER (section 13.3) où on décrit les adresses IP et ports autorisés, le reste étant bloqué. Séparer la fonction de NAT de celle de pare-feu est essentiel : actuellement, les routeurs NAT typiques mélangent les deux, ce qui a mené certaines personnes à croire que le NAT avait un rôle de protection. Outre la sécurité, FILTER peut être utile pour des machines sur batterie : elles éviteront ainsi de gaspiller du courant à traiter des paquets non désirés.

PCP est également utile au cas où on n'a certes besoin que de connexions sortantes mais où on veut influencer des paramètres comme la durée de vie des correspondances créées automatiquement, de manière à ne pas avoir besoin d'envoyer de temps en temps des paquets keepalive. On utilise pour cela l'opération PEER. Cette opération a à peu près les mêmes champs que MAP mais les correspondances crées peuvent avoir des sémantiques autres que Endpoint Independent Filtering. (MAP a le code 1 et PEER 2, dans le registre IANA.)

Un autre usage de l'opération PEER est pour re-créer des correspondances perdues. Un des plus gros inconvénients du NAT est qu'il maintient un état dans le routeur. Normalement, l'Internet est un réseau de paquets, les routeurs intermédiaires font passer les paquets mais n'ont aucune notion de session associées, il font passer du TCP, de l'UDP ou n'importe quel autre protocole sans faire de différence. Un des avantages de ce principe est que le redémarrage d'un routeur ne change rien : les connexions TCP, par exemple, continueront comme si rien ne s'était passé, l'état des connexions étant entièrement contenu dans les machines terminales. Le NAT change tout cela : si un routeur NAT redémarre, toutes les correspondances sont perdues. Si les machines tentent de continuer la communication, de nouvelles correspondances seront créées, avec de nouveaux numéros de port, et ce changement cassera les connexions TCP en cours. C'est notamment insupportable pour SSH.

Comment PCP peut-il aider ? Une machine qui connait la liste des correspondances (elle a pu l'apprendre avec l'opération PEER) peut, lorsqu'elle détecte un redémarrage du routeur, lui renvoyer cette liste (toujours avec PEER mais, cette fois, en remplissant les champs Suggested Address et Suggested Port), rétablissant ainsi la même table des correspondances (section 14). À noter que, pour accélérer la reconstitution de l'état du routeur, un routeur qui sait qu'il va redémarrer peut aussi envoyer des paquets PCP avec l'opération ANNOUNCE (section 14.1.3) pour prévenir les clients. Ces envois se font aux adresses multicast 224.0.0.1:5350 et [ff02::1]:5350 (224.0.0.1 et ff02::1 voulant dire « toutes les machines du réseau »). Les machines clientes peuvent alors savoir qu'elles vont devoir recréer leurs correspondances (après avoir attendu un délai aléatoire, pour éviter qu'elles ne le fassent toutes en même temps).

PEER peut enfin créer une nouvelle correspondance mais cela n'a pas un grand intérêt, puisque tout routeur NAT sait le faire automatiquement au premier paquet d'une nouvelle connexion sortante. (La seule exception est le cas cité plus haut où on restaure l'état d'un routeur NAT qui a redémarré.)

Je ne connais pas l'état actuel de mise en œuvre de PCP dans les routeurs NAT typiques. Pour le programmeur qui veut s'y mettre sérieusement, la section 16 contient un certain nombre de conseils pratiques, aussi bien pour l'écriture de serveurs que pour celle de clients PCP. Quant à la section 17, elle se penche sur les problèmes de déploiement de cette nouvelle technologie. Par exemple, il est important que le routeur rejette les paquets entrants dont l'adresse source ne correspond pas à celles du réseau interne (RFC 2827) pour éviter qu'un méchant n'usurpe une adresse IP.

Tiens, puisqu'on parle de sécurité, la section 18 lui est entièrement consacrée. PCP permet de contrôler plus finement les correspondances dans le routeur, voire de modifier les filtres d'un pare-feu. Il est donc essentiel que ces nouvelles possibilités ne se fassent pas au détriment de la sécurité. Par exemple, une machine du réseau interne autorisée à créer ou modifier des correspondances peut voler le trafic d'une autre. Ce n'est pas très grave pour un réseau local à la maison mais bien plus embêtant dans le cas d'un grand CGN.

PCP, s'il est correctement mis en œuvre, est protégé contre les attaquants situés en dehors du chemin. Par exemple, si une machine quelque part sur l'Internet envoie un paquet PCP prétendant venir d'une des adresses internes (mettons 192.168.1.1), le routeur/serveur PCP rejettera ce paquet qui arrive par l'interface externe (il ne doit accepter les requêtes PCP que si elles sont internes). Par contre, un attaquant interne a à peu près open bar avec PCP. Un serveur PCP doit donc être déployé uniquement si toutes les machines internes sont considérées comme membres de la même bande (une supposition raisonnable pour un réseau domestique) ou si on peut séparer les clients en plusieurs domaines, empêchant M. Michu de voler le trafic de Mme Toutlemonde, située derrière le même CGN.

Une façon de limiter les risques est que le serveur PCP ne configure explicitement que des correspondances qu'il aurait de toute façon configuré implicitement, lorsqu'une nouvelle connexion sort. Cela veut dire qu'il y a des opérations PCP sûres (créer une correspondance sans spécifier le port et l'adresse externes) et d'autres qui peuvent être dangereuses (créer une correspondance avec un port externe spécifié).

Si on autorise PCP à configurer un pare-feu, il faut évidemment faire encore plus attention. Il n'existe pas à l'heure actuelle de mécanisme de sécurité standard pour PCP : son premier domaine d'application concerne des cas où il n'y a déjà pas de sécurité aujourd'hui. Pour d'autres domaines, il faudra trouver de nouvelles solutions de sécurité.

Quelques autres attaques possibles avec PCP :

  • Risque d'attaque par déni de service contre le serveur PCP, par exemple en créant tellement de correspondances qu'on remplit la table qui les garde en mémoire. Le RFC préconise des limites par machine (du genre, « N correspondances PCP maximum par machine »).
  • Risque, en cas de redémarrage d'un routeur NAT, qu'un attaquant rapide ne re-crée une correspondance, avant la machine qui l'avait créée, volant ainsi le trafic. L'attaquant doit agir vite (avant que la victime n'ait re-créé les correspondances) mais c'est possible.

PCP est le successeur d'un protocole très proche nommé PMP (Port Mapping Protocol, RFC 6886). L'annexe A décrit la coexistence entre les implémentations de PMP qui restent, et PCP. L'autre protocole qui avait été envisagé par le groupe de travail PCP était bien sûr UPnP, mais qui était techniquement moins proche de ce qui était souhaité (non routé, peu sécurisé, peu fiable). PMP utilisant les mêmes ports, des dissecteurs de paquets analysent parfois le PCP sous le nom de PMP.

Aujourd'hui, on trouve très peu de mises en œuvre de PCP déployées. Aucun système d'exploitation n'a de client PCP en série. Une solution possible sera peut-être (suggestion de Gunther Ozerito) de faire un relais UPnP <=> PCP comme décrit dans le RFC 6970. Sinon, Wireshark va bientôt avoir un dissecteur PCP (il vient d'être développé et sera livré avec la future version 1.10 ; un autre, sous forme d'un greffon en Lua, est disponible). Attention, Wireshark a aussi un dissecteur pour un autre PCP (Performance Co-Pilot Protocol).

Et j'ai bien envoyé des paquets PCP à ma Freebox, mais je reçois toujours une triste réponse ICMP port 5351 unreachable d'où je déduis qu'elle n'a pas encore de serveur PCP. (Et elle ne diffuse apparemment rien vers le port 5350.)

Au fait, pour les envoyer, j'ai utilisé ce (très grossier) script Scapy, qui est loin de remplir tous les champs mais permet quelques tests :

from scapy.all import *

# http://www.secdev.org/projects/scapy/doc/build_dissect.html
class PCP(Packet):
       name = "Port Control Protocol"
       fields_desc = [ ByteField("Version", 2),
                       BitField("R", 0, 1), # 0 = Request / 1 = Response
                       BitField('Opcode', 1, 7), # MAP is 1, PEER is 2
                       ShortField("Reserved", 0),
                       IntField("RequestedLifetime", 0),
                       LongField("ClientAddressUpper", 0),
                       LongField("ClientAddressLower", 0)
                       ]

p = IP(dst="192.168.2.254")/UDP(sport=0,dport=5351)/PCP(RequestedLifetime=5000,
                                                ClientAddressLower=232236033)
sr1(p)

Un bon article d'introduction sur PCP est « New Technology Demo: PCP » dans le numéro 7.2 de l'IETF Journal.


Téléchargez le RFC 6887


L'article seul

RFC 6935: IPv6 and UDP Checksums for Tunneled Packets

Date de publication du RFC : Avril 2013
Auteur(s) du RFC : M. Eubanks (AmericaFree.TV LLC), P. Chimento (Johns Hopkins University Applied Physics Laboratory, M. Westerlund (Ericsson)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF 6man
Première rédaction de cet article le 1 mai 2013


Ne dites plus qu'en IPv6, la somme de contrôle est toujours obligatoire dans les en-têtes des paquets UDP. Depuis ce RFC 6935, ce n'est plus vrai dans tous les cas. Lors de l'encapsulation de paquets dans un tunnel UDP, on a désormais le droit de ne pas mettre de somme de contrôle dans les paquets UDP, essentiellement pour des raisons de performance.

Le principal demandeur de cette modification était le protocole LISP (RFC 6830), qui dépend énormement de tunnels UDP. Même si le calcul de la somme de contrôle Internet est rapide (RFC 1071), comme ce calcul peut se faire des millions de fois par seconde pour un routeur très actif, on peut chercher à l'économiser. D'autant plus qu'il n'est pas forcément utile puisque, dans le cas d'un tunnel, le protocole qui circule dans le tunnel est déjà protégé par une somme de contrôle. À noter que d'autres protocoles que LISP (comme ceux utilisés pour le multicast) peuvent bénéficier de cette nouvelle indulgence. Mais elle ne s'applique pas aveuglément à tout UDP (comme l'avaient proposé certains au début de la discussion), uniquement aux tunnels.

La norme actuelle sur IPv6, le RFC 2460, imposait (dans sa section 8.1) une somme de contrôle pour les paquets UDP (en IPv4, elle était facultative). En effet, IPv6 n'a pas de somme de contrôle dans la couche 3 (contrairement à son prédecesseur).

Ce RFC est un produit du groupe de travail IETF 6man, qui produit inlassablement d'innombrables RFC pour combler tous les petits problèmes qui trainent encore dans IPv6 et sont révélés par son utilisation dans le vrai monde.

Notez bien que cette dispense de somme de contrôle n'est pas générale : elle concerne les cas où il y a un tunnel et où il utilise UDP. Pourquoi UDP, alors qu'il existe des protocoles de tunnel qui s'en dispensent ? Parce que l'Internet est hélas de plus en plus ossifié, et que des middleboxes stupides et boguées sont partout sur le trajet des pauvres paquets. Les techniques de tunnel directement sur IP (comme l'excellent GRE du RFC 2784) sont souvent bloquées, alors qu'UDP passe partout. On aura donc un protocole X (LISP ou un autre) à l'intérieur du tunnel et de l'UDP à l'extérieur. Hier, cet UDP à l'extérieur était forcément protégé par une somme de contrôle. Pour un routeur qui sert de terminaison à des dizaines de milliers de tunnels (ce qui n'aurait rien d'étonnant avec LISP), calculer et vérifier ces sommes peut être très douloureux. D'autant plus que le protocole X a souvent sa propre somme de contrôle : ne serait-ce pas mieux pour tout le monde que le tunnel soit non sécurisé, ses éventuelles corruptions de paquets étant détectées par le protocole X uniquement ?

La section 4 discute plus en détail de certains aspects du problème mais il vaut mieux consulter le RFC 6936 pour tout savoir. Cet autre RFC précise notamment dans quels cas supprimer la somme de contrôle est une bonne idée et dans quels cas il vaut mieux la garder. La section 4 de notre RFC note particulièrement que les paquets de contrôle du tunnel, ceux qui servent à la signalisation, devraient rester protégés (s'ils sont corrompus, le tunnel peut cesser de fonctionner, c'est-à-dire que la corruption d'un paquet va affecter d'autres paquets). Notons que certains protocoles de tunnel comme GRE n'ont aucun mécanisme de contrôle. Lorsqu'il y en a un, il est souvent utilisé pour établir un contexte au début, avec choix des paramètres pour le tunnel : ce peut être le bon moment pour négocier le non-usage des sommes de contrôle sur les paquets de données.

Autre piège rigolo : certaines middleboxes vont tiquer en voyant les paquets UDP sans somme de contrôle (bien que, normalement, la somme de contrôle soit de bout en bout et ne regarde pas ces équipements intermédiaires). Bien que ce soit désormais légal, il va falloir attendre longtemps avant que tous ces engins soient mis à jour (section 4.3). En attendant ce jour, il est prudent que le tunnel détecte les problèmes en envoyant des paquets avec et sans somme de contrôle au début : si seuls les premiers passent, c'est qu'on a une middlebox agressive sur le trajet et qu'il faut renoncer à appliquer ce RFC 6935. Le test est d'ailleurs à répéter de temps en temps : la route peut changer et on peut donc se retrouver soudain à traverser une nouvelle middlebox.

La section 4.1 conseille également de tenter de détecter la corruption avant de décapsuler, par exemple en examinant l'adresse IP source, pour minimiser le risque d'envoyer au protocole encapsulé un paquet reçu corrompu. Mais cette détection ne marchera pas à tous les cas (sinon, on pourrait supprimer les sommes de contrôle dans tous les cas) et le protocole encapsulé doit donc être robuste et réagit proprement lorsque ces paquets corrompus sont injectés dans un flux existant (section 4.2).

La section 5 contient la nouvelle norme pour les sommes de contrôle UDP. Elle remplace le texte du RFC 2460 (qui disait que la somme de contrôle UDP était toujours obligatoire en IPv6) par un texte plus nuancé : par défaut, la somme de contrôle doit être calculée et mise dans le paquet. Mais on peut s'en dispenser dans le cas de tunnels (et uniquement celui-ci), sur le paquet extérieur. Le protocole à l'intérieur du paquet (qui n'est pas forcément de l'UDP et même pas forcément de l'IPv6) doit rester protégé par sa propre somme de contrôle. Cela ne doit s'appliquer que pour une liste explicite de ports (ceux utilisés par le tunnel) et pas pour tout le trafic UDP de la machine. Et le tout doit se faire en lisant le RFC 6936 qui précise les conditions d'application de cette nouvelle règle.

Les curieux et les chercheurs en informatique noteront que la section 6 liste des points qui mériteraient davantage d'étude. Ainsi, il n'y a pas eu d'étude systématique de la corruption de paquets sur l'Internet depuis 2000 et personne ne sait donc trop si c'est un phénomène fréquent ou pas. Cette section note aussi qu'il existe en théorie une meilleure solution pour les tunnels, UDP Lite (RFC 3828), mais que sa probabilité de passer les middleboxes est plus faible que celle d'UDP.

Plusieurs des mises en œuvre de LISP envoient déjà des paquets UDP sans somme de contrôle (ou plus exactement avec une somme à zéro).


Téléchargez le RFC 6935


L'article seul

RFC 6888: Common requirements for Carrier Grade NATs (CGNs)

Date de publication du RFC : Avril 2013
Auteur(s) du RFC : S. Perreault (Viagenie), I. Yamagata, S. Miyakawa (NTT Communications), A. Nakagawa (Japan Internet Exchange (JPIX)), H. Ashida (IS Consulting G.K.)
Réalisé dans le cadre du groupe de travail IETF behave
Première rédaction de cet article le 1 mai 2013


Qu'on les approuve (ce qui n'est pas mon cas) ou pas, les CGN, ces gros routeurs NAT installés dans le réseau du FAI et gérant des centaines ou des milliers de clients, sont d'ores et déjà une réalité douloureuse dans de nombreux pays d'Asie, pour les pauvres utilisateurs de la 3G, et peut-être demain sur d'autres continents pour les accès fixes. Pour limiter les dégâts qu'ils causent, ce RFC 6888 pose un certain nombre de règles que devraient respecter ces CGN.

D'abord, qu'est-ce qu'un CGN ? Fonctionnellement, il ressemble au petit routeur NAT (RFC 2663) que vous avez chez vous. Comme lui, il fait du NAPT (Network Address and Port Translation), c'est-à-dire qu'il traduit dynamiquement des adresses IP du réseau interne vers celles utilisées à l'extérieur (et vice-versa pour les paquets dans l'autre sens). La grosse différence avec le petit routeur ou box chez vous est qu'il travaille pour de nombreux clients du FAI. Au lieu que l'adresse IP externe soit partagée uniquement entre les membres de votre cercle de famille, elle sera partagée avec des centaines d'inconnus.

Avec le CGN, il y a souvent « double NAT », une fois dans le CPE et une fois dans le CGN. Mais ce n'est pas obligatoire. Lorsqu'il y a double NAT, on parle souvent de NAT444 (deux traductions, d'IPv4 en IPv4).

Sur cette image, on voit du double NAT. Un FAI gère un CGN. cgn Les adresses IP publiques du FAI, allouées par son RIR sont ici 198.51.100.0/25. Ce sont celles qui seront vues, par exemple, par les sites Web où se connectent les clients du FAI. Le FAI n'a pas assez d'adresses IP publiques pour son réseau interne et il utilise donc le 10.0.0.0/8 du RFC 1918. Prenons maintenant le client 1 : son réseau local a des adresses dans la plage 192.168.3.0/24. Les paquets seront donc émis avec ces adresses, NATés une première fois par la machine CPE 1, vers l'adresse 10.0.5.22. Ils seront ensuite NATés une seconde fois par le CGN.

Le CGN a des conséquences, par exemple dans le domaine légal (en théorie, vous pourrez voir les agents de la HADOPI débarquer chez vous parce qu'un autre utilisateur du même CGN a téléchargé illégalement, cf. RFC 6269). Et cela limite sérieusement les activités que vous pourrez avoir sur l'Internet. Par exemple, un moyen courant d'accepter les connexions entrantes, normalement interdites par le NAPT, est de configurer sa box pour rediriger tel numéro de port vers tel service sur le réseau local (par exemple pour faire fonctionner des applications pair-à-pair). Le routeur CGN étant partagé entre de nombreuses personnes qui ne se connaissent pas, cela n'est plus possible. Contrairement au routeur NAT à la maison, le CGN n'est pas géré par les abonnés, qui ne peuvent pas modifier sa configuration.

D'autre part, la simple taille du CGN en fait un engin compliqué et fragile, et sa panne affecte bien plus de clients que le redémarrage d'une box. Enfin, ayant moins de ports sources à sa disposition par client, par rapport au routeur de la maison ou du SOHO, il risque plus souvent de tomber à cours, si les clients font beaucoup de connexions sortantes.

Mais, alors, pourquoi met-on des CGN ? Juste pour embêter les clients ? En fait, les FAI n'ont pas forcément beaucoup le choix. La pénurie d'adresses IPv4, bien que niée par beaucoup de négationnistes, est réelle depuis de nombreuses années. Par exemple, cela fait longtemps qu'on ne peut plus avoir une adresse IP par machine à la maison. Mais, jusqu'à récemment, on pouvait encore avoir une adresse IP publique par foyer. Désormais, l'espace d'adressage IPv4 disponible se resserrant chaque jour, ce n'est même plus le cas. S'il n'y a pas d'adresse IPv4 publique disponible pour chaque client, le CGN est la seule solution pour pouvoir continuer à faire de l'IPv4 (passer à IPv6 ferait moins de travail mais les acteurs du marché sont frileux).

Cela, c'était la raison avouable pour mettre des CGN. Il y en a une moins avouable, c'est que le CGN, grosse machine centrale et point de passage obligatoire pour tous les abonnés, est bien en phase avec la mentalité des opérateurs telco traditionnels. C'est ainsi que, dans l'Internet mobile où les libertés sont bien plus limitées, et l'utilisateur bien plus restreint dans ce qu'il a le droit de faire, tous les opérateurs 3G ont déployé cette solution depuis longtemps, refusant de donner une adresse IPv4 publique à chaque abonné, même avant l'épuisement complet des réserves. Comme le note prudemment le RFC, « there are driving forces other than the shortage of IPv4 addresses ».

À noter qu'un RFC décrit le déploiement de CGN comme une des techniques pouvant aider à la transition vers IPv6 : RFC 6264. Le CGN est un des composants de la solution DS-Lite, décrite dans le RFC 6333 et ce composant doit donc suivre les règles données plus loin.

Maintenant qu'on a présenté les CGN, que contient ce RFC ? Il liste des conseils qui, s'ils étaient appliqués, rendraient les CGN un peu moins insupportables. Comme le note la section 1, la publication de ce RFC ne signifie pas que l'IETF approuve ou même accepte les CGN, simplement que, puisqu'ils existent, autant essayer de limiter leurs effets négatifs. Comme un CGN est un routeur NAT, les précédents documents du groupe de travail Behave, concernant tous les types de NAT, s'appliquent aussi au CGN : RFC 4787, RFC 5382 et RFC 5508 notamment.

Les section 3 à 5 représentent donc le cœur de ce RFC. Elles contiennent les recommandations spécifiques pour les CGN. Chacune est nommée REQ-n où n est un numéro d'ordre. Ainsi, REQ-1 dit que, pour chaque protocole de transport, le CGN doit suivre les recommandations spécifiques à ce protocole (RFC 4787 pour UDP, RFC 5382 pour TCP, RFC 5508 pour ICMP, et RFC 5597 pour DCCP). Notons que les autres protocoles de transport (comme SCTP) ont donc de sérieuses chances de ne pas fonctionner au travers du CGN.

Exigence suivante, REQ-2, qui dit que le comportement de l'IP address pooling doit être paired. Cela signifie quoi ? Qu'une machine donnée doit toujours obtenir la même adresse IP externe (un CGN, contrairement au petit routeur NAT de la maison, a en général plusieurs adresses IP externes à sa disposition). Cela limite les risques de casser les applications. Le RFC 4787, section 4.1, donne les détails sur ce concept de paired.

À propos du nombre d'adresses externes disponible pour le CGN : REQ-3 exige que ces adresses puissent être en nombre quelconque et dans des plages non-contigües (avec l'épuisement des adresses IPv4, il sera de plus en plus dur de trouver des plages contigües).

REQ-4 traite un problème spécifique aux CGN, que n'avaient pas les petits routeurs NAT de la maison : il faut pouvoir limiter le nombre de ports utilisables par un utilisateur donné. Dans le NAPT, il y a moins d'adresses externes que d'adresses internes. On se sert donc des ports pour désambigüiser. Un seul utilisateur gourmand pourrait lancer plein de sessions et épuiser à lui seul la plage de ports disponibles (cela peut même être volontaire, pour faire un déni de service, cf. section 8). C'est pour se protéger contre cette attaque que REQ-4 exige une limitation, configurable, par client. Le RFC recommande aussi qu'on puisse limiter le rythme de création de sessions par utilisateur. C'est nécessaire pour protéger les autres utilisateurs, mais c'est un bon exemple des inconvénients du CGN, qui casse sérieusement la transparence du réseau et le principe de bout en bout. Les routeurs NAT cassaient ces principes mais uniquement entre membres d'un même foyer ou d'un même SOHO. Avec le CGN, on dépend de gens dont on ne connait rien.

Même chose avec REQ-5, consacrée à d'autres ressources partagées dans le CGN, comme sa mémoire. Un CGN a des problèmes d'équité que n'ont pas les routeurs NAT classiques, vue son utilisation entre personnes qui n'ont rien en commun a priori.

Parfois, les cibles que vise l'utilisateur sont situées dans le réseau du FAI, et donc atteignables sans traduction d'adresse. Pour ce cas, REQ-6 demande que le CGN puisse être configuré pour ne pas traduire si la destination est dans une liste d'adresses configurées par l'administrateur réseaux.

Lorsqu'un routeur NAT accepte des paquets entrants du moment qu'il a, dans sa table des traductions, une entrée pour ce couple {adresse,port} de destination, indépendemment de l'adresse IP source d'émission, on dit qu'il fait du Endpoint-Independent Filtering (RFC 4787, section 5). REQ-7 souhaite que ce soit le comportement du CGN, car il casse moins d'applications (notamment jeux en ligne et pair-à-pair) que le Address-Dependent Filtering (où les paquets sont refusés si l'adresse source n'est pas celle dans l'entrée de la table).

REQ-8 légifère sur la réutilisation d'un port externe lorsqu'il n'est plus utilisé. Par défaut, il devrait rester réservé pendant deux minutes, le Maximum Segment Lifetime de TCP (RFC 793, section 3.3), après lequel on est sûr que le paquet ne traîne plus dans le réseau. Cela permet d'éviter une collision entre une ancienne correspondance et une nouvelle, qui utiliserait le même port externe et recevrait par erreur de vieux paquets. Des exceptions sont prévues, notamment :

  • Si le CGN met en œuvre la machine à états de TCP, il peut savoir quand une connexion est terminée et réutiliser alors tout de suite le port,
  • Si certains ports sont statiquement affectés, ils restent utilisables en permanence.

REQ-9 est plus ambitieux car il exige quelque chose qui n'existe pas dans les CGN actuels : un mécanisme permettant à l'utilisateur de changer les affectations de port, et que ce mécanisme soit de préférence PCP (Port Control Protocol, RFC 6887). Aujourd'hui, sur les petits routeurs NAT de la maison ou du SOHO, ce mécanisme d'affectation manuelle des correspondances {adresse externe, port externe} -> {adresse interne, port interne} est typiquement fait par l'interface Web d'administration du routeur, ou bien par UPnP. La disparition d'un tel mécanisme dans les CGN actuels est un des plus gros problèmes que posent les CGN. Il était donc nécessaire de le rétablir, pour que toutes les applications puissent bien fonctionner. Mais PCP est encore très récent et peu déployé.

REQ-10 concerne plutôt les besoins de l'opérateur plus que ceux des simples utilisateurs : il demande que les routeurs CGN soient gérables (MIB du RFC 4008, etc).

Une autre exigence, REQ-11 concerne le traitement des erreurs. Si un routeur CGN ne peut pas créer une corrrespondance entre adresse+port externe et interne, il doit jeter le paquet et devrait renvoyer un message ICMP Destination unreachable / code 1 (Host unreachable). et déclencher une trap SNMP. Le « devrait » (et pas « doit ») est parce que ces deux types de messages peuvent légitimement avoir un débit limité.

Pourquoi Host unreachable et pas Communication administratively prohibited comme c'était le cas dans le RFC 5508, section 6 ? Parce que le code 1 (Host unreachable) est une erreur « douce » (cf. RFC 1122) et ne coupera pas les connexions TCP en cours entre les mêmes machines (RFC 5461).

En outre, le RFC interdit de supprimer des entrées existantes dans la table de correspondances, ce qui permettrait pourtant de faire de la place pour de nouvelles connexions. C'est parce que la plupart des applications gèrent beaucoup mieux une impossibilté à établir une connexion qu'une perturbation ou une interruption d'une connexion en cours (RFC 5508, section 6).

Un bon routeur CGN devrait pouvoir journaliser son activité. La section 4 encadre cette tâche. La principale question qui se pose est l'identification des clients, si une adresse IP externe est repérée pour son comportement abusif (envoi de spam, écriture d'un commentaire de blog défavorable aux autorités, partage de fichiers musicaux, et autres crimes). Le site distant va noter que « 192.0.2.42 a fait quelque chose de mal » et les enquêteurs vont chercher la personne qui est derrière cette adresse. En raison du CGN, des dizaines ou des centaines de personnes peuvent avoir utilisé cette adresse. Pour que l'enquêteur ait la moindre chance de retrouver le coupable, il faut que le site distant journalise, non seulement l'adresse IP source (comme c'est typiquement le cas aujourd'hui), mais aussi le port source (cf. RFC 6302). Et il faut que le routeur CGN ait journalisé ses correspondances, protocole de transport, adresse+port internes, adresse+port externes et heure exacte. (C'est une obligation légale dans certains pays, par exemple en France avec la LCEN.)

Non seulement c'est très Big Brother comme comportement mais, en plus, cela peut rapidement produire une énorme quantité de données, ce qui ne va pas faciliter la tâche de l'opérateur. C'est pour cela que REQ-12 demande que ce ne soit pas activé par défaut, à la fois pour préserver la vie privée des utilisateurs et pour éviter de remplir les disques durs. (Notez aussi que le RFC ne conseille pas de loguer l'adresse IP de destination, ce qui serait bien pire.)

Et, au fait, comment allouer aux utilisateurs cette ressource limitée, les numéros de ports externes ? La section 5 formule trois exigences. Le problème est que les trois sont contradictoires. REQ-13 dit qu'il faudrait chercher à maximiser l'utilisation des ports (ils sont en nombre limités, 65 536 par adresse IP), REQ-14 (qui a suscité beaucoup de discussions dans le groupe de travail) qu'il faudrait minimiser le nombre d'entrées produites dans le journal, par exemple en allouant toute une plage de ports par adresse IP, et REQ-15 que, pour des raisons de sécurité, il faudrait rendre difficile pour un attaquant la prédiction des ports sélectionnés (RFC 6056). Pas de miracle, ces trois exigences ne peuvent pas être satisfaites simultanément et un routeur CGN doit donc choisir lequel est le plus important pour lui. J'emprunte à Simon Perreault une description de la situation en mai 2013 : « Le CGN de Cisco allouait les ports 100 % dynamiquement, comme un NAT traditionnel, et génèrait donc beaucoup de logs. Mais ceux d'autres vendeurs, dont Alcatel, Juniper et Huawei, [ainsi que Cisco désormais, note de Nicolas Février] allouent les ports en bloc, ce qui génère beaucoup moins de logs au prix d'une légère perte de taux d'utilisation des adresses IPv4 externes. Il y a aussi le deterministic NAT qui alloue les ports statiquement tout en conservant une plage d'allocation dynamique pour les débordements. »

Merci à André Sintzoff pour la relecture technique et la détection d'une grosse faute technique. Merci à Nicolas Février pour ses utiles commentaires, même s'il n'est pas d'accord avec moi sur les défauts du CGN.


Téléchargez le RFC 6888


L'article seul

RFC 6936: Applicability Statement for the use of IPv6 UDP Datagrams with Zero Checksums

Date de publication du RFC : Avril 2013
Auteur(s) du RFC : G. Fairhurst (University of Aberdeen), M. Westerlund (Ericsson)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF 6man
Première rédaction de cet article le 1 mai 2013


Le RFC 2460 qui normalise IPv6 indique dans sa section 8.1 que les paquets UDP sur IPv6 doivent avoir une somme de contrôle (elle était facultative en IPv4) calculée selon le RFC 1071. Dans quels cas est-elle réellement nécessaire ? Peut-on s'en passer parfois ? Ce nouveau RFC discute des conditions qui peuvent permettre de mettre zéro dans le champ Checksum, indiquant qu'on n'a pas utilisé de somme de contrôle. Pour résumer : si on veut se passer de somme de contrôle, cela doit se faire application par application, il faut être sûr qu'on supporte les paquets corrompus ou délivrés à tort, et il faut tester le chemin emprunté pour être sûr que les « nouveaux » paquets passent bien.

Ce RFC discute des solutions à un problème de performance d'UDP et des conditions dans lesquels on peut ne plus mettre de somme de contrôle. Il sert donc d'arrière-plan au RFC normatif, le RFC 6935 qui définit les nouvelles règles pour UDP sur IPv6 (somme de contrôle facultative) et fait donc un choix ferme parmi les propositions discutées ici. Notez toutefois qu'il y a pas mal de recouvrement et de redites entre les deux RFC.

UDP est très utilisé, et pour beaucoup d'applications (le RFC 8085 donne des conseils à ce sujet). Un des usages fréquents est pour construire des tunnels, afin de pouvoir passer à travers les millions de middleboxes stupides qui infestent l'Internet, et qui bloquent souvent tous les protocoles autres que UDP et TCP. Or, un routeur d'entrée ou de sortie de tunnel peut avoir à encapsuler ou décapsuler des millions de paquets par seconde et la génération ou la vérification des sommes de contrôle de chaque paquet peut avoir un effet mesurable sur ses performances (sections 1.3.2 et 1.3.3). D'autant plus qu'il n'est pas toujours possible d'utiliser le matériel spécialisé du routeur pour cela car il ne donne souvent accès qu'aux N premiers octets du paquet (avec N typiquement < 128), alors que le calcul de la somme de contrôle nécessite d'accéder à tout le paquet.

En UDP/IPv4, la solution est de couper la somme de contrôle sur le paquet externe (le protocole interne, qui n'est pas forcément UDP, reste protégé par sa propre somme de contrôle), ce qui est légal en IPv4. Le tunnel devient alors un lien virtuel non fiable, pouvant corrompre des paquets (comme c'est le cas d'un certain nombre de liens physiques). C'est par exemple la solution recommandée pour un gros consommateur de tunnels UDP, LISP. Il est donc tentant de l'utiliser également en UDP/IPv6.

Cela peut poser des problèmes avec certaines middleboxes qui vérifient la somme de contrôle UDP et n'accepteront pas d'y trouver zéro. Décréter que la somme de contrôle UDP en IPv6 devient facultative ne signifie donc pas que ces paquets optimisés pourront voyager dès demain sur tout l'Internet : un certain nombre de pare-feux les bloqueront. Cela peut sembler un problème rédhibitoire (on utilisait UDP justement pour passer facilement à travers les middleboxes puis on réforme les règles d'UDP, créant des paquets qui sembleront illégaux à beaucoup de ces middleboxes) mais il faut noter que la plupart des ces middleboxes ne font pas encore d'IPv6 et que donc les premiers déploiements ont des chances de se faire avec des middleboxes conformes à la nouvelle règle.

À part l'UDP existant, et l'UDP avec somme facultative du RFC 6935, quelles sont les autres technologies disponibles pour des tunnels (section 2 du RFC) ? Il y a UDP Lite (RFC 3828), avec une somme de contrôle qui ne couvre que le début du paquet (et est donc rapide à calculer), et qui est certes mis en œuvre dans le noyau Linux mais qui est peu reconnu par les middleboxes. Il utilise un identifiant (champ Next Header qui identifie en général le protocole de transport) différent de celui d'UDP (136 contre le 17 d'UDP) et est donc souvent bloqué par des pare-feux trop zélés. Il y a les techniques de tunnels génériques comme IP-in-IP et GRE. Elles n'ont pas de somme de contrôle du tout et sont donc rapides. Ce sont les solutions idéales pour les tunnels mais elles aussi utilisent un champ Next Header qui peut ne pas être connu de la middlebox (94 pour IP-in-IP et 47 pour GRE) et ils passent certainement moins souvent qu'UDP (d'où le choix d'UDP pour LISP). Notons aussi que la section 6 déconseille les tunnels récursifs (un tunnel dans un tunnel dans un tunnel...) qui augmentent les risques d'erreur pour le paquet le plus interne (et ajoutent une grande complexité à la fragmentation).

La section 3 examine ensuite les choses qui peuvent aller mal avec la solution retenue par le RFC 6935. Si on ne met pas de somme de contrôle dans le paquet UDP (ou, plus exactement, qu'on met zéro, indiquant qu'on n'a pas calculé de somme et que le récepteur ne doit pas vérifier), et qu'un bit du paquet est modifié, que peut-il se passer d'horrible ? Pour IPv4, la somme de contrôle UDP ne servait qu'à protéger les numéros de port et les données, des informations comme l'adresse IP de destination étaient protégées par la somme de contrôle de la couche 3. Celle-ci a disparu en IPv6 et la somme de contrôle UDP doit donc tout faire. Si elle est erronée, on n'est même pas sûr que le paquet nous était bien destiné (l'adresse IP de destination a pu être modifiée).

Comme l'expliquent le RFC 3819 ou des études comme « When the CRC and TCP Checksum Disagree », la corruption arrive réellement dans l'Internet. Des mesures ont indiqué jusqu'à 1 paquet corrompu sur 10 000 (cela dépend fortement du chemin suivi : le taux de corruption est quasi-nul sur certains chemins). Le RFC note (section 3.2) qu'on ne sait pas exactement où la corruption survient : cela peut être dans la RAM du routeur, sur le câble, dans les récepteurs et les émetteurs optiques ou électriques, etc.

Si c'est l'adresse IP de destination qui est modifiée, le paquet peut n'arriver nulle part, ou bien arriver à une machine qui ne l'attend pas. Si aucun programme n'écoute sur le port en question, le paquet est jeté (et un message d'erreur envoyé à la source, qui sera bien surprise). Si un programme écoute, il va recevoir un paquet invalide. Même chose si c'est le port de destination seul qui a été corrompu. Si l'application n'a pas de mécanisme (comme des numéros de séquence) pour détecter le problème, le paquet invalide pourra être accepté. Donc, une règle importante : une application qui est prête à débrayer les sommes de contrôle UDP doit être prête à réagir proprement si elle reçoit un datagramme envoyé à tort. C'est une des raisons pour lesquelles le RFC exige que la suppression de la somme de contrôle UDP ne se fasse pas globalement, pour toute la machine ou pour toute l'interface réseau, mais uniquement sur requête explicite d'une application majeure et consentante (section 3.5)

Si c'est l'adresse IP source qui est corrompue, le paquet arrivera sans doute à la bonne destination (mais pas à coup sûr, par exemple en cas de filtrage RFC 2827). Si l'application garde en mémoire ses correspondants, le paquet de ce correspondant inconnu sera jeté. Si elle ne le fait pas, si une réponse est envoyée... elle le sera au mauvais correspondant.

Et si c'est l'information de fragmentation qui est corrompue ? Cela peut empêcher le réassemblage (menant à la perte du paquet) mais aussi, ce qui est bien pire, conduire à des réassemblages erronés (par exemple, si le champ ID est modifié, attribuant le fragment à un autre datagramme). Comme le note le RFC 5722, il faut multiplier les tests lors du réassemblage.

Nous avons vu plus haut qu'un certain nombre de boîtiers intermédiaires jetteraient probablement sans autre forme de procès ces « nouveaux » paquets UDP avec une somme de contrôle nulle (ils étaient illégaux avant la sortie du RFC 6935). Il est donc essentiel, pour une application qui veut utiliser cette nouveauté, de tester le chemin et de vérifier que rien sur le trajet ne jette les paquets sans somme de contrôle. Il faut aussi penser à répéter ce test de temps en temps : le chemin peut changer (par exemple parce que BGP l'a décidé) et passer tout à coup par des boîtiers différents. (Et il faut faire le test dans les deux sens, ne serait-ce que parce que le routage n'est pas forcément symétrique.)

Dans tous les cas, il faut se rappeler que la somme de contrôle ne fournit de protection que contre la corruption accidentelle. Ce n'est pas un mécanisme d'authentification, et elle ne protège pas du tout contre un attaquant (qui peut modifier le paquet sans changer la somme de contrôle).

Les règles d'applicabilité sont formalisées dans les sections 4 (pour les implémentations) et 5 (pour l'usage de ces implémentations). Les programmes qui mettent en œuvre UDP sur IPv6 :

  • Doivent, par défaut, calculer une somme de contrôle et la mettre dans les paquets,
  • Doivent permettre de débrayer cette somme de contrôle pour certains ports (ceux utilisés par l'application volontaire),
  • Même dans ce cas, il faut fournir un mécanisme pour permettre à l'application d'envoyer certains datagrammes avec une somme de contrôle (pour les paquets keep-alive, par exemple),
  • Doivent, par défaut, rejeter les datagrammes entrants ayant une somme de contrôle nulle (et le journaliser quelque part),
  • Doivent fournir un moyen de supprimer ce contrôle des paquets UDP entrants, pour certains ports,
  • Vérifier les paquets ICMP entrants qui se réfèrent à un paquet UDP ayant une somme de contrôle nulle, par exemple que les adresses dans le paquet cité dans le message ICMP soient correctes.

Cela, c'était pour l'implémentation d'UDP et d'IPv6 (qui, dans un Unix, est dans le noyau). Maintenant, pour les applications qui l'utilisent, la section 5 dit qu'elles :

  • Doivent se souvenir qu'un paquet UDP/IPv6 sans somme de contrôle n'est pas équivalent à un paquet UDP/IPv4 sans somme de contrôle : IPv4 a toujours une somme de contrôle en couche 3, que n'a pas IPv6. UDP/IPv6 sans somme de contrôle est donc plus risqué et doit n'être utilisé qu'à bon escient.
  • Doivent n'activer la suppression de la somme de contrôle que pour un petit nombre de ports, ceux qu'elles utilisent,
  • Doivent avoir un mécanisme de contrôle d'intégrité au dessus d'UDP, idéalement, ce mécanisme devrait détecter la corruption le plus tôt possible, par exemple pour éviter d'injecter des paquets corrompus dans le flot transporté par un tunnel,
  • Doivent tester le chemin (est-ce que les paquets sans somme de contrôle arrivent bien ?) et fonctionner même si le chemin change et que les paquets passent soudain par une nouvelle middlebox, ayant un comportement différent,
  • Doivent utiliser des paquets avec somme de contrôle pour les contrôles, les tests, etc, pour faire la différence entre une rupture complète du lien, et un problème ne touchant que les paquets sans somme de contrôle.

Voilà, les règles d'applicabilités sont posées. Mais le RFC compte aussi une annexe intéressante, l'annexe A, qui est consacrée aux propositions alternatives. La solution choisie par le RFC 6935 a été d'autoriser les sommes de contrôle nulles. Mais on aurait pu faire différemment. Par exemple, le problème de performance et d'accès à la totalité du paquet aurait pu être traité par les calculs incrémentaux de somme de contôle du RFC 1624 (mais ils ne marchent pas quand il y a fragmentation IP). On aurait pu, comme cité, utiliser un protocole comme UDP Lite, ou UDPTT. Il avait aussi été proposé une mesure unilatérale, qu'un receveur ignore la somme de contrôle, quoiqu'ait mis l'émetteur (c'était plus simple mais il était alors impossible de détecter la corruption, pour tous les paquets). D'autres avaient suggéré une nouvelle option dans un en-tête Destination Options, ce qui revenait, à mon avis, à réintroduire une somme de contrôle en couche 3, ce qu'IPv6 avait délibérement abandonné. De toute façon, beaucoup de middleboxes auraient jeté les paquets avec cet en-tête (qui est rare, en pratique). Ces différentes propositions sont examinées en fonction de plusieurs critères : traversabilité des middleboxes, performances, déployabilité et résistance à la corruption de paquets.

Pour la traversée des middleboxes, l'UDP actuel ou bien un UDP avec un calcul incrémental des sommes de contrôle, est ce qui marche le mieux. Aucun changement à faire. L'UDP sans somme de contrôle du RFC 6935 aura sans doute quelques soucis (actuellement, de tels paquets sont illégaux), ainsi que les paquets avec l'en-tête Destination Options (pourtant légaux). Et les tunnels génériques seront sans doute bloqués par défaut par la plupart des pare-feux, ainsi qu'UDP Lite.

C'est à peu près la même chose pour la déployabilité : l'UDP actuel existe déjà et n'a pas à être déployé. Les sommes de contrôle facultatives du RFC 6935 nécessiteront au moins un changement dans les extrémités (ne pas calculer la somme, ne pas la vérifier) mais aussi dans certaines middleboxes qui se mêlent de vérifier la somme de contrôle, alors qu'on ne leur a rien demandé.

Pour les performances, l'UDP actuel est certainement le pire, puisqu'il faut calculer la somme de contrôle sur la totalité du paquet. C'est bien cela qui a motivé tout ce travail sur la réforme des sommes de contrôle UDP. UDP Lite, qui ne vérifie qu'une partie du paquet, et l'UDP réformé du RFC 6935 ont des bien meilleures performances (c'est aussi le cas des tunnels génériques).

Bref, il n'y a pas de solution parfaite, qui résolve tous les problèmes. Si on veut avant tout passer partout, l'UDP actuel est la meilleure solution. Si on veut une solution propre architecturalement, IP-in-IP est parfait. Si on se préoccupe des performances, l'UDP avec somme de contrôle facultative du RFC 6935 est une bonne approche et reçoit un avis favorable dans ce RFC.


Téléchargez le RFC 6936


L'article seul

RFC 6911: RADIUS attributes for IPv6 Access Networks

Date de publication du RFC : Avril 2013
Auteur(s) du RFC : W. Dec (Cisco Systems), B. Sarikaya (Huawei), G. Zorn (Network Zen), D. Miles (Google), B. Lourdelet (Juniper Networks)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF radext
Première rédaction de cet article le 30 avril 2013


Le protocole RADIUS joue un rôle important dans l'accès à l'Internet : c'est le principal mécanisme utilisé pour faire communiquer la machine qui contrôle l'accès physique avec la machine qui contient la base des utilisateurs et les informations sur les autorisations, les configurations spécifiques... RADIUS avait bien sûr déjà la capacité de transporter des informations IPv6 mais ce nouveau RFC en ajoute quelques unes.

Une petite révision sur RADIUS d'abord (vous pouvez suivre sur la figure 1 du RFC). Lorsqu'un utilisateur accède à l'Internet, plusieurs machines sont utilisées. Il y a d'abord la machine terminale de l'utilisateur, ou bien un petit routeur, nommé RG (Residential Gateway). L'un des deux porte les informations d'authentification (identificateur et mot de passe). Cette machine terminale ou bien se petit routeur se connecte au réseau et parle à un AN (Access Node : dans le cas de l'ADSL, c'est le DSLAM qui sert d'AN, dans le cas d'un accès commuté, c'est le serveur de modems). L'authentification pourrait être faite par l'AN. Mais l'utilisateur ne parle pas toujours au même AN (par exemple s'il est mobile) et puis, on gagne en souplesse en découplant les fonctions d'accès et d'authentification. On a donc un serveur qui stocke les informations d'authentification et les paramètres des clients, le AAA (Authentication, Authorization and Accounting). Entre l'AN et le AAA se trouve souvent un NAS (Network Access Server), un routeur IP (dans certains cas, AN et NAS sont confondus, par exemple pour la plupart des serveurs PPP). Le NAS est client RADIUS et utilise ce protocole pour demander à l'AAA « j'autorise ce client ? » L'AAA, serveur RADIUS, répond oui ou non et ajoute une série d'attributs, qui sont les paramètres de la session, par exemple l'adresse IP à utiliser. Notez que RADIUS ne sert qu'entre le NAS et le AAA. Entre le RG et le NAS, on peut utiliser plusieurs autres protocoles, comme PPP ou, plus courant aujourd'hui, DHCP (RFC 8415).

RADIUS avait déjà des attributs pour IPv6 : le RFC 3162 avait Framed-IPv6-Prefix pour indiquer le préfixe IPv6 à utiliser et Framed-Interface-Id qui, combiné avec la valeur précédente, permettait de fabriquer une adresse IP6 pour l'utilisateur (cette séparation puis recombinaison était plus adaptée à PPP qu'à DHCP, qui donne des adresses entières). Et le RFC 4818 avait Delegated-IPv6-Prefix qui permettait de transmettre un préfixe à déléguer à un routeur par l'option de délégation DHCP du RFC 8415.

Quels sont ces attributs qui manquaient dans les RFC 3162 et RFC 4818 ? La section 3 en fournit la liste, et ils sont désormais notés dans le registre IANA (cf. section 6). Le premier est Framed-IPv6-Address qui permet d'attribuer une adresse IPv6 complète au visiteur (a priori via DHCP). Elle peut apparaître dans les réponses RADIUS, mais aussi dans les questions, pour exprimer un souhait (que le serveur RADIUS peut ignorer). Framed-IPv6-Address peut être envoyé dans une réponse RADIUS en même temps que les anciens Framed-IPv6-Prefix and Framed-Interface-Id (par exemple si le réseau local, derrière le RG, utilise à la fois DHCP et l'auto-configuration sans état - SLAAC).

Le second attribut, DNS-Server-IPv6-Address, indique l'adresse IP d'un résolveur DNS. (Un seul résolveur ; mais la réponse RADIUS peut contenir plusieurs attributs DNS-Server-IPv6-Address, afin de transmettre les adresses de plusieurs résolveurs.) Ces serveurs DNS peuvent ensuite être indiqués aux machines du réseau local par les Router Advertisement du RFC 8106 ou bien en DHCP (RFC 3646).

Ensuite, Route-IPv6-Information permet de spécifier une route statique. L'attribut existant, Framed-IPv6-Route (RFC 3162), ne suffit pas car elle est pour l'usage du NAS, il ne la transmet pas au RG. Au contraire, le nouvel attribut Route-IPv6-Information est prévu pour être redistribué. Le NAS pourra transmettre cette information au RG avec les annonces Router Advertisement du RFC 4191 ou bien une méthode équivalente. Les autres données nécessaires dans l'option Route Information de l'annonce (par exemple la préférence ou la durée de vie), devront être connues du NAS par un autre moyen (ce point a été le plus chaud lors des discussions dans le groupe de travail).

Enfin, dernier attribut, Delegated-IPv6-Prefix-Pool indique le nom d'un pool d'adresses IPv6 à utiliser par le NAS. Là encore, c'est un attribute RADIUS conçu pour être relayé avec DHCP mais qui peut coexister avec Framed-IPv6-Pool, plutôt fait pour les Router Advertisement.


Téléchargez le RFC 6911


L'article seul

RFC 6928: Increasing TCP's Initial Window

Date de publication du RFC : Avril 2013
Auteur(s) du RFC : J. Chu, N. Dukkipati, Y. Cheng, M. Mathis (Google)
Expérimental
Réalisé dans le cadre du groupe de travail IETF tcpm
Première rédaction de cet article le 30 avril 2013


Sur l'Internet, il y a des choses qu'on hésite à toucher. Depuis quelques épisodes fameux de « catastrophes congestives », où tout l'Internet s'est arrêté en raison de l'encombrement des tuyaux, la mémoire collective du réseau, incarnée notamment par l'IETF, voit avec une extrême méfiance toute modification des algorithmes de TCP, qui sont la principale ligne de défense de l'Internet face à la congestion. Néanmoins, le réseau évolue, les choses changent et il y a des gens qui insistent pour essayer des changements. Cela fait un certain temps que Google réclame une modification connue sous le doux nom de IW10 (pour Initial Window 10 segments) et ce RFC est le premier à la documenter officiellement, après trois ans de discussion dans le groupe de travail. Pour l'instant, c'est encore étiqueté comme « expérimental ».

La norme reste celle du RFC 3390. Elle dit que la fenêtre initiale d'une connexion TCP, à savoir le nombre maximal d'octets qu'on peut envoyer avant le premier accusé de réception, est donnée par une formule qui, en pratique est d'environ 4 kilo-octets, soit deux à trois segments (paquets TCP), parfois quatre. Voici, vu par tcpdump sur le client, un exemple entre deux machines séparées par 100 ms de RTT, un client HTTP qui demande un gros fichier et un serveur :

21:54:15.371487 IP 204.62.14.153.80 > 192.168.2.1.57886: Flags [.], seq 1:1449, ack 118, win 1810, 
options [nop,nop,TS val 1079804426 ecr 2768078], length 1448
21:54:15.371509 IP 192.168.2.1.57886 > 204.62.14.153.80: Flags [.], ack 1449, win 137, options [nop
,nop,TS val 2768109 ecr 1079804426], length 0
21:54:15.372574 IP 204.62.14.153.80 > 192.168.2.1.57886: Flags [.], seq 1449:2897, ack 118, win 181
0, options [nop,nop,TS val 1079804426 ecr 2768078], length 1448
21:54:15.372593 IP 192.168.2.1.57886 > 204.62.14.153.80: Flags [.], ack 2897, win 182, options [nop
,nop,TS val 2768109 ecr 1079804426], length 0
21:54:15.372615 IP 204.62.14.153.80 > 192.168.2.1.57886: Flags [.], seq 2897:4345, ack 118, win 181
0, options [nop,nop,TS val 1079804426 ecr 2768078], length 1448
21:54:15.372630 IP 192.168.2.1.57886 > 204.62.14.153.80: Flags [.], ack 4345, win 227, options [nop
,nop,TS val 2768109 ecr 1079804426], length 0
21:54:15.372897 IP 204.62.14.153.80 > 192.168.2.1.57886: Flags [P.], seq 4345:5793, ack 118, win 18
10, options [nop,nop,TS val 1079804426 ecr 2768078], length 1448
21:54:15.372910 IP 192.168.2.1.57886 > 204.62.14.153.80: Flags [.], ack 5793, win 273, options [nop
,nop,TS val 2768109 ecr 1079804426], length 0
21:54:15.488019 IP 204.62.14.153.80 > 192.168.2.1.57886: Flags [.], seq 5793:7241, ack 118, win 181
0, options [nop,nop,TS val 1079804455 ecr 2768109], length 1448

On voit que 204.62.14.153 a envoyé quatre segments avant de devoir s'arrêter, les accusés de réception n'ayant pas eu le temps de l'atteindre. La pause dure 116 ms, avant que le serveur ne reprenne son envoi.

Ce nombre de segments est trop petit (bien plus petit que les tampons d'entrée/sortie d'un équipement réseau typique) car, sur les réseaux modernes, cela veut dire qu'un pair TCP qui veut envoyer un gros fichier va très vite remplir cette fenêtre et va devoir attendre ensuite, alors qu'il ne sait absolument pas si le réseau est congestionné ou pas. D'où la proposition IW10 qui est de permettre l'envoi de dix segments. (Pourquoi dix ? Comme l'explique l'annexe A, c'est le résultat de tests avec plusieurs valeurs possibles. Dix était la valeur qui était le meilleur compromis entre les gains et les inconvénients. Regardez le dessin 2 dans l'article An Argument for Increasing TCP's Initial Congestion Window si vous avez besoin d'être convaincu : il montre un progrès jusqu'à 16 et une baisse ensuite. Notez qu'une des techniques étudiées par le groupe de travail - et finalement abandonnée - avait été un système complexe de mesure et de rétroaction, avec des tailles initiales de fenêtre variables.)

La formule proposée par ce RFC (section 2) est fenêtre_initiale (en octets) = minimum (10*MSS, maximum (2*MSS, 14600)). Cela pourra faire jusqu'à dix segments, en fonction de la MSS. Naturellement, la machine aura le droit de choisir une fenêtre plus petite, ce choix n'est en effet pas dangereux ; mais pas de fenêtre plus grande, le but étant d'éviter la congestion de réseau.

Notez bien que cette formule ne s'applique qu'au début de la connexion. Lorsque TCP reprend son algorithme de démarrage en douceur (slow start), par exemple suite à des pertes de paquets, il doit s'en tenir au RFC 2581.

Il y a aussi quelques questions pratiques à se poser. Par exemple, une connexion TCP est bi-directionnelle : ce n'est pas tout d'utiliser une fenêtre plus grande à l'émission, il faut aussi annoncer à son pair une fenêtre de réception plus grande (cf. « An Argument for Increasing TCP's Initial Congestion Window » de Dukkipati, N., Refice, T., Cheng, Y., Chu, J., Sutin, N., Agarwal, A., Herbert, T. et J. Arvind, article de 2010 qui va être souvent cité ici et dont je recommande fortement la lecture. À l'époque de l'article, la plupart des systèmes annonçaient cette grande fenêtre, sauf Linux.)

Ce changement a des conséquences pour les applications qui utilisent TCP (section 3). Ainsi, HTTP 1.1 n'autorisait que deux connexions TCP simultanées vers le même serveur (RFC 2616, section 8.1.4, mais le RFC 7230 a libéralisé cette consigne). Les navigateurs en ouvrent en général plus que cela, pour éviter l'attente due à la faible taille de la fenêtre TCP. (Voir « A Swifter Start for TCP », par Partridge, C., Rockwell, D., Allman, M., Krishnan, R. et J. Sterbenz, rapport technique n° 8339 de BBN en 2002.) C'est égoïste de leur part (cela s'oppose aux mécanismes de contrôle de congestion de TCP) et cela ne devrait logiquement plus être nécessaire avec le déploiement d'IW10. Le RFC conseille donc de réduire le nombre de connexions HTTP simultanées.

La section 4 du RFC donne des éléments de contexte et d'histoire. Au début (cf. le célébrissime article de Van Jacobson, « Congestion Avoidance and Control », en 1998), TCP ne pouvait envoyer qu'un seul segment avant de recevoir le premier accusé de réception. Ce n'était pas un problème pour de longues communications, comme celles de telnet. Mais l'Internet aujourd'hui voit surtout du trafic Web (cf. « Atlas Internet Observatory 2009 Annual Report » de Labovitz, C., Iekel-Johnson, S., McPherson, D., Oberheide, J. Jahanian, F. et M. Karir, présenté à NANOG 47 en 2009.), avec des connexions de courte durée. Attendre longtemps avant de pouvoir envoyer plusieurs segments est très pénalisant (la plupart de ces connexions courtes ne quitteront jamais l'état TCP « démarrage en douceur »).

Surtout, les changements dans la capacité des réseaux ont été spectaculaires. Le rapport « The State of the Internet » d'Akamai en 2010, annonce que les accès à plus de 2 Mb/s forment désormais la majorité, ce qui met la capacité moyenne à 1,7 Mb/s, alors que, pendant ce temps, la fenêtre d'envoi initiale de TCP restait aux 4 ko du RFC 2414, sans bouger pendant dix ans. Avec un RTT de 200 ms, cette fenêtre ne permettait que 200 kb/s.

Des tas de changements avaient été proposés (pour ne citer que les RFC, voir RFC 4782 et RFC 6077) mais sans être réellement déployés. Ce sont donc les applications qui se sont adaptées, comme vu plus haut avec les navigateurs qui ouvrent plusieurs connexions, et les sites Web créant des sous-domaines sans autre raison que de débrayer la limitation du nombre de connexions par serveur (cf. « A Client-Side Argument For Changing TCP Slow Start » en 2010). Le déploiement d'IW10 devrait logiquement s'accompagner d'un changement de stratégie de ces navigateurs Web.

Au fait, en parlant d'HTTP, les connexions persistentes de HTTP 1.1 ne devraient-elles pas résoudre le problème ? Le problème est que les mesures faites avec Chrome (article de Dukkipati et al. cité plus haut) montrent que 35 % des requêtes sont faites sur des nouvelles connexions, ne pouvant pas tirer profit des connexions persistentes.

Bon, mais, au fait, quels sont les avantages exacts qu'il y a à agrandir la fenêtre initiale ? La section 5 les examine en détail. D'abord, on réduit la latence. Par exemple, si on a 21 segments à envoyer, IW3 (fenêtre initiale de trois segments) va nécessiter 4 aller-retour (envoi de données + attente de l'accusé de réception) contre 2 pour IW10. Ensuite, une telle augmentation est cohérente avec l'augmentation régulière de taille des objets. Par exemple, sur le Web, les études citées par le RFC (mesures faites sur le moteur de recherche Google) montrent que seules 10 % des ressources sur le Web tiennent encore dans les 4 ko du RFC 3390. En outre, si on utilise les connexions persistentes de HTTP 1.1, on aura encore plus de données à transmettre sur une connexion HTTP. Le Web grossit, il est logique que la fenêtre initiale de TCP suive le mouvement.

Et il n'y a pas d'inconvénients à augmenter la taille de la fenêtre initiale ? Les sections 6 et 7 décrivent le côté obscur. D'abord, en section 6, les risques pour l'utilisateur. Il y a notamment le risque de remplir complètement les tampons d'entrée-sortie dès le démarrage, pour des petits routeurs. Le RFC estime toutefois que ce risque est faible avec les tampons actuels, en s'appuyant sur l'étude « Characterizing Residential Broadband Networks » de Dischinger, M., Gummadi, K., Haeberlen, A. et S. Saroiu, en 2007, qui montre que le routeur typique de M. Michu a au moins 130 ms de tampon.

Ça, c'était pour l'utilisateur. Et pour le réseau (section 7) ? Risque t-on davantage de congestion ? Probablement pas puisque IW10 ne s'applique qu'au début de la connexion. Tout le reste du mécanisme de contrôle de la congestion de TCP reste en place, inchangé, notamment sa réaction aux pertes de paquets. En revanche, il peut y avoir un problème de justice. Tant qu'une partie des machines applique IW10 et qu'une autre partie en est resté au RFC 3390, les machines IW10 vont prendre une part plus grande des ressources réseau (c'est une question générale de l'Internet : la répartition juste entre différentes connexions concurrentes dépend de leur bonne volonté). C'est donc un point à surveiller. (Un autre problème de justice est traité dans l'annexe A, entre des machines toutes IW10 mais où certaines n'ont pas dix segments à envoyer. Les mesures semblent indiquer que ces dernières machines ne sont pas défavorisées.)

Autre inconvénient possible : comme IW10 remplit plus vite les tampons d'entrée/sortie des routeurs, si ceux-ci sont trop grands (phénomène du bufferbloat), IW10 va aggraver le problème. Les protocoles sensibles à la latence comme le DNS ou certains jeux vont alors souffrir. Les mécanismes proposés comme alternative au bufferbloat (ECN, AQM, etc) sont alors encore plus nécessaires.

En synthèse (section 8), le RFC estime que le plus gros risque est pour les utilisateurs ayant des liaisons lentes avec des tampons d'entrée/sortie réduits, dans leur box. Les 10 segments initiaux peuvent, dans certains cas, faire déborder ces tampons, le réseau ne pouvant pas les envoyer assez vite. Le RFC suggère, si on détecte qu'on est sur un tel lien, de ne pas envoyer forcément les dix segments autorisés, et d'annoncer une fenêtre de réception plus petite. Voir aussi le RFC 3150, sur le problème général de ces liens lents.

La théorie, c'est bien joli mais, quand elle dit qu'il ne faut pas trop s'inquiéter, il est prudent de vérifier par des mesures effectives, pas juste des raisonnements. C'est ce que fait la section 10. L'expérience a été faite par Google dans deux de ses centres de données, l'un voyant plutôt des clients ayant la capacité réseau moyenne, l'autre ayant en moyenne des utilisateurs de connexions lentes (20 % à moins de 100 kb/s). Avec IW10, la latence a baissé de 11,7 % dans le centre moyen et 8,7 % dans le centre lent. En regardant plus finement, les auteurs ont constaté que, comme l'indiquait la théorie, les bénéfices les plus importants d'IW10 ont été pour les gens situés loin (forte latence réseau) mais ayant des connexions rapides (ce qu'on nomme le BDP élévé avec BDP = Bandwidth-Delay Product). Mais, contrairement à la théorie, même les clients à capacité réseau limitée ont vu une amélioration. (Voir l'exposé « Increasing TCP initial window » de Dukkipati, D., Cheng, Y., Chu, J. et M. Mathis, présenté à l'IETF 78 en 2010.) Aucun problème grave n'a été observé.

D'autres expériences ont été faites, listées sur le site Web du projet IW10 ou en section 11 de ce RFC. Notez toutefois que la plupart sont des simulations, pas des mesures sur le vrai Internet. Mais ce n'est pas forcément très grave, l'étude de Google, par son ampleur, a semblé largement suffisante. Bien des RFC ont été adoptés sans une aussi grande étude préalable !

L'annexe A du RFC contient une liste d'inquiétudes théoriques sur IW10 et les résultats des tests spécifiquement liés à chacune de ces inquiétudes. Ainsi, le taux de pertes de paquets n'a pas augmenté lors des tests, sauf lors de cas extrêmes où, même avec les valeurs du RFC 3390, le phénomène de pertes se produisait. De même, des mesures ont été faites en Afrique, pas seulement en Europe et en Amérique du Nord, pour s'assurer qu'IW10 n'aurait pas d'effet pénible pour les liens moins favorisés.

En conclusion, le RFC recommande (section 12) d'activer IW10 mais que les fournisseurs de mises en œuvre de TCP et/ou les administrateurs réseau surveillent le trafic, à la recherche d'indicateurs comme le taux de pertes de paquet, pour détecter une éventuelle augmentation des phénomènes négatifs.

Ce changement de la fenêtre initiale est déjà apparue dans certains systèmes. Par exemple, pour Linux, cela a été fait en 2011 dans le commit git 442b9635c569fef038d5367a7acd906db4677ae1. Notez que, sur Linux, ip route ... initcwnd N vous permet d'ajuster cette variable, pour expérimenter.

Un peu de lecture supplémentaire ? Le premier exposé sur IW10 date de 2010. Une argumentation hostile à IW10 ? Vous pouvez lire l'Internet-Draft draft-gettys-iw10-considered-harmful.


Téléchargez le RFC 6928


L'article seul

RFC 6890: Special-Purpose IP Address Registries

Date de publication du RFC : Avril 2013
Auteur(s) du RFC : M. Cotton (ICANN), L. Vegoda (ICANN), R. Bonica (Juniper), B. Haberman (Johns Hopkins University Applied Physics Lab)
Première rédaction de cet article le 30 avril 2013
Dernière mise à jour le 16 juin 2017


Un certain nombre de préfixes d'adresses IP sont spéciaux, réservés à des tâches comme les exemples dans la documentation, ou bien prévus pour des protocoles particuliers. Ces préfixes n'étaient pas documentés à un endroit unique, ils étaient dans certains RFC, avec parfois des registres IANA. Ce RFC restructure le système, désormais la seule source faisant autorité est le registre IANA (un pour IPv4 et un pour IPv6). En outre, ces deux registres ont désormais une structure bien définie, notamment pour indiquer les propriétés d'un préfixe spécial.

Parmi les nombreux préfixes spéciaux, on peut citer le 0.0.0.0/8 du RFC 1122, qui sert à désigner le réseau local, ou le fe80::/10 que le RFC 4291 dédie aux adresses locales au lien. De temps en temps, un RFC rassemble tous ces préfixes en un seul document et c'est ainsi que le RFC 5735 cataloguait tous les préfixes spéciaux IPv4 alors que le RFC 5156 faisait la même chose pour IPv6. Certains préfixes sont affectés à l'IANA pour une allocation ultérieure (comme le 192.0.0.0/24 du RFC 5736). Ces prefixes-là ont un registre à l'IANA, pour enregistrer ces allocations mais il n'existait pas de registre général de toutes les adresses IPv4 spéciales. Même chose en IPv6 : le RFC 2928 et le RFC 4773 affectaient 2001:0000::/23 à l'IANA et créaient un registre pour les adresses de ce préfixe mais sans prévoir de registre pour tous les préfixes spéciaux. Résultat, lorsqu'un nouveau préfixe était déclaré, il n'y avait plus de source à jour, avant qu'on publie un nouvel RFC de synthèse. Notre RFC 6890 change ce système et crée ce registre unique de la totalité des préfixes spéciaux, pour IPv4 et pour IPv6. Notre RFC annule donc les RFC 5735 et RFC 5156.

La section 2 du RFC liste les décisions prises et que l'IANA devra appliquer (suivant les sections 4.1 et 4.3 du RFC 2860 qui décrit les tâches de l'IANA). Le registre doit conserver, pour chaque préfixe IP, un certain nombre d'informations parmi lesquelles :

  • Le RFC où ce préfixe a été décrit.
  • Un booléen disant si les adresses IP dans ce préfixe peuvent apparaître en adresse source d'un datagramme IP.
  • Un booléen disant si les adresses IP dans ce préfixe peuvent apparaître en adresse destination d'un datagramme IP.
  • Un booléen (« Forwardable ») indiquant si les routeurs peuvent faire suivre les paquets ayant une telle adresse comme destination.
  • Un booléen (« Global » dans le RFC mais renommé « Globally reachable » par le RFC 8190) indiquant si les adresses de ce préfixe peuvent être transmises à un routeur situé dans un autre domaine. Notez que la définition est claire, mais le terme est ambigu (« Global » peut désigner la transmissibilité ou bien l'unicité, la première version de mon article était d'ailleurs erronée sur ce point), d'où le renommage du RFC 8190. Pour comprendre la différence avec le booléen précédent, regardez les adresses IP privées du RFC 1918 : ells peuvent être utilisées entre routeurs, mais uniquement dans le même domaine.
  • J'indique aussi dans les exemples ci-dessous si les adresses tirées de ce préfixe sont uniques au niveau mondial ou pas.

Évidemment, si les adresses IP d'un préfixe n'ont pas le droit d'être présentes en destination, les deux booléens suivants (transmissible par un routeur, et transmissible à d'autres domaines) n'ont pas de sens.

Voici quelques exemples de ces préfixes spéciaux (en mélangeant IPv4 et IPv6 qui, en pratique, sont dans deux registres) :

  • 0.0.0.0/8 : désigne ce réseau local. Décrit dans la section 3.2.1.3 du RFC 1122. Peut apparaître en source, pas en destination.
  • 10.0.0.0/8 : adressage privé. Décrit dans le RFC 1918. Peut apparaitre en source et en destination, transmissible par les routeurs, pas d'unicité mondiale.
  • 2001:10::/28 : préfixe dit « ORCHID » (Overlay Routable Cryptographic Hash Identifiers), utilisé pour des adressages sécurisés avec adresse dépendant d'une clé cryptographique. Décrit dans le RFC 4843. Ne peut apparaitre ni en source, ni en destination (il n'est pas prévu de les mettre directement dans les champs Source et Destination des paquets IPv6). Non transmissible par les routeurs, pas d'unicité mondiale (mais une quasi-unicité due à leur choix imprévisible dans un espace très large).
  • 100.64.0.0/10 : partage d'adresses en CGN. Décrit dans le RFC 6598. Peut apparaitre en source et en destination, transmissible par les routeurs, pas d'unicité mondiale.
  • 169.254.0.0/16 : adresses locales au lien, typiquement auto-attribuées. Décrit dans le RFC 3927. Peut apparaitre en source et en destination, non transmissible par les routeurs (locales au lien...), pas d'unicité mondiale.
  • fc0::/7 : ULA. Décrit dans le RFC 4193. Peut apparaitre en source et en destination, transmissible par les routeurs, pas d'unicité mondiale (il avait été prévu un registre mondial pour une partie de l'espace des ULA mais cela ne s'était jamais concrétisé).
  • 2001:0002::/48 ou 198.18.0.0/15 : adresses réservées pour les mesures en laboratoire. Décrit dans le RFC 2544 ou le RFC 5180. Peut apparaitre en source et en destination, transmissible par les routeurs, pas d'unicité mondiale.
  • 198.51.100.0/24 (et deux autres en IPv4) ou 2001:db8::/32 : adresses réservées à la documentation. Décrit dans le RFC 5737 ou le RFC 3849. Ne peut apparaitre ni en source, ni en destination. Non transmissible par les routeurs, pas d'unicité mondiale. Notez que, en IPv6, ces adresses pourraient être quasi-uniques si elles étaient choisies au hasard dans l'espace immense du 2001:db8::/32. Mais, en pratique, tout le monde prend la première, 2001:db8::1.

Téléchargez le RFC 6890


L'article seul

Latence dans les réseaux, c'est quoi ?

Première rédaction de cet article le 25 avril 2013


Lorsqu'il s'agit de performances des réseaux informatiques, le vocabulaire utilisé, que ce soit sur les forums, sur les réseaux sociaux ou même dans les livres est en général catastrophique, flou et mélangeant tout. D'où deux articles pour préciser rigoureusement ce que sont la latence et la capacité.

D'habitude, lorsque je parle d'un concept comme latence ou capacité, je mets juste un lien vers l'article de Wikipédia. Mais, ici, Wikipédia a curieusement décidé de nommer ce concept d'un terme anglais, lag, un terme que je n'ai jamais entendu en français en dehors du monde du jeu vidéo en ligne. Revenons donc au terme correct, latence.

Pourquoi pinailler sur le vocabulaire ? Parce que, comme je l'indique plus haut, le monde de la mesure de performances est particulièrement mauvais de ce point de vue, préférant des termes flous comme « vitesse ». Ainsi, l'article de Wikipédia sur la latence explique qu'une latence élevée peut être causée par une bande passante insuffisante, ce qui n'est que très approximativement vrai. Et que le vocabulaire flou ou incorrect n'est pas innocent : cela sert par exemple aux commerciaux à vendre des produits inadaptés.

Donc, la latence, c'est simplement le temps que met un message à accomplir un certain trajet. On parle aussi de délai. Elle peut concerner l'aller-simple (c'est ce qu'utilise le RFC 7679) ou l'aller-retour (RFC 2681). Elle n'a pas de lien direct avec la capacité du réseau (ce que certains nomment « bande passante »).

(Avec certains protocoles comme TCP, il y a toutefois une relation subtile entre latence et capacité, voir le RFC 7323.)

Pourquoi est-elle une métrique importante ? Car certaines utilisations du réseau dépendent beaucoup de la latence. Par exemple, des applications interactives (SSH ou XMPP) envoient relativement peu d'octets et sont donc peu sensibles à la capacité du réseau mais le sont beaucoup plus à la latence : lorsque j'envoie un message en XMPP, je voudrais qu'il arrive le plus vite possible, sous peine d'avoir une conversation hachée. D'autres cas d'usage, comme les transferts de gros fichiers, sont relativement insensibles à la latence (si les paramètres de TCP sont corrects).

Certains types de liens réseaux ont une latence particulièrement mauvaise (particulièrement élevée). Ainsi, un satellite géostationnaire ajoute forcément une latence de 238 ms (aller-retour vers le satellite, qui est à 36 000 km d'latitude, divisée par la vitesse de la lumière, qu'on ne peut pas augmenter). C'est une durée très longue et qui explique pourquoi il ne faut utiliser le satellite pour les liaisons Internet que lorsqu'on n'a absolument pas le choix (contrairement à ce que tentent de faire croire les commerciaux qui jouent sur le côté romantique d'une communication spatiale, voir par exemple cette publicité qui parle d'un accès « rapide »).

La définition que j'ai donnée parlait de « message » et, en effet, la latence peut se mesurer dans différentes couches. Le célèbre outil ping mesure une latence aller-retour pour la couche 3 :

% ping6 -c 10 f.root-servers.net
...
10 packets transmitted, 10 received, 0% packet loss, time 9002ms
rtt min/avg/max/mdev = 177.097/183.951/192.332/5.940 ms

Ici, la latence moyenne (ping ne calcule hélas pas la médiane) est de 184 millisecondes. Notez que ping n'est pas un outil très précis : il dépend de la charge des deux machines (celle qui pingue et l'amer), il ne connait pas l'instant exact où le premier bit du paquet touche le réseau (cf. RFC 7679), etc. C'est un outil approximatif, mais suffisant dans la plupart des cas. Un exemple de latence mesurée au niveau 7 est fournie par l'outil check-soa pour le DNS. Dans ce cas, la latence mesurée ne dépend pas que du réseau mais aussi de l'application distante (le serveur DNS) :

% check-soa -i societegenerale.com
tigdns01.socgen.com.
	193.178.155.113: OK: 2013042301 (30 ms)
tigdns02.socgen.com.
	193.178.155.114: OK: 2013042301 (34 ms)

Dernier exemple, avec HTTP, curl a une option peu connue pour afficher au format qu'on souhaite certains résultats de la connexion :

% curl --silent   --write-out "Delay: %{time_total} seconds\n" \
       --output /dev/null http://www.societegenerale.com/
Delay: 0.124 seconds

La documentation de curl indique plusieurs autres variables pour étudier les différents facteurs qui, ensemble, composent la latence :

% curl --silent   --write-out "Delay: %{time_total} s, TCP connection delay: %{time_connect},  Negociation delay: %{time_starttransfer}\n" \
       --output /dev/null http://www.societegenerale.com/ 
Delay: 0.274 s, TCP connection delay: 0.095,  Negociation delay: 0.178

Ici, on voit que le transfert effectif des données ne faisait même pas la moitié de la latence : la majorité du temps était passé à faire la connexion TCP puis à envoyer la commande GET. Pour une page Web de plus grande taille, les résultats seraient bien sûrs différents.

Un bon article en français expliquant clairement la latence et son importance est « Bande passante et temps de latence réseau » d'Alain Faure. Sinon, le grand classique en anglais est « It's the Latency, Stupid » de Stuart Cheshire.


L'article seul

Capacité dans les réseaux, c'est quoi ?

Première rédaction de cet article le 25 avril 2013


Dans les discussions ou les textes sur les performances des réseaux informatiques, on voit souvent une grosse confusion entre des termes comme « vitesse » (qui ne veut rien dire), « bande passante » (qui date de l'époque de l'analogique), « débit » et « capacité ». D'où cet article pour préciser rigoureusement ce qu'est la capacité et en quoi elle est différente des autres termes.

Commençons par « bande passante », car ça doit être le terme le plus populaire. Le paradoxe est qu'il vient du monde de l'analogique et désignait l'intervalle de fréquences utilisable, ce qui n'a qu'un très lointain rapport avec la capacité à faire passer plein d'octets en le minimum de temps. Je veux bien que la langue soit imparfaite et qu'un terme ne corresponde pas forcément à son étymologie mais, quand même, je trouve que ce serait plus clair si on n'utilisait pas du tout ces mots dans le monde du numérique.

Ensuite, quelle différence entre débit et capacité ? Le débit est ce qui passe effectivement dans un réseau à un moment donné. C'est ce que l'on affiche avec Cacti ou les logiciels similaires (ici, l'une des machines qui porte ce blog, dans les dernières 24 heures) : debit-exemple.png

La capacité est ce qui peut passer si on envoie le plus de données possible. C'est le débit maximum. La confusion entre les deux est très fréquente (par exemple quand on parle d'« Internet à haut débit »). La capacité est définie dans le RFC 5136 (voir aussi le RFC 9097).

On peut aussi noter que la capacité est mesurée en bits par seconde mais que, dans certains cas, le facteur qui limite le débit est le nombre de paquets par seconde et qu'il est donc parfois bon de mesurer également ce chiffre.

Pour rendre hommage à Tanenbaum, dans un exemple actualisé par André Sintzoff, notons enfin que la capacité réseau d'un train de marchandises dont les wagons sont remplis de cartes MicroSD rendrait jalouse n'importe quelle fibre optique. Mais la latence serait catastrophique...


L'article seul

RFC 6914: SIMPLE made Simple: An Overview of the IETF Specifications for Instant Messaging and Presence using the Session Initiation Protocol (SIP)

Date de publication du RFC : Avril 2013
Auteur(s) du RFC : J. Rosenberg (jdrosen.net)
Pour information
Réalisé dans le cadre du groupe de travail IETF simple
Première rédaction de cet article le 22 avril 2013


Le monde de la messagerie instantanée est marqué par l'absence d'une norme unique et largement reconnue (au contraire de celui du courrier électronique, où SMTP et ses copains ont remplacé tous les concurrents). La plupart des protocoles courants de messagerie instantanée sont fermés et spécifiques à une seule entreprise. Et, même chez les standards ouverts, il y a deux normes, la plus connue, autour de XMPP, et une seconde, issue de la même organisation (l'IETF), autour de SIP. Car SIP ne sert pas qu'à la téléphonie sur IP. C'est un mécanisme de signalisation très général et il peut être utilisé pour la messagerie instantanée. En fait, de nombreux RFC, depuis des années, normalisent l'utilisation de SIP dans ce cas. Tellement nombreux, ces RFC, qu'il faut faire un méta-RFC pour servir de guide. C'est le rôle de ce RFC 6914 : la liste commentée des RFC qui, tous ensemble, décrivent SIMPLE, la messagerie instantanée utilisant SIP.

SIP lui-même est décrit dans le RFC 3261. Ce nouveau RFC 6914 fait la liste des RFC qui décrivent l'utilisation de SIP pour deux services :

  • La présence, le fait de signaler sa disponibilité pour la communication,
  • La messagerie instantanée proprement dite.

Accrochez-vous, la liste est longue et SIMPLE ne mérite guère son nom. À noter que le groupe de travail IETF SIMPLE a été fermé le 26 février 2013, son travail étant considéré comme achevé.

Commençons par la présence (section 2). Elle se décompose en un service de base, permettant de publier des notifications (« je suis disponible ») et de s'y abonner (« qui est réveillé ? »), et une galaxie de services auxiliaires enrichissant tel ou tel aspect du service de base. Le seul service de base compte cinq RFC :

  • RFC 6665, qui définit les méthodes SUBSCRIBE et NOTIFY, au cœur du service de présence. Il est bâti sur le RFC 3856.
  • RFC 4662, qui étend ce mécanisme à des listes de ressources SIP, notamment les buddy lists, liste de correspondants. Une variante figure dans le RFC 5367.
  • RFC 3903, qui normalise le mécanisme de publication des informations.

Ensuite, comment exprime-t-on les informations publiées et lues ? Le format de base (fondé sur XML) est dans le RFC 3863. Un modèle de données plus général est dans le RFC 4479, avec, dans le RFC 4480, plein d'extensions au format du RFC 3863. Autres extensions, celles du RFC 4481, qui ajoute la gestion du temps (évenements dans le passé et le futur, alors que le RFC 3863 se limitait au présent), et celles du RFC 4482 qui permettent de diffuser des informations sur un correspondant, par exemple une image le représentant.

Enfin, le RFC 5196 permettait d'indiquer, en sus de la présence et des données ci-dessus, les capacités du logiciel SIP qu'on utilise, par exemple pour prévenir ses correspondants qu'on accepte la vidéo.

Tout service de présence soulève évidemment des questions délicates de protection de la vie privée. Je ne souhaite pas forcément que la Terre entière soit au courant de mes déplacements et activités. La section 2.3 décrit les RFC qui s'attaquent au problème de la vie privée dans SIMPLE. Le RFC 4745 définit un format (basé sur XML) pour exprimer des préférences sur la vie privée (du genre « ne jamais diffuser cette information »). Le RFC 5025 utilise ensuite ce format pour décrire les souhaits spécifiques au service de présence. Les RFC 3857 et RFC 3858 décrivent un système d'autorisation préalable où l'utilisateur peut être prévenu si quelqu'un demande s'il est présent.

Un service SIMPLE nécessite un certain nombre de données, par exemple les carnets d'adresse. Comment les enregistre t-on ? Cela se fait avec XCAP (RFC 4825), un protocole qui permet d'envoyer des données stockées en XML. Il en existe des optimisations comme le RFC 5874 qui permet de n'envoyer que les différences avec les données précédentes, pour économiser des ressources réseau. Il se sert pour cela du format XML Diff du RFC 5261. On peut être prévenu de l'apparition de différences avec les mécanismes du RFC 5875. Les formats des données sont ensuite décrites par des documents comme le RFC 4826 (format des carnets d'adresses).

Un des gros intérêts des techniques IETF de messagerie instantanée, comme SIMPLE ou XMPP est qu'elles reposent sur une fédération. Il n'y a pas un service centralisé à qui faire confiance (comme c'est le cas avec les services des silos fermés comme MSN). Chacun peut installer son serveur et les différents serveurs peuvent communiquer entre eux, le DNS leur servant à se trouver. Le RFC 5344 approfondit les mécanismes utilisés pour la fédération.

La présence peut être un service très coûteux. Imaginez que vous receviez des notifications de présence pour une centaine de personnes, et que leurs états changent toutes les minutes (par exemple suite à des connexions/déconnexions). Au-dessus d'une liaison sans-fil, cela peut faire mal au réseau. Le RFC 4460 fournit donc des mécanismes de filtrage, pour ne pas tout recevoir. Les règles sont écrites dans le format du RFC 4461. Le RFC 5262 permet de ne pas recevoir la totalité de la notification mais uniquement la partie qui a changé (là encore, avec le format XML Diff du RFC 5261).

Maintenant qu'on en a terminé avec la présence (un service bien plus compliqué qu'il n'avait l'air au premier abord), revenons à la messagerie instantanée proprement dite (section 3). Dans SIMPLE, il y a deux modes de fonctionnement pour celle-ci. En mode non connecté (page mode, analogue au SMS), une requête SIP MESSAGE est envoyée au destinataire, contenant le message. En mode connecté (session mode), une INVITE SIP est envoyée au destinataire et, une fois la session établie, on envoie les textes de la conversation, comme on enverrait de l'audio avec de la téléphonie SIP.

Le RFC 3428 décrit le mode non connecté et la méthode MESSAGE, le « texto » de SIP. Le RFC 5365 l'étend au cas où il y a plusieurs destinataires.

Le mode connecté utilise des méthodes SIP classiques et sa description est uniquement celle des types de données envoyées, notamment RFC 4975 pour le type « message texte » et RFC 3862 pour les métadonnées.

Une extension très utile aux services de messagerie instantanée est la pièce collective (chat room, ou MUC - pour Multi-User Channel en XMPP). SIMPLE réutilise pour cela les mécanismes de conférence de SIP, normalisés dans les RFC 4353 et RFC 5239. Ensemble, ils indiquent comment on rejoint une conférence, comment on la quitte, etc.

Enfin (rassurez-vous, on arrive au bout), deux fonctions sympa : l'indication de composition dans le RFC 3994 (permettant d'indiquer que le correspondant est en train de taper un texte, il faut patienter), et l'accusé de réception dans le RFC 5438.

Voilà, vous savez désormais tout ce qu'il faut lire si vous voulez faire de la messagerie instantanée avec SIP...


Téléchargez le RFC 6914


L'article seul

RFC 6920: Naming Things with Hashes

Date de publication du RFC : Avril 2013
Auteur(s) du RFC : S. Farrell (Trinity College Dublin), D. Kutscher (NEC), C. Dannewitz (University of Paderborn), B. Ohlman, A. Keranen (Ericsson), P. Hallam-Baker (Comodo Group)
Chemin des normes
Première rédaction de cet article le 22 avril 2013
Dernière mise à jour le 23 avril 2013


La question des identificateurs sur le Web agite des électrons depuis le début. Il n'existe pas d'identificateurs idéaux, ayant toutes les bonnes propriétés. Dans la grande famille des URI (RFC 3986), il faut donc choisir selon l'importance qu'on donne à tel ou tel critère. Par exemple, si on attache du prix à la stabilité de l'identificateur et qu'on veut qu'il ne désigne pas seulement un endroit où se trouve un contenu, mais qu'on veut qu'il désigne ce contenu et pas un autre ? Alors, on peut choisir les nouveaux URI ni: (Named Information) qui désignent un contenu par un condensat (hash). Un URI ni: ne change pas si le contenu change de serveur, mais il est modifié si le contenu lui-même change. C'est donc une forme d'adressage par le contenu.

À quoi cela sert ? À éviter un problème de l'indirection : si je dis « regardez l'image en http://www.example.org/holidays/beach.png » et que l'image de vacances à la plage est remplacée par une photo de LOLcat, l'URI sera toujours valable, alors que le contenu a changé. Inversement, si un webmestre incompétent et qui n'a pas lu « Cool URIs don't change » réorganise le site et met le contenu en http://www.example.org/bigcomplicatedcmswithsecurityholes.php?kind=image&tag=beach&foo=bar&id=612981, l'URI ne marchera plus alors que le contenu est inchangé. Un autre exemple, plus positif, est le cas où un contenu est répliqué en plusieurs endroits, ayant des URL différents. Il faut pouvoir désigner le contenu, indépendamment du service qui l'héberge. C'est pour répondre à ces deux problèmes qu'a été créé par ce RFC le plan d'URI ni: (désormais dans le registre IANA des plans d'URI). Le contenu en question pourra donc être désigné par ni:///sha256;rJAeWFhQWIoTExwyEQ8w_L5uB0UkfmnCGfNIPy7CdDc. Une telle technique a déjà été employée mais de manière non standard (par exemple, on voit parfois des URI du genre http://www.example.org/hash?function=sha256&value=rJAeWFhQWIoTExwyEQ8w_L5uB0UkfmnCGfNIPy7CdDc où un programme situé sur www.example.org récupère la ressource selon le contenu). Désormais, le but est de permettre du vrai adressage par le contenu sur le Web. Cela se nomme information-centric sur les PowerPoint des gourous. Sur ce sujet, le RFC recommande la lecture de « Design Considerations for a Network of Information » de Ahlgren, D'Ambrosio, Dannewitz, Marchisio, Marsh, Ohlman, Pentikousis, Rembarz, Strandberg, et Vercellone, ainsi que des articles de Van Jacobson. On peut aussi lire des articles sur les autres mécanismes d'adressage par le contenu comme les magnet links de plusieurs systèmes pair-à-pair, comme Freenet.

Une fois le contenu récupéré (en HTTP ou par d'autres moyens), le lecteur peut alors recalculer le condensat et vérifier s'il a bien reçu le bon fichier (des protocoles comme BitTorrent utilisent un mécanisme analogue pour s'assurer que le fichier transmis par les pairs est bien celui qu'on voulait).

D'autres informations peuvent se retrouver dans l'URI ni: (voir des exemples plus loin) mais la comparaison de deux URI ni: se fait uniquement sur le couple {fonction de hachage utilisée, valeur du condensat}.

Le condensat est calculé par une fonction de hachage cryptographique et, par défaut, c'est SHA-256 (vous avez noté le sha256 dans l'URI ni: donné en exemple plus haut ?) Les valeurs possibles pour l'algorithme de hachage figurent dans un nouveau registre. Les nouvelles valeurs sont enregistrées selon une procédure légère d'examen par un expert (RFC 5226 et section 9.4 de notre RFC).

Les condensats de SHA-256 sont de grande taille, parfois trop pour certaines utilisations. On a donc le droit de les tronquer à leurs N premiers bits et le nom d'algorithme indiqué doit préciser cette troncation. Ainsi, si on garde les 32 premiers bits, on doit indiquer sha256-32 et pas juste sha256. Attention, c'est évidemment au détriment de la sécurité (si la sortie de SHA-256 est si longue, c'est pour une bonne raison, cf. RFC 3766) et ces condensats raccourcis, quoique simples à manipuler, ne protègent plus tellement. (Notez que le VCS git, qui identifie les commits par un condensat cryptographique, permet également de les raccourcir, pour faciliter son utilisation, par exemple depuis le shell.)

Le format exact des URI ni: figure en section 3. On note un composant dont je n'ai pas encore parlé, l'autorité. On peut écrire ni:///sha256;rJAeWFhQWIoTExwyEQ8w_L5uB0UkfmnCGfNIPy7CdDc mais aussi ni://www.example.net/sha256;rJAeWFhQWIoTExwyEQ8w_L5uB0UkfmnCGfNIPy7CdDc. L'autorité (ici, www.example.net) désigne un endroit où on pourra peut-être récupérer la ressource. Le gros problème des identificateurs fondés sur le contenu du fichier, en effet, est qu'ils sont inutiles pour accéder effectivement au fichier : pas moyen de télécharger un fichier dont on ne connait que le condensat ! Il existe plusieurs solutions et l'une d'elles est de passer par l'autorité. L'idée est que l'URI ni: est automatiquement transformé en un URL HTTP sous .well-known (cf. RFC 8615 et section 4 de notre RFC). Ainsi, ni://www.example.net/sha256;rJAeWFhQWIoTExwyEQ8w_L5uB0UkfmnCGfNIPy7CdDc devient http://www.example.net/.well-known/ni/sha256/rJAeWFhQWIoTExwyEQ8w_L5uB0UkfmnCGfNIPy7CdDc qu'on peut ensuite récupérer par des moyens classiques. On combine alors les avantages de l'adressage par le contenu (le condensat est là pour vérifier le contenu) et du fait que les URL marchent bien pour récupérer un contenu. On notera que le système d'identificateurs ARK a un mécanisme analogue (un identificateur stable et non résolvable plus un préfixe qui permet de faire un URL résolvable et actionnable). On a ainsi le beurre et l'argent du beurre. ni fait désormais partie des termes enregistrés dans le registre "well-known".

Petite question : pourquoi http: et pas https:, qui serait plus sûr ? Parce que tous les serveurs ne gèrent pas HTTPS et aussi parce que ce n'est pas nécessaire pour s'assurer de l'intégrité du fichier récupéré, le condensat cryptographique suffit. Bien sûr, une mise en œuvre de ce RFC est autorisée à essayer avec HTTPS, par exemple pour la confidentialité.

Comme indiqué plus haut, la comparaison entre deux URI ni: se fait uniquement sur le couple {algorithme, condensat} donc ni://datastore.example/sha256;rJAeWFhQWIoTExwyEQ8w_L5uB0UkfmnCGfNIPy7CdDc et ni://www.example.net/sha256;rJAeWFhQWIoTExwyEQ8w_L5uB0UkfmnCGfNIPy7CdDc sont identiques.

Au fait, SHA-256 peut être affiché en binaire ou bien sous une forme hexadécimale. Laquelle est utilisée ? Le format binaire suivi d'un encodage en Base64 (RFC 4648), sous sa forme URL encoding, celle qui utilise _ et - au lieu de / et + (ce n'est pas la forme par défaut : songez que l'outil base64 sur Unix ne permet pas de produire cette variante).

Si on n'a pas besoin d'être lisible par des humains et transmissible dans des textes, il existe aussi une forme binaire, plus compacte, des URI ni:, spécifiée en section 6.

Signe de leur souplesse, les URI ni: ont également une forme « prononçable ». S'il faut dicter un URI au téléphone, l'encodage par défaut est très ambigu (par exemple, minuscules et majuscules n'ont pas la même valeur). D'où la syntaxe nih: (NI for Humans et non pas Not Invented Here, cf. RFC 5513) de la section 7. Les URI sous leur forme nih: sont en Base16 (RFC 4648), peuvent inclure des tirets supplémentaires, pour la lisibilité, et incluent une somme de contrôle (le dernier chiffre, calculé selon l'algorithme de Luhn de la norme ISO 7812) pour détecter les erreurs de compréhension. Un exemple est nih:sha-256-120;5326-9057-e12f-e2b7-4ba0-7c89-2560-a2;f .

Enfin, des paramètres peuvent apparaître dans l'URI, par exemple pour indiquer le type de la ressource (ni:///sha256;rJAeWFhQWIoTExwyEQ8w_L5uB0UkfmnCGfNIPy7CdDc?ct=image/png). Une liste de paramètres possibles est enregistrée.

À noter que l'abréviation ni veut officiellement dire Named Information mais que tout geek va évidemment penser aux chevaliers qui disent Ni...

Avant d'utiliser les URI ni:, il est prudent de lire la section 10, consacrée aux questions de sécurité. Ainsi, il ne faut pas oublier que le condensat cryptographique n'est pas une signature. Il sert à vérifier l'intégrité mais, comme n'importe qui peut générer un condensat pour n'importe quel contenu, il ne prouve rien quant à l'authenticité.

La fonction SHA-256 et ses camarades ne sont pas inversibles. D'un condensat, on ne peut pas remonter au contenu. Toutefois, celui-ci n'est pas vraiment secret. Un attaquant peut toujours deviner plus ou moins le contenu (c'est particulièrement facile si le contenu est très structuré, avec peu de variations possibles) et tester les différentes possibilités. Il peut aussi utiliser un moteur de recherche, si des pages existent déjà avec la correspondance entre une ressource et son condensat (pour empêcher cela, il faudrait que les condensats ni: soient salés, ce qui n'est pas le cas).

Et, naturellement, si vous utilisez des condensats tronqués, comme le permet de RFC, vous perdez beaucoup en sécurité.

La notion d'autorité dans les URI ni: peut être trompeuse. Le nom de domaine qui peut apparaître dans un URI ni: n'est pas forcément la source du contenu, puisque n'importe qui peut copier la ressource, et la servir depuis un programme. Il ne faut donc pas attribuer de sémantique à la soi-disant « autorité ».

Si vous voulez regarder un tel système « en vrai », les articles de ce blog sont tous accessibles via un URI ni:. L'identificateur est calculé toutes les nuits et stocké dans une base de données. Un simple petit programme WSGI permet ensuite de récupérer un fichier en fonction de son identificateur. À noter que ce n'est pas la forme HTML qui est utilisée mais le source en XML (la forme en HTML change trop souvent, par exemple si les outils qui la produisent automatiquement à partir du source sont modifiés). Ainsi, l'URI ni:///sha256;6OuucQ1RgugCDVinT2RGmzYYpra0fenH-zw7tilsx9k correspond au source XML de cet article. En indiquant explicitement l'autorité (le serveur qui permet de faire la récupération), c'est l'URI ni://www.bortzmeyer.org/sha256;6OuucQ1RgugCDVinT2RGmzYYpra0fenH-zw7tilsx9k. Et la version sous forme d'URL est https://www.bortzmeyer.org/.well-known/ni/sha256/6OuucQ1RgugCDVinT2RGmzYYpra0fenH-zw7tilsx9k. Si vous préferez un autre article, ni:///sha256;1etMCVZtd7_cq38MrtnQcoZW_e7J2cslulrFp92lueI correspond au source de cet article.

Notez qu'il n'est pas possible de mettre l'URI ni: de l'article que vous êtes en train de lire dans cet article (inclure le condensat change l'article et il faut donc changer le condensat, ce qui change l'article...)

Vous voulez vérifier ? Allons-y.

% wget -O /tmp/x.xml https://www.bortzmeyer.org/.well-known/ni/sha256/1etMCVZtd7_cq38MrtnQcoZW_e7J2cslulrFp92lueI
...
% openssl dgst -sha256 -binary /tmp/x.xml | base64
1etMCVZtd7/cq38MrtnQcoZW/e7J2cslulrFp92lueI=

Et on retrouve bien l'identificateur 1etMCVZtd... (aux transformations URL encoding près).

Si vous voulez faire depuis le shell Unix les calculs nécessaires, voici quelques exemples avec OpenSSL. Pour calculer le NI de Hello World! :

% echo -n 'Hello World!' | openssl dgst -sha256 -binary | base64
f4OxZX/x/FO5LcGBSKHWXfwtSx+j1ncoSt3SABJtkGk=

Il faut ensuite rechercher/remplacer car base64 (ou bien la commande openssl enc -base64) ne sait pas faire de l'URL encoding de Base64. Avec sed :

% echo -n 'Hello World!' | openssl dgst -sha256 -binary | base64 | sed -e 's#/#_#g' -e 's#+#-#g' -e 's#=$##' 
f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk

(Pour la même manipulation, on peut aussi utiliser tr : tr -cd a-zA-Z0-9+/ | tr +/ -_. Comme expliqué par Kim-Minh Kaplan : « Note le tr -cd pour nettoyer le résultat de l’encodage en Base 64. Si avec SHA-256 il n’est pas nécessaire, avec SHA-512, l’encodeur d’OpenSSL introduira un retour à la ligne qu’il faudra aussi supprimer. ») Si on reprend l'exemple plus haut, on peut combiner les deux opérations : on récupère le fichier grâce au condensat et on vérifie que le contenu est bien le contenu attendu. Utilisons ce simple script :


#!/bin/sh

BASE_URL="https://www.bortzmeyer.org/.well-known/ni/sha256/"

if [ -z "$1" ]; then
    echo "Usage: $0 ni" >&2
    exit 1
fi

ni=$1

hash=$(wget -q -O - ${BASE_URL}/${ni} | openssl dgst -sha256 -binary | openssl enc -base64 | \
    sed -e 's#/#_#g' -e 's#+#-#g' -e 's#=$##')

if [ "$hash" != "$ni" ]; then
    echo "Error: hash is $hash instead of $ni" >&2
    exit 1
else
    exit 0
fi

Et voyons :

% get-and-check-ni 1etMCVZtd7_cq38MrtnQcoZW_e7J2cslulrFp92lueI
%

Si on met une valeur fausse :

% get-and-check-ni 1etMCVZtd7_cq38MrtnQcoZW_e7J2cslulrFp922ueI
Error: hash is 47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU instead of 1etMCVZtd7_cq38MrtnQcoZW_e7J2cslulrFp922ueI

Si vous voulez lire de source de mon programme, il est dans les fichiers de mon blog, scripts/blog2db/blog2db.py pour le stockage dans la base de données et wsgis/ni.py pour la récupération.

Il existe une autre implémentation, par certains des auteurs du RFC, en http://sourceforge.net/projects/netinf/.

Si vous voulez d'autres lectures, le RFC 1737. sur les URN, parlait déjà (en 1994) d'utiliser un condensat cryptographque (avec MD5) pour désigner un contenu. En 2003, une proposition plus élaborée, draft-thiemann-hash-urn décrivait un système d'URN avec adressage par le contenu (des choses comme urn:hash::sha1:LBPI666ED2QSWVD3VSO5BG5R54TE22QL). Mais, avec draft-thiemann-hash-urn, il y a un gros manque : pas moyen d'indiquer un (ou plusieurs, comme dans le cas des magnets) serveur pouvant servir le document en question. Avec draft-thiemann-hash-urn, on n'a que des URN (ils ne sont pas « actionnables »). Enfin, si vous voulez une critique des ni: par rapport aux magnets, voyez la discussion sur LinuxFr.


Téléchargez le RFC 6920


L'article seul

RFC 6918: Formally Deprecating Some ICMPv4 Message Types

Date de publication du RFC : Avril 2013
Auteur(s) du RFC : F. Gont (UTN-FRH / SI6 Networks), C. Pignataro (Cisco Systems)
Chemin des normes
Première rédaction de cet article le 18 avril 2013


Allez, encore un peu de nettoyage dans les registres IANA. Le protocole ICMP pour IPv4 a plein de types de messages différents. Beaucoup sont dépassés mais n'avaient pas été officiellement marqués comme tel. Ce RFC range le registre et reclasse quinze types de messages. En revoyant ces types, nous plongeons dans les essais ratés de TCP/IP...

La notion de type de message ICMP est normalisée dans le RFC 792. Les plus connus des types de message ICMPv4 sont le 8 (echo request) et le 0 (echo reply) à cause de leur utilisation dans ping. Mais il existe bien d'autres types, enregistrés à l'IANA et servant à de nombreuses fonctions discrètes, mais indispensables (comme l'indication qu'un paquet n'a pas pu être délivré, type 3). Le registre des types a aussi vu l'arrivée d'un certain nombre de types expérimentaux, qui n'ont guère eu de succès, et notre RFC s'occupe de les trier. (Rappelez-vous qu'IPv6 a un autre registre ICMP, complètement différent.)

Voici donc la liste des types abandonnés :

  • Type 6 Alternate Host Address : un cas amusant car il n'a jamais été documenté et personne ne semble savoir à quoi il devait servir.
  • Types 15 Information Request et 16 Information Reply : décrits dans le RFC 792, ils servaient à la configuration automatique des machines mais sont devenus inutiles depuis qu'on a DHCP.
  • Types 17 Address Mask Request et 18 Address Mask Reply : normalisés dans le RFC 950, ils devaient permettre à une machine de découvrir le masque de sous-réseau (qui, avant cela, avant le VLSM - Variable-Length Subnet Masking, dépendait de la classe d'adresses). Là encore, DHCP les a rendus inutiles.
  • Type 30 Traceroute : décrit par le RFC 1393, il devait servir à découvrir le chemin parcouru par un paquet. Au contraire de la technique utilisée par l'outil traceroute, il nécessitait du logiciel spécial dans tous les routeurs et n'a jamais été sérieusement déployé. Le RFC 6814 l'avait déjà déclaré inutile.
  • Type 31 Datagram Conversion Error : le RFC 1475 l'avait spécifié pour le protocole TP/IX, bien oublié depuis.
  • Type 32 Mobile Host Redirect : un premier essai (raté) d'un protocole permettant la mobilité des machines de réseau en réseau.
  • Types 33 IPv6 Where-Are-You et 34 IPv6 I-Am-Here : un essai, jamais déployé, pour permettre aux machines IPv4 de découvrir des voisins parlant IPv6.
  • Types 35 Mobile Registration Request et 36 Mobile Registration Reply : autre essai non suivi d'effet lié à la mobilité et à IPv6. (Il était documenté dans l'Internet-Draft draft-simpson-ipv6-mobility qui n'est jamais devenu un RFC.)
  • Types 37 Domain Name Request et 38 Domain Name Reply : normalisés dans le RFC 1788, l'idée était de permettre une traduction d'adresse IP en nom n'utilisant pas le DNS. On envoyait un paquet ICMP à une machine et elle répondait avec son nom. En pratique, cela n'a jamais été utilisé.
  • Type 39 SKIP : prévu pour un protocole qui n'a jamais été terminé.

Tous ces types sont désormais marqués Deprecated dans le registre IANA.


Téléchargez le RFC 6918


L'article seul

RFC 6931: Additional XML Security Uniform Resource Identifiers (URIs)

Date de publication du RFC : Avril 2013
Auteur(s) du RFC : Donald Eastlake (Huawei)
Chemin des normes
Première rédaction de cet article le 18 avril 2013


Il existe tout un ensemble de normes pour assurer la sécurité de documents XML, par exemple les protéger contre la lecture non autorisée, ou bien permettre leur authentification. Ces normes dépendent d'algorithmes cryptographiques identifiés par un URI. Ce RFC met à jour la liste précédente de ces URI (qui était dans le RFC 4051) et crée un registre des identificateurs d'algorithmes.

Ces normes de sécurité de XML étaient à l'origine un travail conjoint de l'IETF et du W3C. C'était par exemple le cas des signatures XML du RFC 3275, du XML canonique des RFC 3076 ou RFC 3741. Elles sont désormais maintenues par le W3C qui a produit des versions plus récentes (par exemple pour les signatures XML, le XML canonique ou le chiffrement XML).

Dans un monde dynamique comme celui de la cryptographie, où les progrès de la cryptanalyse nécessitent des changements d'algorithmes, les normes ne sont pas liées à un algorithme particulier. Elles permettent l'agilité cryptographique (le changement d'algorithme) et il faut donc pouvoir indiquer quel algorithme est utilisé pour signer ou chiffrer un document donné. Pour une norme W3C, on ne s'étonnera pas que l'indication se fait par le biais d'un URI. Ceux-ci commencent désormais par le préfixe http://www.w3.org/2007/05/xmldsig-more# (les anciens algorithmes pouvant avoir d'autres préfixes). Ces nouveaux algorithmes (avec 2007/05 dans leur identificateur) sont relativement rares dans ce RFC : on n'invente quand même pas un bon algorithme de cryptographie tous les jours et la plupart des exemples dans cet article utilisent donc le vieux préfixe. Rappelez-vous qu'il s'agit d'URI, pas forcément d'URL et que vous n'obtiendrez donc pas forcément un résultat en pointant votre navigateur Web vers http://www.w3.org/2001/04/xmlenc#sha256.

Notons que notre RFC 6931 ne prend pas position sur la qualité cryptographique des algorithmes : il fournit un moyen de les désigner sans ambiguité, c'est tout. Si on veut étudier cette qualité cryptographique, il faut lire d'autres documents (comme le RFC 6194 pour SHA-1).

Un exemple d'un ancien algorithme est MD5 pour calculer les condensats cryptographiques. Son URI est http://www.w3.org/2001/04/xmldsig-more#md5. Sa sécurité est aujourd'hui sérieusement battue en brèche (cf. RFC 6151). Autre exemple d'un algorithme qui était déjà dans le RFC 4051, SHA-384, identifié par http://www.w3.org/2001/04/xmldsig-more#sha384.

Un exemple d'un nouvel algorithme pour la condensation cryptographique ? Le NIST ayant récemment annoncé que le vainqueur du concours « SHA-3 » était Keccak, des URI utilisant le nouveau préfixe ont été créés pour lui, par exemple http://www.w3.org/2007/05/xmldsig-more#sha3-512 (regardez bien : sha-3 et plus sha, et la nouvelle date dans le préfixe).

Il existe aussi des identificateurs pour les MAC combinés avec une condensation, par exemple http://www.w3.org/2001/04/xmldsig-more#hmac-sha512 (RFC 6234).

Et pour les signatures avec un système à clé publique ? L'identificateur indique l'algorithme de cryptographie asymétrique et celui de condensation, par exemple http://www.w3.org/2001/04/xmldsig-more#rsa-sha256 (voir aussi le RFC 3447). SHA-256 n'est pas tout récent et, si vous cherchez un algorithme enregistré par notre nouveau RFC, pourquoi pas Whirlpool avec http://www.w3.org/2007/05/xmldsig-more#rsa-whirlpool. Si on trouve RSA ennuyeux, il existe aussi des identificateurs pour un algorithme à courbes elliptiques (RFC 6090 mais notez ses errata), ECDSA, par exemple http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512.

Enfin, il y a les algorithmes de chiffrement symétrique. Par exemple, Camellia (RFC 3713) sera identifié par http://www.w3.org/2001/04/xmldsig-more#camellia256-cbc. Le plus récent SEED (RFC 4269) sera http://www.w3.org/2007/05/xmldsig-more#seed128-cbc.

Voici pour la cryptographie. Mais les normes de sécurité XML prévoient aussi une étape de canonicalisation avant chiffrement ou signature, et là aussi, il y a plusieurs algorithmes, identifiés par des URI comme http://www.w3.org/2000/09/xmldsig#minimal ou http://www.w3.org/2006/12/xmlc14n11#WithComments.

Quelle est la politique d'allocation dans le nouveau registre ? La section 5 décrit celle du W3C (le préfixe http://www.w3.org/2007/05/xmldsig-more# est figé, a priori, on n'y mettra pas de nouveaux algorithmes) et celle de l'IETF : comme il est facile d'obtenir un URI (n'importe qui peut en créer un), la seule question est celle de leur enregistrement. Il se fera après un examen par un expert (voir le RFC 5226 pour les politiques d'allocation IETF) après publication d'un texte décrivant le nouvel algorithme.

Quels changements depuis la version précédente de ce RFC, le RFC 4051 ? L'annexe A les liste. Les principaux, à mon avis, sont :


Téléchargez le RFC 6931


L'article seul

RFC 6895: Domain Name System (DNS) IANA Considerations

Date de publication du RFC : Avril 2013
Auteur(s) du RFC : Donald Eastlake (Huawei)
Réalisé dans le cadre du groupe de travail IETF dnsext
Première rédaction de cet article le 17 avril 2013


Un RFC un peu bureaucratique, pour détailler les mécanismes utilisés pour l'enregistrement dans les registres de l'IANA des paramètres liés au DNS. Il met très légèrement à jour son prédécesseur, le RFC 6195, libéralisant encore un peu plus l'enregistrement de nouveaux types de données dans le DNS.

Un certain nombre de paramètres (section 2, qui résume le format des paquets DNS), dans le DNS, sont enregistrés à l'IANA, afin de s'assurer d'une interprétation identique partout. C'est ainsi que l'IANA gère un registre des paramètres DNS où on trouve, entre autres, les types d'enregistrement (A, codé 1, pour une adresse IPv4, AAAA, codé 28, pour une adresse IPv6, LOC, codé 29, pour les positions géographiques du RFC 1876, TLSA, codé 52, pour le RFC 6698, etc). Cet espace n'étant pas de taille infinie, il faut y enregistrer de nouveaux paramètres avec prudence.

L'affectation dans cet espace forme le point le plus important de ce RFC (section 3). Il faut comprendre qu'il y a trois types de numéros utilisés dans cet espace : ceux qui identifient un type de données (comme les quatre cités plus haut), ceux qui identifient une question et le cas particulier des méta-types. Une question, dans le DNS, peut être un type de données (on met 52 dans le champ QTYPE de la requête pour dire qu'on veut des enregistrements TLSA), mais il existe aussi des questions qui ne correspondent pas à un type unique comme 255 (noté ANY ou ALL ou *) qui veut dire « envoie-moi toutes les données que tu as, quelles que soit leur type ». Enfin, les méta-types sont des données temporaires, liées à une transaction, comme les TSIG (numéro 250) du RFC 8945, qui n'existent que le temps de la session DNS.

Pour les types de données, la politique d'allocation est simple et libérale : on remplit un formulaire (qui se trouve en annexe A du RFC), on l'envoie à l'IANA (via l'adresse dns-rrtype-applications@ietf.org) et un expert l'examinera (procédure Expert Review du RFC 5226) et rendra son jugement. (Il est recommandé de l'envoyer d'abord à la liste du liste de groupe de travail dnsext pour un examen préalable.) Les formulaires approuvés sont ensuite publiquement archivés (mais je n'ai pas trouvé où).

Le RFC donne les critères que doit suivre l'expert pour sa décision :

  • D'abord, être libéral et accepter la plupart des demandes, sauf raison impérieuse. Par défaut, la réponse est oui.
  • Parmi les bonnes raisons de rejeter une demande, l'insuffisance de la documentation fournie, des erreurs DNS dans la spécification du nouveau type (par exemple des suppositions incorrectes sur le fonctionnement des jokers, un cas relativement fréquent) ou un trop grand nombre de types demandés alors que l'application pourrait s'en tirer avec un seul.
  • Il y a une autre raison technique de rejeter une demande, ou en tout cas de l'examiner de plus près : l'enregistrement facile et libéral ne concerne que les types de données où les serveurs de noms n'ont pas besoin d'appliquer un traitement spécial (question I du formulaire à remplir). Autrement dit, ils peuvent traiter le nouveau type comme un type inconnu, selon le RFC 3597. S'il y a besoin d'un traitement spécial (par exemple CNAME, DS), on revient à la procéédure, bien plus lourde, d'une norme en bonne et due forme. Notez que, pour certains types, un traitement spécial est possible mais pas obligatoire (cas de MX, où il est conseillé d'inclure les adresses IP des serveurs de courrier dans la réponse mais, si ce n'est pas fait, le service marche quand même). Dans ce cas, c'est la procédure libérale qui s'applique

Outre l'enregistrement de nouveaux types de ressources DNS, notre RFC mentionne également d'autres champs des messages DNS. Un changement ou une extension de leur sémantique continue à nécessiter une action plus lourde à l'IETF. C'est le cas des classes (comme la plus courante, IN pour Internet). C'est aussi le cas de bits comme RD (Recursion Desired), qui n'a de signification que dans une question DNS. Dans une réponse, il est indéfini et son éventuelle utilisation future nécessitera un RFC sur le chemin des normes. Même chose pour le dernier bit qui reste libre dans les options, le bit Z (section 2.1). Quant aux opcodes qui indiquent le type du message (requête / notification / mise à jour dynamique / etc), un ajout à leur liste nécessitera le même chemin (section 2.2). Ils ont leur propre registre.

Les codes de réponse (rcodes), comme NXDOMAIN (nom inexistant), FORMERR (erreur de format) ou BADTIME (signature trop ancienne ou trop récente, cf. RFC 8945) sont tirés d'un espace plus vaste (il n'y a pas que les quatre bits 12 à 15 dans l'en-tête classique, il y a aussi des extensions comme les pseudo-enregistrements OPT) et la procédure est donc un peu plus libérale (IETF Review, c'est-à-dire un RFC non individuel mais pas forcément sur le chemin des normes, cf. section 2.3). Il y a également un registre de ces codes. À noter qu'une gestion trop légère des registres avait entraîné à une époque une double affectation du rcode 16, enregistré par le RFC 2671, puis ré-enregistré par le RFC 2845...

Notez aussi que notre RFC mentionne (section 3.3) l'allocation des noms, pour rappeler qu'il existe des noms réservés (RFC 2606) et qu'il existe un RFC (bien dépassé par les évolutions politiciennes ultérieures à l'ICANN), le RFC 1591, sur l'allocation et la gestion des TLD.

Les changements depuis le RFC 6195 sont décrits dans l'annexe B. Le seul vraiment important est une simplification du processus d'enregistrement des nouveaux types de données (par exemple, l'examen de la demande d'enregistrement d'un nouveau type de données par le groupe de travail dnsext n'est plus obligatoire). Cette simplification était largement consensuelle. Le reste des changements est un ensemble varié de clarifications et de précisions.


Téléchargez le RFC 6895


L'article seul

RFC 6891: Extension Mechanisms for DNS (EDNS(0))

Date de publication du RFC : Avril 2013
Auteur(s) du RFC : J. Damas (Bond Internet Systems), M. Graff, P. Vixie (Internet Systems Consortium)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dnsext
Première rédaction de cet article le 17 avril 2013


L'extension EDNS au traditionnel DNS a plus de treize ans et fête cette longue durée avec une nouvelle version, essentiellement cosmétique. EDNS a servi à faire sauter un certain nombre de barrières qui limitait la croissance du DNS, notamment l'antédiluvienne limite des réponses à seulement 512 octets.

Le protocole DNS, dans sa forme originale, spécifiée dans le RFC 1034, ne permettait pas de négocier des options, d'indiquer au serveur ce que sait faire le client, en plus des capacités minimales qu'impose le protocole. La norme originale (RFC 1035, section 2.3.4) imposait une limite de 512 octets aux messages DNS envoyés sur UDP. Une telle limite est bien trop basse, depuis longtemps, par exemple pour DNSSEC (section 3 de notre RFC), et ne correspondait pas aux capacités des réseaux et des machines modernes. Le DNS avait d'autres limites comme des champs de taille fixe, ne permettant qu'un petit nombre de valeurs possibles, désormais presque toutes définies (par exemple, avant EDNS, les codes de réponse - RCODE - ne faisaient que quatre bits, donc étaient presque tous épuisés).

EDNS0 est un mécanisme d'extension du DNS et une première extension, pour indiquer une taille supérieure aux 512 octets. L'extension se fait en squattant des champs inutilisés du paquet (DNS est un format binaire rigide, il ne permet donc pas facilement d'ajouter de nouvelles possibilités) et en créant un pseudo-type d'enregistrement, le type OPT. Déclaré comme indispensable par certaines autres extensions (notamment DNSSEC), EDNS fait aujourd'hui partie du bagage nécessaire à toute mise en œuvre du DNS.

L'extension pour indiquer la taille permet au client de spécifier la quantité d'octets qu'il est capable de recevoir (section 4.3). Avec le client DNS dig, cela se fait avec l'option bufsize (désormais activée par défaut dans les versions récentes de dig). Notre RFC recommande une valeur par défaut de 4 096 octets (section 6.2.5).

Prenons par exemple le TLD .hk car c'est un des plus gros en nombre de serveurs de noms. Si je demande cette liste :


% dig NS hk.

; <<>> DiG 9.8.1-P1 <<>> NS hk.
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 65212
;; flags: qr rd ra; QUERY: 1, ANSWER: 10, AUTHORITY: 0, ADDITIONAL: 14

;; QUESTION SECTION:
;hk.				IN	NS

;; ANSWER SECTION:
hk.			69658	IN	NS	X.HKIRC.NET.hk.
hk.			69658	IN	NS	T.HKIRC.NET.hk.
hk.			69658	IN	NS	S.HKIRC.NET.hk.
hk.			69658	IN	NS	A.HKIRC.NET.hk.
hk.			69658	IN	NS	B.HKIRC.NET.hk.
hk.			69658	IN	NS	W.HKIRC.NET.hk.
hk.			69658	IN	NS	Z.HKIRC.NET.hk.
hk.			69658	IN	NS	U.HKIRC.NET.hk.
hk.			69658	IN	NS	Y.HKIRC.NET.hk.
hk.			69658	IN	NS	V.HKIRC.NET.hk.

;; ADDITIONAL SECTION:
A.HKIRC.NET.hk.		69658	IN	A	203.119.2.18
B.HKIRC.NET.hk.		69658	IN	A	203.119.87.19
B.HKIRC.NET.hk.		69658	IN	AAAA	2001:dca:1000::cb77:5713
S.HKIRC.NET.hk.		69658	IN	A	128.32.136.3
S.HKIRC.NET.hk.		69658	IN	AAAA	2607:f140:ffff:fffe::3
T.HKIRC.NET.hk.		69658	IN	A	128.32.136.14
T.HKIRC.NET.hk.		69658	IN	AAAA	2607:f140:ffff:fffe::e
U.HKIRC.NET.hk.		69658	IN	A	210.201.138.58
U.HKIRC.NET.hk.		69658	IN	AAAA	2404:0:10a0::58
V.HKIRC.NET.hk.		69658	IN	A	204.61.216.46
V.HKIRC.NET.hk.		69658	IN	AAAA	2001:500:14:6046:ad::1
W.HKIRC.NET.hk.		69658	IN	A	202.12.28.140
W.HKIRC.NET.hk.		69658	IN	AAAA	2001:dc0:1:0:4777::140
X.HKIRC.NET.hk.		69658	IN	A	202.45.188.39

;; Query time: 1 msec
;; SERVER: 130.129.5.6#53(130.129.5.6)
;; WHEN: Tue Mar 12 19:30:33 2013
;; MSG SIZE  rcvd: 486

On voit que la réponse était proche des 512 octets et que, pour qu'elle tienne dans cette limite, le serveur a dû sérieusement réduire la taille de la section additionnelle (additional section). Si le serveur avait dû réduire encore plus, jusqu'à retirer des enregistrements de la section réponse (answer section), il aurait dû mettre le bit TC (troncation) à VRAI, imposant ainsi au client de reessayer en TCP.

Mais EDNS0 permet d'avoir la totalité de la section additionnelle (notez la pseudo-section lié à l'enregistrement OPT) :


% dig +bufsize=4096 NS hk.

; <<>> DiG 9.8.1-P1 <<>> +bufsize=4096 NS hk.
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 50455
;; flags: qr rd ra; QUERY: 1, ANSWER: 10, AUTHORITY: 0, ADDITIONAL: 20

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;hk.				IN	NS

;; ANSWER SECTION:
hk.			69632	IN	NS	Z.HKIRC.NET.hk.
hk.			69632	IN	NS	S.HKIRC.NET.hk.
hk.			69632	IN	NS	A.HKIRC.NET.hk.
hk.			69632	IN	NS	X.HKIRC.NET.hk.
hk.			69632	IN	NS	T.HKIRC.NET.hk.
hk.			69632	IN	NS	V.HKIRC.NET.hk.
hk.			69632	IN	NS	W.HKIRC.NET.hk.
hk.			69632	IN	NS	Y.HKIRC.NET.hk.
hk.			69632	IN	NS	U.HKIRC.NET.hk.
hk.			69632	IN	NS	B.HKIRC.NET.hk.

;; ADDITIONAL SECTION:
A.HKIRC.NET.hk.		69632	IN	A	203.119.2.18
B.HKIRC.NET.hk.		69632	IN	A	203.119.87.19
B.HKIRC.NET.hk.		69632	IN	AAAA	2001:dca:1000::cb77:5713
S.HKIRC.NET.hk.		69632	IN	A	128.32.136.3
S.HKIRC.NET.hk.		69632	IN	AAAA	2607:f140:ffff:fffe::3
T.HKIRC.NET.hk.		69632	IN	A	128.32.136.14
T.HKIRC.NET.hk.		69632	IN	AAAA	2607:f140:ffff:fffe::e
U.HKIRC.NET.hk.		69632	IN	A	210.201.138.58
U.HKIRC.NET.hk.		69632	IN	AAAA	2404:0:10a0::58
V.HKIRC.NET.hk.		69632	IN	A	204.61.216.46
V.HKIRC.NET.hk.		69632	IN	AAAA	2001:500:14:6046:ad::1
W.HKIRC.NET.hk.		69632	IN	A	202.12.28.140
W.HKIRC.NET.hk.		69632	IN	AAAA	2001:dc0:1:0:4777::140
X.HKIRC.NET.hk.		69632	IN	A	202.45.188.39
X.HKIRC.NET.hk.		69632	IN	AAAA	2405:3001:1:58::1:39
Y.HKIRC.NET.hk.		69632	IN	A	137.189.6.21
Y.HKIRC.NET.hk.		69632	IN	AAAA	2405:3000:3:60::21
Z.HKIRC.NET.hk.		69632	IN	A	194.146.106.70
Z.HKIRC.NET.hk.		69632	IN	AAAA	2001:67c:1010:17::53

;; Query time: 1 msec
;; SERVER: 130.129.5.6#53(130.129.5.6)
;; WHEN: Tue Mar 12 19:30:59 2013
;; MSG SIZE  rcvd: 613

Et voilà, tout le monde est désormais content.

La section 6 décrit le pseudo-enregistrement OPT, dont la présence marque un paquet comme conforme à EDNS. Il est situé dans la section additionnelle du message DNS, a le type 41, le nom de domaine est forcément . (la racine), la classe est détournée de son rôle normal pour indiquer la taille des paquets que l'envoyeur pourra recevoir en retour et le champ TTL est également détourné de son usage normal pour offrir de nouvelles options et de nouveaux codes de retour (rappelez-vous qu'il n'y avait que quatre bits pour ces codes dans le DNS original). Pour l'instant, une seule nouvelle option, le bit DO (DNSSEC OK) qui indique la capacité de l'émetteur à traiter les signatures DNSSEC (il avait été normalisé dans le RFC 3225).

L'ex-champ TTL sert aussi à indiquer le numéro de version d'EDNS, zéro actuellement (d'où le nom EDNS0 qu'on utilise parfois). Programmeurs, attention, certaines API (par exemple celle de DNS Python) nécessitent d'indiquer le numéro de version pour activer EDNS et il faut donc indiquer zéro pour dire qu'on veut de l'EDNS, ce qui peut être déroutant.

Ensuite, les données peuvent contenir plusieurs options. À l'heure actuelle, l'écrasante majoritéé des paquets EDNS n'en contiennent aucune. Mais, si c'est le cas, elles sont codées en TLV, un code indiquant l'option (les valeurs possibles étant dans un registre IANA), une longueur et les données spécifiques à l'option. Un exemple d'une telle option est le NSID du RFC 5001.

On notera qu'EDNS est ce que le DNS appelle une extension hop by hop ce qui veut dire qu'elle s'applique entre deux logiciels adjacents, pas de bout en bout. Si un client DNS demande à un résolveur local, qui demande à son tour à un serveur de .re, les options EDNS mises par le client sont transmises uniquement au résolveur, qui fabriquera ensuite une requête différente (peut-être avec d'autres options), pour le serveur faisant autorité pour .re.

Encore aujourd'hui, il existe des serveurs qui ne gèrent pas EDNS. Par exemple, ceux de microsoft.com répondent FORMERR (Format Error) :


% dig +bufsize=4096 @ns2.msft.net. SOA microsoft.com.

; <<>> DiG 9.8.1-P1 <<>> +bufsize=4096 @ns2.msft.net. SOA microsoft.com.
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: FORMERR, id: 54935
...

La section 6.2.2 de notre RFC précise donc qu'un émetteur intelligent peut alors se rabattre sur du DNS classique et ne pas envoyer l'enregistrement OPT :


% dig @ns2.msft.net. SOA microsoft.com.              

; <<>> DiG 9.8.1-P1 <<>> @ns2.msft.net. SOA microsoft.com.
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 22484
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 2
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;microsoft.com.			IN	SOA

;; ANSWER SECTION:
microsoft.com.		3600	IN	SOA	ns1.msft.net. msnhst.microsoft.com. 2013031202 300 600 2419200 3600
...

Au moins, les serveurs de microsoft.com répondent, même si c'est par un refus. Plus embêtant, les serveurs qui ne répondent plus du tout lorsque la requête est en EDNS, en général en raison d'une boîte noire mal programmée et mal gérée installée devant le serveur (un pare-feu par exemple : beaucoup d'administrateurs réseaux ne supportent pas que le serveur DNS marche bien et mettent donc une middlebox boguée devant, cf. section 8 de notre RFC, ainsi que le RFC 5625). Un logiciel comme BIND, lorsqu'il ne reçoit pas de réponse, réessaie sans EDNS pour voir si c'est cela la cause du problème. Cette possibilité est décrite en section 6.2.5 qui recommande d'essayer d'abord EDNS avec une taille plus petite (inférieure à la MTU, au cas où le problème soit lié à la fragmentation), puis enfin sans EDNS.

L'EDNS original, du RFC 2671, prévoyait également des nouvelles façons de stocker les composants d'un nom de domaine, en plus des deux méthodes DNS traditionnelles, comprimée ou non (sections 4.2 et 5 de notre RFC et section 4.1.4 du RFC 1035). Cette pratique a été très peu utilisée, en raison des difficultés de déploiement (cf. RFC 3363 et RFC 3364). Notre RFC 6891 abandonne donc cette possibilité et reclasse le RFC 2673 (le seul qui avait utilisé un nouveau type de composants, les « composants binaires ») dans le cimetière des RFC dépassés. C'est le principal changement de ce nouveau RFC (les autres étant plutôt des détails, cf. annexe A.) Notons aussi que ce nouveau RFC est désormais « Norme Internet » et plus simplement « Proposition de norme ».

Pour les amateurs de programmation, du code C d'analyse d'un paquet DNS contenant de l'EDNS est dans mon article « Décoder les paquets DNS capturés avec pcap ».

Quelques exemples de code pour finir. Pour analyser un enregistrement OPT d'EDNS, voir comment c'est fait dans DNSmezzo. Ensuite, pour envoyer des requêtes EDNS, en Go, avec godns :

const (
	EDNSBUFFERSIZE  uint16  = 4096
)
...
m := new(dns.Msg)
...
m.SetEdns0(EDNSBUFFERSIZE, true)

En Python, avec DNSpython (notez qu'on indique la version d'EDNS donc zéro pour activer EDNS n'est pas une erreur) :

message = dns.message.make_query(name, type, use_edns=0, payload=4096)

Et pour finir, en C, si vous assemblez le paquet à la main (il y a évidemment des façons plus simples de faire de l'EDNS), le code pourra ressembler à :

 /* OPT pseudo-RR */
 after_qname[4] = 0;     /* root domain */
 /* OPT = type 41 */
 after_qname[5] = 0;
 after_qname[6] = 41;
 /* Class stores the payload size */
 bufsize_wire = htons(bufsize);
 memmove(after_qname + 7, &bufsize_wire, sizeof(bufsize));
 /* TTL store the RCODE and flags */
 after_qname[9] = 0;
 after_qname[10] = 0;
 if (dnssec) {
     after_qname[11] = 128;      /* DO: request DNSSEC signatures */
 } else {
     after_qname[11] = 0;
 }
 after_qname[12] = 0;
 /* Resource data length (empty, here) */
 after_qname[13] = 0;
 after_qname[14] = 0;

Téléchargez le RFC 6891


L'article seul

Creating measurements on RIPE Atlas through the API

First publication of this article on 16 April 2013


The network of Atlas probes managed by the RIPE-NCC exists for a long time. These small probes are installed in many places all over the world and perform periodic measurements, which are the basis of Internet health checks, interesting statistics and many papers. There have been many improvments recently, the addition of UDM (User Defined Measurements), where you can decide your own measurements via a Web interface, then an API to retrieve results in a structured format, and now an API to start measurements. It is currently beta.

Two warnings before you read further away: the UDM are not available for the general public. You need an account at RIPE-NCC and some credits earned from the Atlas system. And a second caveat: the API is in flux (and the measurement creation API is very recent) and therefore it is quite possible that the code published in this article will not work in the future. My goal is to show that it is possible, not to make the definitive documentation. So, always keep an eye on the official documentation (the measurement creation API is documented separately because it is still unstable.)

First, let's create in Python a script to run a measurement in several geographical areas (the world and four big regions). We will ping www.bortzmeyer.org with IPv6. The Atlas API is a simple REST one, taking parameters in JSON and giving back results in the same format. We will use the urllib2 package in Python's standard library and first create a Request because we will need non-standard headers:

url = "https://atlas.ripe.net/api/v1/measurement/?key=%s" % key
request = urllib2.Request(url)
request.add_header("Content-Type", "application/json")
request.add_header("Accept", "application/json")

The two HTTP headers are added because Atlas only speaks JSON. So, we need to define the parameters in JSON after reading the documentation. First, create a Python dictionary (this is Python code, not JSON, even if it is similar):

data = { "definitions": [
           { "target": "www.bortzmeyer.org", "description": "Ping my blog",
           "type": "ping", "af": 6, "is_oneoff": True} ],
         "probes": [
             { "requested": 5, "type": "area", "value": "WW" } ] }

And let's change it at each iteration:

for area in ["WW", "West", "North-East", "South-East", "North-Central", "South-Central"]:
    data["probes"][0]["value"] = area

And start the measurement with an HTTP POST request and the Python dictionary encoded as JSON as a parameter:

conn = urllib2.urlopen(request, json.dumps(data))

Atlas will send us back a JSON object giving, not the actual results, but the ID of this measurement. We will have to retrieve it later, through the Web interface or via the API, as explained in the next paragraphs. But, for the time being, let's just display the measurement ID. This requires parsing the JSON code:

results = json.load(conn) 
print("%s: measurement #%s" % (area, results["measurements"]))

And that's all. The program will display:

% python ping.py                                                      
WW: measurement #[1007970]
West: measurement #[1007971]
North-East: measurement #[1007972]
South-East: measurement #[1007973]
North-Central: measurement #[1007974]
South-Central: measurement #[1007976]

There are two things I did not explain here: the error handling and the API key. To create a measurement, you need an API key, which you get from the Web interface. In my case, I store it in $HOME/.atlas/auth and the script reads it there and adds it to the URL of the request. For the error handling, I suggest you see the actual script, atlas-ping.py.

The above script did only half of the work. It creates a measurement but does not retrieve and parse it. Let's now do that. Measurements can take a long time (in the previous example, because of the parameter is_oneoff, the measurement was done only once; if it is repeated, it lasts of course much longer) and there is no callback in Atlas, you have to poll. You get a JSON object with a member named status which is not thoroughly documented but with trial and errors and help from nice people, you can decipher it. The possible values are:

   0: Specified
   1: Scheduled
   2: Ongoing
   4: Stopped
   5: Forced to stop
   6: No suitable probes
   7: Failed
   8: Archived

Now, Let's poll:

over = False
while not over:
    request = urllib2.Request("%s/%i/?key=%s" % (url, measure, key))
    request.add_header("Accept", "application/json")
    conn = urllib2.urlopen(request)
    results = json.load(conn)
    status = results["status"]["name"]
    if status == "Ongoing" or status == "Specified":
            print("Not yet ready, sleeping...")
            time.sleep(60)
    elif  status == "Stopped":
            over = True
    else:
            print("Unknown status \"%s\"\n" % status)
            time.sleep(120)

So, for measurement 1007970, we retrieve https://atlas.ripe.net/api/v1/measurement/1007970/ and parse the JSON, looking for the status. Once the above while loop is done, the results are ready and we can get them at https://atlas.ripe.net/api/v1/measurement/1007970/result/:

request = urllib2.Request("%s/%i/result/?key=%s" % (url, measure, key))
request.add_header("Accept", "application/json")
conn = urllib2.urlopen(request)
results = json.load(conn)
total_rtt = 0
num_rtt = 0
num_error = 0
for result in results:
   ...

Here, we will do only a trivial computation, finding the average RTT of all the tests for all the probes. Just remember that some probes may fail to do the test (it is unfortunately much more common with IPv6 tests) so we have to check there is indeed a rtt field:

    for result in results:
        for test in result["result"]:
            if test.has_key("rtt"):
                total_rtt += int(test["rtt"])
                num_rtt += 1
            elif test.has_key("error"):
                num_error += 1
            else:
                raise Exception("Result has no field rtt and not field error")
...
print("%i successful tests, %i errors, average RTT: %i" % (num_rtt, num_error, total_rtt/num_rtt))

And that's all, we have a result:

Measurement #1007980, please wait the result (it may be long)
...
12 successful tests, 0 errors, average RTT: 66

The entire script is atlas-ping-retrieve.py.

Now, let's try with a different type of measurements, on the DNS, and a different programming language, Go. The preparation of the HTTP POST request is simple, using the net/http standard package:


client := &http.Client{}
data := strings.NewReader(DATA)
req, err := http.NewRequest("POST", URL + key, data)
req.Header.Add("Content-Type", "application/json")
req.Header.Add("Accept", "application/json")

And its execution also:

response, err := client.Do(req)
body, err := ioutil.ReadAll(response.Body)

But I skipped one step: what is in the DATA constant? It has to be JSON content. Go does not have a way to write a JSON-like object as simply as Python, so, in this case, we cheat, we create the JSON by hand and put it in a string (the proper way would be to create a Go map, with embedded arrays and maps, and to marshall it into JSON):

DATA string = "{ \"definitions\": [ { \"target\":
	      \"d.nic.fr\", \"query_argument\": \"fr\",
	      \"query_class\": \"IN\", \"query_type\": \"SOA\", 
              \"description\": \"DNS AFNIC\", \"type\": \"dns\",
	      \"af\": 6, \"is_oneoff\": \"True\"} ],  \"probes\": 
              [  { \"requested\": 5, \"type\": \"area\", \"value\": \"WW\" } ] }"
)

Now, we just have to parse the JSON content sent back with the standard package encoding/json. Go is a typed language and, by default, type is checked before the program is executed. In the REST/JSON world, we do not always know the complete structure of the JSON object. So we just declare the resulting object as interface{} (meaning untyped). Does it disable all type checking? No, it just postpones it until run-time. We will use type assertions to tell what we expect to find and these assertions will be checked at run-time:


err = json.Unmarshal(body, &object)
mapObject = object.(map[string]interface{})

In the code above, the type assertion is between parenthesis adter the dot: we assert that the object is actually a map indexed by strings, and storing untyped objects. We go on:

status := mapObject["status"].(map[string]interface{})["name"].(string)
if status == "Ongoing" || status == "Specified" {
			fmt.Printf("Not yet ready, be patient...\n")
			time.Sleep(60 * time.Second)
} else if status == "Stopped" {
			over = true
} else {
			fmt.Printf("Unknown status %s\n", status)
			time.Sleep(90 * time.Second)
}

There was two other type assertions above, one to say that mapObject["status"] is itself a map and one to assert that the field name contains character strings. We can now, once the polling loop is over, retrieve the result, parse it and display the result:


err = json.Unmarshal(body, &object)
arrayObject = object.([]interface{})
total_rtt := float64(0)
num_rtt := 0
num_error := 0
for i := range arrayObject {
	mapObject := arrayObject[i].(map[string]interface{})
	result, present := mapObject["result"]
	if present {
		rtt := result.(map[string]interface{})["rt"].(float64)
		num_rtt++
		total_rtt += rtt
	} else {
		num_error++
	}
}
fmt.Printf("%v successes, %v failures, average RTT %v\n", num_rtt, num_error, total_rtt/float64(num_rtt))

And it displays:

Measurement #1008096
...
4 successes, 0 failures, average RTT 53.564

And this is the (temporary) end. The Go program is atlas-dns.go.

Thanks to Daniel Quinn and Iñigo Ortiz de Urbina for their help and tricks and patience. A good tutorial on running UDM and analyzing their results is Hands-on: RIPE Atlas by Nikolay Melnikov.


L'article seul

RFC 6912: Principles for Unicode Code Point Inclusion in Labels in the DNS

Date de publication du RFC : Avril 2013
Auteur(s) du RFC : A. Sullivan (Dyn, Inc), D. Thaler (Microsoft), J. Klensin, O. Kolkman (NLnet Labs)
Pour information
Première rédaction de cet article le 16 avril 2013


Ce RFC de l'IAB expose les principes que, selon l'IAB, devraient suivre les registres de noms de domaine lorsqu'ils décident quels caractères Unicode sont autorisés ou pas, pour l'enregistrement de noms de domaine internationalisés.

Notons tout de suite que les principes exposés dans ce RFC ne sont guère argumentés (les sections 6, 7 et 8, normalement consacrées à cette tâche, sont très pauvres). Dès l'introduction, le RFC dit qu'il ne faut pas autoriser tous les caractères mais ne dit pas pourquoi, ou quels dangers mystérieux menacent ceux qui oseraient passer outre. Mais, une fois qu'on a décidé de ne pas permettre tous les caractères Unicode (enfin, tous ceux qui sont légaux selon le RFC 5892), il reste le problème du choix. Il n'existe pas d'algorithme pour cela (le monde Unicode est bien trop complexe, reflétant la complexité des écritures du monde et nos connaissances insuffisantes) et ce RFC, plutôt que de donner un tel algorithme, pose des principes qui devraient guider ceux et celles qui feront le choix.

La section 1 donne quelques objectifs (sans que la suite du RFC n'indique le rapport entre les principes et ces objectifs) : limiter les possibilités de confusion entre deux noms (par exemple google.com et goog1e.com, regardez bien le second), éviter qu'une adresse IP soit prise pour un nom de domaine comportant des éléments numériques (un faux problème typique, cf. RFC 1123, section 2.1), et favoriser l'accessibilité (cf. WCAG). Le RFC introduit une notion importante, celle de zone publique. Une zone du DNS est un ensemble de sous-domaines contigus et gérés par la même organisation. Certaines sont privées, au sens où une seule organisation les utilisent (par exemple la zone univ-paris-diderot.fr n'est utilisée que par l'université Denis Diderot). D'autres sont publiques au sens où le registre qui la gère accepte des enregistrements de diverses organisations. La plupart des TLD sont des zones publiques (par exemple .fr, .org ou .pm), ainsi que la racine. En effet, le RFC estime qu'il faut des règles particulières pour ces zones publiques (cf. section 4).

L'IAB s'est déjà exprimée sur cette question du choix des caractères autorisés pour les IDN. Notons que personne ne s'est posé la question pour les noms de domaines en ASCII alors que, comme le montre l'exemple goog1e.com plus haut, ils posent exactement les mêmes « problèmes ». Mais l'idée même de permettre à chacun, et pas seulement aux anglophones, d'écrire les noms de domaine avec leur écriture n'est toujours pas complètement acceptée. À part quelques ultra-réactionnaires, plus personne n'ose dire ouvertement qu'il est contre mais l'anti-IDNisme s'exprime plutôt aujourd'hui par un discours de peur, parlant de dangers (jamais clairement spécifiés) et laissant entendre qu'il faudrait contrôler sévèrement les IDN. Les déclarations précédentes de l'IAB peuvent être trouvées dans « IAB Statement: "The interpretation of rules in the ICANN gTLD Applicant Guidebook" » et « Response to ICANN questions concerning 'The interpretation of rules in the ICANN gTLD Applicant Guidebook' ». Dans ces textes, l'IAB plaidait pour un extrême conservatisme dans l'autorisation de caractères, en restreignant encore les règles techniques des RFC 5890 et RFC 5892, par exemple en n'autorisant que les caractères de la catégorie Unicode « Lettres ».

Dans ce RFC, l'IAB veut aller plus loin en interdisant également des caractères de cette catégorie. Le RFC prend l'exemple de ʼ (U+02BC, une apostrophe), qui a un rendu quasiment toujours identique à ’ (U+2019) alors qu'il est dans la catégorie Lettre (U+2019 étant dans la catégorie Ponctuation, mystères des catégories Unicode). Sans compter la traditionnelle ' (U+0027). Bien que, légalement, U+02BC soit un caractère autorisé dans un IDN, le RFC suggère que ce n'est sans doute pas une bonne idée de l'autoriser.

S'il y a des caractères dans la catégorie Lettres qui ne devraient sans doute pas être autorisés (cas ci-dessus), l'inverse existe aussi : des caractères situés dans d'autres catégories sont néanmoins indispensables dans certaines langues, notamment indiennes. Cela illustre le point mentionné plus haut : il n'y a pas d'algorithme pour établir automatiquement la liste des caractères autorisés, il va falloir y aller à la main. La section 4.2.4 du RFC 5891 mentionnait ce travail comme une reponsabilité indispensable du registre, et ce RFC 6912 ajoute que ce travail doit être fait à l'avance, pas décidé lorsqu'une demande d'enregistrement de nom se présente. Une telle décision lorsqu'une demande survient offrirait trop de possibilités à l'arbitraire. Non, il faut des règles pré-établies, et publiées. (À titre d'exemple, vous pouvez regarder les règles d'enregistrement des IDN dans .fr.)

Le RFC estime que ces règles doivent être d'autant plus sévères (doivent autoriser moins de caractères) que l'on monte dans la hiérarchie des zones et que la zone racine doit donc avoir des règles particulièrement conservatrices, puisqu'elle concerne tous les utilisateurs de l'Internet.

Donc, pas d'algorithme (s'il était possible, il aurait sans doute déjà été développé) mais des principes. Quels sont-ils ? La section 3 en fournit une liste. D'abord, le principe de longévité : comme un caractère peut changer de catégorie, invalidant son usage (un exemple figure dans le RFC 6452), il est prudent de n'autoriser que des caractères qui sont stables depuis plusieurs versions d'Unicode.

Ensuite, le principe de moindre étonnement : un utilisateur normal ne devrait pas être trop surpris de la présence ou de l'absence de tel caractère. Notez que cela dépend du contexte : un utilisateur d'une écriture donnée ne sera pas surpris par les mêmes choses qu'un utilisateur d'une autre écriture.

Ces principes étaient valables pour toutes les zones. Mais les zones publiques ont des contraintes supplémentaires (section 4). Il y a le principe conservateur (dans le doute, rejeter le caractère), le principe d'inclusion (les caractères sont interdits par défaut et on inclut ensuite explicitement ceux qu'on estime « sûrs », terme que le RFC ne définit pas, et qui vient du FUD anti-Unicode), le principe de simplicité (un « honnête homme », avec des compétences modérées en DNS et en Unicode, doit pouvoir comprendre les raisons qui ont amené au choix d'acceptation ou de rejet, sans avoir eu besoin d'être présent aux quinze dernières réunions de l'IETF)...

Ce principe de simplicité dépend là encore du contexte. Si l'honnête homme cité plus haut ne connait aucune langue indienne, il ne comprendra sans doute pas les raisons qui ont mené à l'ajout de caractères non-lettres, indispensables pour certaines de ces langues. La racine servant à tous, ses règles devraient être ultra-simples et ne pas demander de compétences linguistiques particulières. Un ccTLD d'un pays donné peut se permettre des règles plus complexes pour des étrangers, mais qui sembleront simples à ceux qui connaissent les langues locales.

Pour les zones publiques, il y a aussi le principe de prédictabilité (les règles doivent donner un résultat identique, dès qu'on les applique sérieusement) et de stabilité (la liste des caractères autorisés ne devrait changer que rarement).

La racine, pour les raisons expliquées plus haut, a droit à une section spéciale (section 5). Le RFC demande qu'elle soit strictement peuplée de lettres, en s'appuyant sur une note de la section 2.1 du RFC 1123 qui dit que c'est le cas (c'était vrai lorsque le RFC 1123 a été publié, mais il n'y a aucun consensus à l'IETF sur l'interprétation de cette note : exprime t-elle une constatation ou une prescription ?) L'idée derrière cette restriction (RFC 4690) est que les noms de domaines n'ont pas vocation à permettre d'écrire tous les mots, encore moins des phrases correctes et complètes, mais uniquement celle de permettre la création de mnémoniques pratiques.

Ce RFC exprimant des opinions très contestables, la discussion avait été animée (voir par exemple les commentaires que j'avais fait sur une précédente version, violemment anti-Unicode).


Téléchargez le RFC 6912


L'article seul

Aucun souvenir assez solide

Première rédaction de cet article le 14 avril 2013


L'auteur de « La Horde du Contrevent », Alain Damasio, a rassemblé dans ce livre plusieurs nouvelles, aussi étranges et aussi entraînantes que son précédent roman.

Dans « Les Hauts® Parleurs® », le langage a été privatisé. Il faut payer des redevances pour les mots que l'on utilise, à part une poignée de termes qui ont été généreusement laissés dans le domaine public. Que reste t-il à faire pour les écrivains et aux poètes ? (Fort logiquement, la nouvelle est en ligne.) « So phare away » parle de communication et de réseau dans un monde où l'eau a tout envahi et seuls quelques phares surnagent, s'envoyant des messages lumineux pas toujours clairs. Et « Une stupéfiante salve d'escarbilles de houille écarlate » est la nouvelle la plus proche de l'univers délirant de « La Horde du Contrevent », on retrouve même, dans cette course délirante dans les airs, un aéromaître.

Le tout avec les inventions typographiques et les jeux de langage de l'auteur : des lectures qui dévissent la tête...


L'article seul

RFC 6922: The application/sql Media Type

Date de publication du RFC : Avril 2013
Auteur(s) du RFC : Y. Shafranovich (BioFortis)
Pour information
Première rédaction de cet article le 11 avril 2013


Premier enregistrement d'un nouveau type de données (type MIME) fait depuis les nouvelles règles du RFC 6838, ce RFC enregistre un type très ancien mais qui n'avait jamais été normalisé, application/sql, pour le code source SQL.

Donc, les nouvelles procédures du RFC 6838 marchent, même pour un type très ancien. SQL a plus de trente ans d'usage derrière lui. La section 3 contient le formulaire d'enregistrement du nouveau type application/sql. Ce formulaire rempli met en garde contre quelques pièges de SQL comme le fait que l'encodage puisse être indiqué dans le fichier (ce qui rend inutile le paramètre charset du type MIME), ou comme les problèmes de sécurité si un client était assez naïf pour exécuter aveuglément du SQL récupéré sur le réseau (quoique j'ai rarement vu du malware en SQL...). Le formulaire d'enregistrement comprend aussi une section sur les problèmes d'interopérabilité et elle note que, bien que SQL soit une norme ISO (norme 9075.2011, pas disponible en ligne), les différences entre mises en œuvre du langage sont quand même très grandes. Verra t-on un jour des types plus spécifiques comme application/oracle+sql ou application/postgres+sql ?

J'ai modifié la configuration Apache de ce blog pour y ajouter :

AddType application/sql .sql

Et, désormais, des fichiers comme joins.sql (cité dans cet article) sont servis avec le nouveau type MIME. N'était-ce pas mieux en text/plain (par défaut affiché dans le navigateur) ? J'hésite.


Téléchargez le RFC 6922


L'article seul

RFC 6924: Registration of Second-Level URN Namespaces Under "ietf"

Date de publication du RFC : Avril 2013
Auteur(s) du RFC : B. Leiba (Huawei)
Pour information
Première rédaction de cet article le 11 avril 2013


Dans la grande famille des URN, l'IETF avait son propre espace, commençant par ietf. Mais il n'existait pas de registre des sous-espaces de ietf. C'est désormais fait.

Le RFC 2648 avait créé cet espace ietf. Il avait quelques sous-espaces comme rfc (donc, par exemple, ce RFC est urn:ietf:rfc:6924.) Le RFC 3553 avait créé un nouveau sous-espace params, et un registre pour ce sous-espace. Ainsi, on voit des URN comme urn:ietf:params:xml:ns:vcard-4.0 (RFC 6350) ou urn:ietf:params:xml:ns:netconf:base:1.0 (RFC 6241). Mais peut-on créer encore d'autres sous-espaces que params ? Et où les décrire ?

Un registre existe désormais à cette fin. Il sera rempli selon la procédure (assez lourde) « examen par l'IETF » du RFC 5226. On n'y trouve pour l'instant que les sous-espaces des RFC 2648 et RFC 3553.


Téléchargez le RFC 6924


L'article seul

RFC 6916: Algorithm Agility Procedure for RPKI

Date de publication du RFC : Avril 2013
Auteur(s) du RFC : R. Gagliano (Cisco Systems), S. Kent (BBN Technologies), S. Turner (IECA)
Réalisé dans le cadre du groupe de travail IETF sidr
Première rédaction de cet article le 11 avril 2013


La grosse infrastructure de sécurisation du routage RPKI+ROA est en train de se mettre en place, les RFC sont sortis, mais l'IETF ne s'arrête pas là. Ce document décrit la façon de changer les algorithmes de cryptographie utilisés par la RPKI lorsque les progrès de la cryptanalyse l'exigeront.

Disons-le tout de suite, cela va être un énorme travail. La RPKI n'a pas de centre, les décisions dépendent d'un grand nombre d'acteurs non coordonnés, des AC qui émettent les certificats aux RP (Relying Parties, les validateurs qui vérifient les ROA - Route Origin Authorizations). Le RFC ne sème pas d'illusion et affirme qu'un éventuel changement d'algorithmes dans la RPKI prendra plusieurs années.

Il y avait en théorie plusieurs stratégies possibles, du bas vers le haut (les acteurs situés le plus bas dans la hiérarchie migrent les premiers) ou celle finalement choisie, après de longues discussions dans le groupe de travail SIDR, du haut vers le bas (les acteurs les plus haut placés commencent).

À noter qu'il s'agit bien de changer d'algorithmes. Remplacer les clés (key rollover) est prévu et normal dans le fonctionnement de la RPKI (RFC 6489). Mais les algorithmes ne sont pas éternels. Ceux normalisés actuellement dans le RFC 6485 (RSA et SHA-256) ne résisteront pas toujours à la cryptanalyse et devront laisser un jour la place à d'autres (fondés sur les courbes elliptiques ?).

Comme le processus sera long, il devra commencer par une mise à jour de ce RFC 6485, documentant les nouveaux algorithmes et par la publication d'un plan de migration, avec chronologie. Puis la procédure décrite en section 4 sera appliquée, dans l'ordre chronologique : les AC commencent à émettre des certificats avec le nouvel algorithme, puis les RP (les validateurs) commencent à pouvoir vérifier le nouvel algorithme, puis les AC arrêtent d'utiliser l'ancien algorithme (période nommée Twilight dans le RFC, mais rien à voir avec Stephenie Meyer), puis on peut déclarer l'ancien algorithme mort. Le passage à chaque étape nécessite que tous les acteurs impliqués aient migré, ce qui explique le délai de plusieurs années envisagé (aucune procédure n'est envisagée pour le cas, catastrophique, où de brusques percées de la cryptanalyse obligeraient à un remplacement d'urgence). Le RFC est plein de phrases comme « If a substantial number of RPs are unable to process product sets signed with Suite B [le nouvel algorithme], the algorithm transition timeline document MUST be reissued, pushing back the date for this and later milestones [...] », qui donnent une idée des problèmes qui vont surgir à cause de cette règle « pas de passage sans unanimité ».

Il y aura donc une (longue) période de coexistence entre les deux algorithmes. La section 6 décrit ce que devra être le comportement des validateurs pendant cette période, notamment si les deux algorithmes donnent des résultats opposés (l'un valide et l'autre pas ; l'expérience avec des techniques cryptographiques comme DNSSEC montre que ce genre de choses arrive).

Et n'oubliez pas que ce beau plan n'a jamais été testé. Rendez-vous dans sept ou quinze ans pour le premier changement d'algorithme de la RPKI...


Téléchargez le RFC 6916


L'article seul

Faire passer XMPP au dessus de SSH (par exemple s'il est bloqué)

Première rédaction de cet article le 4 avril 2013


Si on veut faire de la messagerie instantanée en utilisant un protocole ouvert, avec du logiciel libre, sans serveur centralisé, la solution est le protocole XMPP, normalisé dans le RFC 6121. XMPP, comme le courrier électronique, repose sur le principe de fédération. Mais bien des réseaux bloquent (stupidement, mais c'est une autre histoire) XMPP en sortie. Si SSH passe, une solution possible est de faire passer XMPP sur SSH.

Cela m'est arrivé plusieurs fois : je suis sur un réseau a priori accueillant, je lance mon Pidgin pour bavarder ou discuter sérieusement et crac, pas moyen de se connecter à mon serveur. Les ports utilisés par XMPP sont bloqués par un pare-feu pénible (le port par défaut est 5222, mais l'utilisation des enregistrements SRV permet à un serveur XMPP d'être facilement joignable via un autre port.)

Il existe des tas de solutions à ce problème. Par exemple de configurer un VPN avec une machine externe et de faire passer XMPP par le VPN. Mais comme SSH marche à beaucoup d'endroits, est simple et offre une grande sécurité, j'utilise une solution basée sur SSH.

Je lance d'abord un relais Socks vers une machine de confiance, située en dehors du pare-feu pénible. Mettons le port 3022 :

% ssh -f -N -D 3022 moi@ma.machine.example

Le -f met SSH en arrière-plan, le -N dit de ne pas exécuter de commande distante, de juste faire le relais, et le -D 3022 ouvre un relais Socks sur le port local 3022.

Ensuite, tout dépend du client XMPP utilisé. Dans Pidgin, choisir l'onglet Proxy, Proxy type SOCKS5, mettre comme Host la machine cliente SSH (ici localhost) et comme Port celui choisi (3022 dans l'exemple ci-dessus). Et voilà, on peut recommencer à communiquer.

Avec d'autres clients XMPP qui ne géreraient pas Socks, on peut utiliser tsocks ou Dante.

Pour en apprendre plus sur les tunnels SSH + Socks, je recommande cet excellent article.


L'article seul

Récupérer des débits, via SNMP, sur JunOS

Première rédaction de cet article le 4 avril 2013


Le protocole de gestion de réseau SNMP permet de récupérer la valeur de compteurs sur une machine distante. Ces compteurs sont en général des valeurs cumulées, pas des débits et le gestionnaire SNMP doit donc faire plusieurs requêtes, puis calculer le débit lui-même. Est-il possible de récupérer des débits directement ?

SNMP est normalisé (pour sa version 3, utilisée ici) dans le RFC 3411 et suivants. Mais ces RFC ne normalisent que le protocole. Le modèle de données (arborescent) est dans le RFC 2578. Et la liste des variables qu'on peut récupérer en SNMP est décrite dans des MIB dont la plus célèbre est la standard MIB-II, décrite dans le RFC 1123. Elle offre un certain nombre de variables par interface, comme ifInOctets (nombre d'octets étant rentrés via cette interface), ifOutUcastPkts (nombre de paquets unicast sortis par cette interface), etc. Ces variables ont en commun d'être des compteurs depuis un instant T (typiquement le démarrage de la machine). En général, on est plutôt intéressés par le débit que par le nombre total d'octets ou de paquets. Les programmes comme Cacti, qui affichent des jolis graphes, interrogent à intervalles réguliers l'agent SNMP (la machine surveillée) et calculent ensuite des débits.

Ce n'est pas très pratique lorsqu'on veut déclencher des alarmes (par exemple depuis un logiciel de supervision comme Icinga). Les scripts de surveillance n'ont pas de mémoire et stocker des résultats sur disque n'est pas pratique (si vous utilisez les plugins Nagios officiels, check_snmp a une option --rate qui peut servir : lisez la section Rate calculation de sa documentation.) Peut-on récupérer ces débits directement sur l'agent ?

À ma connaissance, pas de manière standard. Le but de SNMP est de pouvoir tourner sur des machines simples, ayant peu de moyens. Pas question donc de devoir retenir des valeurs compliquées, ou de faire des calculs. Je crois qu'il n'existe rien dans les MIB standards.

Mais ce n'est pas la fin de l'histoire. Tout équipement réseau met en œuvre des MIB non standards qui offrent en général des tas de possibilités supplémentaires intéressantes, dans le sous-arbre 1.3.6.1.4.1 du SMI, sous-arbre dit enterprises. Essayons sur un commutateur/routeur Juniper SRX, avec JunOS. Un examen de la MIB Juniper montre des variables prometteuses :

ifIn1SecRate OBJECT-TYPE
	SYNTAX      Gauge32
	MAX-ACCESS  read-only
	STATUS      current
	DESCRIPTION
		"The number of bits per second (bps), delivered by 
		this (sub-)layer to its next higher (sub-)layer."
	::= { ifJnxEntry 1 }

Il reste à configurer l'engin pour faire du SNMP. Cela ressemble à :

snmp {
    location "Dans le nuage";
    contact "Happy Sysadmin";
    v3 {                                
        usm {
            local-engine {
                user USERNAME {
                    authentication-md5 {
                        authentication-key "SECRETDATA";
                    }
                }
            }
        }
        vacm {
            security-to-group {
                security-model usm {
                            }           
                        }
                    }
                }
            }
        }
        snmp-community all {
            security-name all;
        }
    }
    view all {
        oid .1 include;
        oid system include;
        oid internet include;
    }
}

Si vous ne connaissez pas JunOS, notez que, pour obtenir ce résultat, il a fallu charger ce fichier, ou bien taper dans la console une série de commandes comme :

set snmp v3 usm local-engine user USERNAME authentication-md5 authentication-password MOTDEPASSESECRET

Testons que cela marche avec Net-SNMP sur le routeur d'adresse IP 198.18.0.2 :

% snmpget -v3 -u USERNAME -a MD5 -A MOTDEPASSESECRET \
      -l authNoPriv 198.18.0.2 1.3.6.1.4.1.2636.3.3.1.1.3.513 
SNMPv2-SMI::enterprises.2636.3.3.1.1.3.513 = Gauge32: 11965

Deux explications : l'OID a été trouvé manuellement en suivant la MIB (2636 = Juniper). La liste complète des variables qui m'intéressent est :

1.3.6.1.4.1.2636.3.3.1.1.1.ifIndex :  in rate bits/s
1.3.6.1.4.1.2636.3.3.1.1.2.ifIndex :  in rate bytes/s
1.3.6.1.4.1.2636.3.3.1.1.3.ifIndex :  in rate packets/s
1.3.6.1.4.1.2636.3.3.1.1.4.ifIndex : out rate bits/s
1.3.6.1.4.1.2636.3.3.1.1.5.ifIndex : out rate bytes/s
1.3.6.1.4.1.2636.3.3.1.1.6.ifIndex : out rate packets/s

Pour trouver le ifIndex, on peut demander au Juniper avec show interface. Ou tout afficher avec snmpwalk et regarder les noms des interfaces.

L'affichage de l'OID ci-dessus est un peu triste et on voudrait plutôt avoir les noms des variables de la MIB Juniper. Il faut donc copier celle-ci localement. Sur une machine Debian ou Ubuntu, le plus simple est d'installer le paquetage snmp-mibs-downloader, de copier le fichier de configuration d'exemple /usr/share/doc/snmp-mibs-downloader/examples/junos.conf et /usr/share/doc/snmp-mibs-downloader/examples/junoslist dans /etc/snmp-mibs-downloader, et de faire un download-mibs junos. Après, on indique à snmpget d'utiliser cette MIB :

% snmpget  -v3 -M +/var/lib/mibs/juniper -m JUNIPER-IF-MIB -u USERNAME \
        -a MD5 -A MOTDEPASSESECRET  -l authNoPriv 198.18.0.2 \
        1.3.6.1.4.1.2636.3.3.1.1.3.513
JUNIPER-IF-MIB::ifIn1SecPkts.513 = Gauge32: 11914

Et voilà, on a un joli nom de variable (nombre de paquets/seconde).

Un exemple pendant une période d'activité (en fait, un test d'attaque DNS par réflexion) ? 511 est l'interface où est connectée la victime de l'attaque, 512 celle où est connecté le réflecteur :

% snmpget  -v3 -M +/var/lib/mibs/juniper -m JUNIPER-IF-MIB -u USERNAME -a MD5 -A MOTDEPASSESECRET  -l authNoPriv 198.18.0.2 1.3.6.1.4.1.2636.3.3.1.1.6.512
JUNIPER-IF-MIB::ifOut1SecPkts.512 = Gauge32: 2721

% snmpget  -v3 -M +/var/lib/mibs/juniper -m JUNIPER-IF-MIB -u USERNAME -a MD5 -A MOTDEPASSESECRET  -l authNoPriv 198.18.0.2 1.3.6.1.4.1.2636.3.3.1.1.6.511
JUNIPER-IF-MIB::ifOut1SecPkts.511 = Gauge32: 5358

À cause de la fragmentation, il y a deux fois plus de paquets qui sortent du réflecteur qu'il n'en entre.

Et les autres variables ? Par exemple le débit en bits/s :

JUNIPER-IF-MIB::ifOut1SecRate.511 = Gauge32: 98481600

Presque 100 Mb/s, le maximum de la carte Ethernet en face.

Merci à Jean-Philippe Pick pour sa recherche (réussie) dans les MIB.


L'article seul

RFC 6901: JavaScript Object Notation (JSON) Pointer

Date de publication du RFC : Avril 2013
Auteur(s) du RFC : P. Bryan (Salesforce.com), K. Zyp (SitePen), M. Nottingham (Akamai)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF appsawg
Première rédaction de cet article le 3 avril 2013


Ce court RFC spécifie une syntaxe pour identifier un élément particulier dans un document JSON. Cela permettra de pointer vers l'intérieur d'un document, par exemple depuis un URI.

JSON (RFC 8259) est un format structuré de données très populaire sur le Web. Les documents JSON peuvent être de taille très variable et il serait intéressant d'avoir une syntaxe formelle pour désigner une partie bien spécifique d'un document JSON, comme XPointer le permet pour XML et le RFC 5147 pour le texte brut. Outre les URI cités plus haut, un des usages envisagés est la modification de documents JSON, via la norme JSON patch du RFC 6902, puisque la mise à jour nécessite de dire exactement où on va faire l'ajout ou la suppression de données.

La syntaxe est exposée en section 3 : un JSON pointer est une chaîne de caractères Unicode (JSON pointer travaille entièrement avec des caractères Unicode, pas avec des octets). Il contient plusieurs éléments séparés par des barres obliques. Ce caractère, ainsi que le tilde, sont donc spéciaux et, si on veut avoir leur valeur littérale, il faut un échappement, ~0 pour le ~ et ~1 pour le /. (Programmeurs, attention, en décodant, il faut d'abord remplacer tous les ~1 par des / avant de s'attaquer à la deuxième substitution, sinon ~01 sera mal décodé.)

Pour illustrer ces pointeurs, je vais utiliser pour tous les exemples les données des chemins de fer britanniques disponibles en JSON en http://api.traintimes.im/. Commençons par récupérer la liste des stations :

% wget http://api.traintimes.im/stations_all.json

On peut alors connaître les codes tiploc des gares, ici, on va utiliser WMOR pour Woodsmoor. Cherchons les trains qui passent à Woodsmoor aux alentours de midi :

% wget -O wmor.json http://api.traintimes.im/locations.json\?location=WMOR\&date=2013-02-14\&startTime=1200

Le fichier JSON (passé à jsonlint) ressemble à :

{
  ...
  "services" : [ { 
       "departure_time" : "1141",
         "destination" : { "arrival_time" : "1145",
            "crs" : "HAZ",
            "description" : "Hazel Grove",
            "tiploc" : "HAZL"
          }},
        "departure_time" : "1206",
          "destination" : { "arrival_time" : "1227",
            "crs" : "MAN",
            "description" : "Manchester Piccadilly",
            "tiploc" : "MNCRPIC"
          }} ...

Par exemple, avec ces données /services, /services/1 et /services/1/destination/description sont tous des pointeurs JSON valides.

Et comment est-ce que cela s'interprète ? La section 4 le décrit. On part de la racine du document JSON. Donc, le pointeur composé d'une chaîne vide identifie la totalité du document. Ensuite, si la racine est un objet JSON (avec des champs nommés), l'élement suivant identifie un des champs. Ainsi, /foo identifie le champ foo de l'objet situé à la racine (il doit être unique). Si par contre la racine est un tableau, l'élement suivant doit être un nombre, l'index dans le tableau (en partant de zéro donc /1 identifie le deuxième élément du tableau situé à la racine). Une seule valeur non-numérique est permise, - qui indique l'élément situé après la fin du tableau (pour le JSON patch du RFC 6902, cela sert aux ajouts à la fin du tableau, autrement, cela désigne un élément non-existant). Donc, attention, / n'identifie pas la racine du document mais un élément de nom vide situé à la racine.

Le pointeur JSON est ensuite représenté sous forme texte comme une chaîne de caractères JSON (section 5) ce qui oblige à échapper les caractères spéciaux des chaînes JSON comme la barre inverse ou comme le guillemet. Par exemple, il faudra écrire a\\b pour trouver le membre d'objet JSON nommé a\b.

Et dans un URI (section 6) ? Il faudra encoder le pointeur en UTF-8 et faire un échappement « pour cent » (RFC 3986, section 2.1) des caractères qui sont spéciaux dans un URI (comme le point d'interrogation, section 2.2 du RFC 3986). Ainsi, http://api.traintimes.im/locations.json?location=WMOR\&date=2013-02-14\&startTime=1200#/services/1/destination/arrival_time pointera vers la valeur 1227 (regardez l'identificateur de fragment après le croisillon : c'est un pointeur JSON). À noter que tous les types MIME n'accepteront pas forcément le pointeur JSON comme un moyen normal de désigner un fragment du document JSON et l'exemple ci-dessus est donc hypothétique.

Reste à traiter le cas des erreurs (section 7). Deux erreurs typiques sont un élément non numérique dans le pointeur alors que la valeur est un tableau, ou bien un nom de champ inexistant. Le RFC ne spécifie pas ce qui doit se produire dans un tel cas, cela doit être défini par l'application qui utilise les pointeurs (pour JSON patch, voir les sections 4.1 et 5 du RFC 6902).

Une liste des mises en œuvre connues des pointeurs JSON est disponible à l'IETF (en fait, ce sont les mises en œuvre de JSON Patch mais, comme les pointeurs sont un pré-requis, elle couvre aussi les mises en œuvre des pointeurs). Il existe aussi une implémentation « faite en 20 minutes » en node.js, js-6901. Testons l'implémentation Python :

% git clone https://github.com/stefankoegl/python-json-pointer.git
% cd python-json-pointer
% python setup.py build
% sudo python setup.py install

Et lançons l'interpréteur Python pour voir :


>>> import jsonpointer
>>> import json
>>> doc = json.load(open("wmor.json"))

>>> jsonpointer.resolve_pointer(doc,'/services/1/destination/description')
u'Manchester Piccadilly'

>>> jsonpointer.resolve_pointer(doc,'/services/0/destination/description')
u'Hazel Grove'

>>> jsonpointer.resolve_pointer(doc,'/services/2/destination')
{u'crs': u'BUX', u'arrival_time': u'1251', u'description': u'Buxton', u'tiploc': u'BUXTON'}

Tout marche donc bien et on récupère, soit des valeurs, soit des objets JSON. Et avec un pointeur qui ne pointe vers rien ?


>>> jsonpointer.resolve_pointer(doc,'/zzz')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/dist-packages/jsonpointer.py", line 105, in resolve_pointer
    return pointer.resolve(doc, default)
  File "/usr/local/lib/python2.7/dist-packages/jsonpointer.py", line 140, in resolve
    doc = self.walk(doc, part)
  File "/usr/local/lib/python2.7/dist-packages/jsonpointer.py", line 183, in walk
    raise JsonPointerException("member '%s' not found in %s" % (part, doc))
jsonpointer.JsonPointerException: member 'zzz' not found in { ...

On a, fort logiquement, une exception.


Téléchargez le RFC 6901


L'article seul

RFC 6902: JavaScript Object Notation (JSON) Patch

Date de publication du RFC : Avril 2013
Auteur(s) du RFC : P. Bryan (Salesforce.com), M. Nottingham (Akamai)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF appsawg
Première rédaction de cet article le 3 avril 2013


Le format de données structurées JSON, normalisé dans le RFC 8259, a pris une importance de plus en plus grande et est désormais utilisé dans bien des contextes. Cela entraine l'apparition de normes auxiliaires, spécifiant comment faire telle ou telle opération sur des fichiers JSON. Ainsi, le RFC 6901 indique comment désigner une partie d'un document JSON et ce RFC 6902, sorti en même temps, indique comment exprimer les modifications (patches) à un document JSON.

Logiquement, le patch est lui-même un fichier JSON (de type application/json-patch, cf. la section 6 de notre RFC) et il indique les opérations à faire (ajouter, remplacer, supprimer) à un endroit donné du document (identifié par un pointeur JSON, ceux du RFC 6901). Voici un exemple de patch :

[
     { "op": "add", "path": "/baz", "value": "qux" }
]

Il va ajouter (opération add) un membre nommé baz et de valeur qux. Si le document originel était :

{ "foo": "bar"}

Celui résultant de l'application du patch sera :

{
     "baz": "qux",
     "foo": "bar"
   }

À noter que ces patches travaillent sur le modèle de donnéees JSON, pas directement sur le texte (autrement, on utiliserait le traditionnel format diff), et peuvent donc s'appliquer sur des données qui ont un modèle similaire, quelle que soit la syntaxe qu'ils avaient. Dans les exemples de code Python à la fin, le patch est appliqué à des variables Python issues d'une analyse d'un fichier JSON, mais qui pourraient avoir une autre origine. (Au passage, je rappelle l'existence d'un format équivalent pour XML, le XML patch du RFC 5261.)

Le patch peut être envoyé par divers moyens, mais l'un des plus courants sera sans doute la méthode PATCH de HTTP (RFC 5789). Voici un exemple d'une requête HTTP avec un patch :

PATCH /my/data HTTP/1.1
Host: example.org
Content-Length: 326
Content-Type: application/json-patch
If-Match: "abc123"

[
     { "op": "test", "path": "/a/b/c", "value": "foo" },
     { "op": "remove", "path": "/a/b/c" },
     { "op": "add", "path": "/a/b/c", "value": [ "foo", "bar" ] },
     { "op": "replace", "path": "/a/b/c", "value": 42 },
     { "op": "move", "from": "/a/b/c", "path": "/a/b/d" },
     { "op": "copy", "from": "/a/b/d", "path": "/a/b/e" }
]

Un patch JSON a quelle forme (section 3) ? C'est un tableau dont chaque object qui le compose est une opération, à appliquer dans l'ordre du tableau (dans le premier exemple ci-dessus, le tableau ne comportait qu'une seule opération). L'entité à laquelle on applique le patch est donc transformée successivement et chaque opération s'applique au résultat de l'opération précédente.

Quelles sont les opérations possibles (section 4) ? Le membre op indique l'opération, path la cible et value la nouvelle valeur. op peut être :

  • add : si la cible est dans un tableau, on ajoute la valeur à ce tableau (si le pointeur pointe vers la fin du tableau, avec la valeur -, on ajoute après le dernier élément). Si la cible est un membre inexistant d'un objet, on l'ajoute. S'il existe, on le remplace (ce point a été vigoureusement critiqué au sein du groupe de travail, où plusieurs personnes regrettaient qu'on mélange les sémantiques de add et de replace ; parmi les propositions alternatives, il y avait eu de nommer cette opération set ou put plutôt qu'add).
  • remove : on retire l'élément pointé.
  • replace : on remplace la valeur pointée.
  • move : on déplace l'élément (ce qui nécessite un paramètre supplémentaire, from).
  • copy : on copie la valeur pointée vers un nouvel endroit.
  • test : teste si une valeur donnée est présente à l'endroit indiqué. Cela sert lorsqu'on veut des opérations conditonnelles. Les opérations étant appliquées dans l'ordre, et la première qui échoue stoppant tout le patch, un test peut servir à faire dépendre les opérations suivantes de l'état du document JSON.

Mais à quel endroit applique-t-on cette opération ? C'est indiqué par le membre path qui est un pointeur JSON (cf. RFC 6901). Enfin, value indique la valeur, pour les opérations qui en ont besoin (par exemple add mais évidemment pas remove).

La section 5 spécifie ce qui se passe en cas d'erreurs : le traitement s'arrête au premier problème. Pour le cas de la méthode HTTP PATCH, voir la section 2.2 du RFC 5789. PATCH étant atomique, dans ce cas, le document ne sera pas du tout modifié.

Quelles mises en œuvre existent ? Une liste est disponible en ligne, ainsi que des jeux de test. Je vais ici essayer celle en Python, python-json-patch. D'abord, il faut installer python-json-pointer et python-json-patch :

% git clone https://github.com/stefankoegl/python-json-pointer.git
% cd python-json-pointer
% python setup.py build
% sudo python setup.py install

% git clone https://github.com/stefankoegl/python-json-patch.git
% cd python-json-patch
% python setup.py build
% sudo python setup.py install

Ensuite, on écrit un programme Python qui utilise cette bibliothèque. On va le faire simple, il prend sur la ligne de commande deux arguments, un qui donne le nom du fichier JSON original et un qui donne le nom du fichier contenant le patch. Le résultat sera écrit sur la sortie standard :

#!/usr/bin/env python

import jsonpatch
import json
import sys

if len(sys.argv) != 3:
    raise Exception("Usage: patch.py original patchfile")

old = json.loads(open(sys.argv[1]).read())
patch = json.loads(open(sys.argv[2]).read())

new = jsonpatch.apply_patch(old, patch)

print json.dumps(new)

Maintenant, on peut écrire un fichier JSON de test, test.json, qui décrit ce RFC :

% cat test.json
{
  "Title": "JSON Patch",
  "Number": "NOT PUBLISHED YET",	
  "Authors": [
       "P. Bryan"
   ]
}

On va maintenant essayer avec différents fichiers patch.json contenant des patches (l'annexe A contient plein d'autres exemples). Un ajout à un tableau :

% cat patch.json 
[
     { "op": "add", "path": "/Authors/0", "value": "M. Nottingham" }
]

% python patch.py test.json patch.json
{"Title": "JSON Patch", "Number": "NOT PUBLISHED YET", "Authors": ["M. Nottingham", "P. Bryan"]}

Un changement d'une valeur :

% cat patch.json                      
[
     { "op": "replace", "path": "/Number", "value": "6902" }
]

% python patch.py test.json patch.json
{"Title": "JSON Patch", "Number": "6902", "Authors": ["P. Bryan"]}

Un ajout à un objet :

% cat patch.json
[
     { "op": "add", "path": "/Status", "value": "standard" }
]

% python patch.py test.json patch.json
{"Status": "standard", "Title": "JSON Patch", "Number": "NOT PUBLISHED YET", "Authors": ["P. Bryan"]}

Une suppression d'un champ d'un objet :

% cat patch.json
[
     { "op": "remove", "path": "/Authors" }
]

% python patch.py test.json patch.json
{"Title": "JSON Patch", "Number": "NOT PUBLISHED YET"}

Si vous aimez les controverses, un des débats les plus animés, plus d'un an avant la sortie du RFC, avait été de savoir si l'opération d'ajout devait se noter add (comme cela a finalement été choisi) ou bien simplement +. Le format diff traditionnel utilise des mnémoniques plutôt que des noms et cela peut accroître la lisibilité (cela dépend des goûts).

Merci à Fil pour sa relecture attentive qui a trouvé plusieurs problèmes techniques.


Téléchargez le RFC 6902


L'article seul

RFC 1071: Computing the Internet checksum

Date de publication du RFC : Septembre 1988
Auteur(s) du RFC : R. Braden (USC/Information Sciences Institute), D. Borman (Cray Research), C. Partridge (Bolt Baranek and Newman (BBN) Laboratories), William W. Plummer (Bolt Beranek and Newman, Inc. (BBN))
Statut inconnu, probablement trop ancien
Première rédaction de cet article le 31 mars 2013


Un grand nombre de protocoles de la famille TCP/IP utilisent une somme de contrôle pour détecter les éventuelles corruptions de données pendant le trajet. Chacun de ces protocoles le spécifie comme il veut mais, en pratique, beaucoup utilisent le même algorithme dit « Internet checksum ». Ce RFC donne des conseils sur la mise en œuvre de cette somme de contrôle particulière.

On la trouve à beaucoup d'endroits, IPv4 (RFC 791, section 3.1, « The checksum field is the 16 bit one's complement of the one's complement sum of all 16 bit words in the header », notez qu'IPv6 n'a pas de somme de contrôle), TCP (RFC 793, section 3.1, « The checksum field is the 16 bit one's complement of the one's complement sum of all 16 bit words in the header and text »), UDP (RFC 768, « Checksum is the 16-bit one's complement of the one's complement sum of a pseudo header of information from the IP header, the UDP header, and the data [...] ») ou ICMP (RFC 4443, section 2.3, « The checksum is the 16-bit one's complement of the one's complement sum of the entire ICMPv6 message, starting with the ICMPv6 message type field, and prepended with a "pseudo-header" [...] »). Toutes ces définitions sont équivalentes : la « somme de contrôle Internet » est la somme en complément à un des seizets qui forment le pseudo-en-tête et, parfois, le message. Le pseudo-en-tête est une version simplifiée du vrai en-tête (entre autres, il ne contient pas la somme de contrôle). Par exemple, pour UDP sur IPv6, le pseudo en-tête comporte (RFC 2460, section 8.1), les adresses IP source et destination, la longueur des données, le numéro du protocole qui suit, puis l'en-tête UDP.

À l'époque où ce RFC a été écrit (il y a un quart de siècle !) les processeurs étaient bien plus lents, relativement aux réseaux, qu'aujourd'hui. Le calcul de la somme de contrôle, note notre RFC, peut donc être le facteur limitant dans un envoi de données avec TCP. C'est en partie ce qui explique que la somme de contrôle Internet soit une vraie somme, simple à calculer mais peu robuste, et pas un CRC, pourtant plus sûre (a fortiori pas une condensation cryptographique). Aujourd'hui, une mesure faite sur un PC de bureau ordinaire, en fabriquant les paquets en mode utilisateur avant de les envoyer, montre que l'envoi d'un million de courts paquets UDP sur IPv4 prend exactement le même temps avec ou sans la somme de contrôle (elle est optionnelle pour UDP sur IPv4), et time indique que presque tout le temps CPU a été passé dans le noyau, donc pas à calculer la somme de contrôle. (Le résultat pourrait être différent avec des paquets de plus grande taille, puisque la calcul de la somme de contrôle implique d'accéder à tout le paquet.)

Le RFC, écrit à une autre époque, estime qu'il faut chercher à optimiser vigoureusement le calcul de la somme de contrôle. Comme il est fait à chaque paquet, même un gain minime peut être intéressant.

Pour cette optimisation, le RFC note que la somme de contrôle Internet a quelques propriétés utiles (section 2) :

  • Commutativité,
  • Associativité,
  • Indépendance par rapport à la boutianité. Que votre machine soit gros-boutienne ou petit-boutienne ne changera rien,
  • Parallélisation, une conséquence de l'associativité, on peut répartir la tâche de calcul (voir le code pour le Cray plus loin).

(Il parait que ça en fait un groupe abélien.)

Passons à l'implémentation, le cœur de ce RFC. Naturellement, la plupart des programmeurs réseaux n'auront jamais besoin de savoir calculer la somme de contrôle : quelqu'un (typiquement le noyau) le fait pour eux. Aujourd'hui, calculer la somme de contrôle est surtout utile lorsqu'on veut fabriquer soi-même la totalité du paquet, avant de l'envoyer via une prise brute. C'est surtout utile dans le contexte de la sécurité (faire des paquets que le système ne permettrait pas normalement de faire). Quel sont les problèmes à garder en tête ? La plupart des machines font de l'addition en complément à deux. Pour celles-ci, la solution recommandée est de faire une retenue et de l'ajouter à la fin (ce que fait le code C montré plus loin).

En IPv4, chaque routeur doit recalculer la somme de contrôle IP car le TTL change à chaque saut. On peut optimiser cette opération en faisant un recalcul incrémental (RFC 1624).

Ah, et pour vérifier la somme de contrôle ? Mêmes opérations, mais en incluant la somme de contrôle. On doit trouver uniquement des bits à Un (-0 en complément à un).

Le RFC présente en section 4 plusieurs exemples de code mettant en œuvre ces principes. D'abord, un code portable en C :

{
           /* Compute Internet Checksum for "count" bytes
            *         beginning at location "addr".
            */
       register long sum = 0;

        while( count > 1 )  {
           /*  This is the inner loop */
               sum += * (unsigned short) addr++;
               count -= 2;
       }

           /*  Add left-over byte, if any */
       if( count > 0 )
               sum += * (unsigned char *) addr;

           /*  Fold 32-bit sum to 16 bits */
       while (sum>>16)
           sum = (sum & 0xffff) + (sum >> 16);

       checksum = ~sum;
   }

Mais il y a aussi des codes en assembleur, pour les architectures qu'on trouvait à l'époque. Par exemple, le Motorola 68020. Avec ses 20 MHz de fréquence, ce code calculait en 134 μs/ko :

       movl    d1,d2
       lsrl    #6,d1       | count/64 = # loop traversals
       andl    #0x3c,d2    | Then find fractions of a chunk
       negl    d2
       andb    #0xf,cc     | Clear X (extended carry flag)

       jmp     pc@(2$-.-2:b,d2)  | Jump into loop

   1$:     | Begin inner loop...

       movl    a0@+,d2     |  Fetch 32-bit word
       addxl   d2,d0       |    Add word + previous carry
       movl    a0@+,d2     |  Fetch 32-bit word
       addxl   d2,d0       |    Add word + previous carry

           | ... 14 more replications
   2$:
       dbra    d1,1$   | (NB- dbra doesn't affect X)

       movl    d0,d1   | Fold 32 bit sum to 16 bits
       swap    d1      | (NB- swap doesn't affect X)
       addxw   d1,d0
       jcc     3$
       addw    #1,d0
   3$:
       andl    #0xffff,d0

Plus rigolo, du code assembleur pour Cray. Tirant profit des propriétés de la somme de contrôle Internet, et des caractéristiques du Cray, il effectue des calculs sur un vecteur. Même si les ordinateurs vectoriels ne sont plus à la mode, cela illustre aussi comment on peut paralléliser ce calcul :

         EBM
         A0      A1
         VL      64            use full vectors
         S1      <32           form 32-bit mask from the right.
         A2      32
         V1      ,A0,1            load packet into V1
         V2      S1&V1            Form right-hand 32-bits in V2.
         V3      V1>A2            Form left-hand 32-bits in V3.
         V1      V2+V3            Add the two together.
         A2      63            Prepare to collapse into a scalar.
         S1      0
         S4      <16           Form 16-bit mask from the right.
         A4      16
   CK$LOOP S2    V1,A2
         A2      A2-1
         A0      A2
         S1      S1+S2
         JAN     CK$LOOP
         S2      S1&S4           Form right-hand 16-bits in S2
         S1      S1>A4           Form left-hand 16-bits in S1
         S1      S1+S2
         S2      S1&S4           Form right-hand 16-bits in S2
         S1      S1>A4           Form left-hand 16-bits in S1
         S1      S1+S2
         S1      #S1            Take one's complement
         CMR            At this point, S1 contains the checksum.

Ah, et comment je fais, finalement, dans mes programmes ?

static          uint32_t
checksum_finish(uint32_t sum)
{
    /* Fold 32-bit sum to 16 bits */
    while (sum >> 16)
        sum = (sum & 0xffff) + (sum >> 16);
    return ~sum;
}

static          uint32_t
checksum_feed16(const void *p, unsigned int count)
{
    const uint16_t *t = p;
    uint32_t        sum = 0;
    while (count-- > 0)
        /* This is the inner checksum loop */
        sum += *t++;
    return sum;
}

Code qui s'utilise ainsi pour de l'UDP sur IPv6 (buff pointe vers les données) :

uint16_t
checksum6(struct ip6_hdr ip_h, struct udphdr udp_h, uint8_t * buff, uint16_t len_udp)
{
    uint32_t        sum;
    uint8_t         zero_udp_proto[] = { 0, 0, 0, SOL_UDP };
    uint32_t        length = udp_h.len;
    udp_h.check = 0;
    sum = checksum_feed16(ip_h.ip6_src.s6_addr, 8)
        + checksum_feed16(ip_h.ip6_dst.s6_addr, 8)
        + checksum_feed16(&length, 2)
        + checksum_feed16(zero_udp_proto, 2)
        + checksum_feed16(&udp_h, 4)
        + checksum_feed16(buff, len_udp / 2);
    if (len_udp % 2)
        sum += buff[len_udp - 1];
    return checksum_finish(sum);
}

Si vous voulez lire d'autres codes, regarder la fonction in_cksum dans print-ip.c dans le code source de tcpdump pour la vérification. Si vous regardez le code source de Linux (version 3.9), vous verrez que, pour la plupart des plate-formes que gère Linux, le code de la fonction ip_fast_csum est en assembleur, assembleur (en arch/$ARCHITECTURE/include/asm/checksum.h) que vous pouvez comparez avec les codes du RFC.

On notera que la première étude des propriétés de la somme de contrôle de l'Internet a été faite dans le très détaillé document IEN 45, qui est reproduit à la fin de notre RFC. Ceux qui pratiquent la langue de Konrad Zuse liront avec intérêt « Minus Null ». Une bonne explication sur la différence entre complément à un et complément à deux est « Minus Zero ».

Merci à Lutz Donnerhacke pour ses suggestions de lecture. Merci à Kim-Minh Kaplan pour son travail sur le code.


Téléchargez le RFC 1071


L'article seul

RFC 6905: Requirements for Operations, Administration, and Maintenance (OAM) in Transparent Interconnection of Lots of Links (TRILL)

Date de publication du RFC : Mars 2013
Auteur(s) du RFC : Tissa Senevirathne (CISCO), David Bond (IBM), Sam Aldrin, Yizhou Li (Huawei), Rohit Watve (CISCO)
Pour information
Réalisé dans le cadre du groupe de travail IETF trill
Première rédaction de cet article le 30 mars 2013


Le protocole TRILL est un protocole de routage pour réseaux locaux, qui veut combiner les avantages des réseaux L2 (non routés) et L3 (routés, avec des protocoles plus complexes). Ce RFC est le cahier des charges pour les futurs mécanismes d'administration et de supervision des réseaux TRILL.

TRILL est normalisé dans le RFC 6325. Il vise surtout les gros data centers et les fournisseurs d'infonuagique. Il est par exemple déployé sur le service d'hébergement de Gandi. Comme tous les protocoles, il a besoin d'OAM : Operations, Administration and Maintenance, c'est-à-dire l'ensemble des activités de l'administrateur réseaux pour maintenir le réseau en bon état de marche (cf. RFC 6291 et RFC 5860). Un réseau TRILL est composé de RBridges, engins intermédiaires entre les ponts et les routeurs et ce sont eux qu'il faut gérer. La section 4 du RFC énumère les exigences des futurs mécanismes OAM de TRILL. Parmi elles :

  • N'importe quel RBridge doit pouvoir tester la connectivité vers n'importe quel autre RBridge (ping, quoi).
  • TRILL permet d'envoyer les paquets par différents chemins selon leurs caractéristiques. Il est donc essentiel que les trames utilisées pour l'OAM puissent être forcées à suivre un chemin particulier, celui qu'on veut tester.
  • Ces fonctions de test doivent pouvoir être effectuées à la demande, ou bien en boucle.
  • N'importe quel RBridge doit pouvoir trouver le chemin emprunté par les trames allant vers un autre RBridge (traceroute, quoi).
  • TRILL est purement pour les réseaux locaux. Il faut donc que les trames OAM ne sortent jamais du réseau TRILL.
  • Le système d'OAM doit maintenir un certain nombre de compteurs (notamment des erreurs) et les rendre accessible (par exemple par SNMP).
  • Il est nécessaire de pouvoir mesurer le taux de pertes de trames (tel que défini par le RFC 7680).
  • Il est nécessaire de pouvoir mesurer le temps d'acheminement aller-retour d'une trame (RFC 2681) et il est souhaitable qu'on puisse aussi mesurer le temps d'acheminement aller-simple (plus difficile à faire, RFC 7679).
  • Le RFC mentionne aussi la possibilité d'utiliser le trafic normal pour tester les problèmes et mesurer les performances (mesures passives, et pas seulement actives).
  • Et le tout doit bien sûr être sécurisé, qu'on ne puisse pas accéder aux informations sans être autorisé, et qu'on ne puisse pas utiliser le système d'OAM pour faire des attaques par déni de service.

Il ne reste plus qu'à développer tout cela. Un expert de TRILL parmi mes lecteurs pour expliquer ce que peuvent faire les RBridges actuels, avec résultat de commandes à l'appui ?


Téléchargez le RFC 6905


L'article seul

Fonctionnement du DNS : une explication fausse mais courante

Première rédaction de cet article le 29 mars 2013


Hier, je lisais un article qui contenait une explication du fonctionnement du DNS qui est fausse. Mais comme cette explication est courante, je pense utile de documenter pourquoi elle est fausse et pourquoi c'est important.

L'article en question est intéressant (un témoignage concret sur une erreur de configuration courante) mais il a le tort de vouloir expliquer le fonctionnement du DNS sans le connaître vraiment. (Le journal qui le publie, The Register, est coutumier de ce genre de bavures. Il vise le sensationnel à forte composante technique mais ne font jamais vérifier leurs articles.) Que dit l'article ? « In a recursive configuration the DNS server asks the list of root servers it has preconfigured who owns the ".com" domain. It then asks the .com servers who owns "google.com". It then asks "google.com" who owns "www.google.com" and delivers that address back to you.  » Cette explication est courante (je tape sur The Register mais ils ne sont pas les seuls, loin de là) mais inexacte.

Non, le serveur récursif (le résolveur) ne demande pas à la racine « Qui gère .com ? » Il ne demande pas aux serveurs de Verisign (registre de .com) « Qui gère google.com ? » À chaque étape, le résolveur envoie la demande complète, le FQDN original. La question est toujours « Quelle est l'adresse de www.google.com ? » Et la réponse peut être une adresse IP (quand on est arrivé chez Google) ou bien une référence (referral) : « Je ne sais pas mais demande à Verisign ».

Alors, est-ce du pur pinaillage de ma part que de noter cette erreur fréquente ? Non, car cela a une conséquence importante : les serveurs faisant autorité (ceux de la racine, des TLD, etc, qui connaissent les réponses et qui sont interrogés par les résolveurs) reçoivent un nom complet. Cela leur permet de faire des études, des analyses, des recherches qui ne seraient pas possible autrement. On voit ainsi passer sur ces serveurs des noms qui sont parfois révélateurs, contenant par exemple le type d'application utilisée (« Quelle est l'adresse IP de _bittorrent-tracker._tcp.XXXX.abo.wanadoo.fr ? »).

Pourquoi est-ce que les résolveurs procèdent ainsi ? Ne respecterait pas t-on mieux la vie privée en n'envoyant que le dernier composant du nom, puis les deux derniers, etc ? Mais on ne peut pas : le résolveur ne connait pas le découpage du DNS en zones (ce découpage ne se fait pas sur les points entre les composants d'un nom). Il ne sait pas si la racine fait autorité pour .com ou non, par exemple (pendant longtemps, c'était le cas). Pour prendre un exemple actuel, si un résolveur cherche www.redressement-productif.gouv.fr. Demander aux serveurs de l'AFNIC (registre de .fr) qui gère gouv.fr ne marcherait pas : gouv.fr n'est pas une zone séparée, il est dans la zone .fr.

Pour ceux et celles qui veulent expérimenter avec dig, voici la vraie requête envoyée par un résolveur à la racine pour www.redressement-productif.gouv.fr :


% dig @a.root-servers.net A www.redressement-productif.gouv.fr
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12929
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 7, ADDITIONAL: 11

;; AUTHORITY SECTION:
fr.			172800	IN	NS	e.ext.nic.fr.
fr.			172800	IN	NS	d.ext.nic.fr.
fr.			172800	IN	NS	f.ext.nic.fr.
fr.			172800	IN	NS	d.nic.fr.
fr.			172800	IN	NS	g.ext.nic.fr.
fr.			86400	IN	DS	1336 8 2 C7AEE4D32904728741DB270E72899673D7DFAF212E517F2400C9424B 231CF56B
fr.			86400	IN	RRSIG	DS 8 1 86400 20130405000000 20130328230000 40323 . VMBW3MNHCI9LJRU+SptuwnO3pJgvvaMHCE11AKmbyXry3g5EqBH8wQ7J JZQGa8XUdVFpACzYJU/MUaN1DWlBZ3OyYMXrRUpT6gJIjE/BQpLQbNeW kofVDjtfbUlIEkphoohBR++OAwDaXUSSF7DlLxC4tJ1lKAsQDDnoX/+p C0Y=

;; ADDITIONAL SECTION:
d.ext.nic.fr.		172800	IN	A	192.5.4.2
d.ext.nic.fr.		172800	IN	AAAA	2001:500:2e::2
d.nic.fr.		172800	IN	A	194.0.9.1
d.nic.fr.		172800	IN	AAAA	2001:678:c::1
e.ext.nic.fr.		172800	IN	A	193.176.144.22
e.ext.nic.fr.		172800	IN	AAAA	2a00:d78:0:102:193:176:144:22
f.ext.nic.fr.		172800	IN	A	194.146.106.46
f.ext.nic.fr.		172800	IN	AAAA	2001:67c:1010:11::53
g.ext.nic.fr.		172800	IN	A	194.0.36.1
g.ext.nic.fr.		172800	IN	AAAA	2001:678:4c::1

Le serveur racine ne connaissait pas la réponse (ANSWER: 0) mais a redirigé vers les serveurs de .fr. On peut alors continuer, et c'est vraiment ce que fait le résolveur. Vous ne me croyez pas ? Regardez les statistiques publiques d'un serveur faisant autorité, par exemple le serveur racine K. On voit que les requêtes de type NS (« qui gère tel domaine ? ») sont en quantité négligeable, le gros du trafic étant fait de requêtes A (adresses IPv4), AAAA (adresses IPv6) et MX (relais de courrier électronique).

Autre solution pour vérifier : utilisez tcpdump sur un résolveur qui vient de démarrer (pour avoir un cache vide) :

09:32:33.282971 IP (tos 0x0, ttl 64, id 7716, offset 0, flags [none], proto UDP (17), length 91)
    192.168.2.4.61342 > 193.0.14.129.53: [bad udp cksum 0x9286 -> 0x8ef4!] 10282% [1au] A? www.redressement-productif.gouv.fr. ar: . OPT UDPsize=4096 OK (63)
09:32:33.328175 IP (tos 0x0, ttl 54, id 43405, offset 0, flags [none], proto UDP (17), length 606)
    193.0.14.129.53 > 192.168.2.4.61342: [udp sum ok] 10282- q: A? www.redressement-productif.gouv.fr. 0/7/11 ns: fr. [2d] NS d.ext.nic.fr., fr. [2d] NS d.nic.fr., fr. [2d] NS e.ext.nic.fr., fr. [2d] NS f.ext.nic.fr., fr. [2d] NS g.ext.nic.fr., fr. [1d] DS, fr. [1d] RRSIG ar: d.ext.nic.fr. [2d] A 192.5.4.2, d.nic.fr. [2d] A 194.0.9.1, e.ext.nic.fr. [2d] A 193.176.144.22, f.ext.nic.fr. [2d] A 194.146.106.46, g.ext.nic.fr. [2d] A 194.0.36.1, d.ext.nic.fr. [2d] AAAA 2001:500:2e::2, d.nic.fr. [2d] AAAA 2001:678:c::1, e.ext.nic.fr. [2d] AAAA 2a00:d78:0:102:193:176:144:22, f.ext.nic.fr. [2d] AAAA 2001:67c:1010:11::53, g.ext.nic.fr. [2d] AAAA 2001:678:4c::1, . OPT UDPsize=4096 OK (578)

09:32:33.335300 IP6 (hlim 64, next-header UDP (17) payload length: 71) 2a01:e35:8bd9:8bb0:ba27:ebff:feba:9094.34423 > 2a00:d78:0:102:193:176:144:22.53: [udp sum ok] 34878% [1au] A? www.redressement-productif.gouv.fr. ar: . OPT UDPsize=4096 OK (63)
09:32:33.401859 IP6 (hlim 56, next-header UDP (17) payload length: 623) 2a00:d78:0:102:193:176:144:22.53 > 2a01:e35:8bd9:8bb0:ba27:ebff:feba:9094.34423: [udp sum ok] 34878- q: A? www.redressement-productif.gouv.fr. 0/7/1 ns: redressement-productif.gouv.fr. [2d] NS dns3.jouve-hdi.com., redressement-productif.gouv.fr. [2d] NS dns1.jouve-hdi.com., redressement-productif.gouv.fr. [2d] NS dns2.jouve-hdi.com., P8ILGTMJ17HKLA9HBQEUE3NNE93M8R6Q.fr. [1h30m] Type50, P8ILGTMJ17HKLA9HBQEUE3NNE93M8R6Q.fr. [1h30m] RRSIG, S0TCQDREJ4DDTSGDTGD48KFK1P7TH3T5.fr. [1h30m] Type50, S0TCQDREJ4DDTSGDTGD48KFK1P7TH3T5.fr. [1h30m] RRSIG ar: . OPT UDPsize=4096 OK (615)

09:32:33.695786 IP (tos 0x0, ttl 64, id 28675, offset 0, flags [none], proto UDP (17), length 91)
    192.168.2.4.36882 > 193.108.167.41.53: [bad udp cksum 0x2b9b -> 0x546e!] 10536% [1au] A? www.redressement-productif.gouv.fr. ar: . OPT UDPsize=4096 OK (63)
09:32:33.765944 IP (tos 0x0, ttl 48, id 33891, offset 0, flags [DF], proto UDP (17), length 260)
    193.108.167.41.53 > 192.168.2.4.36882: [udp sum ok] 10536*- q: A? www.redressement-productif.gouv.fr. 1/4/3 www.redressement-productif.gouv.fr. [10m] CNAME www.redressement-productif.gouv.fr.c.footprint.net. ns: c.footprint.net. [6h17m35s] NS it-1.ns.c.footprint.net., c.footprint.net. [6h17m35s] NS c.ns.c.footprint.net., c.footprint.net. [6h17m35s] NS d.ns.c.footprint.net., c.footprint.net. [6h17m35s] NS de-1.ns.c.footprint.net. ar: de-1.ns.c.footprint.net. [6h17m33s] A 209.84.18.51, it-1.ns.c.footprint.net. [6h17m33s] A 8.12.209.51, . OPT UDPsize=4096 OK (232)

Ici, 193.0.14.129 est k.root-servers.net, un des serveurs de la racine. On voit bien qu'il a reçu la question complète, avec le nom intégral. 2a00:d78:0:102:193:176:144:22 est e.ext.nic.fr, un des serveurs de .fr. Notez que sa réponse n'a pas donné les serveurs de gouv.fr (il n'y en a pas) mais directement ceux de redressement-productif.gouv.fr. Quant à 193.108.167.41, c'est un des serveurs de nom du ministère et il donne enfin autre chose qu'une référence.


L'article seul

Quel est le vrai facteur d'amplification lors d'une attaque utilisant le DNS ?

Première rédaction de cet article le 29 mars 2013


À l'occasion de l'attaque par déni de service contre Spamhaus/Cloudflare, plusieurs articles ont tenté de chiffrer l'amplification DNS qui servait de base à l'attaque et, comme les chiffres ronds passent mieux, ont souvent parlé d'un « facteur 100 ». Est-ce exact ? En fait, c'est plus compliqué.

Rappelons le principe de l'attaque : le méchant envoie une requête DNS en usurpant l'adresse IP source de la victime (ce qui est souvent possible, trop peu de FAI ayant déployé les RFC 2827 et RFC 3704). À qui l'envoie t-il ? Il y a deux variantes de l'attaque, une utilisant les serveurs faisant autorité et l'autre utilisant des résolveurs ouverts (laisser de tels résolveurs est très mal). L'attaque Spamhaus/Cloudflare utilisait apparemment les seconds (plus nombreux et moins bien gérés). Ces résolveurs reçoivent la requête et répondent à ce qu'ils croient être le demandeur mais qui est en fait la victime. C'est donc une partie à trois, l'Attaquant, le Réflecteur et la Victime. Mais je ne vais pas vous faire un court complet sur les attaques DNS par réflexion + amplification, je voulais juste calculer le facteur d'amplification. Et, ce qui est pratique, est qu'il est le même dans les deux variantes : la quasi-totalité des serveurs de noms, récursifs ou faisant autorité, a une limite de taille de la réponse à 4 096 octets. C'est la valeur mentionnée par le RFC 6891 et c'est la valeur par défaut de BIND (modifiable avec le paramètre max-udp-size), de NSD (modifiable avec les paramètres ipv4-edns-size et ipv6-edns-size:). et d'Unbound (qui, par contre, ne permet pas de changer cette valeur). Certains changent cette configuration (à ma connaissance, les seuls serveurs de TLD qui n'envoient jamais de réponse aussi grande sont ceux de .com, apparemment limités à 1 460 octets).

Donc, quelle que soient les techniques utilisées (et, notamment, qu'on se serve de DNSSEC ou pas), on aura au maximum une réponse de 4 096 octets. Créons, comme si on était un attaquant, un enregistrement DNS (type TXT car sa partie Valeur n'est pas de taille fixe) de 3 927 octets (ça nous fera une réponse de 4 072 octets, quasiment le maximum) et interrogeons un résolveur (si vous voulez créer de tels TXT, j'ai utilisé ce petit script). tcpdump nous montre :

12:19:41.556276 00:1a:a0:ac:4a:0c > 00:10:db:ff:40:70, ethertype IPv4 (0x0800), length 94: (tos 0x0, ttl 64, id 7072, offset 0, flags [none], proto UDP (17), length 80)
    192.134.6.113.49032 > 149.20.64.21.53: [bad udp cksum 0x9c6e -> 0x2fd9!] 13395+ [1au] TXT? depardieu.example. ar: . OPT UDPsize=4096 OK (52)

12:19:42.352888 00:10:db:ff:40:70 > 00:1a:a0:ac:4a:0c, ethertype IPv4 (0x0800), length 1154: (tos 0x0, ttl 53, id 52397, offset 0, flags [+], proto UDP (17), length 1140)
    149.20.64.21.53 > 192.134.6.113.49032: 13395 q: TXT? depardieu.example. 1/2/1 depardieu.example. [23h59m33s] TXT[|domain]
12:19:42.352960 00:10:db:ff:40:70 > 00:1a:a0:ac:4a:0c, ethertype IPv4 (0x0800), length 1514: (tos 0x0, ttl 53, id 52397, offset 1120, flags [+], proto UDP (17), length 1500)
    149.20.64.21 > 192.134.6.113: ip-proto-17
12:19:42.353000 00:10:db:ff:40:70 > 00:1a:a0:ac:4a:0c, ethertype IPv4 (0x0800), length 1514: (tos 0x0, ttl 53, id 52397, offset 2600, flags [none], proto UDP (17), length 1500)
    149.20.64.21 > 192.134.6.113: ip-proto-17

Trop grosse pour la MTU d'Ethernet, la réponse a été fragmentée en trois datagrammes. Maintenant, calculons. Prenons les tailles en couche 2 (le premier length, le second, après l'étiquette UDP, étant en couche 3, mais cela ne change pas grand'chose au facteur d'amplification). Question : 94 octets. Réponse : 1154+1514+1514 = 4 182 octets. Le facteur d'amplification, dans ce cas idéal, est de 44...

On voit qu'on est loin du facteur 100 vu dans certains articles. En grattant un peu, on peut récupérer quelques octets (essayer de trouver des noms plus courts, par exemple) mais cela ne fera pas de miracle. Donc, pas de facteur 100 en vue, même si le facteur effectif, aux alentours de 45, est déjà largement suffisant pour permettre des attaques violentes.

Une autre solution, bien sûr, est de tricher. Par exemple en comparant les tailles, non pas en octets sur le réseau mais en charge utile uniquement (couche 7). Dans cas, la requête est bien plus petite et on a des amplifications purement théoriques mais bien plus jolies (c'est que ce que fait Bernstein dans le script awk qui accompagne un de ses exposés anti-DNSSEC et il trouve en effet presque un facteur 100).

À noter que le facteur d'amplification discuté ici est le BAF (Bandwidth Amplification Factor). Dans certaines attaques, il faut plutôt considérer le PAF (Packet Amplification Factor). Ce sont des attaques où l'ennemi cherche à obtenir le plus de paquets possibles (et pas le plus d'octets possibles), car certaines ressources Internet sont plutôt limitées en nombre de paquets par seconde. (Merci à Christian Rossow pour la jolie terminologie BAF et PAF.)


L'article seul

RFC 6908: Deployment Considerations for Dual-Stack Lite

Date de publication du RFC : Mars 2013
Auteur(s) du RFC : Y. Lee (Comcast), R. Maglione (Telecom Italia), C. Williams (MCSR Labs), C. Jacquenet (France Telecom), M. Boucadair (France Telecom)
Pour information
Réalisé dans le cadre du groupe de travail IETF softwire
Première rédaction de cet article le 26 mars 2013


DS-Lite est une des nombreuses techniques de transition / co-existence IPv4 / IPv6. Elle est normalisée dans le RFC 6333. Ce nouveau RFC se penche plutôt sur des problèmes opérationnels : comment déployer DS-Lite, quels pièges éviter, etc.

DS-Lite (Dual-Stack Lite) est conçu pour un FAI récent, qui vient d'arriver et n'a donc pas pu obtenir d'adresses IPv4, toutes épuisées. Ce FAI a donc dû numéroter son réseau en IPv6, et comme ses clients ont encore de l'IPv4 à la maison, et comme ils souhaitent accéder à des machines Internet qui sont encore uniquement en IPv4, le FAI en question va donc devoir 1) NATer les adresses de ses clients (RFC 3022) vers le monde extérieur 2) tunneler leurs paquets depuis leur réseau local IPv4 (RFC 2463) jusqu'au CGN, en passant par le réseau purement IPv6 du FAI. C'est là que DS-Lite intervient (RFC 6333).

Apparemment, il n'y a eu qu'un seul déploiement effectif de DS-Lite chez un vrai FAI (le RFC ne dit pas lequel) et ce RFC 6908 est largement tiré de cette expérience réelle. Il est donc une lecture intéressante pour les opérateurs qui aiment le concret.

Ce RFC est en deux parties : les questions liées à l'AFTR et celles liées au B4. Vous ne savez pas ce qu'est un AFTR ou un B4 ? Vous n'avez pas envie de lire le RFC 6333 qui explique cela ? Alors, en deux mots, l'AFTR (Address Family Transition Router) est le gros routeur NAT (le CGN) situé entre le FAI et l'Internet. Et le B4 (Basic Bridging Broadband element) est chez le client, typiquement dans sa box et représente le point d'entrée du tunnel, du « lien virtuel » (soft wire). Prononcez les sigles à voix haute : le B4 est avant le tunnel (before) et l'AFTR après (after).

Donc, bien qu'il soit « après », notre RFC commence par l'AFTR (section 2). D'abord, comme DS-Lite utilise un tunnel, il va y avoir des problèmes dus à la MTU inférieure. Le RFC recommande donc d'essayer de faire un lien entre le B4 et l'AFTR ayant une MTU d'au moins 1540 octets pour que, après avoir retiré les 40 octets de l'encapsulation dans le tunnel, on ait les 1500 octets d'Ethernet. Si ce n'est pas possible, alors le B4 et l'AFTR vont devoir gérer la fragmentation. Comme le réassemblage des paquets est une opération coûteuse en ressources (il faut garder les fragments en mémoire tant que tout n'est pas arrivé), la tâche va être particulièrement lourde pour l'AFTR (des milliers de tunnels peuvent se terminer sur un seul AFTR). Il faut les dimensionner largement ! (C'est un problème général des CGN.)

Ensuite, il faut penser à la journalisation. Le principe de DS-Lite est que tous les clients du FAI partageront la poignée d'adresses IPv4 publiques que NATeront les AFTR. Si un client fait quelque chose de mal (par exemple accéder à un site Web qui déplait au gouvernement), il faut pouvoir l'identifier. Un observateur situé à l'extérieur a vu une adresses IPv4 du FAI et des milliers de clients pouvaient être derrière. L'AFTR doit donc noter au moins l'adresse IPv6 du B4 (elle est spécifique à chaque client) et le port source utilisé après le NAT (en espérant que l'observateur extérieur ne notera pas que l'adresse IPv4 source mais aussi le port, cf. RFC 6302).

Les adresses IP partagées sont une plaie du NAT, ce n'est pas nouveau (RFC 6269). Par exemple, si une adresse IPv4 est mise sur une liste noire suite à son comportement, ce seront des centaines ou des milliers de B4 qui seront privés de connectivité IPv4. Si le destinataire ne tient pas compte du RFC 6302 et bloque sur la seule base de l'adresse IPv4, le support téléphonique du FAI qui a déployé DS-Lite va exploser. (Un travail est en cours à l'IETF pour aider à l'identification de l'utilisateur derrière un CGN. Mais il n'est pas terminé et, de toute façon ne sera pas forcément déployé. L'obstination de tant d'acteurs à rester en IPv4 va se payer cher.)

Un problème analogue se posera si le FAI veut faire de la comptabilité des octets échangés, et s'il ne met pas cette fonction dans le CPE. Le tunnel et le NAT rendront cette analyse plus compliquée (section 2.6). À noter que le RFC 6519 normalise des extensions à Radius pour les problèmes particuliers de DS-Lite.

Mais tout ceci n'est rien par rapport aux problèmes de fiabilité que posent les AFTR. L'Internet normal est très robuste car les équipements intermédiaires (les routeurs) n'ont pas d'état : s'ils redémarrent, rien n'est perdu. S'ils s'arrêtent de fonctionner, on en utilise d'autres. Le NAT met fin à tout cela : le routeur NAT a un état en mémoire, la table des correspondances {adresse interne, adresse externe} et, s'il redémarre, tout est fichu. C'est bien pire pour un CGN : s'il redémarre, ce sont des centaines ou des milliers d'utilisateurs qui perdent leurs connexions en cours. La fiabilité des AFTR est donc cruciale (cf. annexe A.3 du RFC 6333). Notre RFC propose que des AFTR de remplacement soient installés pour être prêts à prendre le relais. Ils peuvent fonctionner en « remplacement à chaud » (Hot Standby), se synchronisant en permanence avec l'AFTR primaire, prêts à le remplacer « sans couture » puisqu'ils ont le même état, ou bien en « remplacement à froid » (Cold Standby), sans synchronisation. Dans ce second cas, l'AFTR de secours fait qu'un AFTR en panne est vite remplacé, mais il n'y a pas de miracle : les clients doivent recommencer toutes leurs sessions. Vue la complexité qu'il y a à mettre en œuvre correctement la synchronisation des états, notre RFC recommande le remplacement à froid, et tant pis si c'est moins agréable pour les utilisateurs.

Et les performances ? Combien faut-il d'AFTR pour servir les utilisateurs ? La section 2.8 discute de ce point et du meilleur placement de ces équipements.

Comme avec tout CGN, DS-Lite, en centralisant les adresses IPv4, limite les possibilités de géo-localisation. Le B4 (donc la maison de l'utilisateur) et l'AFTR peuvent parfaitement être dans des villes différentes (RFC 6269, section 7). Les applications ne devraient donc pas se fier à la géo-localisation mais demander à l'utilisateur où il se trouve, par exemple avec le protocole HELD du RFC 5985 ou en suivant l'architecture du RFC 6280. Le RFC conseille, curieusement, de mettre les AFTR le plus près possible des utilisateurs, pour limiter ce problème (alors que les AFTR ont besoin d'une connectivité IPv4, et que le réseau du FAI ne la fournit pas forcément, sinon il n'aurait pas besoin de DS-Lite).

Autre problème douloureux avec les CGN (dont DS-Lite), les connexions entrantes. Contrairement au NAT traditionnel, celui fait par la box à la maison, plus question de configurer sa box via une interface Web pour rediriger certains ports. Et plus moyen de se servir d'UPnP. Les éventuelles redirections doivent être sur l'AFTR, un engin largement partagé. Donc, pas question de demander une redirection du port 80...

Pour « programmer » l'AFTR, lui demander d'ouvrir certains ports en entrée, notre RFC recommande d'installer un serveur PCP (Port Control Protocol, RFC 6887) sur les AFTR. Il n'est pas évident que cela soit une solution satisfaisante. D'une part, il existe encore très peu de clients PCP (par rapport aux clients UPnP). D'autre part, l'AFTR étant partagé entre plusieurs clients ne se connaissant pas, rien ne dit que la coexistence se passera bien et que les opérateurs accepteront d'ouvrir PCP à leurs clients.

Voilà, c'étaient les points essentiels pour les AFTR, lisez la section 2 du RFC si vous voulez la liste complète. Et les B4 ? Ils font l'objet de la section 3. D'abord, le problème du DNS. Le B4 est censé s'annoncer comme résolveur DNS et relayer les requêtes DNS au dessus d'IPv6 vers l'extérieur. Ce faisant, il est important qu'il suive les recommendations pour les relais DNS du RFC 5625 (en pratique, la grande majorité des boxes et des petits routeurs bas de gamme violent affreusement ces recommendations). C'est notamment nécessaire si on veut que DNSSEC fonctionne.

Si un client sur un réseau local IPv4 fait des requêtes DNS en IPv4 vers une adresse qui n'est pas celle du B4, ces requêtes seront tunnelisées et NATées comme n'importe quel trafic IPv4. Compte-tenu du fait que, du point de vue du NAT, chaque requête DNS est une session à elle seule, l'augmentation de la charge sur les AFTR sera sensible. Ce n'est donc pas conseillé.

Le B4 étant le début du réseau de l'opérateur, et beaucoup de choses dépendant de sa configuration et de son bon fonctionnement, il est important que l'opérateur puisse y accéder à distance, et au dessus d'IPv6, pas au dessus du lien virtuel (qui a davantage de chances d'avoir des problèmes).

À propos d'administration et de supervision du réseau, il est important que les AFTR répondent aux paquets utilisés pour ping et traceroute, afin que le B4 puisse tester que la connectivité IPv4 au dessus du tunnel marche bien. Des adresses IPv4 spéciales ont été réservées pour cela (rappelez-vous que, si vous déployez DS-Lite, c'est que vous n'avez pas assez d'adresses IPv4 publiques), 192.0.0.0/29. Les AFTR sont censés tous répondre aux paquets envoyés à 192.0.0.2.


Téléchargez le RFC 6908


L'article seul

RFC 5575: Dissemination of Flow Specification Rules

Date de publication du RFC : Août 2009
Auteur(s) du RFC : P. Marques (Cisco), N. Sheth (Juniper), R. Raszuk (Cisco), B. Greene (Juniper), J. Mauch (NTT America), D. McPherson (Arbor Networks)
Chemin des normes
Première rédaction de cet article le 25 mars 2013


Lorsqu'on a un grand réseau compliqué, diffuser à tous les routeurs des règles de filtrage, par exemple pour faire face à une attaque par déni de service, peut être complexe. Il existe des logiciels permettant de gérer ses routeurs collectivement mais ne serait-il pas plus simple de réutiliser pour cette tâche les protocoles existants et notamment BGP ? On profiterait ainsi des configurations existantes et de l'expérience disponible. C'est ce que se sont dit les auteurs de ce RFC. « FlowSpec » (nom officieux de cette technique) consiste à diffuser des règles de traitement du trafic en BGP, notamment à des fins de filtrage. Ce RFC a depuis été remplacé par le RFC 8955.

Les routeurs modernes disposent en effet de nombreuses capacités de traitement du trafic. Outre leur tâche de base de faire suivre les paquets, ils peuvent les classifier, limiter leur débit, jeter certains paquets, etc. La décision peut être prise en fonction de critères tels que les adresses IP source et destination ou les ports source et destination. Notre RFC 5575 encode ces critères dans un attribut NLRI (Network Layer Reachability Information est décrit dans la section 4.3 du RFC 4271) BGP, de manière à ce qu'ils puissent être transportés par BGP jusqu'à tous les routeurs concernés. Sans FlowSpec, il aurait fallu qu'un humain ou un programme se connecte sur tous les routeurs et y rentre l'ACL concernée.

Pour reconnaitre les paquets FlowSpec, ils sont marqués avec le SAFI (concept introduit dans le RFC 4760) 133 pour les règles IPv4 et 134 pour celles des VPN.

La section 4 du RFC donne l'encodage du nouveau NLRI. Un message UPDATE de BGP est utilisé, avec les attributs MP_REACH_NLRI et MP_UNREACH_NLRI du RFC 4760 et un NLRI FlowSpec. Celui-ci compte plusieurs couples {type, valeur} où l'interprétation de la valeur dépend du type (le type est codé sur un octet). Voici les principaux types :

  • Type 1 : préfixe de la destination, représenté par un octet pour la longueur, puis le préfixe, encodé comme traditionnellement en BGP (section 4.3 du RFC 4271). Ainsi, le préfixe 10.0.1.0/24 sera encodé (noté en hexadécimal) 01 18 0a 00 01 (type 1, longueur 24 - 18 en hexa - puis le préfixe dont vous noterez que seuls les trois premiers octets sont indiqués, le dernier n'étant pas pertinent ici).
  • Type 2 : préfixe de la source (lors d'une attaque DoS, il est essentiel de pouvoir filtrer aussi sur la source).
  • Type 3 : protocole (TCP, UDP, etc).
  • Types 4, 5 et 6 : port (source ou destination ou les deux). Là encore, c'est un critère très important lors du filtrage d'une attaque DoS. Attention, cela suppose que le routeur soit capable de sauter les en-têtes IP (y compris des choses comme ESP) pour aller décoder TCP ou UDP. Tous les routeurs ne savent pas faire cela (en IPv6, c'est difficile).
  • Type 9 : options activées de TCP, par exemple uniquement les paquets RST.

Tous les types de composants sont enregistrés à l'IANA.

Une fois qu'on a cet arsenal, à quoi peut-on l'utiliser ? La section 5 détaille le cas du filtrage. Autrefois, les règles de filtrage étaient assez statiques (je me souviens de l'époque où tous les réseaux en France avaient une ACL, installée manuellement, pour filtrer le réseau de l'EPITA). Aujourd'hui, avec les nombreuses DoS qui vont et viennent, il faut un mécanisme bien plus dynamique. La première solution apparue a été de publier via le protocole de routage des préfixes de destination à refuser. Cela permet même à un opérateur de laisser un de ses clients contrôler le filtrage, en envoyant en BGP à l'opérateur les préfixes, marqués d'une communauté qui va déclencher le filtrage (à ma connaissance, aucun opérateur n'a utilisé cette possibilité, en raison du risque qu'une erreur du client ne se propage). De toute façon, c'est très limité en cas de DoS (par exemple, on souhaite plus souvent filtrer sur la source que sur la destination). Au contraire, le mécanisme FlowSpec de ce RFC donne bien plus de critères de filtrage.

Cela peut d'ailleurs s'avérer dangereux : une annonce FlowSpec trop générale et on bloque du trafic légitime. C'est particulièrement vrai si un opérateur accepte du FlowSpec de ses clients : il ne faut pas permettre à un client de filtrer les autres. D'où la procédure suggérée par la section 6, qui demande de n'accepter les NLRI FlowSpec que s'ils contiennent un préfixe de destination, et que ce préfixe de destination est routé vers le même client qui envoie le NLRI. Ainsi, un client ne peut pas déclencher le filtrage d'un autre puisqu'il ne peut influencer que le filtrage des paquets qui lui sont destinés.

Au fait, en section 5, on a juste vu comment indiquer les critères de classification du trafic qu'on voulait filtrer. Mais comment indiquer le traitement qu'on veut voir appliqué aux paquets ainsi classés ? (Ce n'est pas forcément les jeter : on peut vouloir être plus subtil.) FlowSpec utilise les communautés étendues du RFC 4360. La valeur sans doute la plus importante est 0x8006, traffic-rate, qui permet de spécifier un débit maximal pour les paquets qui correspondent aux critères mis dans le NLRI. Le débit est en octets/seconde. En mettant zéro, on demande à ce que tous les paquets classés soient jetés. Les autres valeurs possibles permettent des actions comme de modifier les bits DSCP du trafic classé.

Comme toutes les armes, celle-ci peut être dangereuse pour celui qui la manipule. La section 10 est donc la bienvenue, pour avertir de ces risques. Par exemple, comme indiqué plus haut, si on permet aux messages FlowSpec de franchir les frontières entre AS, un AS maladroit ou méchant risque de déclencher un filtrage chez son voisin. D'où l'importance de la validation, n'accepter des règles FlowSpec que pour les préfixes de l'AS qui annonce ces règles.

Ensuite, comme tous les systèmes de commande des routeurs à distance, FlowSpec permet de déclencher un filtrage sur tous les routeurs qui l'accepteront. Si ce filtrage est subtil (par exemple, filtrer tous les paquets plus grands que 900 octets), les problèmes qui en résultent seront difficiles à diagnostiquer.

Et les réalisations concrètes ? Parmi les auteurs du RFC, il y a autant d'employés de Cisco que de Juniper mais ce sont des arrivés récents chez Cisco. Ce RFC a d'abord été mis en œuvre sur les Juniper (on peut consulter leur documentation en ligne), puis chez Alcatel. Il existe aussi une implémentation de FlowSpec dans le logiciel d'injection de routes ExaBGP. D'autre part, en utilisant FlowSpec, attention aux problèmes de performance.

FlowSpec a joué un rôle important dans la panne CloudFlare du 3 mars 2013, en propageant des critères incorrects (une taille de paquet supérieure au maximum permis par IP) à tous les routeurs. Ce n'est pas une bogue de FlowSpec : tout mécanisme de diffusion automatique de l'information à N machines différentes a le même problème potentiel. Si l'information était fausse, le mécanisme de diffusion transmet l'erreur à tous... (Dans le monde des serveurs Unix, le même problème peut se produire avec des logiciels comme Chef ou Puppet. Lisez un cas rigolo avec Ansible.) Comme le prévient notre RFC : « When automated systems are used, care should be taken to ensure their correctness as well as to limit the number and advertisement rate of flow routes. » Toutefois, contrairement à ce que laisse entendre le RFC, il n'y a pas que les processus automatiques qui injectent des erreurs : les humains le font aussi.

Si vous voulez en apprendre plus sur FlowSpec :

Si vous vous intéressez à l'utilisation de BGP lors d'attaques par déni de service, vous pouvez aussi consulter les RFC 3882 et RFC 5635.


Téléchargez le RFC 5575


L'article seul

Exposé « Connexions Internet, qui paie ? » aux journées FedeRez

Première rédaction de cet article le 24 mars 2013
Dernière mise à jour le 5 octobre 2013


FedeRez est la fédération nationale des associations d'étudiants qui gèrent des réseaux informatiques. Elle tient des journées annuelles et, à celles de 2013 à Toulouse, j'ai fait un court exposé sur le thème « Connexions internet: qui paie ? ».

Si l'économie ne vous fait pas peur, et que vous en avez assez de ne lire que des articles techniques, voici les transparents de mon exposé :

Les enregistrements vidéo sont disponibles sur le site Web. Tous les exposés étaient très intéressants, je choisis notamment de manière tout à fait subjective celui de Jean-Baptiste Kempf sur VLC (un projet étudiant à l'origine, et un des grands succès du logiciel libre), et celui de Rémy Sanchez sur le fonctionnement de Maiznet, le réseau étudiants de Télécom Lille.

Les journées étaient aussi l'occasion de l'Assemblée Générale de FedeRez et d'intéressantes discussions sur la vie associative.


L'article seul

RFC 6903: Additional Link Relation Types

Date de publication du RFC : Mars 2013
Auteur(s) du RFC : J. Snell
Pour information
Première rédaction de cet article le 21 mars 2013


Allez, encore tout un lot de types de liens Web qui sont enregistrés. Pas de point commun entre les types créés par ce RFC, juste quelques types intéressants.

Tous suivent les principes du RFC 8288 qui normalise cette idée de type de lien et décrit le registre où ils sont désormais stockés.

Le premier, about pointe vers une ressource qui décrit celle qui contient le lien. L'exemple donné par le RFC est celui d'un article de test d'un produit, qui pointe vers une page Web décrivant le produit. Avec les en-têtes HTTP :


HTTP/1.1 200 OK
Content-Type: text/html
Link: <http://store.example.org/product/abc>; rel="about"

Le second, preview permet de pointer vers une ressource qui offre une version limitée, plus courte ou à plus basse résolution, pour ceux qui voudraient aller vite. Ici, par exemple, une vidéo a un lien vers une version courte de dix secondes :


HTTP/1.1 200 OK
Content-Text: video/mpeg
Link: <http://example.org/preview/10-second-preview.mpg>;
       rel="preview"; type="video/mpeg"

Le troisième, privacy-policy, permet de pointer vers une ressource (par exemple une page Web) décrivant la politique du gérant, relative à la vie privée. Si vous regardez le source de ce blog, vous trouverez un tel lien en HTML, allant vers ma politique :


<link rel="privacy-policy" href="/privacy-policy.html"/>

Le RFC rappelle bien que cela n'a aucune valeur juridique : le Web est plein de « politiques de vie privée » que personne ne consulte et qui n'engagent nullement le site Web qui les affiche.

À noter que, pour indiquer ces pratiques (collectes de données personnelles, enregistrement des visites, etc), il existe un autre mécanisme, P3P. Le mécanisme de lien privacy-policy peut pointer vers une ressource P3P mais ce n'est pas obligatoire.

Le quatrième type est terms-of-service, qui pointe vers les conditions d'utilisation. Comme vous le savez, personne ne les lit, et pour des bonnes raisons (ce sont de longs textes incompréhensibles). Un exemple :


<html>
    <head>
         ...
         <link href="/tos.html" rel="terms-of-service"/>
         ...
    </head>
    <body>
         ...
    </body>
</html>

Le RFC note à juste titre que celui qui les écrit peut ensuite les violer impunément. Ce lien n'a donc d'autre rôle que de signaler ces conditions d'utilisation.

Enfin, dernier type décrit ici, type, permet de dire qu'une ressource est une instance d'une classe plus générale, identifiée par un URI, ici qu'une page décrit une personne :


HTTP/1.1 200 OK
Content-Type: text/plain
Link: <http://example.org/Person/givenName>; rel="type"

Jeanne Michu

C'est probablement surtout utile pour le Web sémantique. Attention, ce type n'a rien à voir avec le Content-type qui indique le format physique (dit souvent « type MIME »).


Téléchargez le RFC 6903


L'article seul

RFC 6906: The 'profile' Link Relation Type

Date de publication du RFC : Mars 2013
Auteur(s) du RFC : E. Wilde (EMC Corporation)
Pour information
Première rédaction de cet article le 21 mars 2013


Les liens sont à la base du Web, tout le monde le sait, mais on sait moins que les liens sont typés, marqués avec un type qui indique leur sémantique. Ainsi, le type profile, décrit dans ce RFC, indique que le lien pointe vers un profil, une spécification du format utilisé qui restreint les possibilités d'un format donné.

Ce concept de profil est très fréquent en informatique (mais pas vraiment défini de manière rigoureuse). Lorsqu'on veut réutiliser un format mais qu'on n'a besoin que d'une petite partie de ses possibilités, on définit un profil qui consiste en gros à dire « dans tel format, n'utiliser que ci et ça ». Un profil peut être un peu plus compliqué qu'une simple restriction, par exemple il peut spécifier quelques extensions obligatoires. Le point important est qu'un programme qui sait traiter le format doit savoir traiter un fichier utilisant un profil de ce format. Ainsi, un podcast est un flux de syndication (et doit donc pouvoir être traité par tout programme gérant ces flux) mais avec des éléments spécifiques, qui peuvent être compris par un lecteur de podcasts, comme Apple iTunes.

Le format lui-même est indiqué par d'autres méthodes. Par exemple, en HTTP, le format peut être indiqué par le type de media (ou type MIME), comme text/html. On peut aussi indiquer le format dans le document lui-même : en HTML, on va utiliser la déclaration DOCTYPE pour cela. Et pour indiquer le profil ? Eh bien on va se servir d'un lien. (HTML 4 avait un attribut profile dans l'élément <head> mais il n'est pas sûr que HTML 5 le garde et, de toute façon, la solution de ce RFC est plus générale.)

Ces liens suivent le cadre général normalisé dans le RFC 8288. Ce cadre comprend notamment un registre des types de liens (dans lequel se trouve désormais profile), et plusieurs syntaxes pour mettre les liens dans le document (cas du <link> de HTML) ou dans le protocole d'accès (cas de l'en-tête Link: de HTTP).

La distinction entre profils et formats est parfois subtile. Ainsi, XHTML n'est pas considéré comme un profil de XML parce que, pour les usages de XHTML, afficher du XML brut, sans les traitements spécifiques de XHTML, n'aurait guère d'intérêt. En revanche, hCard est bien un profil de XHTML, car, si un logiciel ne comprend pas hCard, le traiter et l'afficher comme du bête XHTML est utile.

Les profils sont identifiés par un URI (comme les espaces de noms de XML). Ces URI ne sont pas forcément déréférençables (on ne peut pas toujours les donner à un navigateur Web), ce sont juste des identificateurs et le logiciel doit donc les traiter comme tels, pas les présenter systématiquement comme des liens cliquables. Le RFC conseille juste (ce n'est pas une obligation) de les rendre déréférençables, et de mettre une jolie documentation du profil au bout de l'URI. Ainsi, si je crée un profil de HTML nommé http://www.example.org/profiles/myprofile, il est recommandé (juste recommandé) qu'une page Web décrivant myprofile se trouve effectivement à cette adresse.

Une curiosité : un document peut correspondre à plusieurs profils et le lien de type profile peut donc pointer vers une liste.

La section 5 du RFC donne quelques exemples concrets. D'abord, hCard, déjà cité. Il permet de mettre des vCard (RFC 6350) dans HTML. Son URI est http://microformats.org/profile/hcard, on peut donc l'indiquer par un lien comme <link rel="profile" href="http://microformats.org/profile/hcard" /> et on trouve plein d'exemples dans la documentation

Autre exemple, Dublin Core, identifié par le profil http://dublincore.org/documents/2008/08/04/dc-html/ qui permet de mettre des métadonnées Dublin Core dans une page en HTML. (Je n'en ai pas mis dans ce blog mais mes flux de syndication, en XML, continnent du Dublin Core.) Un exemple simple, les éléments Dublin Core ayant un nom commençant par DC :


<html>
<head>
<title>Expressing Dublin Core in HTML/XHTML meta and link elements</title>
<link rel="profile" href="http://dublincore.org/documents/2008/08/04/dc-html/"/>
<meta name="DC.title" lang="en" content="Expressing Dublin Core
in HTML/XHTML meta and link elements" />
<meta name="DC.creator" content="Andy Powell, UKOLN, University of Bath" />
<meta name="DCTERMS.issued" scheme="DCTERMS.W3CDTF" content="2003-11-01" />
<meta name="DCTERMS.abstract" content="This document describes how
qualified Dublin Core metadata can be encoded
in HTML/XHTML &lt;meta&gt; elements" />
<meta name="DC.format" scheme="DCTERMS.IMT" content="text/html" />
</head>

Dernier exemple, déjà cité, les podcasts. Il n'y a pas d'identificateur officiel (on pourrait utiliser l'URI http://www.apple.com/itunes/podcasts/specs.html).

Il existe désormais un registre de ces profils, créé par le RFC 7284.


Téléchargez le RFC 6906


L'article seul

Rendre l'auto-hébergement facile et sans douleur

Première rédaction de cet article le 20 mars 2013


Aujourd'hui, des millions d'utilisateurs innocents sous-traitent leur présence en ligne à des gros industriels du cloud comme Google ou Facebook. Cela, au détriment de leur vie privée et au prix d'une complète perte de contrôle de leurs propres données. L'alternative libre est évidemment l'auto-hébergement, avoir un jeu d'applications qui mettent en œuvre cette présence en ligne, sur une machine qu'on contrôle. Mais tout le monde n'a pas forcément la compétence, ou tout simplement le temps ou l'envie, pour gérer cette machine et ces applications. N'est-il pas temps de développer un système tout fait pour cela ?

Les dangers de l'hébergement infonuagique ont déjà été décrits plein de fois. Par Richard Stallman, John Harris, et d'autres. Bruce Schneier a bien noté que l'hébergement en nuage était un retour à la féodalité (on abandonne sa liberté en échange d'un service hypothétique). Avec l'hébergement dans le nuage, on peut être coupé brutalement des autres, on peut ne plus avoir accès à ses propres données alors que des polices étrangères le peuvent. Je ne vais pas revenir sur ces dangers : si vous n'êtes pas convaincu, si vous croyez que Google est une association humanitaire, et que Facebook a été créé pour aider bénévolement, lisez d'abord les articles cités plus haut. (Si c'est gratuit, c'est parce que vous n'êtes pas le client, mais la marchandise.)

Mais pourquoi les gens utilisent-ils massivement ces services, alors ? Parce qu'il n'y a pas d'alternative ? Ou bien celles-ci ont-elles des défauts sérieux ? L'alternative la plus souvent proposé par les « nébuloclastes » (les anti-cloud) est l'auto-hébergement : on prend une machine chez soi, ou bien hébergée chez un professionnel, on y met les logiciels nécessaires (il en existe plein, souvent sous une licence libre) et on a son petit nuage à soi, échappant aux problèmes notés plus haut. (Une petite nuance au passage : si la machine est chez un hébergeur - ce qui se nomme l'IaaS, celui-ci a quand même un certain contrôle sur votre présence en ligne, mais nettement moins direct que s'il manipule directement les données, comme il le fait avec le SaaS.)

Mais alors pourquoi tout le monde ne s'auto-héberge pas ? Une première raison est que cette solution nécessite certaines compétences techniques. Installer et gérer un MTA, pour pouvoir faire du courrier, et avec son identité indépendante du fournisseur, est plus compliqué que d'installer un nouveau navigateur Web. Mais il y a une autre raison derrière : même si on a les compétences nécessaires, installer, configurer et ensuite gérer ces services est très chronophage. Même un ingénieur système expérimenté a peut-être envie de consacrer son temps libre à autre chose.

D'où la vision que je voudrais proposer ici : ce qu'il manque pour développer l'auto-hébergement, et remplacer les méchants géants du nuage, c'est un paquetage tout fait, qui s'installe facilement et rapidement, et permet à chacun d'avoir une présence en ligne qu'il ou elle contrôle. Le reste de cet article est consacré à quelques détails pratiques.

Un tel paquetage devrait être sous forme d'une image qui s'installerait telle quelle sur une machine dédiée (les autres solutions sont moins simples, car elles doivent coexister avec les logiciels existants sur une machine). Les logiciels disponibles (mais pas forcément activés par défaut) devraient être :

  • Un serveur de courrier par exemple Postfix (et Courier pour le IMAP),
  • Un serveur de messagerie instantanée par exemple ejabberd,
  • Un serveur de fichiers par exemple ownCloud ou SparkleShare,
  • Un serveur de calendrier, de contacts, etc (ownCloud, là aussi ?),
  • Un logiciel de partage de fichiers (BitTorrent),
  • Un serveur DNS ? Ce n'est pas évident, j'en discute plus loin,
  • Un serveur Web permettant d'héberger des services comme webfinger (RFC 7033), un blog, un remplacement à Google Reader comme NewsBlur, etc,
  • Des trucs d'échange comme StatusNet ?
  • Les services dont ont besoin les services ci-dessus (par exemple un SGBD pour le blog), mais sans que l'utilisateur ait besoin de les voir ou de savoir qu'ils sont là,
  • Et bien sûr une interface d'administration pour gérer le tout depuis un navigateur.

À mon avis, l'interface d'administration devrait être réduite : une part de configuration (indiquer le nom de domaine, les services qu'on souhaite activer, etc) et une de surveillance et de statistiques.

Est-ce réaliste, comme cahier des charges ? Les composants existent déjà presque tous et n'auraient pas besoin d'être modifiés. Le travail serait d'intégration et de développement de l'interface Web d'administration. Je n'ai pas le temps de m'y lancer mais je suggère l'idée aux développeurs ambitieux. Lorsque l'objectif est d'avoir un truc simple, la difficulté est la qualité : il faut du zéro bogue. Il existe déjà plein de logiciels « auto-hébergement » et qui sont faits à 95 % ce qui n'est pas suffisant. Une partie du succès de Google vient de sa qualité (pas d'erreur 500 en cours de navigation...)

Un problème difficile sera celui de la sécurité. Il y a la sécurité des applications (le logiciel de blog écrit en PHP qu'il faut mettre à jour sinon on est craqué et on se retrouve à héberger un site de hameçonnage ; ou bien l'interface Web ayant un mot de passe par défaut, et 99 % des utilisateurs qui ne le changeront pas). Et il y a le problème plus général de la responsabilité : être administrateur système, ce n'est pas uniquement de la technique, c'est de la responsabilité, suivre les problèmes, répondre aux messages envoyés à abuse, etc. Il ne faudrait pas que des millions de machines d'auto-hébergement se transforment en autant de zombies ! Pour limiter les risques, le logiciel doit donc être configuré de manière à être très blindé, et mis à jour automatiquement.

Reste le cas du DNS. C'est un support essentiel de l'identité en ligne (si votre identité est facebook.com/BêteCompany, vous ne contrôlez pas votre identité, c'est Facebook qui le fait). Il semble donc logique qu'il y ait un serveur DNS dans le paquetage. Mais cela laisse deux problèmes difficiles : l'interaction avec le bureau d'enregistrement (la plupart des registres imposent un passage par cet intermédiaire, et il n'existe pas de protocole de communication standard entre le client et le BE, regardez comment cela complique la doc de YunoHost), et les serveurs DNS secondaires (le RFC 1034 décrète sagement qu'il faut au moins deux serveurs par zone, pour des raisons de résilience). Idées bienvenues.

Une fois le logiciel défini et réalisé, il faut en faire une image. Le type d'image dépend de l'hébergement physique. Si on utilise l'IaaS, certains fournisseurs (pas tous, loin de là) permettent de créer ses propres images et de démarrer ensuite une machine virtuelle dessus. C'est de très loin le plus simple pour l'utilisateur. Pour Amazon EC2, le processus de création d'images est décrit dans de nombreux articles et la relative facilité de création et de publication d'images a mené au développement d'innombrables images toutes faites, pour tous les besoins. Pour Gandi, le processus est documenté mais, malheureusement, on ne peut pas mettre ces images à la disposition des autres, comme on peut le faire chez Amazon. Pour d'autres hébergeurs, je ne sais pas, n'hésitez pas à m'envoyer des informations.

Alors, évidemment, utiliser un hébergeur est simple et bon marché mais a des limites. Celui-ci, après tout, a le contrôle complet des machines et les données sur celles-ci ne sont donc pas forcément en sécurité. Et si on veut héberger ce paquetage de présence en ligne chez soi ? Pour que l'installation reste simple, il vaut mieux une image conçue pour une machine physique donnée. Par exemple, on pourrait imaginer des images pour les Soekris. Ou, pour un engin plus limité mais beaucoup moins cher et consommant très peu (donc pouvant être laissé branché en permanence), le Raspberry Pi, on peut noter qu'il existe déjà énormément d'images pour le Pi dédiées à divers usages. On pourrait donc en ajouter une dédiée à la présence en ligne. (Un exemple d'installation de beaucoup de logiciels serveurs sur un Pi est documenté ici.)

Rien n'interdirait d'ailleurs de développer une appliance matérielle, ayant déjà l'image installée, sur le modèle de certains NAS grand public actuels (j'ai entendu plusieurs avis favorables sur les produits de Synology mais cela n'a pas l'air très libre.).

Notez qu'il n'y a pas de miracle : héberger chez soi ne résout pas tous les problèmes (votre FAI peut vous couper) et, en IPv4, il faut prévoir des complications (comme d'ouvrir sur la box les ports permettant l'accès à distance).

Voilà, comme j'aime bien donner du travail aux autres, je vais m'arrêter là. Je serais ravi que des développeurs courageux s'emparent de cette idée et la réalisent. Notez bien qu'il n'est pas nécessaire (et sans doute pas souhaitable) qu'il n'y ait qu'un seul logiciel mettant en œuvre ce concept. Si tout le monde utilise des normes ouvertes comme HTTP et XMPP, il n'est pas nécessaire de n'avoir qu'un seul logiciel, ils pourront interagir. Et, dans l'intérêt de la sécurité, il vaut sans doute mieux ne pas mettre tous ses œufs dans le même panier et donc avoir plusieurs logiciels.

Quelques projets existants qui ont un rapport avec cette idée (merci à Daniel Le Bray pour la première liste) :

  • BeedBox (projet abandonné : comme beaucoup de projets en informatique, commencer est facile, terminer à 100 % est difficile). La description du projet est très proche de ce que je propose.
  • YunoHost.
  • CozyCloud. Attention, ils ont deux offres, une hébergée (du SaaS classique) et une où on s’auto-héberge. Le logiciel est libre, mais pas encore fini (« In the future there will be a fully packaged virtual machine » c'est-à-dire exactement ce que je souhaitais).
  • Helios.im, qui est une appliance physique (en l'occurrence un Raspberry Pi).
  • Sur le Rasperry Pi, voir aussi arkOS (encore expérimental).
  • Amahi, un logiciel pour transformer son PC en serveur d'auto-hébergement.
  • Qy.share. Cela semble très bien mais je ne trouve aucun détail sur leur site Web.
  • FreedomBox, qui a des ambitions bien plus sécuritaires que l'idée que j'ai développé ici. Je pensais au contrôle des données, FreedomBox est plus dans une logique de sécurité.
  • SME Server.

On peut aussi noter qu'il n'y pas de choix qu'entre les gros monstres du cloud et l'auto-hébergement. On peut imaginer des systèmes coopératifs, où un certain nombre de citoyens se regroupent pour monter une plate-forme commune (merci à Fil pour avoir rappelé cette possibilité). Jean-Baptiste Favre a fait un excellent article sur ce thème. Un projet dans cet esprit est http://the.re/.

Comme ce blog n'a pas de système de commentaires, le mieux pour discuter de cette idée est d'aller sur SeenThis. (Une autre discussion - plus technique ? - a lieu sur LinuxFr.) Enfin, dernier article, une intéressante réflexion sur l'auto-hébergement chez soi.


L'article seul

Sécurité du pair-à-pair et composant central

Première rédaction de cet article le 16 mars 2013


Les techniques fondées sur le pair-à-pair sont souvent présentées comme permettant un Internet sans centre et sans autorité. Ce n'est vrai que si on ne se préoccupe pas de sécurité. Dès qu'on est confronté à des méchants qui tentent délibérement d'attaquer le réseau, le problème est bien plus complexe. Désolé de jouer les porteurs de mauvaise nouvelle mais la plupart des promoteurs du pair-à-pair se font des illusions.

Quel est le problème ? Les participants à un réseau pair-à-pair doivent accomplir un certain nombre d'actions pour que le réseau fonctionne. Par exemple, dans une DHT, ils doivent faire suivre les requêtes qui ne sont pas pour eux, ils doivent stocker les données qui sont pour eux, et ils doivent les restituer lorsque c'est demandé. Un nœud byzantin dans une DHT et plus rien ne marche. De même, dans un réseau maillé pair-à-pair, chacun doit faire suivre les messages, pas les garder et pas les modifier (dans les réseaux classiques, les opérateurs ne se gênent pas pour tripoter les messages de leurs clients).

Bon, pas de problème, disent les défenseurs du pair-à-pair, il suffit d'avoir de la redondance. Dans une DHT, on va confier chaque donnée à N pairs et pas à un seul. Un seul méchant ne pourra donc pas bloquer le fonctionnement de la DHT. Même chose pour le réseau maillé : s'il y a plusieurs chemins possibles entre deux pairs, un seul méchant ne pourra pas empêcher la communication.

Mais ce mécanisme ne marche que si les attaquants sont nettement moins nombreux que les défenseurs. Bruce Schneier a écrit beaucoup de textes intéressants à ce sujet. Dans une société normale, les gens honnêtes sont plus nombreux que les délinquants et pas mal de mécanismes de sécurité du monde réel fonctionnent sur cette base. Mais ce modèle ne peut pas se transmettre aux réseaux informatiques : ici, l'attaquant peut générer autant d'identités qu'il le veut. Cela se nomme une attaque Sybil. Dans une DHT de 10 000 pairs, l'attaquant crée 20 000 machines virtuelles, elles rejoignent la DHT et peuvent la bloquer complètement. « Bourrer les urnes » est trivial dans le monde virtuel.

La clé de la sécurité d'un tel réseau pair-à-pair est le mécanisme d'inscription des pairs (enrollment, dans la langue de Will Smith). Dans les réseaux complètement open bar, tout pair qui arrive est pris, immédiatement. Dans d'autres, il y a un processus de vérification : authentification et autorisation du pair. Et qui va la faire, cette vérification ? Elle ne peut pas être faite par les autres pairs (ou bien on retombe dans le problème précédent). Elle est donc forcément faite par un composant central (ou, à la rigueur, par un système hiérarchique, avec délégation de l'autorité). Celui-ci va alors dire « OK, tu a un certificat valide, tu es inscrit » ou bien « non, rejeté ». Cela marche, mais il a fallu accepter de ne pas faire du pair-à-pair pur.

Tous les systèmes de pair-à-pair qui fonctionnnent ont un tel composant central. Parfois, toutes les machines sont dans la même entreprise (l'inscription est alors un problème simple). Parfois, ce n'est pas le cas, mais tous les pairs font confiance à un système d'inscription central. Les systèmes qui n'ont pas un tel composant central d'inscription (comme le réseau maillé Qaul qui se prétend utilisable dans un environnement hostile) s'écrouleront à la première attaque.

Cette impossibilité d'empêcher les attaques Sybil sans composant central (ou hiérarchique) est-elle prouvée mathématiquement (comme on a prouvé le théorème CAP) ? À ma connaissance, non. Il y a donc un espoir pour les chercheurs mais n'espérez pas trop : le problème est difficile.

Et BitTorrent, me dira t-on ? Les pairs utilisant une DHT (trackerless) récupèrent tous les jours leurs fichiers (d'ailleurs, si quelqu'un a la saison 3 de Game of Thrones, ça m'intéresse) et sans composant central. Mais si ! Le composant central est le moteur de recherche (par exemple The Pirate Bay) qui distribue les sommes de contrôle grâce auquel on vérifie qu'on a bien récupéré le fichier voulu. De même, si on veut juste stocker des données dans une DHT et vérifier qu'elles n'ont pas été modifiées par les pairs stockeurs, il existe des méthodes mais elles nécessitent d'avoir obtenu la clé de manière sécurisée, donc typiquement par un composant central.

Je résume donc mon opinion « un réseau pair-à-pair sans composant central (ou hiérarchique) ne peut PAS être sécurisé contre les attaques Sybil ».

Un exemple de système pair-à-pair avec inscription centralisée est le protocole RELOAD de l'IETF (RFC 6940), qui servira à faire du SIP en pair-à-pair. Le RFC 5694 est une bonne lecture, pour tous ceux et celles qui s'intéressent à la sécurité du pair-à-pair. Comme ce blog n'a pas de système de commentaires, si vous voulez discuter, approuver, contester, le mieux est d'aller sur SeenThis.


L'article seul

À partir d'un nom de domaine, trouver le domaine « responsable »

Première rédaction de cet article le 15 mars 2013


C'est un problème qui revient souvent sur l'Internet. On a un nom de domaine et on voudrait trouver quel est le « nom responsable » ou « nom enregistré ». Par exemple, étant donné machin.truc.bortzmeyer.org, le nom responsable est bortzmeyer.org. Cela parait trivial, mais cela ne l'est pas, comme cela a encore été illustré cette semaine dans les discussions à la réunion IETF d'Orlando.

D'abord, voyons pourquoi on veut faire cela. Il existe de nombreux cas où c'est utile (merci à John Levine pour une compilation) :

  • Le cas le plus connu est celui des cookies du Web (RFC 6265). Le serveur peut indiquer pour quel domaine un cookie est valable, par exemple le serveur en machin.example.org peut dire que ses cookies sont valables pour tout example.org et que le client devra donc les envoyer à, mettons, le serveur truc.example.org. Mais un serveur en example.com peut-il dire que ses cookies valent pour tout .com ? Évidemment non, car .com n'est pas sous la même administration. Mais comment le navigateur Web pourrait-il le savoir ?
  • Certains mécanismes d'authentification partent d'un domaine et cherchent le domaine responsable pour définir une politique pour les sous-domaines. C'est le cas de DMARC. Ou, autre exemple, des autorités de certification X.509 qui, lorsqu'on leur demande un certificat pour www.example.net vont interroger le titulaire de example.net pour vérifier si cette demande est autorisée. Et, si vous demandez un certificat pour *.com, il devra normalement être refusé.
  • En cas d'abus, on cherche à prévenir le responsable. Si machin.truc.example.org héberge un site de hameçonnage, dois-je prévenir le titulaire de truc.example.org ou bien celui de example.org ?

Certaines personnes, arrivées là, se demandent où est le problème. Il suffit de retirer le composant le plus à gauche du nom de domaine et on trouve le domaine responsable. Un problème avec www.example.com ? Le responsable est example.com. Mais cet algorithme trivial ne marche pas dans des cas comme truc.machin.example.com qui est parfaitement légal (pour un exemple réel, regardez le site Web de la mairie d'Hiroshima, en www.city.hiroshima.lg.jp.) Bon, pas grave, se disent les « simplificateurs ». Ne gardons que les deux composants les plus à droite. Comme cela, le responsable de www.example.com est example.com et celui de truc.machin.example.com est aussi example.com. Mais cela ne marche pas car tous les TLD ne font pas de délégation au deuxième niveau : .uk et .jp ne délèguent qu'au troisième niveau (l'Université de Cambridge est en cam.ac.uk, pas cam.uk). Et il existe des TLD qui délèguent au deuxième niveau et au troisième, comme .fr ou comme tout TLD qui a un registre parmi ses clients (par exemple eu.org : machin.eu.org n'est pas sous la même administration que truc.eu.org). Donc, un algorithme portant sur le nom n'est pas une solution.

D'autres personnes, plus techniques, se disent qu'il suffit de faire une requête DNS et de regarder le domaine de l'enregistrement SOA, qui donnera le nom du domaine responsable (je vous épargne quelques petits détails techniques comme le fait que le SOA n'est renvoyé que si les données demandées n'existent pas) :


% dig A foo.bar.doesnotexist.cam.ac.uk
...
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 39210
...
;; AUTHORITY SECTION:
cam.ac.uk.		10800	IN	SOA	authdns0.csx.cam.ac.uk. hostmaster.ucs.cam.ac.uk. 1363381148 14400 3600 604800 14400

On voit que ce nom n'existe pas et que l'autorité est en cam.ac.uk. Mais la notion d'« administration » n'est pas technique. Cette méthode DNS ne détecte que les frontières techniques entre les zones DNS (ce qu'on nomme les zone cuts), pas les politiques appliquées.


% dig A www.doesnotexist.asso.fr     
...
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 16619
...
;; AUTHORITY SECTION:
fr.			5312	IN	SOA	nsmaster.nic.fr. hostmaster.nic.fr. 2222270543 3600 1800 3600000 5400

Comme asso.fr est dans la même zone DNS que .fr, on peut avoir l'impression que les délégations se font sous .fr (alors qu'il y en a sous asso.fr).

Bref, il n'y a pas de solution algorithmique. Il faut récupérer l'information quelque part. Il existe plusieurs listes compilées à la main et qui ont toutes en commun d'être insuffisantes, non officielles et pas à jour. Ce dernier problème est amené à s'aggraver avec le programme de création de nouveaux gTLD. La plus connue de ces listes est gérée par Mozilla et se nomme la Public Suffix List. Elle est notamment utilisée par les navigateurs Firefox et Chrome. Cela a provoqué des frustrations comme lorsque .cw n'était pas reconnu par Chrome qui envoyait les visiteurs sur un moteur de recherche !

Alors, quelles solutions ont été discutées à l'IETF ? Elles avaient toutes en commun de permettre aux gérants des zones DNS de publier l'information (contrairement à la Public Suffix List, gérée par des tiers qui ne sont pas forcément au courant). La plus aboutie, due à Andrew Sullivan et décrite dans l'Internet Draft draft-sullivan-domain-origin-assert, consiste à placer des enregistrements d'un nouveau type, SOPA (pour Start Of Policy Authority) qui déclarent « ce nom est sous la même autorité que moi ». Ainsi, si on a cet enregistrement SOPA :

bortzmeyer.org. 86400 IN SOPA www.bortzmeyer.org.

et qu'un serveur Web accédé sous le nom www.bortzmeyer.org va tenter de placer un cookie pour le nom bortzmeyer.org, le navigateur Web pourra vérifier que bortzmeyer.org avait donné son autorisation (en se déclarant sous la même administration que www.bortzmeyer.org). Cette solution est donc très générale (on peut imaginer des schémas très rigolos comme example.net déclarant que example.com est sous la même autorité) mais cela peut être un peu complexe parfois.

Une autre proposition plus simple (mais pas encore documentée dans un texte écrit), moins générale mais collant mieux à la nature arborescente du DNS, est de permettre à toute zone DNS de dire « je suis un point de délégation public, c'est-à-dire que les noms en dessous ne sont pas sous mon autorité ». Ainsi, fr, lg.jp ou eu.org pourraient dire (le nom de l'enregistrement, PHB, vient des initiales de l'auteur, Phillip Hallam-Baker, puisque la proposition n'est pas encore écrite) :

org.   86400 IN  PHB PUBLIC

et tout le monde pourrait alors savoir que .org est une zone de délégation publique. Les sous-domaines de .org pourraient ne rien mettre, mettre un enregistrement disant explicitement qu'ils ne sont pas une zone de délégation publique, ou bien, comme eu.org, avoir un enregistrement disant qu'eux aussi délèguent.

(Une autre solution proposée a été d'utiliser un autre protocole que le DNS, par exemple le successeur de whois sur lequel travaille le groupe WEIRDS.)

A priori, pour l'instant, les participants à l'IETF penchent pour la solution SOPA. (À noter que, trois mois après cet article, une autre proposition technique, plus simple, a été faite, en draft-levine-orgboundary.)


L'article seul

RFC 6885: Stringprep Revision and PRECIS Problem Statement

Date de publication du RFC : Mars 2013
Auteur(s) du RFC : M. Blanchet (Viagenie), A. Sullivan (Dyn, Inc.)
Pour information
Réalisé dans le cadre du groupe de travail IETF precis
Première rédaction de cet article le 14 mars 2013


Dans bien des protocoles, il y a besoin de comparer deux chaînes de caractères, pour voir si elles sont égales. Par exemple, un protocole d'authentification va comparer un identificateur à ceux enregistrés dans sa base, pour voir s'il est présent. Si les chaînes de caractères sont uniquement en US-ASCII, il n'y a guère de problèmes, à part décider si la comparaison est sensible à la casse. Mais si elles sont en Unicode ce qui, en 2013, est la moindre des choses ? Alors, c'est plus compliqué. Dans ce cas, on décide de préparer les chaînes avant la comparaison, pour les ramener à une forme de référence (en ASCII, un exemple simple de préparation serait de tout mettre en minuscules). Beaucoup de protocoles IETF utilisaient pour cette opération le stringprep du RFC 3454, popularisé par son utilisation dans les noms de domaines internationalisés. Mais la mise à jour de ces noms de domaines, en 2010, a abandonné stringprep (cf. RFC 5890). Dans ces conditions, les autres protocoles se retrouvaient privés d'une référence bien pratique. Le groupe de travail PRECIS a été créé pour étudier la mise en place d'un cadre général de préparation des chaînes Unicode pour tous les protocoles. Ce RFC 6885 est son premier RFC et il décrit le problème, sans proposer encore de solution.

C'est que stringprep avait été un grand succès. Voici une liste incomplète des protocoles qui l'utilisent :

  • NFS version 4 (RFC 8881),
  • le protocole d'authentification EAP (RFC 3748),
  • le protocole de communication XMPP (RFC 6120, profils Nodeprep et Resourceprep, car un identificateur XMPP comme stéphane@dns-oarc.net/Théâtre est légal),
  • les noms dans les certificats X509 (RFC 4683),
  • tous les protocoles qui passent par SASL comme l'authentification SMTP (RFC 4954) ou POP (RFC 5034),
  • le registre des algorithmes de comparaison (RFC 4790), et certains de ses algorithmes (comme celui du RFC 5051),
  • iSCSI (RFC 3722) lorsqu'il s'agit de nommer l'initiateur (la machine) et la cible (le disque),
  • et bien d'autres. Une évaluation très détaillée des différents profils figure dans l'annexe B de ce RFC.

Pour gérer plus facilement ce bestiaire, on peut les regrouper en quelques catégories (voir l'étude de Marc Blanchet), d'autant plus que beaucoup utilisent le même profil SASLprep du RFC 4013. L'annexe A de notre RFC liste ces catégories.

On l'a dit, la motivation immédiate pour le travail du groupe PRECIS était la perte de la référence que constituait les IDN, qui utilisent désormais d'autres méthodes. Puisque, de toute façon, il va falloir remettre à plat cette question de la préparation des identificateurs Unicode, c'était l'occasion de faire un bilan (il a commencé à la réunion IETF 77 dans une Bof nommée « Newprep » dont le compte-rendu est en ligne). La section 4 étudie les profils de stringprep existants et leurs limites :

  • Stringprep est lié à la version 3.2 d'Unicode. Or, plusieurs versions sont sorties depuis et stringprep ne permet pas de les utiliser.
  • Ce point est d'autant plus gênant qu'une application n'a en général pas le choix de la version Unicode : elle utilise ce que le système hôte lui fournit.
  • Les chaînes de caractère à comparer (par exemple les identificateurs) sont souvent passés d'un protocole à l'autre et il serait donc souhaitable d'avoir des règles communes. Notez que, par exemple, XMPP utilise deux profils stringprep différents pour les composants du JID (l'identificateur XMPP) : la ressource, le domaine et la partie locale n'obéissent pas aux mêmes règles. Allez donc expliquer la syntaxe légale d'un JID dans ces conditions !

Bref, c'est sur la base de ce cahier des charges informel qu'a été créé le groupe PRECIS avec l'ambition de servir des protocoles très différents (mais qui ne bénéficiaient pas des compétences d'experts en internationalisation), en s'inspirant (sans forcément le copier aveuglément) de l'IDN bis du RFC 5890 et suivants.

La section 5 de ce RFC est le cahier des charges formel. D'abord, sur la question de la comparaison entre chaînes, un rappel du problème. Il y a trois catégories de chaînes, pour ce qui concerne la comparaison :

  • Les absolues, qu'on compare octet par octet,
  • Les définies, où la comparaison est plus complexe mais est bien définie, par un algorithme standard,
  • Les indéfinies où il n'existe pas de règle standard (il n'y en a heureusement pas d'exemple connu dans les protocoles IETF).

Par exemple, deux chaînes Unicode identiques pour la deuxième catégorie (même séquence de points de code) peuvent ne pas l'être pour la première (par exemple si une est en UTF-8 et l'autre en UTF-32). Mais il peut exister un algorithme pour les comparer (tout convertir en UTF-8 puis comparer les octets). Le tableau en annexe A indique, pour les protocoles existants, à quelle catégorie ils appartiennent.

Ensuite, les caractères eux-même, un problème que la taille du bestiaire Unicode (plus de 100 000 caractères) rend difficile. Commençons par la casse. IDN v1 faisait une comparaison indépendante de la casse en convertissant tout en minuscules. IDN v2 a décidé de n'accepter que les minuscules, une éventuelle conversion des majuscules étant à faire en dehors du cadre IDN (RFC 5892). Le système défini par PRECIS doit donc gérer plusieurs cas, avec ou sans sensibilité à la casse, avec ou sans préservation de la casse.

Ensuite, la canonicalisation. Comme il existe plusieurs chaînes Unicode dont le rendu peut être identique (exemple classique : U+00C8, d'une part, et U+0045 U+0300, d'autre part, vont tous les deux donner É), Unicode prévoit des algorithmes de canonicalisation qui réduisent les chaînes de caractères à une forme canonique, avant la comparaison. La plupart des profils de stringprep se servent de NFKC. Est-ce le bon choix ? Dans tous les cas ? NFC peut être une meilleure idée (au fait, dans l'exemple ci-dessus, la chaîne deviendra U+00C8 avec NFC et avec NFKC).

Autre question délicate à considérer, les caractères interdits. Par exemple, un protocole peut avoir des caractères spéciaux comme @ ou / qu'il faudra interdire dans les identificateurs. Faut-il définir les caractères interdits (et autoriser donc le reste) ou au contraire les caractères permis (et donc interdire tous les autres) ?

Cette question est partiellement liée à la question de l'homographie. Ce RFC reprend la légende (pourtant bien démontée par UTR36) comme quoi les caractères pourraient avoir un rôle dans le hameçonnage. Mais il reconnait qu'il n'y a pas de solution technique à cette question.

Autre question sur les données, d'où viennent-elles ? Sont-elles typiquement saisies par un utilisateur (et, dans ce cas, il faut probablement lui laisser un grand choix de variantes possibles) ou bien sont-elles générées par un programme ? Derrière cette question se trouve la frontière oh combien mouvante entre ce qui relève de l'interface utilisateur et ce qui relève des protocoles (voir le RFC 5895 et aussi, même s'il n'est pas cité, le RFC 2277).

Après l'entrée, la sortie de ces chaînes de caractères soulève aussi des questions. Si les caractères sortent du monde « machine » et sont imprimés, pour se retrouver sur une carte de visite ou sur les flancs d'un autobus, les problèmes de risque de confusion visuelle seront plus aigus.

Et il y a le fait que certaines chaînes de caractères servent d'entrée au processus suivant, condensation cryptographique ou concaténation, par exemple.

Dernier problème à garder en mémoire, le risque de changements incompatibles lors de la sortie d'une nouvelle version d'Unicode. Idéalement, un caractère, une fois déclaré valide pour un protocole donné, devrait le rester éternellement, assurant ainsi la stabilité des identificateurs construits avec ce caractère. Mais Unicode ne fournit pas cette garantie (au passage, c'est pour cela que stringprep était lié à une version particulière d'Unicode). Un caractère peut changer de catégorie et, si sa validité était déterminée algorithmiquement à partir de sa catégorie, il peut passer de valide à invalide. Le cas s'est déjà produit (cf. RFC 6452).

La section 6 est ensuite le relevé des décisions (unanimes) concernant le travail du groupe PRECIS :

  • Accord pour développer un remplaçant pour stringprep, ne gérant qu'Unicode (les autres jeux de caractères sont éliminés).
  • Reprendre le mécanisme d'IDNA bis pour être indépendant de la version d'Unicode, à savoir faire dériver la validité ou nom d'un caractère d'un algorithme utilisant les propriétés Unicode, algorithme qu'il suffira de refaire tourner à chaque nouvelle version d'Unicode.
  • Essayer de définir un petit nombre de profils, chacun pouvant convenir à une grande classe de protocoles.
  • Garder en tête tous les problèmes posés en section 5.

Téléchargez le RFC 6885


L'article seul

RFC 6892: The 'describes' Link Relation Type

Date de publication du RFC : Mars 2013
Auteur(s) du RFC : E. Wilde (EMC Corporation)
Pour information
Première rédaction de cet article le 13 mars 2013


Dans le registre des types de liens, il y avait déjà un describedby qui indiquait une ressource Web décrivant la ressource courante. Désormais, il y a aussi l'inverse, describes, qui va d'une ressource à celle qu'elle décrit.

C'est dans le RFC 8288 que sont spécifiés ces types de liens. describedby avait été spécifié par la norme W3C POWDER mais celle-ci ne spéficiait pas le type du lien inverse. Notons que describes est très général, il ne spécifie pas le format à utiliser et, notamment, on n'est pas obligé de se limiter à RDF, on a tout à fait le droit de fournir des descriptions en XML ou JSON (section 4 de notre RFC).

Par exemple, si une page Web parle du livre Net.Lang, elle peut le référencer ainsi, en utilisant comme identificateur du livre l'URL de son site officiel :


<link rel="describes" href="http://net-lang.net/"/>

ou bien, pourquoi pas, avec l'ISBN (RFC 8254) :


<link rel="describes" href="urn:isbn:978-2-915825-08-4"/>

Il peut y avoir sur le Web plusieurs ressources qui pointent, via un lien describes, vers une ressource donnée.

Attention, n'importe qui peut toujours mettre un lien describes pointant vers n'importe où : la seule existence de ce lien n'implique pas qu'il fasse autorité (section 5).


Téléchargez le RFC 6892


L'article seul

Résolution de noms : les programmeurs vont-ils avoir de meilleures interfaces ?

Première rédaction de cet article le 12 mars 2013


La vie du programmeur d'applications réseau n'est pas facile. Il a souvent besoin de résoudre des noms en adresses IP. Il existe pour cela des API standards depuis longtemps. Mais elles ne donnent pas toute l'information nécessaire, loin de là. Aura-t-on un jour de meilleures API ?

Le mécanisme normal en C pour résoudre un nom en adresse est getaddrinfo(). (Si vous rencontrez un programmeur qui utilise encore gethostbyname(), euthanasiez-le : cette fonction, qui était limitée à IPv4, a été remplacée il y a longtemps.) Dans d'autres langages de programmation, des fonctions similaires existent, parfois avec le même nom (comme getaddrinfo() en Python), parfois sous un autre nom (comme LookupHost en Go). Notez que, dans ces langages de plus haut niveau, on n'a la plupart du temps pas besoin de faire ces résolutions de noms explicitement. On appele des fonctions de connexion qui prennent un nom en paramètre (comme Dial en Go).

Ces fonctions ont des limitations communes. D'abord, elles n'indiquent pas pendant combien de temps l'information est valable. Or, les adresses IP changent et une application qui fonctionne longtemps (un navigateur Web, par exemple), si elle voulait garder en mémoire le résultat de getaddrinfo() ne saurait pas pour combien de temps cela serait possible (si le nom a été trouvé dans le DNS, getaddrinfo() ne permet pas de récupérer le TTL). Résultat, l'application continue parfois à utiliser une adresse qui n'est plus valable, phénomène connu sous le nom de pinning (cf. RFC 5887, par exemple).

Autre limite de getaddrinfo() et de ses équivalents, il n'indique pas si la résolution a été sécurisée ou pas. getaddrinfo() peut utiliser plusieurs sources pour faire la résolution : le DNS mais aussi /etc/hosts (ou équivalent, pour les systèmes non-Unix), LDAP, etc (la liste des sources est configurable, par exemple sur Ubuntu, c'est dans /etc/nsswitch.conf.) Certaines de ces sources peuvent être considérées comme sûres (/etc/hosts, LDAP avec TLS, DNS avec DNSSEC), d'autres pas (DNS sans DNSSEC, car il est vulnérable aux attaques par empoisonnement de cache). Mais l'application qui utilise getaddrinfo() ne le sait pas ! L'information (pourtant essentielle) sur l'authenticité du résultat n'est pas renvoyée au programme.

Ce n'est pas tout : une autre limite de ces fonctions de résolution de noms est qu'elles ne permettent que de trouver une adresse IP en échange d'un nom. On a souvent besoin de plus d'informations, que l'on trouve dans le DNS. Par exemple, la plupart des protocoles réseau (mais, hélas, pas HTTP) permettent de stocker dans le DNS le nom du serveur qui assure un service pour un domaine donné (ce qui sépare le nom du domaine de celui du serveur alors qu'en HTTP, le serveur du domaine example.com est forcément la machine example.com), avec d'autres indications comme le numéro de port à utiliser. Cela se fait via les enregistrements SRV décrits dans le RFC 2782. Ils sont utilisés, par exemple, dans XMPP. Cela veut dire qu'un logiciel de messagerie instantanée ne peut pas se contenter de getaddrinfo(), il doit faire des requêtes DNS plus générales. Même cas pour OpenSSH lorsqu'il cherche des clés publiques dans le DNS (RFC 4255) ou pour un client Web qui veut trouver les enregistrements DANE (RFC 6698).

Et c'est là que les ennuis commencent : il n'existe pas d'API standard pour cela. (Voir deux questions sur Stack Overflow, « Code to do a direct DNS lookup » ou « Querying full DNS record ».) On ne manque pas de bibliothèques mais aucune n'est standard, obligeant le programmeur à en choisir une et à demander à ceux qui compilent son programme d'installer ladite bibliothèque. En C, on a :

  • ldns (celle que je préfère, bien documentée et facile d'usage),
  • la plus ancienne et plus traditionnelle libbind (qui faisait autrefois partie de BIND et s'appelait libresolv, mais peut maintenant s'installer seule), avec les fonctions anciennes et connues comme res_query(), qui font que certains la considèrent comme la solution standard, malgré ses difficultés d'utilisation,
  • libunbound, tirée du résolveur du même nom.

Et c'est pareil pour tous les langages de programmation par exemple, en Python, il a l'excellente DNSpython mais aussi plusieurs autres bibliothèques. Même chose pour Go qui a godns mais pas du tout de paquetage DNS standard. Et ces trois langages ne sont que des exemples, ce n'est pas mieux pour les autres langages (signalez-moi les langages de programmation ayant une bibliothèque standard permettant de récupérer des enregistrements SSHFP et de vérifier si cela a été obtenu de manière sécurisée).

Bref, avoir une API standard ne serait pas du luxe. Pour C, un nouvel effort est en cours, et fait l'objet d'une campagne de promotion à la réunion IETF d'Orlando : getdns. getdns a tous les services souhaités ici, est conçu pour C (si c'est un succès, son adaptation à d'autres langages viendra peut-être par la suite), n'a pas encore de mise en œuvre et a la particularité que les structures de données, parfois complexes, du DNS, sont modélisées dans un langage très proche de JSON.

Programmeurs d'applications réseau utilisant C, c'est le moment de lire la proposition d'API, et de faire des commentaires !


L'article seul

RFC 6858: Simplified POP/IMAP Downgrading for Internationalized Email

Date de publication du RFC : Mars 2013
Auteur(s) du RFC : Arnt Gulbrandsen
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF eai
Première rédaction de cet article le 12 mars 2013


Lorsqu'un message complètement internationalisé (avec en-têtes en Unicode, adresse d'expéditeur en Unicode, etc) est stocké sur un serveur de messagerie, et qu'un client IMAP ou POP veut le récupérer, que faire si le dit client n'est pas capable de gérer les messages entièrement internationalisés ? Le message a déjà été reçu et stocké. Il est trop tard pour le renvoyer à l'expéditeur (le courrier électronique étant asynchrone, on ne peut pas en général signaler à l'expéditeur qu'on ne sait pas gérer ses messages). Il faut donc se résigner à effectuer un repli stratégique (downgrading) et à transcrire plus ou moins bien le message en ASCII. Il existe deux algorithmes pour cela, un très simple dans ce RFC 6858 et un plus riche dans le RFC 6857.

Car notre RFC 6858 ne prétend pas faire un travail satisfaisant. Si M. Li, en Chine, a utilisé son nom comme adresse (From: 李@中国科学院.中国), il n'existe pas de mécanisme automatique satisfaisant pour transformer cette adresse en une adresse qui marche toujours (par exemple, qui permette d'y répondre). Le repli (downgrade) est donc toujours rudimentaire et le message ne sera donc qu'imparfaitement rendu.

Une des solutions permises par le RFC 6855 est de dissimuler le message aux yeux des clients IMAP archaïques. Notre RFC en propose une autre, afficher un message dégradé (le « message de synthèse »), considérant que cela vaut mieux que rien.

L'algorithme de ce court RFC se veut simple, considérant que, si le programmeur est courageux et prêt à faire des choses compliquées, il a plutôt intérêt à mettre en œuvre le RFC 6855, pour gérer complètement l'Unicode. (L'autre algorithme, celui du RFC 6857, n'est pas d'accord.)

Le gros du RFC est la section 2, qui indique les transformations opérées pour transformer le message Unicode en du pur ASCII :

  • Les adresses en Unicode sont remplacées par une adresse ASCII bidon (qui ne marchera pas), indiquant ce qui s'est passé. Ainsi, le From: 李@中国科学院.中国 ci-dessus pourra devenir, par exemple, From: Internationalized Address =?utf-8?b?5p2O?= <international@address.invalid>. Le TLD .invalid est réservé par le RFC 2606. Ici, le nom de M. Li a été encodé avec le RFC 2047 (le truc qui commence avec =?). Cette transformation s'applique à tous les champs contenant des adresses (From:, ici, mais aussi Cc:, Reply-To:, etc).
  • Les paramètres MIME en Unicode sont simplement retirés. Ainsi, Content-Disposition: attachment; filename=اعلامیه_مطبوعاتی deviendra Content-Disposition: attachment.
  • Le Subject: sera encodé en RFC 2047. Ainsi, Subject: Venez découvrir ce café deviendra Subject: =?utf-8?q?Venez_d=C3=A9couvrir_ce_caf=C3=A9?=. Contrairement au cas de l'adresse (où le repli produit un en-tête qui ne marchera plus), ici, le MUA pourra reconstruire le sujet original.
  • Tous les autres champs qui contiennent de l'Unicode seront tout simplement retirés (dans l'algorithme du RFC 6857, ils sont transformés).

Voilà, j'avais promis un algorithme simple, il l'est. Il permet à un serveur IMAP ou POP de ne pas trop dérouter ses lecteurs non-Unicode. Il reste quelques petits détails, dans les sections 3 et 5. Ainsi, des commandes IMAP comme FETCH RFC822.SIZE permettent de connaître la taille d'un message avant de le télécharger. Comme le repli en ASCII change la taille, notre RFC permet au serveur de renvoyer la taille du message originel, pas celle du message de synthèse, pour lui simplifier la vie.

Question sécurité, le repli n'est pas idéal (section 5) :

  • Il invalide les signatures,
  • Des champs importants comme Message-ID: ont pu disparaître purement et simplement dans l'opération,
  • Et le plus gênant : si le client POP ou IMAP (comme le permet fetchmail) récupère le message en local, puis le détruit sur le serveur, le message original est irrémédiablement perdu et le client se retrouve avec uniquement le message de synthèse...

À noter que les réponses du serveur IMAP pourront désormais inclure le mot-clé DOWNGRADED, désormais dans le registre IANA des réponses possibles.


Téléchargez le RFC 6858


L'article seul

RFC 6855: IMAP Support for UTF-8

Date de publication du RFC : Mars 2013
Auteur(s) du RFC : P. Resnick (Qualcomm), C. Newman (Oracle), S. Shen (CNNIC)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF eai
Première rédaction de cet article le 12 mars 2013


Successeur du RFC 5738, voici la normalisation de la gestion d'Unicode par le protocole IMAP d'accès aux boîtes aux lettres.

Normalisé dans le RFC 3501, IMAP permet d'accéder à des boîtes aux lettres situées sur un serveur distant. Ces boîtes peuvent maintenant avoir des noms en Unicode, les utilisateurs peuvent utiliser Unicode pour se nommer et les adresses gérées peuvent être en Unicode. L'encodage utilisé est UTF-8 (RFC 3629). C'est donc une des composantes d'un courrier électronique complètement international (RFC 6530). Le RFC précédent sur le sujet, le RFC 5738 avait le statut « Expérimental » alors que notre RFC 6855 est sur le « Chemin des Normes ». (Il existe un RFC équivalent pour POP le RFC 6856.)

Tout commence par la possibilité d'indiquer le support d'UTF-8. Un serveur IMAP, à l'ouverture de la connexion, indique les extensions d'IMAP qu'il gère et notre RFC en normalise une nouvelle, UTF8=ACCEPT (section 3). En l'utilisant, le serveur proclame qu'il sait faire de l'UTF-8. Par le biais de l'extension ENABLE (RFC 5161), le client peut à son tour indiquer qu'il va utiliser UTF-8. Une fois que cela sera fait, client et serveur pourront faire de l'IMAP UTF-8. La section 3.1 détaille la représentation des chaînes de caractères UTF-8 sur le réseau.

Les nouvelles capacités sont toutes décrites dans la section 9 et enregistrées dans le registre IANA.

On peut désormais imaginer des boîtes aux lettres qui ne puissent être manipulées qu'en UTF-8. Les noms de ces boîtes doivent se limiter au profil « Net-Unicode » décrit dans le RFC 5198, avec une restriction supplémentaire : pas de caractères de contrôle.

Il n'y a bien sûr pas que les boîtes, il y a aussi les noms d'utilisateurs qui peuvent être en Unicode, et la section 5 spécifie ce point. Elle note que le serveur IMAP s'appuie souvent sur un système d'authentification externe (comme /etc/passwd sur Unix) et que, de toute façon, ce système n'est pas forcément UTF-8. Prudence, donc.

Aujourd'hui, rares sont les serveurs IMAP qui gèrent l'UTF-8. Mais, dans le futur, on peut espérer que l'internationalisation devienne la norme et la limitation à US-ASCII l'exception. Pour cet avenir radieux, la section 6 du RFC prévoit une capacité UTF8=ONLY. Si le serveur l'annonce, cela indique qu'il ne gère plus l'ASCII seul, que tout est forcément en UTF-8 (un tel serveur, en 2013, n'aurait guère de clients, puisqu'il ne peut plus interagir avec les anciens clients IMAP pré-Unicode...)

Outre les noms des boîtes et ceux des utilisateurs, cette norme IMAP UTF-8 permet à un serveur de stocker et de distribuer des messages dont les en-têtes sont en UTF-8, comme le prévoit le RFC 6532.

La section 7 expose le problème général des clients IMAP historiques. Un serveur peut savoir si le client accepte UTF-8 ou pas (par le biais de l'extension ENABLE) mais, si le client ne l'accepte pas, que peut faire le serveur ? Le courrier électronique étant asynchrone, l'expéditeur ne savait pas, au moment de l'envoi si tous les composants, côté réception, étaient bien UTF-8. Le RFC, après des années de discussions vives dans le groupe de travail EAI, n'impose pas une solution unique. Le serveur peut dissimuler le message problématique au client archaïque. Il peut générer un message d'erreur. Ou il peut créer un substitut, un ersatz du message originel, en utilisant les algorithmes du RFC 6857 ou du RFC 6858. Ce ne sera pas parfait, loin de là. Par exemple, de tels messages « de repli » auront certainement des signatures invalides. Et, s'ils sont lus par des logiciels différents (ce qui est un des avantages d'IMAP), certains gérant l'Unicode et d'autres pas, l'utilisateur sera probablement très surpris de ne pas voir le même message, par exemple entre son client traditionnel et depuis son webmail. C'est affreux, mais inévitable : bien des solutions ont été proposées, discutées et même décrites dans des RFC (RFC 5504) mais aucune d'idéale n'a été trouvée.

Je ne connais pas encore d'implémentation en logiciel libre mais il existe déjà, en Extrême-Orient, pas mal d'utilisateurs du courrier électronique en Unicode.

Notre RFC ne contient pas de résumé des différences avec son prédécesseur, le RFC 5738. Les principales sont à mon avis :

  • Plus de mécanisme de repli (downgrade) obligatoire. Les serveurs IMAP peuvent désormais choisir entre plusieurs stratégies, selon leur public, pour gérer les clients historiques, pré-Unicode.
  • Suppression de capacités IMAP spécifiques comme UTF8=USER pour les noms d'utilisateur et eux seuls. Désormais, un serveur IMAP internationalisé est complètement UTF-8 ou pas.
  • De même, plus de paramètre UTF-8 pour des commandes comme EXAMINE. Désormais, une fois qu'on est en UTF-8, on l'est complètement. Ce RFC est donc plus simple et plus court que son prédecesseur, ce qui est rare dans le monde de la normalisation !

Téléchargez le RFC 6855


L'article seul

RFC 6857: Post-delivery Message Downgrading for Internationalized Email Messages

Date de publication du RFC : Mars 2013
Auteur(s) du RFC : K. Fujiwara (JPRS)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF eai
Première rédaction de cet article le 12 mars 2013


Ce nouveau RFC normalise un mécanisme de repli (downgrade) lorsqu'un serveur POP ou IMAP a reçu des courriers entièrement internationalisés et qu'un client POP ou IMAP de l'ancienne génération, qui ne comprend pas les adresses en Unicode, veut récupérer ce courrier. Le mécanisme de ce RFC est plus complet (et plus complexe) que celui, concurrent, du RFC 6858.

Dans la première version du courrier électronique entièrement en Unicode (celle normalisée dans les RFC 5335 et suivants), il était prévu un repli effectué entre serveurs SMTP. Si un serveur détectait que le serveur suivant ne gérait pas la nouvelle norme, il se repliait automatiquement sur un format compatible. Ce mécanisme, spécifié dans le RFC 5504, était compliqué et fragile et a été abandonné dans la deuxième version du courrier électronique entièrement internationalisé, celle des RFC 6530 et suivants. Désormais, les seuls endroits où un repli (downgrade) peut se faire sont à l'expédition, dans le MUA (de manière non standardisée, c'est un problème d'interface utilisateur) ou bien par les serveurs POP ou IMAP, lorsqu'ils ont reçu un message internationalisé et découvrent après qu'un de leurs clients ne gère pas cette norme (chose qu'on ne peut pas savoir à l'avance). Les RFC 6856 et RFC 6855 ne définissent pas de mécanisme obligatoire pour ce cas. Ils prévoient plusieurs possibilités (rejeter les vieux clients, cacher le message, comme s'il n'avait jamais été reçu, etc) parmi lesquelles le repli automatique vers un format compatible. Un tel repli n'est jamais une solution satisfaisante (il fait perdre de l'information, on ne pourra pas toujours répondre aux messages en question) mais, dans certains cas, cela peut être la moins mauvaise solution. Pour éviter une prolifération de mécanismes de repli différents, donnant des résultats distincts, deux algorithmes de repli sont normalisés, un très simple à mettre en œuvre (et faisant perdre beaucoup d'information), dans le RFC 6858, et un plus proche de l'esprit du RFC 5504, qui respecte davantage le message original, essayant de garder le plus d'information possible (mais qui sera plus compliqué à programmer), celui de notre RFC 6857.

La grosse différence entre le courrier actuel, complètement internationalisé (RFC 6532), et la version immédiatement précédente (RFC 5322), est qu'il est désormais possible d'avoir de l'Unicode, encodé en UTF-8, dans tous les en-têtes, et y compris dans les adresses (on peut avoir From: stéphane@bortzmeyer.org ou From: المنصف@التحرير.تونس, qui étaient interdits dans le RFC 5322). Pour le reste du message, notamment le corps, le problème est réglé depuis longtemps par MIME. Mais ces en-têtes en Unicode ne sont pas compris par les vieux clients POP et IMAP et la question se pose donc : comment leur transmettre ?

La section 1.2 liste plusieurs solutions (en en oubliant une, qui était mentionnée dans d'autres RFC, cacher le message) : rejeter le message au moment de la distribution (si on sait qu'on a une majorité de clients anciens), envoyer un faux message qui dit qu'il y a intérêt à mettre à jour le client IMAP pour tout voir, ou bien effectuer un repli en transformant le message internationalisé en quelque chose de compatible, avec des en-têtes entièrement en US-ASCII. C'est cette dernière approche qui est choisie par notre RFC (et par son concurrent RFC 6858). Il reconnait pourtant qu'il n'existe pas de solution idéale à ce problème et que celle exposée ici est « la moins mauvaise ».

Donc, première opération, la plus importante, transformer (dégrader) les en-têtes, en section 3. (Les exemples sont tirés de l'annexe A du RFC, mais elle n'a malheureusement pas d'exemple avec les IDN.) La méthode est de diviser la valeur de l'en-tête en ses différentes composantes, et de transformer, dans chaque composante, l'UTF-8 dans l'encodage du RFC 2047. Cela marche bien pour des choses comme le nom affiché dans l'adresse, et c'est en général réversible (on ne perd donc pas d'information, mais le RFC ne mentionne pas ce point, pour ne pas susciter de faux espoirs ; voir le traitement des espaces par le RFC 2047 dans la section 6 de notre RFC). Ici, par exemple, le sujet et un en-tête inconnu ont été ainsi traités. L'original disait :

Subject: Qui télécharge de la musique vole un œuf et qui vole un œuf assassine les artistes
X-Hadopi: Ne pas lire ce message est une négligence caractérisée

Et la version après repli est :

Subject: =?utf-8?q?Qui_t=C3=A9l=C3=A9charge_de_la_musique_vole_un_=C5=93uf_et_qui_?=
 =?utf-8?q?vole_un_=C5=93uf_assassine_les_artistes?=
X-Hadopi: ?utf-8?q?Ne_pas_lire_ce_message_est_une_n=C3=A9gligence_caract=C3=A9ris?=
 =?utf-8?b?w6ll?=

On notera que c'est la forme actuellement utilisée par les MUA traditionnels, pour transmettre des caractères non-ASCII « déguisés » en ASCII. Le repli ramène donc à la situation antérieure au RFC 6532.

Deux exceptions : les noms de domaines et la partie locale des adresses. Les IDN sont réécrits en Punycode (RFC 3492) donc नईदिल्ली.भारत devient xn--o1b4de6ba0fj6h.xn--h2brj9c. Exception dans l'exception, cette traduction en Punycode n'est pas faite si la partie locale de l'adresse est elle-même en Unicode (voir l'exemple de M. Li plus loin).

Et une deuxième exception, plus sérieuse, les parties locales des adresses. On utilise aussi le RFC 2047 mais cette transformation est bien plus intrusive puisque le résultat ne sera pas, la plupart du temps, une adresse utilisable (le logiciel qui tenterait de répondre à un message qui a subi cette opération récupérer un avis de non-remise). Ainsi, नेहरू deviendra =?utf-8?b?4KSo4KWH4KS54KSw4KWC?= qui, typiquement, ne sera pas accepté par le serveur de messagerie indien... Cela s'applique pour tous les en-têtes qui peuvent contenir des adresses comme From:, To:, Cc:, etc.

Combinant ces deux exceptions, voici ce que deviendra l'adresse de M. Li, qui était :

From: 李@中国科学院.中国

et qui, après le repli, est :

From: =?utf-8?b?5p2OQOS4reWbveenkeWtpumZoi7kuK3lm70=?=

Joli, non ?

Lorsque l'opération fait perdre trop d'information, le serveur POP ou IMAP peut préserver l'ancien en-tête, globalement encodé en RFC 2047 (et non plus composante par composante), dans un en-tête dont le nom est préfixé par Downgraded-. Ainsi, avec un Message-ID:, il est globalement encodé (on ne cherche pas le nom de domaine, qu'il contient souvent) :

Message-ID: <50EF7C49.4060203@नईदिल्ली.भारत>

devient :

Downgraded-Message-ID: =?utf-8?b?PDUwRUY3QzQ5LjQwNjAyMDNA4KSo4KSI4KSm4KS/4KSy4KWN4KSy4KWALg==?=
 =?utf-8?b?4KSt4KS+4KSw4KSkPg==?=

Si on avait suivi l'autre algorithme, celui du RFC 6858, cet en-tête aurait tout simplement été retiré. Ces nouveaux en-têtes commençant par Downgraded- sont désormais enregistrés à l'IANA. Les en-têtes Downgraded-* expérimentaux du RFC 5504 sont officiellement abandonnés.

La deuxième opération, en section 4, concerne les parties MIME du message, et les messages encapsulés comme les accusés de réception de la section 6 du RFC 3461. Eux aussi contiennent de l'UTF-8 et doivent subir une opération de repli analogue.

La section 5, sur la sécurité, rappelle les limites de la méthode : on ne peut pas, en général, répondre aux messages ayant subi le repli (les adresses ont été massacrées), le message est plus difficile à analyser par le destinataire (il y a donc plus de possibilités de tromperie), les signatures DKIM sont presque à coup sûr invalidées (celles en PGP peuvent tenir bon, dans certains cas), etc.

Je ne connais pas encore d'implémentation de ce RFC particulier.


Téléchargez le RFC 6857


L'article seul

RFC 6883: IPv6 Guidance for Internet Content Providers and Application Service Providers

Date de publication du RFC : Mars 2013
Auteur(s) du RFC : B. Carpenter (Univ. of Auckland), S. Jiang (Huawei)
Pour information
Réalisé dans le cadre du groupe de travail IETF v6ops
Première rédaction de cet article le 8 mars 2013


Ce nouveau RFC sur IPv6 ne spécifie pas un protocole réseau mais rassemble simplement un ensemble de conseils pour les gens qui gèrent des serveurs Internet et qui veulent les rendre accessibles en IPv6. Bien sûr, en 2013, tous les serveurs devraient depuis longtemps être ainsi accessibles. Mais le déploiement d'IPv6 a pris du retard et ce RFC est une des nombreuses tentatives pour tenir la main des retardataires qui hésitent encore à traverser le gué.

Pourquoi faut-il une stratégie de déploiement IPv6 ? Pourquoi ne pas tout simplement se dire « Au diable les mines ! En avant toute ! » ? Parce que l'administrateur typique d'un serveur Internet pense à ses utilisateurs et il veut que l'introduction d'IPv6 ne rende pas les choses moins bonnes qu'en IPv4. Certaines techniques de transition et/ou de coexistence entre IPv4 et IPv6 ayant eu des effets négatifs, il est prudent de réfléchir et de ne pas se lancer aveuglément.

Comme indiqué plus haut, ce RFC ne concerne pas le pur utilisateur qui veut se connecter en IPv6, mais le gérant de serveurs, qui est un professionnel de l'hébergement, ou simplement une organisation qui gère ses propres serveurs (serveurs Web ou autres). Il n'est pas écrit pour l'expert IPv6 (qui n'apprendra rien de nouveau) mais pour l'administrateur système/réseaux de l'hébergeur de serveurs.

La stratégie recommandée par le RFC est celle dite de la « double pile » (RFC 6180), qui consiste à avoir à la fois IPv4 et IPv6 sur les serveurs. Comme on ne va pas déployer IPv6 instantanément partout, elle se subdivise en deux approches : de l'extérieur vers l'intérieur (on rend les serveurs externes accessibles en IPv6, peut-être via un relais comme décrit en section 7, puis on migre progressivement l'infrastructure interne) ou bien de l'intérieur vers l'extérieur (on passe l'infrastructure, les serveurs de base de données, les serveurs LDAP, etc, en IPv6, avant de petit à petit ouvrir IPv6 à l'extérieur). La première approche, de l'extérieur vers l'intérieur, a l'avantage qu'un bénéfice visible pour les utilisateurs est immédiat. Elle marche même si certains services internes sont coincés en IPv4 (par exemple une vieille application tournant sur un vieux système, indispensable à votre activité mais qu'on ne peut pas mettre à jour). Certaines organisations se vantent donc d'être accessibles en IPv6 alors qu'à l'intérieur, le déploiement du nouveau protocole est loin d'être achevé.

La deuxième approche, de l'intérieur vers l'extérieur, est surtout intéressante pour les organisations de petite taille (qui contrôlent tous les systèmes internes) ou récentes (qui n'ont plus d'AS/400 en production, et encore puisque même celui-ci a IPv6). Avec cette approche, l'activation d'IPv6 sur les serveurs externes sera simple, tout sera en place avant.

Le fournisseur de services doit aussi se rappeler qu'il ne contrôle pas les clients. Certains resteront en IPv4 pur pendant longtemps, d'autres seront double-pile et on verra sans doute apparaître bientôt des clients purement IPv6. Certains clients (les mobiles, par exemple) passeront même d'IPv4 à IPv6 au cours d'une seule visite sur le site Web.

Bref, le déploiement d'IPv6 nécessitera quelques études préalables, en vérifiant les capacités du logiciel déployé (cf. RFC 8504).

Maintenant, en route vers le déploiement. Première étape suggérée par le RFC, la formation (section 3). Aujourd'hui, rares sont les formations initiales qui mentionnent IPv6 (en France, la situation dans les IUT semble particulièrement mauvaise). C'est donc souvent dans l'entreprise qu'il faudra former les employés aux différences entre IPv4 et IPv6. Il faut surtout éviter le syndrome de l'expert IPv6 isolé. En 2013, tout professionnel IP doit connaître IPv6 aussi bien qu'IPv4. C'est donc la totalité du personnel informaticien qui va devoir progresser. Le RFC dit « everybody who knows about IPv4 needs to know about IPv6, from network architect to help desk responder ».

Le but est d'éviter des résultats ridicules comme ce réseau où, lors du déploiement d'IPv6, les adresses comportant les chiffres hexadécimaux entre A et F étaient soigneusement évitées, de peur de créer de la confusion chez les techniciens ! Évidemment, si on a des techniciens assez arriérés pour ne pas savoir gérer de l'hexadécimal, on a un problème... Autre anecdote embarrassante, cet employé du help desk qui parlait à un client de « one Pv6 » car il avait cru voir un 1 dans IPv6... L'un des buts de la formation est d'éviter ce genre de bavure.

L'approche du RFC est d'éviter de traiter IPv6 à part, par exemple d'avoir une procédure de remontée des problèmes différente pour IPv6, menant vers l'unique gourou IPv6. Plutôt qu'un « service IPv6 » spécialisé, le RFC recommande qu'IPv6 soit simplement traité comme IPv4.

Dernier point délicat sur la formation, le meilleur moment où la faire. Trop tôt, et elle sera oubliée lorsque le déploiement effectif commencera. Il faut donc essayer de la synchroniser avec le déploiement.

Ensuite, il faut obtenir une connectivité IPv6 (section 4). Elle peut être native (directement sur la couche 2, comme en IPv4) ou via un tunnel géré. Historiquement, bien des expérimentations IPv6 ont été faites en se connectant par un tunnel non géré et les résultats (en performances et en fiabilité) ont découragé beaucoup de gens de continuer avec IPv6. Le RFC recommande très fortement de ne pas perdre de temps avec les tunnels et de faire du natif. Toutefois, si on se connecte via un tunnel, cela doit être un tunnel géré (le RFC ne donne pas de noms mais c'est, par exemple, un service qu'Hurricane Electric offre très bien). Les solutions avec des tunnels automatiques, non gérés, comme 6to4 (que le RFC ne cite pas) sont à fuir.

Un tunnel géré a quand même des défauts : les performances seront inférieures, et la MTU réduite va mener à des problèmes pénibles à déboguer. Bref, le fournisseur de services ne devrait pas utiliser autre chose qu'une connexion native avant d'offrir un accès de production à ses services.

Notez que cela ne concerne que le fournisseur : on ne contrôle pas les clients et il faut donc se préparer à ce que certains utilisent des bricolages non fiables comme Teredo (cf. section 9).

Étape suivante (dans le RFC ; dans le déploiement, on peut paralléliser ces tâches), l'infrastructure IPv6 (section 5). D'abord, l'attribution des adresses. Comme en IPv4, on peut utiliser des adresses PI ou PA, selon ses besoins et selon la politique du RIR local. Si on utilise du PA, il faut se préparer à de futures renumérotations et, pour cela, bien relire le RFC 4192. Naturellement, si le fournisseur de service a hébergé ses services dans le cloud, il n'a pas le choix, il devra suivre la politique de l'hébergeur.

Pour gérer les adresses IPv6 locales, on peut utiliser un logiciel spécialisé, un IPAM. Pour distribuer les adresses aux machines, on peut le faire manuellement ou via un programme qui automatise partiellement la gestion du parc, comme Puppet ou Chef. Mais on peut aussi les distribuer par DHCP (RFC 8415). Le RFC suggère DHCP, car il facilitera une éventuelle renumérotation.

Plus exotique est la possibilité de ne pas avoir d'adresses statiques pour les serveurs mais de compter uniquement sur l'auto-configuration sans état d'IPv6 (SLAAC, RFC 4862), combinée avec des mises à jour dynamiques du DNS (RFC 3007). Dans ce cas, ce sont les noms des serveurs qui sont statiques, pas leurs adresses IP. Le RFC note bien que c'est une possibilité théorique mais que personne n'a encore essayé cela pour un grand réseau de production.

Pour la topologie du réseau (physique, via les câbles, ou logique, via les VLAN), le RFC recommande d'avoir la même topologie en IPv4 et IPv6. Ce n'est pas obligatoire mais cela facilitera grandement le débogage lorsqu'il y aura un problème.

Une fois les adresses attribuées, le routage : tous les protocoles de routage ont la capacité de router IPv6, même RIP (RFC 2080). La méthode la plus courante aujourd'hui est de déployer deux routages parallèles et indépendants, un pour IPv4 et un pour IPv6. Toutefois, deux protocoles de routage, IS-IS (RFC 5308) et OSPF (RFC 5838), ont la capacité de gérer les deux versions de manière intégrée, ce qui peut simplifier la gestion du réseau. (Pour OSPF, c'est encore très peu déployé, la plupart des sites OSPF font tourner deux routages parallèles.) Comme les concepts de routage sont les mêmes en IPv6 et en IPv4, il ne devrait pas y avoir trop de problèmes pour l'équipe qui s'en occupe.

Parmi les points qui risquent d'être différents en IPv6 figurera le cas où un site a plusieurs préfixes PA (un pour chaque fournisseur de connectivité). Il faudra alors soigner le routage pour éviter de faire sortir via le fournisseur A un paquet dont l'adresse source est prise dans le préfixe du fournisseur B : si A met en œuvre les filtrages recommandés par les RFC 2827 et RFC 3704, le paquet sera jeté.

C'est seulement lorsque tout est déployé et testé, au niveau adressage et routage, qu'on pourra envisager d'annoncer les adresses IPv6 des serveurs dans le DNS. Ne faites pas l'erreur d'un gros fournisseur de raccourcisseur d'URL qui avait fait cette annonce alors que son serveur ne marchait pas en IPv6 ! Ou comme l'avait fait Yahoo qui avait mis le AAAA sans configurer Apache.Testez donc d'abord (par exemple avec un nom spécifique comme ipv6.example.com, comme expliqué en section 9). Ensuite, mettez les enregistrements AAAA dans le DNS. Dès qu'ils seront publiés, le trafic arrivera.

Un équipement souvent placé devant les serveurs est le répartiteur de charge (section 6). Comme tous les intermédiaires, ils sont une source importante de problèmes. Après un long retard, la plupart gèrent aujourd'hui IPv6, mais il est important d'insister auprès des fournisseurs de tels équipements pour qu'IPv6 ait le même niveau de performance qu'IPv4.

Le logiciel sur les serveurs, maintenant (section 8). Dans les systèmes d'exploitation, il n'y a guère de problème, tout fonctionne en IPv6 depuis longtemps. C'est le cas des noyaux mais aussi des « grands » logiciels serveurs comme Apache, NSD ou Postfix. Mais les applications spécifiques, c'est une autre histoire, certaines ne sont pas forcément prêtes. Pour les applications client, le fait d'utiliser des noms de domaines au lieu des adresses IP aide beaucoup. Pour les serveurs, il peut y avoir des surprises, par exemple au moment de journaliser la requête, lorqu'on voudra enregistrer l'adresse IP du client. Des tests soigneux seront nécessaires.

Beaucoup de fournisseurs de service géo-localisent leurs utilisateurs. Dans ce cas, les bases de géo-localisation typiques comme GeoIP n'étant pas forcément prêtes pour IPv6, il y aura des problèmes, à moins de passer à une méthode de géolocalisation plus fiable que celle fondée sur l'adresse IP, par exemple avec la technique HELD du RFC 5985.

Lorsque le client change d'adresse IP (ce qui arrive avec les mobiles), il peut même changer de version d'IP. Si les cookies distribués sont liés à une adresse IP, il faudra en tenir compte.

On l'a vu plus haut, le fournisseur de service ne contrôle pas ses clients. Il peut tout à fait arriver que ceux-ci ont choisi des techniques de transition/coexistence entre IPv4 et IPv6 et que celles-ci soient peu fiables (par exemple Teredo). Avec l'approche recommandée dans ce RFC, la double pile, il n'y aura normalement pas de requêtes venant de NAT64 (RFC 6146). Mais on peut imaginer d'autres problèmes, y compris des doubles traductions, de v6 en v4 puis encore en v6, et que le serveur ne peut pas détecter.

Reste le cas des tunnels automatiques comme le 6to4 du RFC 3068. Le RFC 6343 donne plein de bons conseils pour limiter les dégâts. Les deux points importants, du côté du serveur, sont :

  • S'assurer que la détection de la MTU du chemin fonctionne (ce qui veut dire, en pratique, ne pas bloquer bêtement tout ICMP),
  • S'assurer que le serveur gère bien la négociation de la MSS de TCP (RFC 2923).

Mais l'hébergeur a un pouvoir limité : il peut vérifier que les paquets ICMP passent bien sur son réseau mais il ne peut rien garantir quant aux autres réseaux traversés. C'est pour cela que 6to4 est désormais abandonné (RFC 7526).

Certains fournisseurs de service ont donc choisi une approche plus violente en configurant leurs serveurs DNS pour ne pas envoyer les enregistrements AAAA au résolveur si celui-ci est dans un réseau dont on sait qu'il a des problèmes, notamment de PMTUd. Encore plus pessimiste, l'approche inverse où on n'envoie les AAAA qu'aux réseaux dont on sait qu'ils ont une connectivité IPv6 native correcte (Google avait utilisé ce mécanisme au début). Cette solution, décrite dans le RFC 6589, est coûteuse en temps (il faut gérer la liste noire ou la liste blanche) et pas tenable sur le long terme.

Malheureusement, les pouvoirs du fournisseur de service s'arrêtent là. Il ne contrôle pas la chaîne complète jusqu'au client et ne peut donc pas garantir à celui-ci un vécu parfait. La voie la plus prometteuse semble être le déploiement progressif du mécanisme happy eyeballs (globes oculaires heureux) du RFC 6555.

Et si le fournisseur de service utilise des CDN (section 10) ? Cela peut marcher, avec IPv6 comme avec IPv4 si le fournisseur du CDN suit, comme celui du serveur principal, les recommandations de ce RFC. À noter que, le CDN étant géré par une organisation différente de celle qui gère le serveur original, on aura parfois, si le CDN est plus avancé, un contenu partiellement accessible en IPv6 alors que le serveur original n'a pas IPv6. Sinon, parmi les pièges spécifiques aux CDN, la synchronisation. Le contenu à servir est distribué à tous les nœuds du CDN via l'Internet et ce processus n'est pas instantané. Comme le contenu n'est pas forcément servi en IPv4 et en IPv6 par les mêmes machines, un visiteur peut avoir, pendant les périodes où la synchronisation est en cours, un contenu différent selon qu'il y accède en v4 ou en v6.

La section 12 rassemble ensuite une liste hétérogène de problèmes potentiels supplémentaires. Par exemple, comme vu plus haut dans le cas du CDN, un service moderne comprend typiquement plusieurs éléments, parfois hébergés à des endroits différents (pensez à une page Web contenant du JavaScript et du Flash stockés sur les serveurs de Google). Dans ce cas, le service peut être partiellement accessible en IPv6 sans même que son gérant ne s'en rende compte. Si le visiteur a des problèmes de connectivité IPv6, les équipes du fournisseur de service risquent de ne pas comprendre tout de suite ce qui se passe en cas d'« IPv6 involontaire ».

C'est donc l'occasion de rappeler (section 13) que le déploiement d'IPv6 n'est pas juste un coup sans lendemain, qu'on pourrait sous-traiter, en « mode projet » : au contraire, il faut assurer la maintenance et le fonctionnement opérationnel dans le futur. Cela n'a rien d'extraordinaire et ne nécessite pas de compétences surhumaines. Il existe des réseaux et des sites en double pile depuis de nombreuses années. Mais il faut le faire.

Un exemple parmi d'autres : il est important d'assurer la supervision aussi bien en IPv6 qu'en IPv4. Cela concerne bien sûr les réseaux (pinguer les adresses IPv6 comme les adresses IPv4) mais aussi les services (si un service a été accidentellement lancé sans écoute en IPv6, il faut que cela soit détecté). À noter que, avec la plupart (peut-être tous) les logiciels de supervision existants, tester des machines ou des services qui écoutent sur plusieurs adresses IP (que celles-ci soient une adresse v4 et une adresse v6 ou bien plusieurs adresses v4) est souvent un peu pénible et pas vraiment prévu. Par exemple, avec Icinga, il faut mettre explicitement deux tests, un en IPv4 et un en IPv6, le programme de test ne testant qu'une seule des adresses du service. Si on ne fait pas attention, on risque donc de se rassurer en voyant l'écran vert du logiciel de supervision, sans avoir perçu que le service ne marchait plus en IPv6 (ou en v4, selon le cas).

Et la sécurité (section 14) ? Elle est évidemment aussi importante en IPv6 qu'en IPv4 mais on manque encore d'expérience. En pratique, début 2013, très peu d'attaques sont lancées en IPv6 (elles bénéficient par contre d'une exposition médiatique démesurée, justement parce qu'elles sont rares). Cela ne durera pas éternellement et les responsables réseaux et systèmes doivent donc se préoccuper de ces risques. En gros, comme IPv6 est uniquement une nouvelle version d'IPv4, fondée sur les mêmes concepts, la quasi-totalité des risques présents en IPv4 (de l'attaque par déni de service aux tentatives de se connecter au serveur SSH) existent en IPv6.

Aujourd'hui, il est difficile de répondre simplement à une question comme « est-ce plus dangereux en IPv6 ? » Comme on l'a vu, il y a beaucoup moins d'attaques. Mais les défenses sont également moins bonnes : il est fréquent qu'une organisation soit protégé par un pare-feu en IPv4 mais que tout le trafic IPv6 passe librement. En fait, aujourd'hui, aussi bien les attaquants que les défenseurs ne prennent guère en compte IPv6. On a donc un équilibre... instable. Sur ce sujet de la sécurité d'IPv6, on peut consulter mon exposé à l'ESGI.


Téléchargez le RFC 6883


L'article seul

Un exemple du forçage des TTL DNS

Première rédaction de cet article le 7 mars 2013


Le DNS ne marche que parce que les données sont conservées dans les caches par les résolveurs. Autrement, si chaque requête remontait aux serveurs faisant autorité, ceux-ci souffriraient beaucoup. Combien de temps le résolveur peut-il garder l'information dans les caches ? C'est le serveur faisant autorité qui choisit, via le champ TTL de la réponse. Certains abusent en mettant des TTL très bas, poussant d'autres à ne pas les respecter.

Voici un exemple d'une requête DNS avec dig, montrant le TTL :

% dig @ns1.fdn.org MX fdn.fr
...
;; ANSWER SECTION:
fdn.fr.			86400	IN	MX	20 mx2.fdn.fr.
fdn.fr.			86400	IN	MX	10 mail.fdn.fr.
...

Le TTL est ici de 86 400 (secondes, soit une journée). C'est ce que sert ns1.fdn.org, qui est un des serveurs faisant autorité pour fdn.fr. Sur le résolveur, le TTL sera égal ou inférieur puisqu'il vaut la valeur originelle, au début, puis diminue avec le temps. Sur le résolveur de ma machine :

% dig MX fdn.fr
...
;; ANSWER SECTION:
fdn.fr.			4250	IN	MX	20 mx2.fdn.fr.
fdn.fr.			4250	IN	MX	10 mail.fdn.fr.

Ici, l'information est dans le cache depuis 22 heures (86 400 secondes - 4 250).

Jusqu'ici, tout va bien. Le problème est que certains gérants DNS mettent des valeurs ridiculement basses, en général parce qu'ils n'ont pas compris à quoi servaient les caches, et qu'ils fantasment sur une information distribuée en temps réel. On voit ainsi des TTL de moins d'une minute, par exemple pour dyn.com :

% dig @ns1.p01.dynect.net. A dyn.com
...
;; ANSWER SECTION:
dyn.com.		30	IN	A	134.0.76.51

C'est très bas. C'est très égoïste puisque cela va augmenter le trafic réseau.

On voit aussi des administrateurs de résolveurs DNS qui répondent en violant le protocole DNS. Ce dernier est normalisé dans le RFC 1034 (le TTL est décrit dans sa section 3.6). Un résolveur peut garder l'information en cache moins longtemps que le TTL (par exemple s'il redémarre, le résolveur typique perd tout). Il existe aussi des options des logiciels serveurs pour imposer un TTL maximal, pour économiser la mémoire (max-cache-ttl dans BIND, cache-max-ttl dans Unbound). Mais BIND n'a pas d'option pour mettre une valeur minimale, et pour cause, ce serait une violation du protocole : le TTL est fixé par le serveur faisant autorité, le résolveur n'a normalement pas le droit de le prolonger.

Certains, pourtant, ont modifié leur logiciel pour le faire. Voici le résolveur d'une Freebox :

% dig A dyn.com
...
;; ANSWER SECTION:
dyn.com.		823	IN	A	134.0.76.51

823 est supérieur à 30. Le TTL a donc été remonté à une valeur non décidée par le serveur faisant autorité et va donc rester dans le cache plus longtemps que souhaité par le gérant de dyn.com. (Le résolveur de la Freebox étant un dnsmasq, qui n'a pas non plus d'option pour cela, il s'agit sans doute d'une version localement modifiée. Notez qu'Unbound, lui, a une option pour forcer un TTL en ne respectant pas les valeurs indiquées, cache-min-ttl, merci à Laurent Frigault pour ce rappel.)

Il faut aussi savoir que les signatures DNSSEC protègent également le TTL (RFC 4034, section 3.1.4) et que ce forçage de TTL, comme toute modification non autorisée, peut potentiellement invalider les signatures (merci à Phil Regnauld pour avoir noté ce point).

À noter un article des gens de dyn.com expliquant leur choix. Merci à m0_o pour l'idée et les données.


L'article seul

Fabriquer sa bombe... sans chercher sur l'Internet

Première rédaction de cet article le 3 mars 2013


Comme l'Internet dérange beaucoup de gens (par exemple ceux habitués à la communication traditionnelle, strictement du haut vers le bas, des autorités vers un peuple passif), il a souvent été accusé de tout et n'importe quoi. Un des mèmes les plus répandus est l'idée qu'on trouve des recettes de bombe sur l'Internet. Eh bien, nul besoin de l'Internet pour cela, un numéro de 1906 de « La Vie Illustrée » (journal tellement oublié aujourd'hui qu'il n'a même pas sa page Wikipédia) le faisait déjà.

Dans ce numéro du 18 mai 1906, on trouve sous le titre « Chez les anarchistes - la fabrication d'une bombe » un article prétendant expliquer les recettes des anarchistes. N'y cherchez pas d'honnêteté intellectuelle ou de précisions. C'est uniquement du sensationnalisme, mais se présentant comme de la documentation. La photo de couverture illustre bien la démarche : anarchistes-bombe-small.jpg (Vous pouvez aussi en avoir une version agrandie.)

Alors qu'ils sont dans leur atelier, les deux terroristes ont pris soin de mettre un masque pour qu'on voit qu'ils sont des méchants (non, ce n'est pas pour se protéger contre les produits chimiques, leurs mains sont nues). Leur atelier ressemble aux photos de l'époque où Louis Pasteur ou Marie Curie travaillaient pour la science. Et le texte s'adresse au lecteur curieux de chimie car il cite plein de produits utiles pour faire une bombe (« mélangeons de la poudre de chlorate de potasse avec du sucre »).

Hypocritement, l'article cite même un débat très ancien en matière de sécurité : faut-il publier ces informations ? Et il note que les vrais terroristes connaissent déjà ces recettes.


L'article seul

RFC 6878: IANA Registry for the Session Initiation Protocol (SIP) "Priority" Header Field

Date de publication du RFC : Mars 2013
Auteur(s) du RFC : A. B. Roach (Mozilla)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF sipcore
Première rédaction de cet article le 2 mars 2013


Cet ultra-court RFC crée officiellement un registre pour stocker les valeurs possibles du champ Priority du protocole SIP.

Le RFC 3261, qui normalise le système de téléphonie sur IP SIP incluait un champ pour indiquer la priorité d'une communication (section 20.26 du RFC 3261). Quatre valeurs possibles étaient définies, non-urgent, normal, urgent et emergency, tout en précisant que d'autres pourraient l'être mais sans indiquer comment. Ce RFC 6878 comble ce manque.

Il y donc désormais :

  • Un registre à l'IANA de ces priorités, comportant les quatre valeurs indiquées,
  • Une politique d'enregistrement, suivant le RFC 5226. Cette politique est IETF Review, qui implique un RFC non-individuel (de façon à s'assurer un passage à l'IESG) mais pas forcément sur le chemin des normes.

Téléchargez le RFC 6878


L'article seul

RFC 6863: Analysis of OSPF Security According to KARP Design Guide

Date de publication du RFC : Mars 2013
Auteur(s) du RFC : S. Hartman (Painless Security), D. Zhang (Huawei)
Pour information
Réalisé dans le cadre du groupe de travail IETF karp
Première rédaction de cet article le 2 mars 2013


Le projet KARP (Keying and Authentication for Routing Protocols) vise à améliorer la sécurité des communications entre routeurs. La toute première étape est d'analyser l'état actuel de cette sécurité et ce RFC le fait pour le cas du protocole OSPF.

Il suit pour cela les principes posés dans le RFC 6518 dans sa section 4.2, « Work Items per Routing Protocol ». Le RFC 6039 avait déjà fait une telle analyse sous l'angle de la cryptographie. Des Internet-Drafts comme draft-ietf-rpsec-ospf-vuln ont été écrits sur des aspects plus généraux de la sécurité d'OSPF. Et des travaux ont déjà bien avancés pour améliorer cette sécurité (comme l'ajout de l'authentification à OSPF v3 dans le RFC 6506). Ce nouveau RFC 6863 couvre le reste.

D'abord, la gestion des clés. Celle-ci est manuelle, dans OSPF. C'est à l'administrateur réseaux de choisir les clés, de configurer les routeurs, de changer les clés en allant modifier chaque routeur, etc. Pour un protocole à gestion manuelle, OSPF est plutôt bon : l'intégrité des communications est protégée, le changement d'algorithme cryptographique est possible (ce que l'on nomme l'agilité cryptographique), la sécurité n'empêche pas de prioritiser certains paquets (comme les HELLO), etc.

Mais, par rapport aux exigences du RFC 6862, il reste quelque manques, et ce RFC a pour but de les lister. Par exemple :

  • OSPF utilise directement les PSK (voir le RFC 6862 pour le vocabulaire), les clés fournies. Il ne fait pas de dérivation, ce qui permet certaines attaques.
  • Les protections contre les attaques par rejeu sont inexistantes en OSPF v3 et insuffisantes en v2. Notez qu'il existe des attaques à l'intérieur d'une session OSPF établie (le RFC dit intra-connection) et d'autres en dehors d'une session (attaques inter-connections).
  • OSPF v3 n'avait pas d'autre sécurité qu'IPsec. Mais IPsec interfère sérieusement avec la prioritisation des paquets. On souhaite typiquement que les paquets HELLO, indispensables au maintien de la session, aient la priorité. Mais s'ils sont chiffrés avec IPsec, ce n'est plus possible, tous les paquets doivent être traités par IPsec, avant qu'on puisse les identifier et donc les prioritiser.
  • L'identification du voisin ne se fait dans certains cas qu'avec l'adresse IP, ce qui n'est pas suffisant pour la sécurité.

Si vous voulez un résumé de la sécurité dans OSPF, la section 2 du RFC est faite pour vous, elle détaille l'état actuel, et les faiblesses. Rappelez-vous qu'il existe deux versions d'OSPF en service, OSPF v2 (RFC 2328), probablement le plus fréquent dans la nature, et OSPF v3 (RFC 5340 et RFC 5838) qui n'a pas été un grand succès.

D'abord, OSPF v2. L'annexe D du RFC 2328 décrit son mécanisme de protection cryptographique. En gros, on prend la plupart des champs de l'en-tête du paquet (mais pas l'adresse IP), plus un secret, on les condense et on ajoute le MAC au paquet. À l'époque, la fonction de condensation était forcément du MD5. Le RFC 5709 a permis des algorithmes modernes comme la famille SHA-2. Notez que la cryptographie n'est pas sans défauts (section 7) : comme elle impose des calculs importants à des engins qui n'ont pas forcément de gros processeurs, elle fournit une voie d'attaque par déni de service. Des protections supplémentaires comme celle du RFC 5082, permettant d'empêcher un attaquant extérieur d'injecter des paquets, sont à considérer.

OSPF v2 a une protection limitée contre le rejeu. Les paquets comportent un numéro de séquence qui est croissant. Il n'est donc pas possible de rejouer un vieux paquet, son numéro de séquence trop bas le trahirait. Mais il y a quelques limites : la norme impose que le numéro ne décroisse jamais, mais n'oblige pas à l'incrémenter à chaque paquet. Et elle ne précise rien sur le numéro initial (au démarrage du routeur) donc certains risquent de choisir un numéro initial identique à chaque démarrage (par exemple, avoir un numéro de séquence qui soit purement et simplement le nombre de secondes écoulées depuis le démarrage du routeur est tout à fait compatible avec la norme, mais très peu sûr). Autre piège, l'adresse IP n'est pas incluse dans la somme de contrôle, donc un attaquant peut copier un paquet envoyé par un pair, changer l'adresse IP et se faire ainsi passer pour un autre pair.

Par contre, OSPF v2 est tout à fait satisfaisant pour ce qui concerne le remplacement des clés. Les clés ont un identificateur, et des durées de vie explicitement indiquées (annexe D.3 du RFC 2328, qui permet d'accepter une nouvelle clé avant de l'utiliser soi-même), ce qui permet de faire des remplacements propres des clés.

Et OSPF v3 ? Malgré son numéro de version supérieur, il était plutôt moins bien placé, question sécurité. L'idée avait été de ne plus mettre de fonctions de sécurité dans OSPF, mais de compter sur IPsec pour tout (RFC 4552). IPsec fournissait tous les services demandés (et même d'autres comme la confidentialité), avec les caractéristiques souhaitées (comme l'agilité cryptographique). Mais IPsec ayant été très peu déployé, les sessions OSPF v3 se retrouvaient en pratique toutes nues. (Il y avait aussi des problèmes moins graves comme le fait que le chiffrement IPsec empêchait de prioritiser certaines paquets OSPF, puisqu'il fallait tout déchiffrer dans l'ordre d'arrivée avant de savoir lesquels étaient prioritaires. Même sans chiffrement, les techniques d'encapsulation d'IPsec rendaient l'analyse des paquets entrants difficile.)

La section 3 revient plus en détail sur les problèmes de rejeu. Aucune des deux versions d'OSPF n'est parfaite sur ce plan mais OSPF v3 est nettement plus vulnérable.

Après cet examen de l'existant, la section 4 résume ce qui manque à OSPF :

  • Meilleure protection contre le rejeu,
  • Inclure l'en-tête IP, notamment l'adresse source, dans la partie protégée du paquet,
  • Fournir une solution d'authentification à OSPF v3, ne nécessitant pas IPsec (cela a été fait dans le RFC 6506).

La section 5 pose ensuite les étapes du travail :

  • Spécifier un mécanisme où le numéro de séquence est séparé en deux parties, une stockant un nombre qui s'accroit à chaque redémarrage du routeur (et doit donc être stocké sur un support stable, ce qui n'est pas évident pour tous les routeurs) et une strictement croissante depuis le démarrage. Cela garantira que le numéro de séquence ne décroit jamais, même en cas de redémarrage.
  • Décrire un mécanisme de dérivation de clés, de manière à éviter qu'une clé utilisée pour OSPF et un autre protocole ne fasse tomber les deux protocoles, en cas de compromission.
  • Et divers autres mécanismes à normaliser (ce travail est déjà bien avancé, dans l'Internet-Draft ietf-ospf-security-extension-manual-keying).

Téléchargez le RFC 6863


L'article seul

RFC 6862: Keying and Authentication for Routing Protocols (KARP) Overview, Threats, and Requirements

Date de publication du RFC : Mars 2013
Auteur(s) du RFC : G. Lebovitz, M. Bhatia (Alcatel-Lucent), B. Weis (Cisco Systems)
Pour information
Réalisé dans le cadre du groupe de travail IETF karp
Première rédaction de cet article le 2 mars 2013


Le groupe de travail KARP de l'IETF travaille sur une partie bien spécifique du vaste programme de la sécurisation du routage sur l'Internet : il s'occupe de l'authentification réciproque des routeurs et de comment l'améliorer. Ce RFC fait l'analyse des menaces pesant sur cette authentification et expose le cahier des charges pour les nouveaux RFC qui vont s'attaquer à ces menaces (le premier RFC du groupe KARP, le RFC 6518, le recouvre partiellement mais se focalisait sur les tâches à long terme à accomplir).

Ce RFC 6862 ne spécifie pas un nouveau protocole, il sert de base au travail concret que le groupe KARP a désormais entamé. D'abord, l'analyse des menaces : comme le documente la section 8.1 du RFC 4948 (le compte-rendu d'un atelier sur le trafic Internet non sollicité), la meilleure solution pour un méchant qui veut perturber l'activité des autres est souvent de s'attaquer aux routeurs. Le RFC 4593 détaillait les attaques contre les protocoles de routage, et le RFC 6039 dénonçait le fait que les mécanismes de sécurité existant dans les routeurs étaient bien primitifs, par exemple parce qu'ils ne permettaient pas de changer les clés sans perturber sérieusement le fonctionnement du réseau (ce qui casserait les SLA), avec le résultat que bien des opérateurs ne changent jamais ces clés. (On peut aussi consulter le RFC 4949, un glossaire de la sécurité sur l'Internet.)

Quels sont les protocoles de routage concernés ? BGP, OSPF, IS-IS, LDP et RIP ont tous déjà des mécanismes cryptographiques de protection de la communication entre routeurs. Le but du projet KARP est d'améliorer ces mécanismes, pour lesquels il existe déjà du code qui tourne et de l'expérience opérationnelle, pas de les jeter et de les remplacer (principe dit « crawl, walk, run », autrement dit, ramper lorsqu'on n'a pas le choix, marcher si on peut, courir dans le meilleur des cas ; c'est tiré d'une citation célèbre de Martin Luther King). KARP est donc un projet incrémental (section 2.2). Parmi les raisons qui ne permettent pas d'envisager un passage à court terme vers des solutions radicalement différentes, avec de la cryptographie forte, partout, il y a le fait que les routeurs actuellement déployés ont des capacités matérielles très variables, par exemple, ils n'ont pas forcément d'accélérateur cryptographique. D'une manière générale, KARP essaie d'être réaliste et de coller aux témoignages des opérateurs, tels qu'exprimés dans le rapport Arbor.

Ce rapport note, par exemple, qu'aucun des opérateurs interrogés n'utilise IPsec entre ses routeurs (alors qu'il résoudrait un bon nombre des problèmes de sécurité de KARP). Par contre, 70  % utilisent les mots de passe MD5 sur les sessions BGP externes et 55 % sur les internes. Les clés sont très peu changées (des clés de plus de cinq ans sont courantes), en raison des conséquences (en BGP, changer la clé coupe la session, faisant osciller les routes) et des difficultés opérationnelles que cause leur changement (il faut se concerter avec le pair dont, bien souvent, on n'a plus les coordonnées, puis organiser le changement pile au même moment). Tout ceci pour un ROI nul. La décision du PHB est donc vite prise : on ne change pas les clés.

Le rapport Arbor cite même un opérateur qui utilisait la même clé pour tous ses clients et, à ceux qui s'inquiétaient de la sécurité et demandaient une clé spécifique, répondait que ce n'était pas possible. C'est gonflé, mais cela simplifiait beaucoup la vie de cet opérateur.

Ce travail de KARP, comme décrit dans le RFC 6518, aura deux phases :

  • La phase 1 portera sur cette amélioration de l'existant,
  • La phase 2 portera sur un protocole de gestion de clés.

Un bon exemple d'amélioration par déploiement incrémental a été pour BGP, où l'antédiluvien mécanisme de sécurité du RFC 2385 a d'abord été remplacé par l'AO (Authentication Option) du RFC 5925, alors même qu'il n'existait pas encore de protocole de gestion de clés, que plusieurs cryptographes estimaient indispensable. AO résout une partie des problèmes des mots de passe MD5 (notamment l'agilité cryptographique, la possibilité de changer d'algorithme) mais n'essaie pas de tout résoudre d'un coup.

Un peu de vocabulaire au passage : une KDF (Key Derivation Function) est une fonction qui génère une clé à partir d'une autre clé et de données diverses. Par exemple, une KDF possible est de concaténer la clé de départ (clé de dérivation) et une adresse IP, puis de condenser cryptographiquement le tout.

Un KMP (Key Management Protocol, le protocole qui fera l'objet de la phase 2) est un protocole de gestion de clés cryptographiques, permettant leur distribution aux routeurs. Le but d'un KMP est de permettre le changement relativement fréquent des clés (à l'heure actuelle, le changement des clés dans les protocoles de routage est manuel : comme c'est une opération pénible, elle n'est en général pas faite et les routeurs gardent en général les mêmes clés toute leur vie).

Une PSK (Pre-Shared Key) est une clé secrète partagée entre N routeurs, par exemple les mots de passe d'OSPF v2 ou bien les « mots de passe MD5 » de BGP. En l'absence de KMP, elles sont distribuées manuellement (copier-coller dans un terminal virtuel, par exemple).

Une bonne analyse de sécurité nécessite d'être conscient des capacités de l'adversaire. Première catégorie, les attaquants extérieurs à l'organisation (outsiders, section 3.1.1). Ils n'ont pas les clés. Notre RFC fait une distinction importante entre les attaquants extérieurs mais situés sur le chemin entre deux routeurs (on-path attackers) et ceux situés en dehors (off-path attackers). Les premiers peuvent écouter le trafic et injecter des paquets qui seront indistinguables des vrais. Les seconds ne peuvent pas écouter le trafic, peuvent parfois injecter des paquets mais, comme ils travaillent en aveugle, ils auront beaucoup plus de mal à les faire accepter comme authentiques. Le méchant situé sur le chemin (le plus dangereux) peut donc :

  • rejouer des vieux paquets (qui pouvaient être signés pour l'authentification),
  • insérer des paquets,
  • changer des paquets.

Les méchants extérieurs, qu'ils soient sur le chemin ou pas, peuvent aussi tenter de découvrir un mot de passe par force brute, en essayant de se connecter avec plein de mots de passe courants. Ou essayer de découvrir les clés par des essais systématiques (qui peuvent réussir si la clé est trop courte.)

Deuxième catégorie, les attaquants qui ont réussi à avoir une clé (section 3.1.2). Un exemple typique est un ex-employé mécontent (le taux de rotation du personnel est élevé dans ce métier). C'est à cause d'eux qu'il faut changer régulièrement les clés : on ne peut jamais être 100 % sûr que la clé n'a pas fuité et il est donc nécessaire de ne pas l'utiliser éternellement.

Enfin, il y a les byzantins, les pires (section 3.1.3). Ce sont les participants légitimes qui, pour une raison ou une autre, trahissent. Cela peut être un routeur bogué, qui émet des paquets incorrects. Ou un routeur piraté par le méchant. Comme le projet KARP vise à une meilleure authentification des pairs, le cas d'un pair légitime, mais traître, n'est pas traité dans le cadre de ce projet. (Idem pour un routeur qui jouerait correctement les protocoles de routage, mais jetterait ensuite les paquets, créant un trou noir.)

Avec de telles capacités, même les autres attaquants peuvent causer beaucoup de dégâts. À noter que les attaques par déni de service utilisant les protocoles de routage font partie des menaces considérées par KARP, par exemple des paquets signés ou chiffrés qui entraînent des calculs cryptographiques lourds. Les attaques par déni de service volumétriques (pure force brute, on envoie plein de paquets ordinaires) ne sont par contre pas prises en compte par KARP. D'autres attaques par déni de service sont des objectifs de KARP. Par exemple, si on faisait tourner BGP sur TLS, pour le sécuriser, un attaquant sur le chemin pourrait toujours envoyer des paquets TCP RST (ReSeT) qui couperaient la connexion. KARP vise à empêcher aussi ce genre d'attaques. (Si l'attaquant en question n'est pas sur le chemin, et travaille donc en aveugle, cette attaque sera plus compliquée pour lui, voir le RFC 5961.)

Il y aussi trois « non-objectifs », que KARP n'essaie même pas d'atteindre :

  • Protection de la vie privée. Les sniffeurs purement passifs peuvent apprendre des choses, mais pas perturber le routage. Les sections 2.1 et 3.3 rappellent donc que la confidentialité est un non-but.
  • Vérification de la validité des messages. En effet, faire confiance à un routeur n'est pas la même chose que faire confiance au contenu de ses mises à jour. Les attaques comme celle de Pakistan Telecom dépendent donc d'un autre groupe de travail.
  • La non-répudiation des paquets par les routeurs.

Et les solutions ? KARP se propose de mieux sécuriser les communications entre routeurs (il existe déjà des tas de techniques, mais imparfaites). Cette amélioration doit être incrémentale (pas question de faire de la table rase).

Le cahier des charges du travail de KARP (la « phase 1 », l'amélioration de l'existant, est déjà largement entamée) est donc ici, sous forme d'une longue liste d'exigences (section 4 du RFC) :

  • Une meilleure description de ce qu'on protège,
  • Des algorithmes cryptographiques sûrs (MD5 doit être abandonné),
  • Une agilité de ces algorithmes, permettant leur remplacement (la question n'est pas de savoir si un algorithme cryptographique sera cassé mais quand),
  • Changement des clés (rekeying) sans casser les sessions en cours,
  • Mécanismes pour une utilisation plus sûre des PSK (secrets partagés),
  • Une sécurité par pair (et pas globale),
  • Possibilité d'utiliser aujourd'hui la gestion manuelle des clés (la seule réaliste actuellement) tout en permettant l'usage futur d'un KMP (protocole de gestion automatique des clés),
  • La compatibilité avec l'existant, si on veut avoir la moindre chance que ce soit déployé un jour.

Téléchargez le RFC 6862


L'article seul

RFC 6866: Problem Statement for Renumbering IPv6 Hosts with Static Addresses in Enterprise Networks

Date de publication du RFC : Février 2013
Auteur(s) du RFC : B. Carpenter (Univ. of Auckland), S. Jiang (Huawei)
Pour information
Réalisé dans le cadre du groupe de travail IETF 6renum
Première rédaction de cet article le 28 février 2013


Comment renuméroter (changer les adresses IP) le réseau d'une organisation ? Quels sont les obstacles techniques qui font que cette renumérotation est parfois difficile ? Ce RFC décrit le problème du renumérotage en IPv6 pour le cas des adresses statiques, le RFC 6879 fournissant des solutions pour les autres cas (le RFC 4192 fournissait déjà certaines pistes).

Le problème avait été posé par le RFC 5887 : changer les adresses IP sur un réseau local nécessite du travail, trop de travail. Peut-on faciliter la vie des administrateurs réseaux sur ce point ? C'est le travail du groupe 6renum de l'IETF dont voici le premier RFC. 6renum se focalise sur les réseaux IPv6 (en IPv4, la pénurie d'adresses rend le problème bien pire). Et ce RFC de description du problème se lmite au cas où les machines ont des adresses statiques, c'est-à-dire stables sur une longue période. Autrement, pour les adresses dynamiques, renuméroter est bien plus simple (en général, on redémarre les machines et c'est tout). Les Enterprise Networks dont parle le titre du RFC sont les réseaux assez grands et complexes pour avoir pas mal d'adresses statiques (le petit réseau de la maison ou du SOHO est en général 100 % en adresses dynamiques).

Notons qu'avec une autre architecture de réseau, par exemple une séparation de l'identificateur et du localisateur, le problème n'existerait pas. Mais, comme le note la section 3.2 du RFC 6250, l'Internet a commencé avec uniquement des adresses statiques (DHCP n'existait pas) et les programmeurs ont supposé certaines propriétés des adresses IP qui étaient vraies à l'époque mais ne le sont plus forcément aujourd'hui. C'est à cause de cela qu'il est parfois plus simple aujourd'hui d'avoir des adresses statiques, bien que les raisons de ce choix ne soient pas toujours incontestables :

  • Certains serveurs doivent être connus par une adresse IP, pas par un nom (c'est typiquement le cas des serveurs DNS),
  • Certains serveurs pourraient être identifiés par un nom, résolu via le DNS, mais l'administrateur ne maitrise pas assez le DNS et ne l'utilise pas (de mon expérience, c'était très fréquent encore au début des années 1990 mais aujourd'hui, cela me semble rare),
  • Une adresse statique facilite la gestion du parc des machines, et leur localisation, par exemple en cas d'incident de sécurité,
  • Certains mécanismes de licence logicielle sont fondés sur l'adresse IP (très mauvaise idée mais qu'on rencontre dans la nature),
  • Les équipements du réseau (par exemple les routeurs) ont souvent des adresses statiques, par exemple pour faciliter la supervision,
  • Les ACL et autres mécanismes de sécurité sont souvent basés sur des adresses IP fixes.

Attention, on parle bien d'adresses statiques, pas d'adresses manuellement affectées. Les adresses manuelles sont toujours statiques mais l'inverse n'est pas vrai : on peut attribuer des adresses statiques par DHCP, pour centraliser la configuration et éviter de modifier chaque machine.

La section 3 résume le problème à résoudre et l'approche proposée pour l'instant :

  • Éviter de désigner des machines par des adresses IP, utiliser les noms pour leur stabilité,
  • Avoir une gestion de configuration centralisée où, à partir d'une base de données centrale, les informations de configuration sont automatiquement calculées et poussées vers toutes les machines,
  • Utiliser les ULA du RFC 4193 pour le trafic purement interne,
  • Lorsqu'on renumérote, suivre les procédures du RFC 4192.

La section 2 analyse en détail chacun des points délicats. D'abord, pour avoir des adresses statiques, il faut aussi des préfixes IP statiques. Cela facilite certains diagnostics (« tous les gens qui se plaignent sont dans 2001:db8:199:ac:: donc il doit y avoir un problème de ce côté-là ») mais, en IPv6, ce n'est nullement obligatoire, les préfixes, comme les adresses, peuvent être entièrement dynamiques (d'autant plus que, contrairement aux préfixes IPv4, ceux d'IPv6 sont difficiles à mémoriser). Pour les petits réseaux, c'est certainement la meilleure solution.

Et les machines qui sont référencées par une adresse IP ? Pourquoi des gens font cela alors qu'ils pourraient utiliser le DNS, le SLP du RFC 2608 ou mDNS (combiné avec Service Discovery) ? C'est parce qu'utiliser des adresses IP peut représenter moins de travail pour les petites organisations que d'installer et de configurer un serveur DNS. Et SLP, comme mDNS, est largement implémenté mais très rarement déployé dans les réseaux d'« entreprise ». Bref, pas mal de gens numérotent l'imprimante 10.1.1.2 et communiquent cette adresse aux utilisateurs pour qu'ils l'entrent dans leur configuration. Cela empêche une renumérotation facile. Il n'est pas évident que cette pratique continue en IPv6, où les adresses sont nettement plus difficiles à communiquer (« Non, j'ai dit 2001 comme le film, deux points, non l'un au dessus de l'autre, pas un point suivi d'un autre, db8, oui, D comme Denise et B comme Béatrice... »).

Naturellement, il n'y a pas que les imprimantes : les serveurs ont souvent des adresses IP fixes. Il serait mieux que les serveurs soient accédés par leurs noms, pas par leurs adresses. Mais cela suppose de mettre à jour le DNS en cas de renumérotation, ce que certains ont du mal à faire. Du DNS mis à jour dynamiquement et de manière sécurisée (RFC 3007) serait peut-être une solution. Cela laisserait toutefois la question du TTL (RFC 4192).

Je le répète, adresse statique ne signifie pas forcément adresse manuellement configurée quelque part sur le serveur. On peut parfaitement distribuer des adresses statiques avec DHCP. Si la zone DNS et la configuration DHCP sont dérivées automatiquement de la même base de données, la cohérence est assurée. C'est une bonne pratique, comme indiqué plus haut : nul besoin d'usines à gaz, un fichier plat et un script Python de quelques lignes suffisent. Sans cette pratique, il faut se connecter à chaque serveur pour changer sa configuration (ou bien utiliser des systèmes comme Ansible ou peut-être Chef).

Les routeurs et autres composants du réseau (comme les commutateurs) sont également souvent numérotés de manière fixe. Comme ils sont essentiels au bon fonctionnement du réseau, ils sont en général sous supervision. Cela rend difficile la renumérotation car il faut alors changer la configuration de Nagios ou de son équivalent. Il y a une école qui défend l'idée d'adresses ULA (RFC 4193) pour tous ces éléments de l'infrastructure, de manière à les préserver contre la renumérotation.

On l'a vu, une autre raison importante pour laquelle les administrateurs réseaux utilisent des adresses IP statiques est la gestion de parc. L'adresse IP sert alors d'identificateur pour la machine, simplifiant certaines procédures. L'IDS dit que 2001:db8:21:1::1:134 fait plein de connexions vers le port 25 ? On retrouve facilement de quelle machine il s'agit. Notons toutefois qu'aujourd'hui, même dans les réseaux qui ont une telle pratique, les machines connectées en WiFi y échappent, et ont des adresses dynamiques.

À noter que les bons conseils de la section 3 laissent ouverts quelques problèmes :

  • Même en suivant tous ces conseils, les sessions de très longue durée (SSH, par exemple) seront coupées. Est-ce acceptable ?
  • Est-ce que la rénumérotation des éléments du réseau (comme les routeurs) sans couper les sessions utilisateur est possible ?

Téléchargez le RFC 6866


L'article seul

RFC 6879: IPv6 Enterprise Network Renumbering Scenarios, Considerations and Methods

Date de publication du RFC : Février 2013
Auteur(s) du RFC : S. Jiang, B. Liu (Huawei Technologies), B. Carpenter (University of Auckland)
Pour information
Réalisé dans le cadre du groupe de travail IETF 6renum
Première rédaction de cet article le 28 février 2013


Ce RFC ne normalise pas un protocole mais a pour ambition de servir de guide lors de la rénumérotation d'un réseau IPv6. Pourquoi renuméroter ? Et comment ? Les administrateurs réseaux ont tout intérêt à le lire, et de préférence avant la renumérotation et même avant la mise en production du réseau, pour ne pas mettre dans l'architecture de celui-ci des éléments qui gêneront les renumérotations futures.

C'est le deuxième RFC du groupe de travail 6renum qui planche sur les scénarios de renumérotation de réseaux IPv6, ainsi que sur les moyens de rendre ces renumérotations plus faciles. Ce RFC particulier se focalise sur le cas d'une organisation de taille significative : ni un SOHO, ni un opérateur réseau, un client de taille moyenne qui a IPv6 sur son réseau local, une ou plusieurs connexions à l'Internet et au moins un employé chargé d'administrer le réseau (cf. RFC 4057).

La seule façon d'être sûr de ne jamais renuméroter serait de n'utiliser que des adresses PI. Mais, comme le note le RFC 4116, cela aurait des conséquences quantitatives néfastes pour BGP. Donc, on part du principe que l'organisation aura à renuméroter un jour. Lisons les prérequis (RFC 4192 et RFC 5887) et allons-y.

Les machines reçoivent des adresses IP dynamiques (si elles ont des adresses statiques, le problème est plus compliqué, et c'est le domaine du RFC 6866). Pour cela, on utilise DHCP ou les annonces des routeurs (SLAAC).

Mais pourquoi renumérote-t-on ? Pourquoi s'embêter dans cette opération au lieu de se contenter de garder ses adresses actuelles ? La section 3 décrit plusieurs scénarios déclencheurs. Certains peuvent être externes, d'autres internes. Parmi les externes :

  • Passage à un nouveau FAI qui a d'autres adresses pour ses clients. Idéalement, il y aura une période de recouvrement pendant laquelle l'organisation sera connectée par les deux FAI. Si ce n'est pas possible, il y aura un flag day où il faudra tout basculer d'un coup.
  • Renumérotation chez le FAI, soit parce que lui-même a changé de fournisseur, soit parce qu'il a réorganisé son réseau.
  • Ajout d'un deuxième FAI, pour une organisation qui n'en avait qu'un et qui souhaite davantage de redondance. Les anciennes adresses ne changent pas mais de nouvelles s'y ajoutent.

Et les causes internes ?

  • Réorganisation de l'organisation : fusion, acquisition, ou autre événement business qui a des conséquences sur le réseau.
  • Réorganisation technique du réseau.

La section 4 décrit ensuite les méthodes existantes pour faire ces renumérotations avec le moins de douleur possible. Parmi les mécanismes qui peuvent aider, il ne faut pas oublier la délégation de préfixe IP (RFC 8415 et RFC 6603), qui permet à un routeur d'informer d'autres routeurs sur les préfixes qu'ils vont devoir gérer (annoncer avec des RA, router, etc). Ainsi, on n'aura pas à reconfigurer tous les routeurs. Autre mécanisme important, l'utilisation de noms de domaine le plus souvent possible, car ils sont plus stables que les adresses IP. Par exemple, pour IPsec, nul besoin de configurer en utilisant des adresses, des noms peuvent être utilisés (RFC 5996), simplifiant ainsi beaucoup les futures renumérotations. (Pour les réseaux sans serveur DNS, le RFC rappelle l'existence de Multicast DNS, RFC 6762.) De même, les applications devraient aussi utiliser des noms et pas des adresses. Configurer une application avec une adresse IP, c'est placer une bombe qui explosera lors de la prochaine renumérotation du réseau.

Mais les adresses IP peuvent se cacher en d'autres endroits, comme dans les ACL des pare-feux. Au minimum, ces configurations devraient être paramétrisées : on n'utilise l'adresse IP qu'une fois, pour lui donner un identificateur, puis on se sert de cet identificateur partout (des outils comme m4 ou cpp peuvent être utilisés pour cela). C'est le B A BA de l'administration réseaux, mais ce n'est pas toujours fait.

Pendant qu'on parle d'adresses IP qui traînent, il ne faut évidemment pas mettre dans ses configurations des adresses IP d'autres sites. Sinon, lorsqu'ils renuméroteront, ils ne penseront sans doute pas à vous prévenir...

Un truc plus exotique est l'utilisation d'ULA, des adresses IP locales (RFC 4193). L'idée est de tout numéroter avec les ULA et d'effectuer une traduction d'adresses ou un relayage dans les routeurs de sortie. Ainsi, la renumérotation n'impacte que ces routeurs. Les ULA sont donc une sorte de substitut aux adresses PI.

Continuons avec les techniques utilisées sur le réseau local : comment les adresses IP arrivent-elles aux machines terminales ? En IPv6, il y a deux solutions, SLAAC (RFC 4862) et DHCP (RFC 8415). Ce RFC ne tranche pas entre les deux : du point de vue de la renumérotation, ils ont à peu près les mêmes possibilités. (DHCP a une option, RECONFIGURE qui permet, si le client DHCP la gère, de faire des renumérotations imprévues.)

Et le DNS ? Un petit site ne gère pas forcément ses propres serveurs DNS. Leur reconfiguration pourra nécessiter une coordination avec l'hébergeur DNS. Ce que le RFC recommande, c'est de ne pas le faire manuellement. Le fichier de zone édité avec vi et contenant les adresses IP de toutes les machines de l'organisation, c'est un mécanisme archaïque, et, en 2013, on doit normalement mieux faire : soit les données DNS sont dérivées automatiquement d'une base de données de machines (cela n'a pas besoin d'être une usine à gaz, cela peut être un simple script Perl/Python/Ruby), soit les machines (ou les serveurs DHCP) mettent à jour le DNS automatiquement avec les mises à jour dynamiques (RFC 3007).

Une fois qu'on a fait le tour de son réseau et des techniques utilisées, il faut se préparer, et planifier soigneusement. D'abord, diminuer la durée de vie des annonces d'adresses pour que la transition soit la plus courte possible et que les vieilles adresses ne trainent pas dans les caches. Avec l'autoconfiguration sans état (SLAAC), on ne peut pas réduire la durée de vie des annonces à moins de deux heures, il faudra faire avec. D'autre part, cette diminution va évidemment augmenter le trafic et il ne faut donc pas la faire des semaines à l'avance. Une telle durée de vie est stockée dans les enregistrements DNS (qu'il faut donc ajuster), mais aussi dans les annonces indiquant le résolveur DNS à utiliser (RFC 8106 pour SLAAC et RFC 3646 pour DHCP, où il faut réduire la durée du bail, on ne peut pas réduire seulement la durée de vie de l'option DNS). À noter que les applications qui maintiennent des connexions sur de longues périodes (SSH, par exemple), n'ont pas de mécanisme propre pour gérer la renumérotation. Il faudra faire une déconnexion/reconnexion.

Bref, anticiper et planifier sont des nécessités.


Téléchargez le RFC 6879


L'article seul

Fiche de lecture : Congo - Une histoire

Auteur(s) du livre : David Van Reybrouck
Éditeur : Actes Sud
978-2-330-00930-4
Publié en 2012
Première rédaction de cet article le 25 février 2013


Ce livre est une histoire complète du Congo, commençant avec la préhistoire (et non pas, comme dans les cours d'histoire du Congo faits pendant la colonisation, avec l'arrivée des Européens...). Très bien documenté, passionnant à lire, c'est un exemple pour l'histoire de l'Afrique (qui est encore loin d'avoir fait l'objet d'autant de travaux que celle de l'Europe).

L'auteur a passé beaucoup de temps sur place, à parler avec les témoins (car les sources écrites d'avant l'indépendance sont presque toutes faites par les colons). Il a même rencontré un témoin qui prétend être né en 1882, avant la colonisation et qui a en tout cas des tas de récits intéressants. Parce que le Congo a eu une histoire compliquée. Lors de la mainmise belge sur le pays, le Congo n'était pas une colonie mais un État indépendant... dont le roi se trouvait être également roi des Belges. Ce dernier, Léopold II, était à Bruxelles un monarque constitutionnel, obligé de tenir compte du parlement, des lois... Mais, en Afrique, il pouvait faire tout ce qu'il voulait, sans aucun contrôle, et ce fut un pillage et des massacres terribles.

La Belgique a fini par annexer l'État indépendant et les habitants ont été nettement mieux traités sous la colonisation officielle... (Au fait, l'auteur, un belge néerlandophone, ne mentionne pas une seule fois Tintin. Il préfère le point de vue des Congolais.)

Ensuite, le Congo a suivi la voie habituelle des pays colonisés. Ses soldats ont joué un rôle important (et largement oublié) pendant les deux guerres mondiales. Pendant la première, ils ont repoussé les troupes allemandes venues de l'Est. Il y a peu de témoins de cette époque sauf la voix d'un soldat congolais, capturé par les Allemands et qui, à Berlin, a été l'objet d'une étude ethnologique avec enregistrement de ses récits dans sa langue maternelle. Une des rares traces du Congo de l'époque se trouve donc en Allemagne.

Et, pendant la seconde guerre mondiale, les soldats congolais ont combattu partout, en Afrique, certes, mais aussi jusqu'en Birmanie. Car, cette fois, il reste des témoins vivants et l'auteur en a retrouvé un, qui avait participé à cette campagne. L'un de ces anciens combattants lui a d'ailleurs confié « c'est la première fois qu'un blanc me demande mes souvenirs de la guerre ».

Puis ce fut l'indépendance et des nouveaux malheurs pour le Congo. Guerre civile, intervention massive de mercenaires aux ordres de telle ou telle puissance européenne ou américaine, dictature de Mobutu et guerre sur la frontière orientale, qui continue encore aujourd'hui.

Pour terminer sur une note plus positive, l'un des meilleurs chapitres du livre est celui où l'auteur a accompagné un groupe de marchands congolais en Chine. Un aspect de la mondialisation pas forcément connu en Europe est que le business se fait désormais entre l'Afrique et la Chine et que, comme le note l'auteur, à Kinshasa, la file d'attente pour les visas est désormais plus longue devant l'ambassade de Chine que devant celle de France.

Au cours de ce voyage, l'auteur entendra un Chinois parler lingala avec ses clients africains, discutera avec des Congolais installés en Chine et pouvant négocier en cantonais, et verra l'achat de nombreuses marchandises, dont plusieurs iPhone contrefaits, qui se retrouveront en vente au Congo. (Au passage, sur cette nouvelle route commerciale Afrique<->Chine, je recommande cet excellent article.)


L'article seul

RFC 6874: Representing IPv6 Zone Identifiers in Address Literals and Uniform Resource Identifiers

Date de publication du RFC : Février 2013
Auteur(s) du RFC : B. Carpenter (Univ. of Auckland), S. Cheshire (Apple), R. Hinden (Check Point)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF 6man
Première rédaction de cet article le 23 février 2013


Ce court RFC normalise la façon d'indiquer la zone dans un URI contenant une adresse IPv6 littérale.

Les zones sont définies et expliquées dans le RFC 4007. En gros, une adresse IPv6 n'est pas forcément globale, elle peut avoir une signification limitée à une seule zone, une zone étant un ensemble de sous-réseaux contigus, souvent composé d'un seul lien Ethernet. Les adresses locales au lien, par exemple, celles qui sont dans le préfixe fe80::/10, sont dans ce cas, le lien qui les relie forme une zone. Pour indiquer cette zone, la convention de mettre un %, puis l'identificateur de la zone, après l'adresse, est fréquemment utilisée. Mais elle n'était pas normalisée, dans le cas où l'adresse apparaissait dans un URI. Ce RFC répare ce manque.

Car il peut y avoir des adresses IP littérales dans un URI (section 3.2.2 du RFC 3986). Par exemple, http://[2001:db8:1::23]/ est un URI valide. (Et je viens de tester avec mon Firefox qui l'a accepté sans problèmes.) Mais, si cette adresse est locale à une zone ? D'habitude, on utilise la convention du % (décrite en section 11 du RFC 4007). Ici, sur une machine Linux récente (cela ne marchait pas autrefois, il fallait utiliser l'option -I) :

% ping6 -c3 fe80::21e:8cff:fe76:29b6%eth0
PING fe80::21e:8cff:fe76:29b6%eth0(fe80::21e:8cff:fe76:29b6) 56 data bytes
64 bytes from fe80::21e:8cff:fe76:29b6: icmp_seq=1 ttl=64 time=8.36 ms
64 bytes from fe80::21e:8cff:fe76:29b6: icmp_seq=2 ttl=64 time=4.97 ms
64 bytes from fe80::21e:8cff:fe76:29b6: icmp_seq=3 ttl=64 time=4.84 ms

--- fe80::21e:8cff:fe76:29b6%eth0 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 4.847/6.060/8.363/1.631 ms

On teste la machine fe80:1::23 reliée au réseau identifié par eth0 (dans le cas de Linux, c'est le nom d'une interface réseau mais d'autres systèmes d'exploitation peuvent utiliser une syntaxe différente, par exemple identifier les zones par un simple numéro). Cette possibilité de désigner une zone spécifique est essentielle pour les activités de débogage (M. Toutlemonde n'a sans doute jamais besoin d'URI incluant des adresses IP). Mais si on utilise un navigateur Web pour cette activité, comment mettre la zone ? Le RFC 4007 était muet à ce sujet. Certains navigateurs (par exemple certaines versions anciennes de Firefox) acceptaient des adresses suivies d'un pour-cent (alors que ce caractère est spécial dans les URI et que ces navigateurs violaient donc le RFC 3986).

Encore mieux, comme le RFC 4007 ne précise pas quels sont les caractères autorisés dans un identificateur de zone, on pourrait voir des zones avec un nom invalide dans un URI (comme / ou #).

La syntaxe standard normalisée par notre RFC est donc :

  • Mettre l'identificateur de zone après un pour-cent encodé (donc, %25, ce qui était déjà la méthode déployée par Internet Explorer),
  • Fortement conseiller de ne pas utiliser de caractères spéciaux dans les identificateurs de zone mais, si cela arrive, les encoder avec le système « pour-cent » du RFC 3986 (section 2.1),
  • Suivre les recommandations du RFC 5952 pour représenter l'adresse IPv6.

Pour faciliter la vie de l'administrateur réseaux, notre RFC recommande que les navigateurs acceptent un URI incluant un % tout nu, s'il est suivi d'au moins deux caractères qui ne peuvent pas être des chiffres hexadécimaux. Cela permet de copier-coller une adresse comme fe80::a%en1 dans le navigateur et que cela marche. (Par contre, fe80::a%ee1 ne serait pas accepté car E peut être un chiffre hexadécimal et il y aurait une ambiguité entre %ee et î, qui est encodé ainsi en notation pour-cent.) Cette opération de copier/coller sera sans doute le principal usage de ces URI comportant une adresse IPv6 et une zone : on ne voit pas bien dans quels cas ils se retrouveraient dans une page HTML, sauf peut-être produite automatiquement par des systèmes d'administration de réseaux (l'interface Web d'un routeur, par exemple).

Donc, désormais, http://[fe80::dead:beef%25en1] ou http://[fe80::1:2%25Ethernet%230] sont des URI légaux (dans le deuxième, le nom de la zone était Ethernet/0). Essayez-les sur votre navigateur !

Comme ces identificateurs de zone n'ont de signification que pour une machine donnée, les relais HTTP, par exemple, doivent les retirer des URI.

Voilà, c'est tout, les amateurs d'alternatives peuvent lire l'annexe A, consacrée aux raisons du choix qui a été fait. Il a l'avantage de ne pas changer le format des URI et les inconvénients qu'il n'est pas très joli, et que le copier/coller d'une console vers un navigateur ne marche pas toujours. Les autres possibilités considérées (les discussions ont été chaudes et longues) étaient :

  • Ne rien normaliser, en considérant que ping ou telnet depuis une console étaient plus pratique que d'utiliser un navigateur Web. C'était le choix le plus simple.
  • Entériner l'usage des % nus dans l'URI. Cela était cohérent avec le RFC 4007 et cela permettait le copier/coller mais cela produisait des URI illégaux.
  • Trouver un autre caractère que le % pour séparer l'adresse de la zone, par exemple le -, comme dans http://[fe80::a-ee1] (au passage, pourquoi pas un tiret bas ? parce que les navigateurs soulignent souvent automatiquement les URI, rendant le trait invisible). Mais une telle réforme du RFC 4007 aurait nécessité de changer tous les outils IPv6 et toutes les documentations.
  • Se servir de la production IPvFuture de la section 3.2.2 du RFC 3986 pour écrire, par exemple http://[v6.fe80::a-en1]. Mais cela ne permettait pas le copier/coller. (Et j'ajoute qu'aucun navigateur ne gère cette possibilité IPvFuture.)

Téléchargez le RFC 6874


L'article seul

RFC 6875: The P2P Network Experiment Council's Activities and Experiments with Application-Layer Traffic Optimization (ALTO) in Japan

Date de publication du RFC : Février 2013
Auteur(s) du RFC : S. Kamei (NTT Communications), T. Momose (Cisco), T. Inoue, T. Nishitani (NTT Communications)
Pour information
Première rédaction de cet article le 23 février 2013


Ce RFC décrit une expérience faite il y a quelques années au Japon pour tester l'efficacité des mécanismes de sélection de pairs dans un réseau pair à pair. Elle montre que cette sélection peut améliorer l'efficacité des protocoles pair à pair, une leçon utile pour le projet ALTO (Application-Layer Traffic Optimization, RFC 5693).

Le réseau pair à pair typique relie des machines, les pairs, qui peuvent être très éloignées les unes des autres. Les relations des machines entre elles ne correspondent pas forcément aux réalités de l'interconnexion. En bref, un pair risque de télécharger des données depuis un pair lointain alors qu'il en existait un plus proche. Des tas de propositions ont été faites pour un mécanisme de sélection des pairs, menant théoriquement à une plus grande efficacité. De 2007 à 2008, au Japon, le P2P Network Experiment Council a réalisé une série de mesures pour comparer théorie et pratique. Une intense répression sous les ordres de l'industrie du divertissement, avec plusieurs arrestations, a réduit l'usage du pair à pair dans ce pays depuis, sans toutefois réussir à le réduire à zéro.

Le Japon est souvent un cas à part et, à l'époque en question, le système de pair à pair le plus populaire n'était pas Bit Torrent mais Winny ou Share. Leur trafic total combiné était estimé à 40 % du trafic total. Pour l'opérateur de réseaux, le pair à pair (P2P) a donc un impact important et cela les motive pour chercher des économies, justement ce que promettent les techniques de sélection du pair. Parmi les autres solutions envisagées par les FAI : faire un effort pour placer le contenu très demandé plus près des utilisateurs (les CDN, par exemple), augmenter les prix, ou limiter autoritairement le trafic.

L'approche choisie par le P2P Network Experiment Council, organisme créé par le gouvernement japonais en 2006, était de tester les solutions de sélection du pair. Pour cela, le conseil a déployé un réseau de serveurs indicatifs (les oracles, selon la terminologie généralement utilisée chez les chercheurs de ce domaine), indépendants d'un système de P2P particulier et donnant des indications sur le meilleur pair.

La section 3 décrit plus en détail ce « conseil pour des expériences P2P ». Créé par le ministère des télécommunications, à la suite de débats sur des sujets comme la neutralité du réseau, il est documenté (en japonais) dans le rapport « Disclosure of the Report `Working Group on P2P Networks' » et placé sous l'égide d'une fondation (oui, encore un texte dans la langue de Naoki Urasawa). Outre les tests qui font l'objet de ce RFC, le conseil a une activité de promotion des bonnes pratiques en matière de P2P.

La section 4 de notre RFC décrit les expériences menées : au début, il n'y avait aucun doute sur les économies en matière de serveurs, lorsqu'on migre vers le pair à pair. Ainsi, l'entreprise Utagoe annonçait une réduction de 90 % de son trafic sortant en migrant vers leur système UGLive. Et TV Bank Corp a vu 80 à 96 % de gain avec BB Broadcast. Mais ce sont des gains pour les fournisseurs de contenu. Et pour les opérateurs réseau ? Il y a eu de études au Japon sur le trafic total (comme celle de Cho, Fukuda, Esaki et Kato). Mais étudier le comportement des applications réellement installées sur les utilisateurs demande des mesures fort intrusives, par exemple avec du DPI.

Le choix du conseil avait donc été d'installer des faux utilisateurs : des PC munis de logiciels P2P modifiés (pour demander à l'oracle) ont été placés dans les réseaux des FAI. On peut ainsi faire varier librement et facilement tous les paramètres de mesure (et, bien que le RFC ne le dise pas, cela évite tout problème lié à la vie privée). Le faux utilisateur est donc un PC avec CentOS, VMware et un Windows par dessus. Le système hôte CentOS peut ainsi observer tout le trafic sans déranger. 60 machines ont été installées chez 40 FAI.

La section 5 décrit l'oracle (hint server), le serveur qui va distribuer les indications. C'est l'équivalent du « serveur ALTO » dans le protocole ALTO (RFC 6708). Lorsqu'un pair démarre, il indique à l'oracle son adresse IP et des informations comme les caractéristiques de la liaison Internet utilisée. L'oracle, en utilisant des informations sur la topologie du réseau informations fournies par le FAI et une table de routage obtenue via BGP (l'oracle inclut un Quagga), peut alors envoyer au pair une table des meilleurs pairs possibles. Dans ce cas idéal, l'optimisation réalisée est presque parfaite. En pratique, l'oracle n'a pas forcément toute l'information nécessaire : le FAI, l'estimant confidentielle, a pu ne pas donner une information complète.

Pour prendre sa décision, l'oracle s'appuie sur :

  • La longueur du chemin d'AS entre le client et le pair potentiel (rappelez-vous que l'oracle participe à BGP),
  • La distance géographique entre ces deux pairs possibles. Ne connaissant par la longitude et la latitude de chaque machine, l'oracle fait une approximation : il trouve la préfecture dans une base GeoIP, puis utilise la position physique de la capitale de la préfecture.

Voici un exemple simplifié d'une requête d'un pair à l'oracle, et de la réponse de l'oracle. Le tout est transporté sur HTTP et les données sont encodées en couples {type, valeur} :

POST /PeerSelection HTTP/1.1
Host: OracleServerName
User-Agent: ClientName
Content-Type: text/plain; charset=utf-8

v=Version number
ip=IP address of physical interface
port=1978
nat=unknown
ub=256
db=15000

Vous avez compris que ub et db sont les capacités réseau montant et descendantes, et que nat indique (si le pair le sait), si le pair est coincé ou non derrière un routeur NAT, qui rend difficile les connexions entrantes. Et voici la réponse :

HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8

v=Version number
ttl=ttl
client_ip=192.0.2.67
numpeers=11
...

La section 6 résume les résultats de l'expérience. Soit un pair situé à Tokyo. Sans l'oracle, de 22 à 29 % des pairs sélectionnés étaient déjà dans le même FAI, et de 19 à 23 % dans le même district (il est important de connaître ces valeurs car, si un contenu est peu populaire et ne se trouve pas du tout dans le même FAI que l'utilisateur, aucun oracle au monde ne pourra indiquer un pair proche). Avec l'oracle, la distance moyenne avec le pair a été réduite de 10 %. (Opinion personnelle : le RFC est beaucoup plus détaillé sur la configuration de l'expérience que sur les résultats obtenus, très brefs.)

Les auteurs estiment que ces résultats montrent l'intérêt d'un système de sélection du pair. Quelles conclusions pour le groupe de travail ALTO, qui standardise une technologie analogue ? Que l'information publiquement accessible via BGP est une source utile pour optimiser le trafic entre FAI. Que, pour le trafic interne au FAI, il faut une information détaillée de la topologie du réseau de ce FAI, information qui peut être difficile à obtenir. Que les demandes futures seront peut-être d'avoir une sélection plus précise, nécessitant peut-être une structure hiérarchique dans ALTO (des serveurs ALTO utilisant eux-même d'autres serveurs ALTO). Et qu'il serait bon que l'oracle soit un peu plus bavard sur les mécanismes qu'il a utilisé pour trier les pairs possibles, afin que le pair puisse combiner le jugement de l'oracle avec ses propres critères.

Sur l'évaluation des mécanismes de sélection du pair, voir aussi le RFC 6821.


Téléchargez le RFC 6875


L'article seul

Exposé sur la sécurité d'IPv6 à l'ESGI

Première rédaction de cet article le 22 février 2013
Dernière mise à jour le 26 février 2013


Le 21 janvier, à l'ESGI, j'ai fait un exposé sur la sécurité du protocole IPv6.

Cet événement était organisé par le laboratoire de sécurité de l'ESGI. Les vidéos devraient être en ligne un de ces jours, la mienne est déjà sur ToiTuyau. En attendant, voici des photos de la journée (prises par Olivier Calzi) et les transparents :

Voir aussi mes notes du cours de hacking IPv6 de Fernando Gont.


L'article seul

RFC 6840: Clarifications and Implementation Notes for DNS Security (DNSSEC)

Date de publication du RFC : Février 2013
Auteur(s) du RFC : S. Weiler (SPARTA), D. Blacka (Verisign)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dnsext
Première rédaction de cet article le 22 février 2013


DNSSEC, normalisé notamment dans le RFC 4033 et suivants, est une technologie très complexe et une erreur est vite arrivée lorsqu'on essaie de le mettre en œuvre. L'expérience de plusieurs programmeurs et de nombreux administrateurs système a permis de découvrir un certain nombre de faiblesses, voire de bogues, dans la spécification de DNSSEC et ce nouveau RFC rassemble des précisions et corrections. Leçon principale à en tirer : il n'y a pas que les logiciels qui ont des bogues, les normes aussi.

D'abord, des points qui étaient optionnels lors de leur introduction mais qu'on doit maintenant, au vu de l'évolution du monde, considérer comme faisant partie du cœur de DNSSEC, et sont donc obligatoires. C'est le cas de NSEC3, introduit par le RFC 5155. Étant donné que des zones très importantes comme .com et .fr sont signées avec NSEC3, un résolveur DNSSEC validant qui ne gérerait pas NSEC3 serait, en 2013, bien inutile... Le RFC demande donc que tous les résolveurs mettent en œuvre NSEC3. Notez que les anciens noms d'algorithmes DNSSEC avaient une version NSEC et une version NSEC3 mais ce n'est plus le cas. l'algorithme 8, par exemple (RSA + SHA-256), permet d'utiliser NSEC ou NSEC3.

À propos de SHA, notre RFC considère aussi que la famille SHA-2 (RFC 5702) est désormais obligatoire (elle est utilisée pour la racine donc un résolveur qui ne la connait pas n'irait pas bien loin).

Après cet ajout de nouvelles techniques cryptographiques, un mot sur le passage à l'échelle (section 3). Notre RFC demande désormais fortement que les résolveurs DNSSEC validants aient un cache des erreurs de signature. Si une signature est invalide, réessayer immédiatement ne sert qu'à charger le réseau inutilement : le problème ne va pas se résoudre seul. Un tel ré-essai ne peut mener qu'au « Rollover and die ». Le RFC 4035, section 4.7, permettait un tel cache mais il est désormais fortement recommandé.

Bon, venons-en maintenant aux bogues et problèmes, en section 4. Le RFC suit dans cette section 4 à peu près un plan d'importance décroissante : au début, les bogues graves, pouvant mener à des failles de sécurité. À la fin, les améliorations non-critiques. Pour commencer, les preuves de non-existence. L'algorithme donné en section 5.4 du RFC 4035 est incomplet. Mis en œuvre littéralement, il permettrait de valider la non-existence d'un nom avec un NSEC ou un NSEC3 situé plus haut dans l'arbre, même en dehors de la zone. La nouvelle formulation impose au résolveur validant de ne pas chercher de NSEC (ou NSEC3) au delà des frontières de zone.

Autre sous-spécification : lorsque la requête est de type ANY (on demande tous les types connus du serveur), il est parfaitement légal de n'en renvoyer qu'une partie (un serveur ne faisant pas autorité n'a pas forcément en cache tous les enregistrements pour un nom donné, cf. section 6.2.2 du RFC 1034). Comment on valide cela ? Rien n'était dit dans le RFC 4035. La nouvelle règle est que, si un seul des ensembles d'enregistrements (RRset) est invalide, toute la réponse doit être considérée comme invalide. Mais, si tous les ensembles sont valides, il ne faut pas pour autant que le résolveur croie qu'il a tout obtenu.

Il y a aussi deux autres erreurs de sécurité corrigées par notre RFC. Et le RFC continue avec la section 5, les problèmes d'interopérabilité. D'abord, encore un problème posé par une règle qui, dans le RFC 1034 (section 3.1), semblait bien innocente, celle comme quoi les comparaisons de noms de domaines sont insensibles à la casse. Or, DNSSEC nécessite souvent des comparaisons et des tris (par exemple pour ordonner les noms pour NSEC). Le RFC 3755 disait « Embedded domain names in RRSIG and NSEC RRs [donc, dans la partie droite des enregistrements] are not downcased for purposes of DNSSEC canonical form and ordering nor for equality comparison » mais le RFC 4034 disait le contraire « all uppercase US-ASCII letters in the DNS names contained within the RDATA are replaced by the corresponding lowercase US-ASCII letters ». Les deux formulations sont acceptables mais il faut évidemment que tout le monde utilise la même. Et que faisaient les résolveurs, face à cette contradiction ? Eh bien, leurs auteurs avaient tranché en ne mettant en œuvre aucun des deux RFC (le RFC ne dit pas comment ces auteurs étaient arrivés à cet accord) : les noms dans la partie droite d'un NSEC ne sont pas convertis en minuscule, ceux dans la partie droite d'un RRSIG le sont. Le RFC 6840 entérine cette pratique en en faisant la nouvelle règle.

Autre problème d'interopérabilité. Le RFC 4035 est clair sur ce que doit faire un résolveur qui ne connait aucun des algorithmes utilisés pour signer une zone (par exemple parce que l'auteur de la zone a choisi uniquement des algorithmes très récents comme ceux du RFC 6605) : dans ce cas, la zone est considérée comme non signée. Mais si un enregistrement DS est condensé avec un algorithme de condensation non connu du résolveur ? Le cas n'était pas prévu mais il l'est désormais : le résolveur doit faire comme s'il n'y avait pas de DS (donc considérer la zone comme non signée).

Un cas plus fréquent en pratique est celui d'un ensemble d'enregistrements signés plusieurs fois, par exemple avec des clés différentes (certains mécanismes de remplacement de clés fonctionnent ainsi), ou bien avec des algorithmes différents (par exemple lorsqu'on déploie un nouvel algorithme pas encore très connu et qu'on garde donc des signatures faites avec l'ancien algorithme). Si ces signatures donnent des résultats différents (mettons que l'une est valide et l'autre pas), que doit faire le résolveur ? On peut imaginer deux politiques possibles, imposer que toutes les signatures soient valides (politique AND, la plus sûre) ou n'exiger qu'une seule signature valide pour être content (politique OR, celle qui créera le moins de problèmes). La section 5.3.3 du RFC 4035 renvoyait le problème au résolveur en disant qu'il choisissait librement sa politique de sécurité. Notre RFC 6840 tranche plus nettement : il faut utiliser la politique OR. Autrement, on ne pourrait pas introduire de nouveaux algorithmes cryptographiques. Et certains problèmes liés au moment exact où une donnée est introduite dans le cache du résolveur mènerait à des échecs de validation (par exemple, remplacement d'une clé, l'ancienne clé n'est plus disponible mais des signatures faites avec elle sont toujours dans le cache). D'autre part, une politique AND faciliterait certaines attaques par déni de service : un méchant n'aurait qu'à insérer des signatures bidon pour empêcher la validation. Enfin, personnellement, je rajoute que DNSSEC est assez compliqué comme cela, qu'il y a déjà suffisamment de problèmes et qu'une politique laxiste est plus raisonnable à l'heure actuelle.

Autre cas où les RFC originels sur DNSSEC n'avaient pas assez pinaillé dans les détails et avaient omis de spécifier des cas un peu exotiques : que doit-on faire si le bit AD (Authentic Data) est mis à 1 dans une question ? Désormais, cela a une sémantique précise : que le client DNS lit le bit AD, que sa valeur l'intéresse et que ce serait donc sympa de la part du serveur d'essayer de le déterminer. (C'est séparé du bit DO : le bit AD dans une requête n'implique pas qu'on veut recevoir toutes les données DNSSEC.)

Et le bit CD (Checking Disabled) dans les requêtes ? Désormais, la règle est qu'il vaut toujours mieux le mettre à 1 lorsqu'on fait suivre une requête, afin d'augmenter les chances d'obtenir toutes les données disponibles chez le serveur en face. C'était une des deux décisions les plus contestées de ce nouveau RFC (l'autre étant le cas où plusieurs clés sont disponibles pour une zone). En pratique, cela n'a d'importance que si on a plusieurs résolveurs à la queue-leu-leu, par exemple avec la directive forwarders de BIND. Sans le dire clairement, le RFC 4035 semblait impliquer qu'il y ait au maximum un résolveur validant entre le stub resolver et les serveurs faisant autorité. Mais ce n'est pas toujours le cas. En suivant la nouvelle règle de ce RFC (toujours mettre le bit CD à 1 lorsqu'on fait suivre une requête), on simplifie : certes, il y a plusieurs validateurs sur le trajet mais un seul, le premier, fera la validation. Cela rendra le débogage des problèmes plus facile. L'annexe B décrit plus en détail ce problème et ce choix. Elle présente des politiques alternatives, avec leurs avantages et leurs inconvénients. Notamment, mettre le bit CD à 1, dans certaines politiques, dépend de s'il était à 1 dans la requête originale.

Encore un cas vicieux ? Vous aimez cela ? Alors, demandez-vous ce que doit faire un résolveur validant avec DNSSEC lorsqu'il dispose de plusieurs clés de confiance pour valider une zone. Mettons (exemple purement théorique) qu'on ait la clé publique de la racine et qu'on ait installé celle de gouv.fr car on est un ministère et on veut pouvoir valider les domaines du gouvernement national sans dépendre de la racine. Quelle clé utiliser pour valider culturecommunication.gouv.fr ? Notre RFC ne tranche pas : cela reste une question de politique de sécurité locale (la question a été très disputée dans le groupe de travail et aucun consensus n'est apparu). Mais le RFC recommande que cela soit configurable, avec l'option par défaut la plus laxiste : « accepter n'importe quelle clé qui marche ». (Avec cette politique, la validation n'échoue que si toutes les clés échouent.) L'annexe C présente la liste des politiques possibles, avec leurs avantages et inconvénients :

  • La clé la plus proche : collant à la nature arborescente et répartie du DNS, on choisit la clé la plus spécifique (ici, on choisira la clé de gouv.fr de préférence à celle de la racine, pour valider culturecommunication.gouv.fr). C'est la politique la plus raisonnable pour les cas où, comme dans mon exemple imaginaire, on a davantage confiance dans la clé située plus bas dans l'arbre. Mais elle nécessite une grande rigueur dans la gestion des clés des sous-zones. Si la clé de gouv.fr change, il faudra être sûr que tous les résolveurs gouvernementaux ont été mis à jour. (En pratique, je conseille de n'avoir au maximum que trois clés de confiance - incluant celle de la racine - et, de préférence, une seule - celle de la racine. Au delà, on risque vraiment d'avoir un jour ou l'autre une clé abandonnée.)
  • N'importe quelle clé qui marche : c'est la politique recommandée par ce RFC, car c'est celle qui causera le moins d'erreurs de validation (les faux positfs étant une des plaies de la cryptographie). Son principal inconvénient est que la sécurité d'une zone est désormais celle de la clé la plus faible du lot.
  • Choisir une clé en fonction de sa source : c'est plus compliqué à programmer mais l'idée est que toutes les clés ne se valent pas. Un validateur qui a DLV (RFC 5074), les DS trouvés dans le DNS et quelques clés gérées à la main peut décider, par exemple, qu'il fait plus confiance aux clés gérées à la main, quelle que soit leur place dans l'arborescence.

J'avoue n'avoir pas testé avec des validateurs DNSSEC existants quelle était leur politique...

Voilà, bon courage aux programmeurs, ils ont désormais un RFC de plus à garder sous le coude lorsqu'ils créent un logiciel DNSSEC... Une bonne partie des règles de ce RFC sont déjà largement mises en œuvre dans les validateurs existants comme BIND ou Unbound.


Téléchargez le RFC 6840


L'article seul

RFC 6763: DNS-Based Service Discovery

Date de publication du RFC : Février 2013
Auteur(s) du RFC : S. Cheshire (Apple), M. Krochmal (Apple)
Chemin des normes
Première rédaction de cet article le 20 février 2013


Ce RFC normalise une technique pour trouver des ressources sur un réseau. Soit une machine qui arrive sur ce réseau. Elle cherche une imprimante, un serveur de fichiers, comment fait-elle ? Il ne s'agit pas juste de trouver une information technique unique (comme le routeur par défaut, qui est indiqué par DHCP ou RA, les Router Advertisement du RFC 4862) mais de récolter une liste de mises en œuvre possible de ce service, liste parmi laquelle on choisira ensuite. SD (Service Discovery) fonctionne en interrogeant le DNS, avec le nom du service, la réponse indiquant les machines qui fournissent ce service.

Ce protocole est fondé sur le DNS et utilise du DNS standard : même format, mêmes messages, etc. (Rappelons que le DNS, contrairement à ce que racontent les articles des médias et les textes « DNS pour les nuls », ne sert pas qu'à trouver les adresses IP, c'est au contraire un protocole de base de données très général.) SD est donc uniquement un ensemble de conventions (notamment de nommage) au dessus du DNS. SD est souvent utilisé au dessus du Multicast DNS du RFC 6762, mais peut aussi être utilisé sans lui. Avec Multicast DNS, SD fournit une solution « zéro configuration ».

L'idée de base est que les services sont décrits par des enregistrements SRV (RFC 2782) dont le nom est le nom d'une instance du service et dont le contenu indique le nom du serveur rendant ce service, ainsi que le port à utiliser. Un enregistrement TXT permet, si nécessaire, d'indiquer d'autres informations, qui ne rentrent pas dans un enregistrement SRV. Et pour trouver toutes les instances d'un service ? On se sert d'un enregistrement PTR dont le nom est celui du service.

Par exemple, si une machine Multicast DNS cherche une imprimante (service IPP, cf. RFC 2910), elle va faire une requête PTR _ipp._tcp.local (où .local est le pseudo-TLD de Multicast DNS). Mettons qu'elle obtienne deux réponses, Imprimante comptabilité.local et myprinter.local. Si l'utilisateur, via une interface de sélection, choisit l'imprimante de la comptabilité, l'étape suivante sera de faire une requête SRV Imprimante comptabilité.local (rappelez-vous que le DNS permet caractères Unicode et espace, contrairement à ce qu'on lit parfois, et c'est courant dans le monde Multicast DNS). Mettons que cette requête donne comme résultat a56grthg43.local, port 9818, alors la machine qui veut imprimer se connectera à l'adresse de a56grthg43.local, port 9818. Voilà, en quelques mots, le fonctionnement de Multicast DNS. La section 13, décrite plus loin, fournit des exemples réels.

Pour mieux comprendre SD, il est utile de lire la section 3, qui expose le cahier des charges de ce protocole :

  • Permettre l'énumération de toutes les instances qui rendent un certain service dans un certain domaine,
  • Pour une instance donnée, pouvoir résoudre ce nom en des informations techniques permettant de contacter l'instance (typiquement, une adresse IP et un port ; l'adresse IP peut être IPv4 ou IPv6, SD gère les deux, voir section 14),
  • Identifier les instances par un nom relativement stable (« Imprimante comptabilité ») de manière à ce que l'utilisateur n'ait rien à faire si ladite instance change d'adresse,
  • Être suffisamment simple pour être mis en œuvre dans des engins ayant des ressources limitées (comme, justement, des imprimantes). Plus facile à dire qu'à faire, le RFC fait quand même 54 pages.

SD se veut l'héritier du protocole NBP d'Apple (celui popularisé par le Chooser/Sélecteur des anciens Macintosh) et une plus longue discussion de cet héritage figure dans le RFC 6760.

La section 4 explique comment fonctionne l'énumération des instances d'un service. On l'a vu, le client SD doit faire une requête de type PTR pour un nom qui est la concaténation du service et du domaine. Si le client cherchait à accéder au service foobar, il fera des requêtes PTR pour _foobar._tcp.local en Multicast DNS et _foobar._tcp.example.net autrement (si example.net est le domaine du client). La requêtes renverra des noms d'instance. Ces noms d'instance sont en Unicode (dans le profil du RFC 5198, qui exclut les caractères de contrôle mais pas grand'chose d'autres ; voir l'annexe C pour une discussion de ce choix et l'annexe E pour ses conséquences). Ainsi, un nom d'instance peut comprendre des points (voir la section 4.3 pour les précautions à prendre). Notez que, vue la façon dont fonctionne l'encodage UTF-8, les limites de taille du DNS peuvent réduire le nom à quinze caractères, dans le pire des cas (caractères Unicode en dehors du Plan Multilingue de Base). Notez que le DNS a deux limites, une de 63 octets sur la longueur d'un composant du FQDN et une de 255 octets sur le FQDN (section 7.2 pour les détails). Il y a aussi une taille imposée par la raison : si le but est de présenter une liste d'instances d'un service à un utilisateur, une liste de, mettons, cent entrées, n'a guère de sens.

Le nom de l'instance doit pouvoir être choisi par l'utilisateur, et ne devrait pas être un nom unique généré à l'usine, nom qui serait probablement incompréhensible (genre dérivé de l'adresse MAC ou d'un autre identificateur technique, par exemple Mac064389AB5). L'annexe D explique pourquoi ces noms d'usine sont une mauvaise idée. Notamment, le fonctionnement de Multicast DNS et SD fait que des noms uniques ne sont pas nécessaires.

Quand au nom de domaine à la fin (.local avec Multicast DNS ou un nom de domaine habituel autrement), il n'a pas de règles particulières. Notez encore que le FQDN n'est pas limité aux lettres-chiffres-tiret du RFC 952. En effet, contrairement à ce que dit une légende tenace, le DNS n'a jamais été limité à ASCII. Des noms comme εκτυπωτής.local ou Building A, 1st floor printer.example.com sont donc parfaitement valables. Comme indiqué plus haut, s'ils comportent des caractères non-ASCII, ils sont stockés dans le DNS en UTF-8 (RFC 5198, qui normalise le profil Unicode de l'Internet, incluant la canonicalisation choisie). Un client SD qui n'obtient pas de réponse pour une requête en UTF-8 a toutefois le droit de reessayer en Punycode (RFC 3492) mais ce n'est pas obligatoire.

Les RFC normalisent des protocoles tels qu'ils s'expriment sur le câble, pas des interfaces utilisateurs. Néanmoins, la section 4.2 et l'annexe F donnent quelques conseils sur la présentation des résultats à l'utilisateur. Typiquement, le logiciel fait sa requête PTR, récolte une liste d'instances, et montre la liste à l'utilisateur pour qu'il choisisse. A priori, seul le premier composant est montré, pas le FQDN (donc, εκτυπωτής et pas εκτυπωτής.local ou bien Building A, 1st floor printer et non pas Building A, 1st floor printer.example.com).

Après l'énumération des instances, la section 5 explique la résolution du nom d'une instance. Dans la section précédente, on a obtenu le nom Building A, 1st floor printer.example.com et on va chercher à contacter la machine. C'est là que le client SD va faire une requête SRV (pour obtenir nom de machine et port) et une requête TXT (pour obtenir des détails qui n'étaient pas prévus dans l'enregistrement SRV). Les enregistrements SRV (RFC 2782) sont très précieux car ils évitent des numéros de port fixes (il n'y en a que 65 535 et ce n'est pas possible d'en réserver un à l'usage exclusif de chaque service, même si ça se faisait au début de l'Internet). N'importe quel service peut tourner sur n'importe quel port, le client trouvera le port dans l'enregistrement SRV. Autre avantage des SRV : les champs Priorité et Poids qui permettent d'assurer la répartition de charge et la résistance aux pannes. Notez que, si vous êtes programmeur et que cela vous fatigue de gérer les règles de priorité et de poids, il existe des bibliothèques qui font cela pour vous, comme RULI.

La section 6 décrit les enregistrements TXT. Les SRV sont très utiles, notamment parce qu'ils sont normalisés depuis longtemps et déjà mis en œuvre dans certains logiciels. Mais ils ne permettent pas d'enregistrer toutes les nuances qu'on voudrait spécifier. D'où l'usage des enregistrements TXT, du texte libre où on peut encoder ce qu'on veut. Par exemple, si un client SD cherche une imprimante, savoir le nom de la machine et le port ne suffit pas. Le vieux protocole LPR (RFC 1179 impose également un nom de file d'attente d'impression. De même, un serveur de fichiers peut avoir plusieurs volumes à servir. On va alors les stocker dans un TXT, avec des règles exactes qui dépendent de l'application (impression, service de fichiers, etc).

Cet enregistrement TXT est obligatoire, même si on n'a rien à dire. Cela permet notamment de choisir le TTL de cette information (autrement, c'est celui de la zone qui s'appliquerait). Le RFC recommande de le garder d'une taille raisonnable (quelques centaines d'octets), même si la théorie permet davantage. Mais, par exemple, il existe des mises en œuvre de Multicast DNS dans le matériel, qui permettent à une machine d'être découvrable sur le réseau même lorsqu'elle est en hibernation et ces mises en œuvre ont souvent des limites ridicules (par exemple 256 octets maximum pour un TXT).

Et le contenu de ce TXT, alors ? Ce sont des couples clé=valeur, contenant des informations qui dépendent du service (par exemple, pour le service d'impression, on peut consulter Bonjour Printing Specification). La valeur est facultative. Donc, on peut avoir un couple PlugIns=JPEG,MPEG2,MPEG4 (indiquant quels formats sont acceptés) ou PaperSize=A4, mais aussi uniquement passreq (juste une clé, sans valeur, ce qui est utile pour les attributs booléens, cet enregistrement est équivalent à passreq=true). La valeur peut être également de taille nulle (PlugIns= pour indiquer qu'aucun format supplémentaire n'est disponible).

Idéalement, ces informations devraient être facultatives, de simples optimisations du service, et la négociation entre le client et le serveur devrait suffire. En pratique, certains protocoles, comme LPR cité plus haut, imposent des informations qu'on ne trouve que dans le TXT (par exemple, le protocole LPR ne fournit aucun moyen pour une imprimante de dire à son client qu'elle accepte PostScript ou pas). En outre, lorsqu'une information est distribuée via ce TXT, il est important de veiller à ce qu'elle soit cohérente avec ce qui est réellement disponible sur la machine qui répond aux requêtes SD.

Dans les couples clé=valeur, la clé est courte (il n'est pas prévu de la montrer aux utilisateurs, elle n'a pas à être « conviviale  »), en ASCII uniquement, et unique. Elle est insensible à la casse. La valeur peut être n'importe quoi, y compris du binaire (attention donc si vous l'affichez). Mais c'est souvent du texte, ASCII ou UTF-8.

Si un service risque d'évoluer dans le futur, et de manière incompatible, le RFC recommande de mettre un attribut indiquant la version, de clé txtvers, par exemple txtvers=1. Cela aidera le client à savoir à quel genre de serveur il parle.

Maintenant, discutons du noms des services. La section 7 dit qu'ils sont faits de deux composants, le nom proprement dit (suivant le registre décrit dans le RFC 6335, cf. section 16), précédé d'un tiret bas, puis _tcp ou _udp. Et les autres protocoles, comme SCTP ? Ils n'ont malheureusement pas de domaine pour eux, tout ce qui n'est pas TCP doit être mis sous _udp. Le point est discuté dans la section 7 mais l'argumentation est invraisemblable, je ne sais même pas comment l'IESG a laissé passer cela, bien que c'était explicitement mentionné dans les revues du futur RFC.

Un point plus sérieux est celui du choix du nom d'un protocole. Il est courant de bâtir un protocole applicatif au dessus d'un autre, souvent au dessus de HTTP, à la fois pour bénéficier des nombreuses bibliothèques existantes, et pour être raisonnablement sûr de passer les pare-feux. C'est ainsi que le protocole de partage de musique DAAP, utilisé par iTunes, est construit au dessus de HTTP. Le service, dans les enregistrements SF, doit-il être _http._tcp.DOMAIN ou bien _daap._tcp.DOMAIN ? La réponse est claire, c'est le second choix qui est le bon : DAAP n'a de sens qu'avec un client iTunes (un navigateur Web normal, par exemple, serait bien embêté est se connectant à un serveur DAAP, et un client iTunes ne saurait pas quoi faire d'un serveur HTTP générique), et le fait que ce soit du HTTP sous-jacent n'est qu'un détail technique, qui ne se reflète pas dans le nom du service. SD publie le service, pas la façon dont il est mis en œuvre.

À partir d'ici, le RFC continue mais il s'agit plutôt de points de détail, qui n'affectent pas la compréhension globale de SD.

Dans certains cas, il peut être utile de restreindre la demande à un sous-ensemble des machines implémentant un service. Prenons l'exemple d'une imprimante, dotée d'un serveur HTTP pour en permettre l'administration. Si un navigateur Web qui cherche les imprimantes à administrer demande _http._tcp.DOMAIN, il va trouver des tas de serveurs n'ayant rien à voir avec les imprimantes. SD permet donc d'ajouter un champ, le sous-type, pour faire une requête _printer._sub._http._tcp.DOMAIN pour « sous-service Imprimante du service HTTP ». (Notez le _sub, dont le RFC n'explique pas le rôle.) Notez que c'est un problème différent de celui du paragraphe précédent  : ici, le service d'administration des imprimantes n'est pas juste « bâti sur HTTP », il est en HTTP et un navigateur HTTP générique peut l'utiliser (la section 7.1 détaille dans quels cas les sous-types sont utiles et dans quels cas ils ne le sont pas). Le navigateur Safari sur MacOS fonctionne ainsi. En parlant de MacOS, la commande dns-sd permet de publier sur le réseau local un nom de service. Par exemple, ici, on publie le service HTTP A web page :

% dns-sd -R "A web page"           _http._tcp          local 100

Alors qu'ici on publie un « sous-service » printer nommé A printer's web page (ouvrez bien l'œil, il y a une virgule, pas un point) :

% dns-sd -R "A printer's web page" _http._tcp,_printer local 101

Avec la syntaxe standard des fichiers de zone du DNS (RFC 1035, section 5), les mêmes déclarations seraient :

; One PTR record advertises "A web page"
_http._tcp.local. PTR A\032web\032page._http._tcp.local.

; Two different PTR records advertise "A printer's web page"
_http._tcp.local. PTR A\032printer's\032web\032page._http._tcp.local.
_printer._sub._http._tcp.local.  PTR A\032printer's\032web\032page._http._tcp.local.

Que fait SD lorsque plusieurs protocoles assurent à peu près la même fonction (section 8) ? C'est un cas courant, pour des raisons historiques, ou bien lorsque plusieurs équipes n'ont pas pu résister à la tentation de développer leur propre jouet. Par exemple, la fonction d'impression peut être faite par LPR (RFC 1179) ou IPP (RFC 2910), sans compter des protocoles spécifiques d'un vendeur. Le principe de SD dans ce cas, est de décider qu'un des protocoles est le « vaisseau amiral ». Une instance a alors tout intérêt à mettre en œuvre ce protocole privilégié pour assurer le service. Toutefois, si ce n'est pas le cas, elle doit quand même créer un enregistrement SRV pour ce protocole, avec un port de zéro (signifiant qu'il n'est pas utilisable) afin que la détection de duplicata fonctionne.

En général, un client SD donné ne s'intéresse qu'à un seul service. S'il veut imprimer, il cherche une imprimante, et se moque des autres services existants sur le réseau. Toutefois, lorsqu'on veut analyser et déboguer un réseau où il y a du SD, il est pratique de pouvoir demander « toutes les instances de tous les services ». Cela se fait (section 9) en demandant _services._dns-sd._udp.DOMAIN.

Au fait, comment est-ce que les informations SD arrivent dans le DNS (section 10) ? Fondamentalement, ce n'est pas notre problème : le RFC 6763 normalise les interactions sur le réseau, pas la façon dont chaque machine est configurée, et dont cette configuration arrive dans le DNS. Il peut y avoir deux méthodes : si on utilise Multicast DNS, chaque machine connait sa propre information et y répond. Sinon, il faut configurer un serveur DNS traditionnel. Cela peut se faire à la main (en éditant le fichier de zone) mais SD est plutôt conçu pour des réseaux non-gérés, où il n'y a pas d'administrateur système (même pas d'administrateur système incompétent). Il faut donc plutôt envisager des mécanismes automatiques, par exemple un programme qui balaie le réseau (en utilisant d'autres protocoles) puis produit le fichier de zone (cette possibilité est citée par le RFC mais semble peu déployée en pratique).

Comme un des buts de SD est de permettre l'énumération de choses inconnues, par exemple lorsqu'un portable arrive sur un nouveau réseau, et sans configuration manuelle préalable, comment apprendre les noms de domaine à utiliser dans les requêtes SD (section 11) ? S'il n'y a pas de serveur DHCP qui répond, il faut sans doute utiliser le .local de Multicast DNS. S'il y a un serveur DHCP, il indique un nom par l'option 15, Domain (RFC 2132), ou par l'option 119 Domain Search (RFC 3397). À noter qu'en IPv6, ce sera sans doute RA et non pas DHCP qui sera utilisé, et qu'il peut aussi indiquer un domaine (RFC 8106).

Une fois qu'on a ce nom, on peut former des requêtes spéciales pour découvrir d'autres choses :

  • b._dns-sd._udp.DOMAIN donne la liste de tous les domaines disponibles pour l'exploration,
  • db._dns-sd._udp.DOMAIN donne le domaine recommandé pour l'exploration,
  • r._dns-sd._udp.DOMAIN et dr._dns-sd._udp.DOMAIN les ou le domaine à utiliser pour enregistrer des noms via les mises à jour dynamiques du DNS.

Notons que beaucoup de clients SD n'utiliseront pas ces requêtes et se contenteront du premier domaine déterminé (.local ou bien celui appris par DHCP).

Le RFC recommande, en section 12, aux serveurs DNS qui répondront au requêtes SD d'inclure dans la section additionnelle des informations supplémentaires, non indispensables, mais qui peuvent diminuer le trafic en évitant au client de poser la question par la suite. Par exemple, lorsqu'on envoie une réponse SRV, inclure les adresses du serveur nommé dans l'enregistrement SRV est raisonnable. Bien sûr, le client est libre d'en tenir compte ou pas (il peut estimer que, pour des raisons de sécurité, il vaut mieux reposer la question : la section additionnelle est un bon endroit pour tenter d'empoisonner un client DNS avec des informations bidon).

La section 13 contient des exemples réels, en utilisant le domaine dns-sd.org, qui est servi par des BIND standard (SD ne nécessite aucune modification des serveurs de noms). Pour voir, on va l'interroger avec drill, livré avec ldns (le RFC utilise l'antédiluvien nslookup et moi je me sers habituellement de dig). Commençons par les services HTTP :


% drill -b 4096  PTR  _http._tcp.dns-sd.org. 
...
;; ANSWER SECTION:
_http._tcp.dns-sd.org.  60      IN      PTR     \032*\032Google,\032searching\032the\032Web._http._tcp.dns-sd.org.
_http._tcp.dns-sd.org.  60      IN      PTR     \032*\032Amazon\.com,\032on-line\032shopping._http._tcp.dns-sd.org.
_http._tcp.dns-sd.org.  60      IN      PTR     \032*\032Yahoo,\032maps,\032weather,\032and\032stock\032quotes._http._tcp.dns-sd.org.
_http._tcp.dns-sd.org.  60      IN      PTR     \032*\032SlashDot,\032News\032for\032Nerds,\032Stuff\032that\032Matters._http._tcp.dns-sd.org.
_http._tcp.dns-sd.org.  60      IN      PTR     \032*\032DNS\032Service\032Discovery._http._tcp.dns-sd.org.
...

L'option -b (indiquer au serveur la taille des réponses qu'on peut recevoir) est là car la réponse est de grande taille. Notez aussi que drill a représenté les espaces par un code pour éviter toute ambiguité. Affichée à un humain, cette liste donnerait :

* Google, searching the Web.
* Amazon.com, on-line shopping.
* Yahoo, maps, weather, and stock quotes.
* SlashDot, News for Nerds, Stuff that Matters.
* DNS Service Discovery.
...

Une fois qu'on a choisi un des services découverts, comment le contacter ?


% drill SRV '\032*\032DNS\032Service\032Discovery._http._tcp.dns-sd.org' 
...
;; ANSWER SECTION:
\032*\032DNS\032Service\032Discovery._http._tcp.dns-sd.org.     60      IN      SRV     0 0 80 dns-sd.org.
...

% drill TXT '\032*\032DNS\032Service\032Discovery._http._tcp.dns-sd.org'   
...
;; ANSWER SECTION:
\032*\032DNS\032Service\032Discovery._http._tcp.dns-sd.org.     60      IN      TXT     "txtvers=1" "path=/"

Bref, on peut joindre l'instance DNS Service Discovery du service HTTP sur le port 80 en contactant la machine dns-sd.org. Le TXT indique une option non triviale, path=/. À noter que les noms b et r cités plus haut ne donnent aucun résultat sur le domaine de test dns-sd.org.

Voici maintenant un exemple réel, vu avec tcpdump, d'une machine cherchant les instances du service sane-port en Multicast DNS :

21:06:04.877355 IP6 (hlim 255, next-header UDP (17) payload length: 47) \
    2a01:e35:8bd9:8bb0:21e:8cff:fe7f:48fa.5353 > ff02::fb.5353: [udp sum ok] 0 \
    PTR (QM)? _sane-port._tcp.local. (39)

tcpdump sait décoder le Multicast DNS et a vu la demande d'énumération (type PTR demandé) des instances du service _sane-port._tcp.local.

La section 15 résume ce qu'il faut savoir de la sécurité de DNS-SD. Le RFC est très court à ce sujet et oublie de préciser clairement que DNS-SD n'offre en soi aucune sécurité. S'il est utilisé sur Multicast DNS, il en hérite l'absence totale de protection. Sinon, il a la sécurité du DNS (faible) et ses protections (DNSSEC mais, évidemment, les réseaux locaux sans administrateur n'auront pas DNSSEC, technique encore trop complexe à mettre en œuvre).

Chose rare dans les RFC, les pincipaux choix techhniques faits par les concepteurs de SD sont documentés dans le RFC, dans les annexes. Ce sont de très intéressantes lectures. Ainsi, l'annexe A explique pourquoi SD s'appuie sur le DNS et pas sur un nouveau protocole, peut-être plus adapté : c'est essentiellement pour pouvoir utiliser toute une infrastructure de normes (DNSSEC, mises à jour dynamiques), de logiciels (serveurs, clients comme drill, analyseurs) et de compétences, infrastructure qui a largement fait ses preuves. Technologie mûre, éprouvée, pour laquelle il existe beaucoup d'implémentations, beaucoup de livres et d'articles, et beaucoup de gens compétents : le DNS n'a aucun concurrent réaliste aujourd'hui.

L'annexe B explique pourquoi les noms interrogés sont écrits INSTANCE.SERVICE.DOMAINE et pas SERVICE.INSTANCE.DOMAINE. Il y a des raisons sémantiques (les noms de domaines sont petit-boutiens et le service est plus général que l'instance) mais aussi techniques (la compression de noms dans le DNS marche mieux dans ce cas).

L'annexe C est une très intéressante réflexion sur les services de découverte en général. C'est le genre de problèmes qui devrait être plus souvent discuté lors des enseignements de réseaux informatiques à l'Université (plus que les sempiternels réseaux de Petri). Certains services de découverte choisissent de donner à chaque instance un identificateur unique et opaque, typiquement représenté sous forme d'une longue chaîne de chiffres hexadécimaux. Le nom montré à l'utilisateur n'est alors que pour information, le protocole travaille avec les identificateurs uniques et opaques. SD n'a pas choisi cette approche, car elle sépare trop radicalement ce que voit l'utilisateur de ce qui se passe réellement sur le réseau. Par exemple, si deux instances différentes (et ayant donc des identificateurs opaques différents) ont le même nom montré ? Que va penser l'utilisateur de voir deux « Corridor Printer » ? Laquelle est la bonne ? En pratique, dans ce cas et dans d'autres (comme le remplacement d'un engin par un autre à qui on donne le même nom montré mais qui a un identificateur différent), l'utilisateur va devoir tôt ou tard apprendre l'existence des identificateurs cachés et se colleter avec eux. Résultat, pour SD, le nom montré à l'utilisateur et celui utilisé dans le réseau sont toujours le même.

Un autre problème à la frontière entre l'ergonomie et l'informatique est celui des noms configurés à l'usine, avant que la machine ne soit livrée au client (annexe D). Certains fabricants, croyant bien faire, configurent des noms « inamicaux » par exemple en incluant un numéro de série ou bien une adresse MAC. Leur idée est de garantir l'absence de conflit de noms. Toutefois, lorsque SD utilise Multicast DNS, c'est tout à fait inutile, puisque Multicast DNS dispose d'un mécanisme de détection et de résolution de conflits (RFC 6762, section 9). Et ces noms inamicaux sont incompréhensibles par l'utilisateur. Le RFC prend l'exemple d'un utilisateur n'ayant qu'une seule imprimante. Le nom « Printer » sera unique et un nom globalement unique comme « Printer 18:03:73:66:e5:68 » ne servirait qu'à troubler l'utilisateur. S'il a deux imprimantes, la détection de conflits de Multicast DNS les nommera « Printer » et « Printer (2) », ce qui est certainement mieux que « Printer 18:03:73:66:e5:68 » et « Printer 18:03:73:98:a3:12 ». Et, s'il a dix imprimantes, il va de toute façon devoir passer un peu de temps pour les nommer et les configurer.

Le RFC recommande donc simplement de choisir des noms d'usine qui décrivent le produit, comme « Xerox Phaser 6200DX » ou « HP LaserJet 4600 » et de compter sur la résolution de conflits de Multicast DNS pour le cas où deux HP LaserJet se retrouvent sur le même réseau.

On l'a déjà dit, SD n'est pas du tout limité à l'ASCII et peut utiliser Unicode. L'annexe E rappelle le contexte et insiste sur le fait qu'Unicode est une possibilité, pas une obligation. Si l'administrateur des machines n'aime pas Unicode et veut nommer ses machines uniquement en ASCII, il a évidemment le droit.

Normalement, l'IETF ne se préoccupe que de ce qui passe sur le câble et pas des interfaces utilisateur. On trouve donc peu de RFC qui mentionnent des problèmes d'IHM. Mais l'annexe F de ce RFC 6763 estime nécessaire d'insister sur une question qui a une influence directe sur le protocole et les implémentations : le fait que la découverte de services avec SD est un processus continu. On ne peut pas se contenter de présenter une liste à l'utilisateur et de le laisser choisir une fois pour toutes. Des nouvelles machines peuvent apparaître à tout instant, et d'autres disparaître (c'est évidemment particulièrement fréquent avec Multicast DNS). Plus important, des machines peuvent répondre avec retard et un service de découverte qui s'arrêterait au bout de quelques secondes risquerait de les rater. De plus, les concepteurs de SD considèrent que ce n'est pas sympa que de demander à l'utilisateur de relancer une découverte explicitement.

Le modèle privilégié par SD est donc : on affiche immédiatement la liste des instances trouvées (même si elle est initialement vide) et on met à jour cette liste en permanence (plus exactement jusqu'à ce que l'utilisateur ferme la fenêtre). La liste affichée doit représenter en permanence l'état actuel du réseau (on débranche le câble : elle se vide, on le rebranche, quelques secondes après les instances réapparaissent).

Ce RFC 6763 arrive longtemps après les premiers déploiements de SD. On n'est pas dans le cas d'un RFC qui propose une nouvelle technologie, encore à implémenter, mais dans celui d'un RFC qui décrit a posteriori un protocole qu'Apple a imposé unilatéralement. L'annexe G décrit la longue histoire de SD, depuis les réflexions originales en 1997, jusqu'au RFC actuel.

SD est aujourd'hui mis en œuvre sur Mac OS, Windows mais aussi sur de nombreux autres systèmes. Il existe par exemple une implémentations en C, mDNSResponder, une version Unix, Avahi, et plein d'autres.

À noter que j'avais été le relecteur Gen-ART (cf. RFC 6385) pour ce document: http://www.ietf.org/mail-archive/web/gen-art/current/msg05815.html.


Téléchargez le RFC 6763


L'article seul

RFC 6760: Requirements for a Protocol to Replace AppleTalk NBP

Date de publication du RFC : Février 2013
Auteur(s) du RFC : Stuart Cheshire (Apple), Marc Krochmal (Apple)
Pour information
Première rédaction de cet article le 20 février 2013


Il y a bien longtemps, à l'époque où même DHCP n'existait pas, et où les seules machines connectées à l'Internet étaient de gros Vax configurés à la main, Apple avait mis au point un ensemble de protocoles concurrents de TCP/IP, la famille AppleTalk. Durant les années suivantes, ces protocoles privés ont été petit à petit remplacé par les normes ouvertes et AppleTalk a quasiment disparu. Mais certains des protocoles de la famille n'ont pas été réellement remplacés et c'est dommage. Parmi eux, NBP, le Name Binding Protocol, qui n'a pas encore d'équivalent standard dans le monde TCP/IP. Que faudrait-il pour le remplacer ? Ce RFC décrit les fonctions souhaitées.

AppleTalk comportait tout un ensemble de protocoles, même si l'insistance des marketroïdes d'Apple à appeler « AppleTalk » le mécanisme physique de connexion LocalTalk a sérieusement brouillé les pistes. Ces protocoles AppleTalk avaient en commun de pouvoir fonctionner sans configuration, dans la configuration dite « bureau du dentiste ». Le dentiste est supposé riche (il a plusieurs ordinateurs) mais n'a pas de compétence en informatique. Il faut donc que tout marche tout seul et NBP jouait un rôle essentiel dans cette auto-configuration.

Cette partie du projet de remplacement d'AppleTalk par IP, concernant l'auto-configuration, a souvent été désignée du nom de « Zeroconf ». Pour développer un équivalent à NBP, il faut le connaître et c'est un des rôles de ce RFC. Un autre rôle est de spécifier plus rigoureusement le remplaçant de NBP. Faire au moins aussi bien était un des buts mais pas le seul. Le protocole dont les propriétés sont décrites dans ce RFC 6760 étend NBP sur plusieurs aspects comme l'internationalisation. AppleTalk utilisait un jeu de caractères privé, Apple Extended ASCII, alors que son successeur se sert évidemment d'Unicode. Un autre changement, moins visible, est que NBP, conçu uniquement pour des LAN était très bavard et que son successeur doit être plus économe des ressources réseau.

Ce RFC 6760 désigne comme successeur de NBP les protocoles Multicast DNS (RFC 6762, notons que le nom est très mauvais puisque ce protocole n'est pas le DNS) et DNS-based service discovery (RFC 6763). Ce sont deux protocoles conçus entièrement par Apple, sans participation de l'IETF, et qu'Apple a essayé pendant des années de faire adopter par l'IETF. Le RFC 6760 n'a donc pas uniquempent un rôle technique mais sert aussi de plaidoyer pro domo d'Apple. Ce RFC 6760 sert donc aussi d'arrière-plan et de justification aux RFC 6761, RFC 6762 et RFC 6763.

Revenons à l'auto-configuration (section 2). Traditionnellement, tous les protocoles TCP/IP avaient été conçus pour des configurations manuelles (par exemple dans le fichier /etc/network/interfaces sur une Debian). Cette configuration peut être centralisée, grâce à DHCP (RFC 2131), qui évite de configurer chaque machine. AppleTalk permettait au contraire une auto-configuration des ordinateurs du dentiste, sans qu'aucun administrateur réseaux ne soit intervenu. Bref, AppleTalk était pair-à-pair même si Apple, entreprise costard-cravate, n'utilise guère ce terme, trop connoté « pirate ».

IP dispose désormais de mécanismes d'auto-configuration, comme les adresses lien-local (RFC 4862 et RFC 3927). Il reste donc à auto-configurer le mécanisme de résolution de noms en adresses.

La section 3 donne la liste des exigences pour le nouveau protocole. Elle découle des fonctions qu'assurait NBP. La plus connue et la plus spectaculaire est le choix d'un service réseau via le Chooser (Sélecteur) du Macintosh mais la section 3.1 nous rappelle que ce n'est qu'une extension : le premier service de NBP n'est pas le butinage, c'est la traduction de nom en adresse. À chaque fois que le dentiste veut imprimer, NBP est appelé pour traduire le nom de l'imprimante sélectionnée en une adresse, vers laquelle on va ensuite établir une session, avec le protocole d'impression.

Deuxième point important de NBP (section 3.2), il nomme des services pas des machines. Supposons que le même ordinateur porte un service de fichiers et un service d'impression, le dentiste Michu se moque de savoir si les deux services sont sur la même machine ou pas. Seul l'administrateur réseaux se préoccupe des machines, l'utilisateur pense aux services. Même si on est administrateur réseaux, d'ailleurs, on ne communique pas avec des machines mais avec le logiciel qui tourne sur ces machines. Comme le dit le RFC, « on ne pingue pas une machine, on pingue le logiciel sur cette machine qui met en œuvre le RFC 792 ». Conséquence, les machines n'ont pas de nom dans AppleTalk, seuls les services en ont.

Le RFC rappelle d'ailleurs que le DNS a déjà cette possibilité de nommer des services et pas des machines. On ne sait pas si www.example.org et ldap.example.org sont sur la même machine et, d'ailleurs, on s'en fiche (sauf si on est l'administrateur réseaux en train de déboguer). Toutefois, cette approche a une limite, c'est que le DNS ne fournit en échange du nom qu'une adresse IP. Pour se connecter au service, il faut encore un numéro de port. Parfois, il est bien connu, fixé en dur dans le protocole (80 pour HTTP). Si on veut deux services HTTP distincts (par exemple www.example.org et www.makemoney.example), c'est à l'application de gérer le démultiplexage (dans le cas de HTTP, avec le champ Host: de la requête). Celle-ci double alors un travail que le noyau sait déjà faire. Et même ce démultiplexage par l'application ne résout pas tout : par exemple il est difficile de faire tourner deux serveurs HTTP différents (mettons Apache et nginx) sur la même machine. Parfois, le port est indiqué explicitement par l'utilisateur, par exemple http://www.example.org:8042/, ce qui n'est pas pratique et annule une bonne partie de l'intérêt d'avoir un système d'annuaire. Et puis le nombre de ports est limité (65536) et le fait d'avoir des ports fixes n'aide pas à la gestion de cette ressource limitée.

NBP, au contraire (section 3.3) fournissait systématiquement adresse et port en échange d'un nom (le port était nommé socket number). Son remplaçant doit donc garder la même propriété.

Mes lecteurs qui connaissent le DNS, à ce stade, sont déjà devenus tout rouges en criant « Mais il suffit d'utiliser le RFC 2782 ! » Mais ces enregistrements SRV ne résolvent pas tout : ils prennent en entrée un nom de domaine alors que, pour un service d'impression, on veut en plus utiliser d'autres éléments comme le nom de la file d'attente lpr. (Je suis personnellement sceptique par rapport à cet argument : si le serveur d'impression a deux files, library et secretariat, pourquoi ne pas avoir deux noms, library.printer.example.org et secretariat.printer.example.org, chacun avec son SRV ?)

NBP permettait également de chercher un service par type et par zone. La syntaxe complète était Nom:Type@Zone où les valeurs pouvaient être remplacées par des signes égal pour indiquer qu'on recherchait tout (voir section 3.10). Le Type indiquait le service recherché (par exemple, pour des raisons historiques, le type LaserWriter désignait tout service parlant PostScript au dessus du protocole PAP, même si ce service n'était pas une imprimante laser). Quant à la Zone, elle fournissait un mécanisme permettant de répartir les grands réseaux AppleTalk en plusieurs zones dans lesquelles la recherche se faisait indépendemment. Rappelez-vous que NBP travaillait par inondation dans tous les réseaux connectés, et ne passait donc pas à l'échelle. Dès qu'on avait un ensemble de réseaux plus grand que le bureau du dentiste, par exemple à l'échelle d'un campus, il fallait le découper en zones (le mécanisme de découverte des zones distantes fonctionnait également par inondation : AppleTalk était conçu avec une vision étroite des réseaux, limités à une seule organisation, et n'avait pas tiré les leçons du développement de l'Internet). Bref, le remplaçant de NBP doit fournir également un service de partitionnement, qu'on puisse avoir plusieurs serveurs de fichiers nommés File server. Il doit également permettre d'informer l'utilisateur de quelle est la zone courante et quelle est la liste des zones accessibles (section 3.11).

Et la syntaxe des noms ? La section 3.5 note que des noms qui sont tapés sur la ligne de commande doivent être courts et sans fioritures (pas d'espace). Mais des noms choisis dans une liste ont plutôt intérêt à être longs et précis. Donc, lp-fred convient bien à l'imprimante dans le bureau de Frédérique si on travaille en ligne de commande, mais « Imprimante couleur de Frédérique » est préférable pour choisir la bonne imprimante dans une liste de possibilités. Le remplaçant de NBP doit donc autoriser peu ou prou tous les caractères Unicode, de préférence encodés en UTF-8. La section 3.5 rappelle également que des caractères comme . ou : doivent être autorisés dans les noms.

NBP était conçu pour fonctionner sans aucune configuration et la section 3.6 demande que son successeur en fasse autant, tout en pouvant tirer profit de l'infrastructure existante, s'il en existe une.

Un réseau sans configuration est très sympa, pas d'administrateur réseaux barbu et grognon à supporter, pas de formulaires à remplir, le rêve des utilisateurs : ils sortent le Mac tout neuf de sa boîte, le branchent, le nomment « Mon Macintosh » et c'est parti, sans rien demander à personne. C'est cool, oui, mais ce n'est pas sans risque. Que se passe t-il si Jean-Michel et Frédérique appelent tous les deux leur ordinateur « Mon Macintosh » ? Ou si le fabriquant d'imprimantes Brother livre des imprimantes qui sont toutes pré-configurées avec le nom « Brother Printer » ? La section 3.7 se consacre à la gestion des noms. Le remplaçant de NBP doit donc gérer ces cas. Pour une machine qui a un utilisateur humain juste en face, comme un ordinateur, on peut imaginer un message « Tiens, une autre machine nommée « Mon Mac » vient d'apparaître, voulez-vous changer le nom de la vôtre ? » Pour une machine sans écran et clavier, comme une imprimante, le logiciel doit d'autorité affecter un nouveau nom comme « Brother Printer 2 », l'utilisateur pouvant toujours la renommer ensuite. Attention, cette vérification d'unicité doit se faire en permanence, pas juste au démarrage, car les machines se déplacent et une nouvelle machine risque toujours d'apparaître.

Avec AppleTalk, mais aussi avec des techniques IP comme DHCP ou bien les adresses locales au lien (RFC 4862), une machine n'a pas d'adresse stable. Le logiciel ne doit donc pas, une fois la résolution faite, stocker des adresses. Il ne doit mémoriser que des noms et refaire une requête de résolution avant chaque connexion (section 3.8).

On l'a vu, NBP permet un mécanisme de joker, où le caractère = remplace n'importe quel nom. Ainsi, la requête NBP =:LaserWriter@MaZone signifie « N'importe quelle imprimante compatible dans MaZone ». Cela permet d'énumérer toutes les instances d'un service donné et de présenter une liste à l'utilisateur humain (section 3.10) et cette possibilité doit donc être gardée.

Autre demande pour l'interface utilisateur : le protocole doit fournir un moyen de présenter à l'humain une liste à jour en permanence (section 3.15). Pas question d'obliger ce dernier à cliquer sur Refresh et à attendre dix secondes l'apparition d'une nouvelle liste. Les nouvelles machines sur le réseau doivent donc pouvoir signaler leur présence tout de suite (sans que chaque machine ne doive interroger les autres en permanence, ce qui chargerait le réseau).

Cela commence à faire pas mal d'exigences mais la section 3.9 ajoute une méta-exigence difficile : que le logiciel soit suffisamment simple pour qu'il puisse être mis en œuvre dans des équipements bas de gamme (par exemple une imprimante à jet d'encre bon marché). Voir aussi la section 3.12 sur les économies d'énergie.

Autre méta-exigence, le protocole qui remplacera NBP doit être relativement stable sur le long terme (section 3.13). Pas question de le faire dépendre d'une mode comme par exemple le format de données structuré du moment (XML, JSON, etc sont sans doute visés, en des termes fort critiques pour l'industrie informatique).

Après une telle liste, on peut se demander s'il est possible de concevoir un protocole qui ait toutes ces qualités. La section 4 explore déjà un protocole existant. Question qui fâche : l'IETF n'a-t-elle pas déjà un protocole qui fait tout cela, SLP (RFC 2608) ? Non, répond le RFC : même s'il fournit bien plus de choses que ne faisait NBP en matière de découverte de services, SLP ne fait pas de détection de conflit, et n'a pas de mécanisme efficace de traduction de nom en adresse, la principale fonction de NBP.

Reste la question de la sécurité (section 6). AppleTalk et NBP n'en offraient aucune. C'est clairement un point où le nouveau protocole ne peut pas se contenter de faire « aussi bien » que NBP et où il doit faire mieux.

(Il avait existé un groupe de travail nommé Zeroconf mais qui n'était pas allé très loin, à part le RFC 3927. Le terme est donc surtout du marketing Apple.)


Téléchargez le RFC 6760


L'article seul

RFC 6761: Special-Use Domain Names

Date de publication du RFC : Février 2013
Auteur(s) du RFC : S. Cheshire (Apple), M. Krochmal (Apple)
Chemin des normes
Première rédaction de cet article le 20 février 2013


Parmi tous les noms de domaines existants, certains sont « spéciaux » au sens où ils ont des propriétés particulières ou ont été réservés pour un certain usage. Jusqu'à présent, il n'y avait pas de liste exhaustive de tels noms, ni de définition stricte, ni surtout de spécification des conséquences (par exemple, est-ce que les mises en œuvre du DNS sont censées traiter différemment ces noms ?) C'est désormais fait avec ce RFC, qui fournit une description de ces noms « spéciaux » et crée un registre où ils seront répertoriés. Écrit chez Apple, il a surtout pour but de permettre l'enregistrement direct (sans passer par l'ICANN) du TLD .local, utilisé unilatéralement par le protocole Apple Bonjour. L'utilisation sans vergogne de ce nom avait en effet suscité bien des critiques.

On peut faire une analogie avec les adresses IP : certaines sont « spéciales » (RFC 6890) et certaines de ces adresses spéciales sont reconnues par les mises en œuvre d'IP, qui les traitent d'une manière particulière. C'est par exemple le cas des adresses multicast comme 224.0.0.0 à 239.255.255.255 (en IPv4), ou comme l'adresse locale ::1 (en IPv6, cf. RFC 4291). Les noms de domaine ont un concept analogue avec les noms réservés du RFC 2606 comme example.org. Mais le RFC 2606 ne précise pas si un client ou un serveur DNS doit appliquer un traitement particulier à ces noms. Et il n'est pas extensible, il ne fournit pas de mécanisme d'enregistrement de noms supplémentaires. Si on voulait, mettons, ajouter un exemple IDN, il faudrait une nouvelle version du RFC 2606.

Pour mieux comprendre ce qu'est un nom de domaine « spécial » et ce que signifie un traitement spécial, reprenons l'exemple des adresses IP. Lorsque le multicast a été créé par le RFC 1112, les mises en œuvre d'IP ont du être modifiées pour reconnaître une adresse multicast et savoir en faire quelque chose. Ainsi, une adresse comme 224.0.0.1 (qui désigne toutes les machines à la fois) devenait « spéciale » et du code particulier était nécessaire (essayez de configurer une machine IP avec 224.0.0.1 comme adresse et vous verrez tout un tas de choses bizarres se produire, puisque cette adresse est traitée spécialement par la pile IP). Ce traitement spécial s'applique à toute machine IP, quel que soit le réseau auquel elle est connectée, et qu'elle utilise le multicast ou pas.

De la même façon, un nom de domaine va être spécial lorsqu'on aura besoin d'un traitement particulier de ce nom, par le logiciel. Le RFC donne l'exemple d'une norme qui utilise un nom dont on est certain qu'il n'existe pas (il renvoie toujours NXDOMAIN, le code de retour pour « domaine non existent »). On ne peut pas garantir un tel nom avec les procédures d'enregistrement actuelles. Prenons par exemple foobar.42, qui n'existe pas aujourd'hui. Même si la racine n'inclut pas un TLD .42, rien ne garantit qu'un résolveur quelque part ne va pas utiliser une autre racine ou, tout simplement, avoir une règle spéciale pour le TLD .42 (directives stub-zone ou local-zone dans Unbound, par exemple).

Si on veut garantir un certain comportement, il ne suffit donc pas de compter sur les règles d'enregistrement, il faut l'indiquer dans le code. (Et cela a l'avantage de couper court à la discussion sur le fait de savoir s'il faut que l'IETF débourse 185 000 $ à l'ICANN lorsqu'elle a besoin d'un TLD spécial.) À l'inverse, si on n'a pas besoin d'un comportement uniforme sur toutes les machines IP, connectées à l'Internet ou pas, alors on n'a pas besoin de ces noms spéciaux.

Bon, d'accord, les noms spéciaux sont cool, j'en veux un, comment je fais ? La section 3 expose les règles d'enregistrement dans la liste des domaines spéciaux. Il faut une norme ou bien une approbation de l'IESG (cf. RFC 5226). À noter que ce n'est pas juste un nom qui est ainsi réservé mais tout un sous-arbre des noms de domaines, commençant par ce nom. La demande de réservation d'un nom spécial doit préciser (section 5 du RFC) :

  • Si les utilisateurs humains doivent reconnaître ce nom comme différent et le traiter d'une manière spéciale.
  • Si les applications qui manipulent des noms de domaine (par exemple un navigateur Web) doivent reconnaître le caractère spécial de ce nom et le traiter différemment.
  • Si les bibliothèques de manipulation et de résolution des noms (par exemple getaddrinfo) doivent traiter ces noms spécialement.
  • Si les serveurs DNS récursifs (les résolveurs) doivent gérer ces noms de manière spécifique.
  • Si les serveurs DNS faisant autorité doivent appliquer une politique particulière pour ces noms.
  • Si les gérants des serveurs DNS doivent connaître ces noms spéciaux. Par exemple, si un serveur faisant autorité, par défaut, répond pour un tel nom, même sans avoir été configuré pour cela, que se passe-t-il si son opérateur tente de le configurer explicitement ?
  • Si les registres et bureaux d'enregistrement (curieusement, le RFC ne parle que de ces derniers, comme si tous les domaines permettant l'enregistrement imposaient le passage par un tel bureau) doivent traiter spécialement ces noms et, pas exemple, ne pas permettre leur enregistrement. Le RFC note avec humour qu'example.org est réservé par les procédures normales d'enregistrement et que le site Web derrière affirme au contraire que ce nom ne peut pas être enregistré.

Si la réponse à toutes ces sept questions est non (pas de traitement spécial), le RFC note que, dans ce cas, il vaut mieux abandonner l'enregistrement, qui n'a pas de sens.

Pour mieux comprendre les sept questions, voyons leur application aux domaines spéciaux qui font partie du registre initial. D'abord, les noms correspondant aux adresses IP privées du RFC 1918, par exemple 23.172.in-addr.arpa :

  • Les utilisateurs peuvent s'en servir comme ils veulent, une fois qu'on les a prévenu que ces noms, n'étant pas gérés par un registre, donneront probablement des résultats différents selon le lieu.
  • Les applications ne devraient pas considérer ces noms comme spéciaux.
  • Même chose pour les bibliothèques.
  • Mais les serveurs récursifs, eux, doivent traiter ces noms à part. Ils ne devraient pas chercher les résultats dans le DNS mais, par défaut, générer une réponse locale, afin de limiter la charge sur les serveurs de ces domaines (RFC 7534). (C'était déjà normalisé dans le RFC 6303, que notre RFC Apple ignore complètement.)
  • Même chose pour les serveurs faisant autorité.
  • Les opérateurs de serveurs DNS peuvent déclarer ces zones sur leurs serveurs, s'ils utilisent ces adresses.
  • Et évidemment les registres ne doivent pas permettre l'enregistrement de noms sous ces noms...

Autre exemple, le TLD .test qui avait été réservé par le RFC 2606 :

  • Les utilisateurs peuvent s'en servir, sachant que, le TLD n'étant pas enregistré, les résultats vont varier selon le lieu.
  • Applications et bibliothèques ne devraient pas avoir de code spécial pour ces noms.
  • Les serveurs DNS (récursifs ou faisant autorité) devraient par défaut traiter ces noms à part : pas de recherche dans le DNS et émission de réponse synthétisées localement (probablement NXDOMAIN par défaut). Le but est de ne pas embêter les serveurs racine avec ces noms bidon.
  • Mais les opérateurs des serveurs DNS sont libres de configurer leurs serveurs pour ces noms.
  • Et les registres ne devraient pas les enregistrer.

Les TLD .localhost et .invalid sont traités ensuite. Par exemple, pour .invalid, le fait de répondre NXDOMAIN est demandé (alors que, pour .test, ce n'était qu'une possibilité). D'autre part, pour ces deux TLD, il est recommandé que les bibliothèques de manipulation de noms de domaine traitent ces noms à part, n'envoyant pas de requêtes au résolveur DNS.

Quant aux domaines d'exemple du RFC 2606, il est également demandé qu'ils soient considérés comme spéciaux et ne génèrent pas de requêtes DNS (et, si c'est le cas, qu'elles reçoivent immédiatement une réponse négative). Ce n'est pas le cas actuellement et, comme vu plus haut, vous pouvez visiter http://www.example.org/.

Voilà, le registre géré par l'IANA est désormais en ligne et .local y a déjà été ajouté (RFC 6762). Le second TLD important qui a été mis dans ce registre a été le .onion dans le RFC 7686, en octobre 2015. Cet enregistrement a fait des vagues, et mené à des critiques, exprimées dans le RFC 8244.


Téléchargez le RFC 6761


L'article seul

RFC 6762: Multicast DNS

Date de publication du RFC : Février 2013
Auteur(s) du RFC : S. Cheshire (Apple), M. Krochmal (Apple)
Chemin des normes
Première rédaction de cet article le 20 février 2013


Après une très longue négociation (l'IETF n'était pas enthousiaste pour entériner le coup de force d'Apple), le protocole de résolution de noms « Multicast DNS » est désormais normalisé dans ce RFC. Multicast DNS permet de résoudre un nom de domaine en données (par exemple en adresses IP) sur le réseau local, sans faire appel à un serveur DNS configuré. Le demandeur claironne la question et la machine qui se reconnaît répond. Les noms résolus par Multicast DNS utilisent presque toujours le pseudo-TLD .local, décidé par Apple.

Le problème que tente de résoudre Multicast DNS est celui du réseau local rempli de petites machines (smartphones, tablettes, grille-pains, etc) et pas d'administrateur réseaux compétent pour configurer le tout. De tels réseaux sont de plus en plus fréquents. Trouver l'adresse IP du grille-pain par les mécanismes DNS classiques (un administrateur réseau installe un serveur DNS, puis ajoute grille-pain IN AAAA 2001:db8:1337::2 dans sa configuration) n'est pas envisageable. L'idée de base de Multicast DNS est de faire en sorte que chaque machine réponde aux requêtes pour son propre nom. Ainsi, pas besoin d'un serveur DNS configuré manuellement. Multicast DNS est donc une solution « zéro infrastructure ».

Multicast DNS est issu du projet de remplacement du protocole NBP d'AppleTalk, projet décrit dans le RFC 6760. L'idée de base, connue sous le nom de « Zeroconf » (le produit commercial d'Apple aujourd'hui se nomme « Bonjour ») était de rendre les réseaux IP aussi simples de configuration (pour un petit réseau sans importance) que l'étaient les réseaux AppleTalk. Au niveau de l'adressage, cela était déjà fait dans les RFC 3927 et RFC 4862, il restait à le faire pour le nommage.

Multicast DNS est du DNS (RFC 1034 et RFC 1035) au sens où il réutilise le format des paquets, les types de données et la syntaxe des noms. En revanche, le protocole utilisé pour la résolution de noms est nouveau. Il n'y a pas de récursion, la machine demandeuse diffuse simplement sur le réseau local sa question et la machine qui reconnaît son nom répond. Multicast DNS, qui n'est donc pas le DNS, tourne sur un autre port, le 5353.

Multicast DNS vise donc à être simple pour l'utilisateur (réseau sans administration). Mais le RFC est long et compliqué et plein de détails. Courage.

Avant de décrire plus en détail Multicast DNS, un peu de vocabulaire (section 2) :

  • Un enregistrement DNS partagé est un enregistrement où plusieurs machines peuvent légitimement répondre, pour le même nom et type.
  • Un enregistrement unique est un enregistrement qui est censé n'être géré que par une seule machine. Multicast DNS étant conçu pour des réseaux non administrés, les collisions seront sans doute fréquentes (tout le monde appelera son imprimante « printer »). Avant de servir un enregistrement unique, les machines devront donc s'assurer de cette unicité, en interrogeant le réseau pour savoir si quelqu'un d'autre répond déjà pour ce nom et ce type. (Pour des raisons de tolérance aux pannes, c'est permis, si les données servies sont les mêmes. Autrement, il y a conflit.)

La section 3 du RFC couvre un point délicat, les noms à utiliser. Le concurrent de Multicast DNS, LLMNR (RFC 4795) utilise des noms normaux comme gandalf.middleearth.example. Les concepteurs de Multicast DNS considèrent que tout le monde n'a pas de nom de domaine où y enregistrer ses machines et qu'il est donc nécessaire d'avoir un espace spécial pour mettre les engins qui répondent en Multicast DNS, le pseudo-TLD .local. Multicast DNS peut résoudre des noms habituels mais le cas privilégié est celui des noms se terminant par .local. Normalement, réserver un TLD nécessite une procédure lente et très coûteuse (185 000 $ uniquement pour déposer le dossier !), mais Apple semble avoir des privilèges particuliers et a pris ce TLD sans demander son avis à l'ICANN, ni suivre aucune procédure habituelle. C'était un des aspects les plus brûlants de cette norme, et qui avait suscité le plus de débats. Voir aussi annexe G.

Dans .local, toute machine peut « enregistrer » un nom, simplement en s'en proclamant propriétaire et en répondant aux requêtes Multicast DNS pour ce nom. Ainsi, si je nomme mon smartphone dumbledore, il répondra aux requêtes Multicast DNS dumbledore.local, et ce nom pourra être utilisé en argument des commandes comme ping, ou mis dans un URL (http://dumbledore.local/). L'utilisation d'un seul composant avant .local (ici, dumbledore) est recommandé.

Voici un dialogue Multicast DNS entre le PC/Ubuntu « tyrion » et le Raspberry Pi « alarmpi ». Tous les deux ont le logiciel Avahi. tyrion veut pinguer alarmpi :

09:11:25.650228 IP (tos 0x0, ttl 255, id 0, offset 0, flags [DF], proto UDP (17), length 59)
    192.168.2.26.5353 > 224.0.0.251.5353: [udp sum ok] 0 A (QM)? alarmpi.local. (31)
09:11:25.651092 IP (tos 0x0, ttl 255, id 0, offset 0, flags [DF], proto UDP (17), length 69)
    192.168.2.4.5353 > 224.0.0.251.5353: [bad udp cksum db2!] 0*- [0q] 1/0/0 alarmpi.local. (Cache flush) [2m] A 192.168.2.4 (41)

On voit que 192.168.2.26 (tyrion) a demandé à la cantonade (224.0.0.251) qui était alarmpi.local. La question était posée en multicast (QM). La réponse contenait l'adresse d'alarmpi, 192.168.2.4. Ensuite, tyrion veut résoudre cette adresse en nom, il va faire une requête PTR :

09:11:25.779570 IP (tos 0x0, ttl 255, id 0, offset 0, flags [DF], proto UDP (17), length 70)
    192.168.2.26.5353 > 224.0.0.251.5353: [udp sum ok] 0 PTR (QM)? 4.2.168.192.in-addr.arpa. (42)
09:11:25.780463 IP (tos 0x0, ttl 255, id 0, offset 0, flags [DF], proto UDP (17), length 91)
    192.168.2.4.5353 > 224.0.0.251.5353: [bad udp cksum 8d1!] 0*- [0q] 1/0/0 4.2.168.192.in-addr.arpa. (Cache flush) [2m] PTR alarmpi.local. (63)

.local, quoique non enregistré dans le RFC 2606 est donc un nom spécial. Les noms dans ce pseudo-TLD n'ont pas de signification globale, un peu comme les adresses IP locales au lien des RFC 3927 et RFC 4291. Les requêtes pour un nom se terminant en .local sont donc envoyées en Multicast DNS aux adresses de diffusion restreinte 224.0.0.251 ou ff02::fb (désormais enregistrées à l'IANA - idem en IPv6, cf. section 22). Les autres noms peuvent aussi être résolus en Multicast DNS mais ce n'est pas l'usage. Cela permettrait à la résolution de noms locaux de fonctionner, même en cas de coupure de l'accès Internet. Mais cela poserait de gros problèmes de sécurité puisque, en Multicast DNS, n'importe quelle machine du réseau local peut répondre « oui, je suis onlinebanking.banqueserieuse.example ». Le RFC demande que DNSSEC, ou un mécanisme équivalent, soit alors utilisé...

Naturellement, il peut y avoir des conflits, puisqu'il n'y a pas de registre chargé d'attribuer les noms de manière unique. Multicast DNS résout ce problème en testant un nom sur le réseau local avant de l'utiliser. S'il est déjà utilisé, la machine Multicast DNS fait marche arrière et choisit un autre nom.

Multicast DNS peut aussi être utilisé pour la résolution d'adresse en nom (section 4). Dans ce cas, il n'utilise pas .local mais les noms en .arpa des adresses IP locales au lien, 254.169.in-addr.arpa et de 8.e.f.ip6.arpa à b.e.f.ip6.arpa.

Une fois les noms décidés, reste à envoyer les requêtes et à y répondre. Il existe deux acteurs, le demandeur, ou client (Querier) et le répondeur, ou serveur (Responder). Multicast DNS a deux modes (section 5) : envoi unique et envoi continu. Le premier est très proche du fonctionnement actuel du DNS. Le demandeur Multicast DNS envoie un paquet vers 224.0.0.251:5353 ou [ff02::fb]:5353 et attend la réponse. Le client n'a même pas besoin de savoir que c'est une adresse multicast. Il suffit donc de changer quelques lignes de code dans le client, pour dire « si le nom se termine par .local, envoie le paquet DNS à [ff02::fb]:5353, sinon envoie au résolveur normal ». (Il faut aussi éviter d'utiliser le port source 5353 car celui-ci indique un client Multicast DNS complet, qui utilise le second mode.) Rappelez-vous que Multicast DNS utilise le format habituel des paquets DNS donc la construction du paquet de requête et l'analyse de la réponse ne changent pas.

Un tel client simple acceptera probablement la première réponse qui arrivera. Cela a quelques inconvénients. Si on réclame myprinter.local et que plusieurs imprimantes sur le réseau local portent ce nom, seule la plus rapide à répondre sera prise en compte. Il est donc préférable de patcher un peu plus le demandeur et d'en faire un client Multicast DNS complet, utilisant le second mode.

Ce deuxième mode de fonctionnement, en continu, ne va pas se contenter de la première réponse, mais va continuer jusqu'à une conclusion satisfaisante. Par exemple, si un navigateur Web veut se connecter à http://myprinter.local/controlpanel, la conclusion est satisfaisante quand la page est affichée. Si l'utilisateur est en train de naviguer dans le réseau local à la recherche de ressources (par exemple avec le Service Discovery du RFC 6763), la conclusion n'arrive que lorsque la fenêtre de navigation est fermée (tant que ce n'est pas le cas, il peut y avoir des nouvautés à afficher et il faut continuer l'interrogation). Dans le cas de recherche d'une imprimante cité plus haut, cela permet de ne pas se limiter à l'imprimante qui a le répondeur Multicast DNS le plus rapide, mais de s'assurer au contraire qu'on a reçu de l'information de toutes les imprimantes.

Pour cela, le répondeur va donc tourner en permanence, et répéter les questions, notant les nouvelles réponses, jusqu'à ce que le programme qui lui a demandé une résolution qui signale qu'il n'est plus intéressé.

Pour indiquer la gestion complète de Multicast DNS, y compris le mode d'interrogation en continu, le demandeur utilise le port source 5353 dans ses requêtes. Multicast DNS détourne un bit (section 5.4) dans le champ « classe » des paquets (champ quasi-inutilisé puisque seule la classe IN - pour Internet - est réellement déployée) pour indiquer si la réponse doit elle-même être envoyée en diffusion ou en unicast. Le fonctionnement normal est que la réponse elle-même soit diffusée, pour permettre aux autres clients Multicast DNS du réseau local d'en prendre connaissance, économisant ainsi du trafic. Le bit est mis alors à zéro dans ces requêtes QM (Query Multicast, comme dans l'exemple entre tyrion et alarmpi plus haut), et c'est en général ce que vous verrez dans la sortie de tcpdump si vous surveillez le trafic Multicast DNS. Sinon, si le bit est mis à un, les requêtes sont QU (Query Unicast) et la réponse sera envoyée en unicast. Voici le dialogue précédent, entre tyrion et alarmpi, vu par tshark : mdns1-tshark.txt.

Et le répondeur, que doit-il faire (section 6) ? Multicast DNS n'a pas la distinction entre résolveur/cache et serveur faisant autorité, qui est si importante dans le DNS. Un répondeur fait toujours autorité, il ne met jamais dans la réponse les informations qu'il a apprises sur le réseau. Avec Multicast DNS, on ne sert que ses propres informations. Si le répondeur a l'information demandé, il répond avec autorité (bit AA - Authoritative Answer - mis à un), sinon, il ne répond tout simplement pas. C'est donc un comportement très différent de celui d'un serveur DNS habituel.

Si le répondeur a déterminé qu'un nom, mettons example.local, était unique et chez lui, il répond positivement aux requêtes sur ce nom, s'il a des données sur le type demandé. Il répond négativement s'il n'en a pas (par exemple à une requête pour des adresses IPv4 si le répondeur ne connait qu'une adresse IPv6, sections 6.1 et 20). Si le nom est partagé, et que le répondeur n'a pas d'information, il ne répond pas, il n'envoie pas de NXDOMAIN. S'il a de l'information (par exemple, il sait qu'il est le seul majoliemachine.local sur le réseau) et que la question porte sur un type qu'il n'a pas, il renvoie une réponse avec un enregistrement NSEC (voir l'annexe E pour les raisons du choix). Celui-ci joue un rôle analogue à celui qu'il a en DNSSEC : dire clairement qu'on n'a pas une information (voir section 20 aussi).

Comme tous les protocoles « zéro configuration », Multicast DNS peut être assez bavard et il y a donc des règles pour limiter le trafic, comme de retarder aléatoirement la réponse, pour éviter que tous les répondeurs ayant une information ne veulent émettre en même temps sur l'Ethernet.

À noter que, dans la grande majorité des cas, le répondeur ne répond pas en unicast mais en multicast. Le but est de permettre aux autres machines Multicast DNS d'observer les réponses (cf. section 10.5 et annexe D). D'une manière générale, les répondeurs coopèrent en écoutant les réponses des autres. Si le nom est partagé, il n'y a pas de problème. Si un répondeur détecte une réponse pour un nom qui est censé être unique et dont il est détenteur, il y a conflit et on passe alors à la section 9. (Si les données dans la réponse sont identiques, par contre, il n'y a pas de conflit : cela permet de répartir le travail entre plusieurs répondeurs, par exemple pour la résistance aux pannes.)

Les requêtes de type ANY (où le demandeur veut la totalité des enregistrements, quel que soit leur type) sont un cas particulier (section 6.5). Dans le DNS, elles ont une sémantique subtile et beaucoup d'utilisateurs se trompent à ce sujet, croyant par exemple d'un récurseur va leur renvoyer tous les enregistrements qui existent, alors qu'il n'envoie que ceux qu'il a dans son cache. Avec Multicast DNS, c'est plus simple : comme tous les répondeurs sont des serveurs faisant autorité, la réponse à une requête ANY est toujours complète, elle inclut tous les enregistrements pour un nom.

J'ai déjà parlé de l'intensité du trafic que peut générer Multicast DNS sur le réseau local. La section 7 regroupe un ensemble de techniques de « réduction de bruit », qui permettent de limiter ce trafic. Bien sûr, sur un LAN, la capacité réseau ne coûte pas trop cher. Néanmoins, il est toujours plus sympa de ne pas abuser de la ressource partagée. Par exemple, si un demandeur connait déjà une partie des réponses, il les inclut dans le paquet de requête. Les répondeurs savent alors que ce n'est pas la peine d'y répondre. (Cela ne concerne en général que les noms partagés.) On économise ainsi un paquet (celui de la réponse).

Autre cas, si un répondeur s'apprête à répondre mais voit passer sur le réseau une réponse identique à celle qu'il allait donner, il se tait. Si plusieurs répondeurs ont les mêmes données, il n'est donc pas nécessaire, bien au contraire, qu'ils répondent tous. Au passage, c'est une excellente illustration de l'intérêt qu'il y a à envoyer les réponses en multicast, pour que les autres puissent les lire.

Avant de commencer son service, un répondeur doit savoir ce qu'il y a sur le réseau local, et notamment si d'autres répondeurs traiteront le même nom. C'est le sondage (probing) et c'est couvert en section 8. Le sondage est suivi de l'annonce (announcing). Ces deux opérations doivent être faites dès que la connectivité de la machine change (démarrage, arrivée sur un nouveau réseau, coupure/reconnexion du câble, etc).

D'abord, le sondage. Si le répondeur gère des noms censés être uniques, il doit envoyer une requête sur le réseau pour ces noms (avec le type ANY). Normalement, elle ne doit pas avoir de réponse. Avant d'envoyer la requête, on attend un court délai aléatoire (entre 0 et 250 ms), aléatoire afin d'éviter, en cas de coupure de courant, par exemple, ou de remise en service d'un commutateur, que tout le réseau ne hurle en même temps. Cette requête est répétée trois fois mais cela veut dire que le délai total, pour une machine existante, pour défendre son nom contre un nouveau venu, est relativement court, sur certains réseaux lents. Le sondage peut donc ne pas détecter tous les conflits et il est donc nécessaire, en phase de fonctionnement normal, d'écouter en permanence les requêtes des autres et d'y répondre immédiatement (pas de délai aléatoire, cette fois).

Si un conflit est détecté, la machine doit renoncer à ce nom et en chercher un autre (par exemple en demandant à son utilisateur humain).

Ça, c'était le sondage, pour voir si quelqu'un utilisait « mon » nom. Et l'annonce ? Décrite en section 8.3, elle consiste, une fois que le sondage est fait, à répondre (sans qu'il y ait eu de question) en diffusant tous ses enregistrements. Un écoutant passif saura alors que ce nom est pris et pourra mettre à jour son cache. Pour être sûr que cette « réponse » soit reçue, on en transmet au moins deux exemplaires. Par contre, on ne répéte pas cette réponse non sollicitée périodiquement ; elle n'est renvoyéee que si la connectivité réseau change ou bien si les données changent (section 8.4). Dans ce dernier cas, il n'est pas nécessaire de répéter l'étape du sondage, puisqu'on sait que le nom est déjà unique.

Maintenant, voyons un cas très difficile mais qui est fréquent sur les réseaux non-gérés pour lesquels Multicast DNS est fait : le conflit (section 9). Un répondeur a un nom unique, monmactrescher.local et il entend tout à coup sur le réseau une réponse Multicast DNS pour le même nom ! Il y a conflit ! Quelqu'un d'autre a pris ce nom ! Si les données sont les mêmes, ce n'est pas grave (c'est même une technique utilisée par Multicast DNS pour la résistance aux pannes). Mais si elles sont différentes, que faire ? Si un demandeur envoie une requête pour l'adresse IP de monmactrescher.local, que va-t-il recevoir ? La mienne ou celle du méchant qui a pris le même nom pour sa machine ? Le résultat ne sera pas du tout le même ! Le RFC impose que, dès qu'un conflit est détecté, toutes les machines en conflit repartent à la section 8 et recommencent les étapes de sondage et d'annonce. Une des deux machines va alors l'emporter, l'autre devra changer de nom. Ce changement peut se faire manuellement (« Une autre machine sur le réseau se nomme monmactrescher. Choisissez un autre nom. ») ou automatiquement (le RFC suggère d'ajouter « 2 » à la fin du nom, « 3 » si monmactrescher2.local existe déjà, etc.) Dans le cas où le nom a été changé automatiquement, le RFC suggère de prévenir l'utilisateur, par une boîte de dialogue si la machine a une interface graphique, par des moyens adaptés sinon (SNMP, par exemple).

Une des métadonnées dans les enregistrements DNS est le TTL. Quelle valeur doit être utilisée en Multicast DNS (section 10) ? Le RFC recommande, pour les enregistrements liés à un nom de machine, notamment les adresses IP, 2 minutes (valeur faible, mais rappelez-vous qu'il n'existe pas d'équivalent des résolveurs/caches en Multicast DNS ; chaque machine fait autorité et a un cache). Pour les autres, la valeur demandée est de 75 minutes. Cette valeur, au contraire de la première, peut sembler élevée. Des informations dépassées pourraient rester plus d'une heure dans les caches. Mais plusieurs techniques permettent de limiter le risque :

  • Les paquets d'adieu : lorsqu'une machine sait que ses enregistrements vont changer (par exemple lorsqu'elle est en train de s'éteindre), elle envoie une réponse avec ses données, mais un TTL de zéro, pour vider les caches.
  • Les réponses gratuites : lorsqu'une machine connait un changement, dans ses données ou dans sa connectivité, elle envoie une réponse non sollicitée, qui va remplacer les vieilles valeurs qui se trouvaient dans les caches.
  • L'observation passive des échecs : la section 10.5 décrit un algorithme astucieux. Si un répondeur a une information dans son cache (« l'adresse IP de le Mac de Mic.local est 2001:db8:1337::2 »), qu'il voit passer une requête par un tiers (« quelle est l'adresse IP de le Mac de Mic.local ? ») mais qu'il ne voit passer aucune réponse (le Mac de Mic est éteint...), alors ce répondeur sait qu'il peut virer l'enregistrement de son cache.

Vous avez déjà noté (je reviendrais là-dessus plus tard en discutant la section 21 du RFC) que Multicast DNS n'offre aucune sécurité : n'importe quelle machine peut répondre n'importe quoi. Pour limiter les risques, le RFC impose quelques vérifications sur l'origine du paquet (section 11). Le test que le TTL était à 255, qui était dans les premières versions du protocole, a été abandonné (j'ignore pourquoi car ce test, décrit dans le RFC 5082, est simple et efficace). En revanche, le récepteur d'un paquet Multicast DNS envoyé à une adresse unicast doit vérifier que l'adresse IP source est bien sur le réseau local (un test qui, pour être utile, suppose que le pare-feu interdit l'entrée du réseau local aux paquets ayant une adresse IP source de ce réseau). Si le paquet a une adresse de destination multicast, pas besoin d'autre test, on compte que le routeur d'entrée de site ne l'aurait pas laissé passer, de toute façon.

Les noms utilisés par Multicast DNS ont quelques caractéristiques spéciales par rapport au DNS auquel on est habitué. La section 12 liste ces caractéristiques, qui peuvent dérouter l'administrateur système qui connait le DNS (s'il ne ne connnait pas, il peut sauter cette section). D'abord, les noms en .local n'ont une signification que... locale. Autrefois, le DNS était prévu pour qu'un nom ait partout le même sens et que sa résolution donne partout le même résultat. Aujourd'hui, avec des bricolages comme le split view de BIND, ou comme les pare-feux, ce n'est déjà plus le cas. Avec Multicast DNS c'est encore plus marqué. machine à café.local ne pointera donc pas vers les mêmes données selon le lieu où on se trouve.

D'autre part, il n'y a pas de délégation dans Multicast DNS et donc pas d'enregistrements NS. Si une machine répond à machine à café.local, rien ne garantit qu'elle réponde à sucre.machine à café.local.

Ah, et un point de multilinguisme : le FQDN n'est pas prévu pour être montré aux utilisateurs. Le RFC précise donc qu'il ne faut pas traduire le .local...

Comme tout le monde n'a pas forcément envie de faire du Multicast DNS, la section 13 du RFC précise que le fait de passer en Multicast DNS pour un nom qui ne se termine pas en .local devrait être configurable par l'utilisateur. Et, pour des raisons de sécurité, devrait être débrayée par défaut. (Sinon, www.mabanque.example pourrait être résolue par Multicast DNS, avec son absence de sécurité...)

Dans les exemples cités ci-dessus, vous avez déjà vu des noms qui peuvent sembler surprenants, par exemple parce qu'ils comportents des espaces. La section 16 discute du cas des noms ayant des caractères sortant du traditionnel LDH (Letter-Digit-Hyphen avec Letter restreint à US-ASCII). Il faut bien noter que, contrairement à ce qu'affirme une légende tenace, le DNS a toujours permis tous les caractères. La restriction à LDH est une tradition, maintenue de crainte de planter les applications qui se croient dans un monde purement anglophone. Multicast DNS a l'avantage de la nouveauté et n'a pas d'héritage à assumer : dès le début, tous les noms peuvent être en Unicode, encodé en UTF-8 (dans le profil du RFC 5198). Notez bien que Multicast DNS n'utilise pas Punycode (l'annexe F discute cet excellent choix).

Cela a toutefois quelques conséquences qui peuvent sembler déroutantes. Ainsi, Multicast DNS, comme le DNS, prétend être insensible à la casse. Mais ce n'est vrai que pour les caractères ASCII. La machine MyPrinter.local va répondre aux requêtes Multicast DNS pour myprinter.local mais Machine À Café.local ne répondra pas pour machine à café.local ! Pour faire une telle équivalence, il faurait fallu s'aventurer dans la jungle des conversions de casse en Unicode, un sujet très complexe (dans certains cas, cela dépend de la langue).

Pour les mêmes raisons, Multicast DNS ne fournit pas d'équivalence automatique, par exemple entre version accentuée et non accentuée d'un nom. Si on cherche machine à café.local, on ne trouvera pas machine a cafe.local. Si on veut que cela fonctionne, il faut que le répondeur décide de répondre à tous ces noms (ou bien que quelqu'un ait créé des enregistrements CNAME).

Continuous cette longue exploration des points de détails qui font que Multicast DNS est plus compliqué qu'il n'en a l'air à première vue. La section 17 étudie le problème de la taille des paquets. Au tout début, il y a très longtemps, du temps des dinosaures, les paquets DNS étaient limités à 512 octets. Cette limite a sauté il y a des années, et, de toute façon, elle n'a guère de sens en réseau local, le domaine de Multicast DNS. Il n'y a pas non plus de problème de découverte de la MTU du chemin. Les paquets Multicast DNS peuvent donc avoir la taille de la MTU du réseau. La fragmentation IP est bien sûr possible, mais déconseillée.

Quel est le format exact des paquets Multicast DNS (section 18) ? Bien sûr, c'est du DNS. Mais il y a quelques particularités. Je ne vais pas répéter toute la section 18 mais je note deux points :

  • Le bit TC (troncation) a une sémantique différente de celle du DNS : utilisé dans une question, il indique que le demandeur connait d'autres réponses, qu'il va les envoyer, et que le répondeur devrait donc attendre un peu avant de répondre.
  • Le champ Classe de la question a été détourné : son bit de plus fort poids indique, s'il est mis à un, qu'on préfère une réponse en unicast. Il n'est donc pas possible, avec Multicast DNS, d'avoir des classes > 127 (pas en problème en pratique, seules trois classes ont été enregistrées jusqu'à présent).

D'ailleurs, quelles sont les différences entre Multicast DNS et le DNS ? La section 19 offre un utile résumé. Quelques points qui méritent d'être retenus (la liste exacte est bien plus longue) :

  • Port 5353 et pas 53,
  • Un TLD dédié, .local,
  • Pas de SOA, pas de NS,
  • UTF-8 systématique,
  • Plusieurs questions dans un paquet Question,
  • Les requêtes de type ANY donnent toujours le même résultat,
  • Il peut y avoir des réponses sans qu'aucune question n'ait été posé (annonces gratuites),
  • Surveillance des questions et des réponses des autres, pour apprendre ce qui se passe.

Et, par contre, ce qui ne change pas :

  • Même syntaxe des noms de domaine,
  • Mêmes types d'enregistrement,
  • Mêmes API.

Arrivé à ce stade, il est temps de faire un tour complet de la sécurité de Multicast DNS. La section 21 est consacrée à ce point. Pour résumer, Multicast DNS n'offre aucune sécurité, encore moins que le DNS normal. Multicast DNS suppose que tous les participants coopèrent sincèrement. En cas de désaccord, il n'existe par définition aucune autorité supérieure qui pourrait trancher. Multicast DNS est une parfaite an-archie et, comme pour tous les protocoles « zéro-configuration », est donc très difficile à sécuriser. Si on craint la présence d'un ou plusieurs méchants sur le réseau local, la première solution est d'utiliser un autre protocole. Si on connait les gentils, on peut toujours utiliser IPsec, pour être sûr de ne communiquer qu'avec les gentils (je trouve cette idée curieuse, IPsec n'étant pas spécialement « zéro-configuration »...) DNSSEC est également bien sûr une solution possible (mais il a le même problème). DNSSEC est évidemment impératif si on utilise Multicast DNS pour résoudre des noms en dehors de .local. Notons au passage que ce modèle de sécurité pose un problème à l'utilisateur : celui-ci devra prêter attention aux noms et savoir que .local est moins sûr. Un défi pour Monsieur Toutlemonde. C'est en raison de cette sécurité inexistante de .local que le RFC demande que les logiciels n'ajoutent pas automatiquement .local à un nom qui soit déjà un FQDN (par exemple www.example.com) mais seulement à des noms faits d'un seul composant.

La section 22.1 revient sur les domaines que Multicast DNS considère comme spéciaux et sur leur usage : si les applications peuvent les traiter à part, elles ne sont pas obligées (Multicast DNS fonctionne donc avec les applications existantes). (Tous les détails sur ces « noms spéciaux » figurent dans le RFC 6761.) Pour que Multicast DNS fonctionne bien, c'est la bibliothèque de résolution de noms (la libc sur Unix) qui doit reconnaitre ces noms comme spéciaux, et les passer à Multicast DNS. D'autres acteurs de l'Internet doivent également veiller à considérer ces noms comme spéciaux : par exemple, un bureau d'enregistrement ne doit pas permettre leur location, un hébergeur DNS ne doit pas permettre de les gérer, etc.

Dans la plupart des RFC, il n'y a pas de justification des choix effectués, et on passe souvent beaucoup de temps à méditer devant la norme en se demandant « pourquoi X et pas Y ? » Ce n'est pas le cas ici, et ce RFC fournit plusieurs annexes (non normatives) détaillant les raisons des différents choix. Une très bonne lecture pour comprendre. Ainsi, l'annexe A explique pourquoi utiliser un port spécifique (5353) et pas le standard 53. Réutiliser l'ancien port aurait permis de ne pas modifier du tout les bibliothèques de résolution de noms mais :

  • Multicast DNS n'est pas le DNS,
  • Utiliser le même port aurait rendu difficile d'utiliser à la fois un répondeur Multicast DNS et un serveur DNS classique sur la même machine,
  • Le port 53, sur certains systèmes, est réservé à root.

L'annexe B, elle, répond à une question plus rigolote : pourquoi utiliser une seule adresse Multicast (ff02::fb en IPv6) plutôt que de condenser le nom demandé, utilisant le résultat de cette condensation comme adresse, diminuant ainsi la charge sur les répondeurs (pas besoin de traiter les paquets qui arrivent pour d'autres noms que ceux qu'on gère) ? IPv6 fait cela dans le RFC 4861. Mais cela a des défauts : les machines ayant beaucoup de noms peuvent avoir besoin de s'inscrire à beaucoup de groupes multicast, on ne peut plus utiliser plusieurs questions dans un même paquet si elles portent sur des noms différents (ou, plus exactement, se condensent en des adresses différentes), et surtout des tas de fonctions de réduction de trafic (comme l'écoute du trafic des autres) ne fonctionnent plus.

L'annexe E explique comment NSEC a été choisi pour encoder les réponses négatives. Le code de retour NXDOMAIN est global au paquet et ne convient donc pas s'il y avait plusieurs questions dans une même requête. Une autre possibilité envisagée avait été d'utiliser des enregistrements dont les données étaient de taille nulle. Mais, dans certains cas, on peut avoir besoin de tels enregistrements, sans qu'ils soient interprétés comme une réponse négative. Il ne restait donc que les enregistrements NSEC.

Et l'annexe G ? Elle discute des conflits possibles entre des usages locaux du TLD .local et Multicast DNS. Un certain nombre de sites ont en effet utilisé un pseudo-TLD local pour nommer les machines internes. .local semble le nom le plus répandu mais on en trouve d'autres (.prive, .intranet, .home, etc). Le RFC note que c'est bien sûr une mauvaise idée, entre autres parce qu'elle rentre en collision avec Multicast DNS. Malheureusement, cette annexe a aussi la mauvaise idée de suggérer d'autres noms possibles, alors qu'ils ont des problèmes analogues.

L'annexe H décrit la longue histoire de Multicast DNS : depuis la première proposition de faire tourner NBP sur IP, en 1997, aux premières mises en œuvre et au premier Internet-Draft en 2000, jusqu'aux premiers vrais déploiements en 2002.

Finalement, l'IETF a entériné l'existant (processus connu sous le nom peu flatteur de rubber-stamping, allusion aux tampons de l'administration), marquant son mécontentement uniquement par de longs délais.

Aujourd'hui, il existe de très nombreuses mises en œuvre de Multicast DNS. Citons parmi d'autres :

Si vous aimez regardez des pcap, attention sur pcapr.net, il y a plein de traces étiquetées mdns qui n'en sont pas. Mais d'autres le sont par exemple http://www.pcapr.net/view/tyson.key/2009/8/2/8/WebSense_and_mDNS.pcap.html ou http://www.pcapr.net/view/tyson.key/2009/9/6/6/Storage_Protocols_2.html.


Téléchargez le RFC 6762


L'article seul

Un cas compliqué d'utilisation d'un préfixe AfriNIC en dehors de l'Afrique

Première rédaction de cet article le 18 février 2013
Dernière mise à jour le 19 février 2013


On le sait, les adresses IPv4 sont désormais épuisées dans la plupart des régions du monde et pas mal de sites n'ont toujours pas déployé IPv6, rendant cette pénurie pénible. Il est donc tentant, plutôt que de faire l'effort d'un passage à IPv6, d'aller chercher des adresses IPv4 là où il y en a encore, notamment en Afrique. On a souvent dit que des entreprises extérieures au continent allaient « faire leurs courses » en Afrique en créant une filiale bidon qui allait demander à AfriNIC des adresses qui seraient ensuite annoncées ailleurs. Mais, là, c'est plus amusant, c'est un préfixe qui fait partie de la réserve AfriNIC mais qui n'est pas enregistré via AfriNIC.

Commençons par le commencement : un service français nommé Qwant fait pas mal de publicité (avec même l'aide d'une ancienne ministre) et annonce un site Web en http://www.qwant.com/. L'adresse IP correspondante peut être trouvée facilement et vaut 154.45.216.7. Toute adresse IP utilisée sur l'Internet fait partie d'un réseau qui est documenté publiquement, via le protocole whois. Est-ce le cas ici ?

% whois 154.45.216.7
% This is the AfriNIC Whois server.

% Note: this output has been filtered.

% Information related to '154.0.0.0 - 154.255.255.255'

inetnum:        154.0.0.0 - 154.255.255.255
netname:        AFRINIC-20090508
...

On est renvoyé à AfriNIC mais, là, il n'y a rien, aucune déclaration correspondant à ce réseau. Il n'est pas affecté. C'est tout à fait anormal. Creusons un peu.

Le préfixe 154.0.0.0/8 vu ci-dessus est bien à AfriNIC. On le voit à l'IANA en regardant la liste des allocations où on lit {154/8; Administered by AFRINIC ; (depuis) 1993-05 ; whois.afrinic.net}. Notez la date : le préfixe a été utilisé avant car, en 1993, AfriNIC n'existait pas (Wayback Machine montre qu'en 2003, ce préfixe était encore various registries). Mais, aujourd'hui, il est censé être entièrement chez AfriNIC, avec toutefois des affectations qui avaient été faites avant. Le RIR africain n'a pas affecté de blocs dans ce préfixe, comme on le voit en regardant la liste des affectations aujourd'hui. On y voit que la délégation sous 154.0.0.0/8 n'a pas encore commencé, ce qui est normal, AfriNIC ayant encore plusieurs /8. Mais c'est bien cette réserve importante (alors qu'APNIC et le RIPE-NCC ont épuisé la leur) qui peut en tenter certains.

Bon, mais alors comment se fait-il que ce préfixe fantôme fonctionne ? C'est parce qu'il n'y a nul besoin qu'un préfixe soit enregistré pour fonctionner. N'importe qui peut annoncer n'importe quoi, surtout si personne d'autre ne le fait. On peut voir l'annonce du préfixe englobant 154.45.216.7 par plusieurs moyens :

% bgproute 154.45.216.7
AS path: 3130 2914 174
Route: 154.40.0.0/13

Ou par des services sur le Web comme chez Hurricane Electric ou au RIPE-NCC. Conclusion en regardant ce qui se passe dans le monde des routes annoncées en BGP : enregistré ou pas, documenté via whois ou pas, 154.40.0.0/13 est bien vivant, il est annoncé par Cogent (l'AS 174), depuis au moins 2006 (je ne sais pas si les statistiques remontent pas au delà) et il fonctionne (on peut joindre cette adresse). traceroute nous montre que le site est bien chez Cogent, dans les environs de Paris :

% traceroute 154.45.216.7
traceroute to 154.45.216.7 (154.45.216.7), 30 hops max, 60 byte packets
 1  freebox (192.168.2.254)  10.117 ms  10.100 ms  10.091 ms
 2  88.189.152.254 (88.189.152.254)  36.830 ms  36.834 ms  36.835 ms
 3  78.254.1.62 (78.254.1.62)  38.480 ms  38.490 ms  38.491 ms
 4  rke75-1-v900.intf.nra.proxad.net (78.254.255.42)  38.395 ms  38.399 ms  41.759 ms
 5  cev75-1-v902.intf.nra.proxad.net (78.254.255.46)  40.177 ms  41.744 ms  41.764 ms
 6  * * *
 7  th2-crs16-1-be1002.intf.routers.proxad.net (212.27.57.217)  35.829 ms  64.348 ms  66.053 ms
 8  th2-9k-1-be1000.intf.routers.proxad.net (212.27.59.206)  30.479 ms  30.481 ms  30.473 ms
 9  * ix-15-547.tcore1.PVU-Paris.as6453.net (195.219.241.173)  32.592 ms  32.603 ms
10  te0-0-0-23.ccr21.par04.atlas.cogentco.com (130.117.15.33)  36.124 ms te0-7-0-23.ccr21.par04.atlas.cogentco.com (130.117.15.37)  41.034 ms  41.041 ms
11  te0-5-0-2.mpd22.par01.atlas.cogentco.com (154.54.58.233)  41.341 ms te0-6-0-4.mpd22.par01.atlas.cogentco.com (130.117.0.157)  41.349 ms te0-1-0-4.ccr22.par01.atlas.cogentco.com (130.117.48.145)  41.329 ms
12  te1-1.ccr01.par05.atlas.cogentco.com (130.117.1.70)  42.823 ms te8-1.ccr01.par05.atlas.cogentco.com (154.54.58.122)  99.808 ms te3-1.ccr01.par05.atlas.cogentco.com (154.54.39.74)  99.798 ms
13  te2-1.ccr01.par13.atlas.cogentco.com (154.54.61.90)  101.346 ms  99.259 ms  99.253 ms
14  * * *
15  * * *
...

S'agit-il d'un « vol », d'un « détournement » ? Ce n'est pas si simple. D'abord, personne d'autre n'est titulaire de ce préfixe. Son utilisation par Cogent et son client Qwant ne gêne donc personne, tant qu'AfriNIC ne commence pas à utiliser ce préfixe (auquel cas il faudra faire attention à ces allocations du passé). Ensuite, certes, il n'y a aucune trace de l'enregistrement de ces adresses dans les bases AfriNIC mais AfriNIC est quand même au courant puisque le domaine DNS 45.154.in-addr.arpa (servant aux résolutions d'adresses en noms) est bien délégué par AfriNIC à Cogent. Peut-être y a-t-il simplement eu un cafouillage, facilité par l'héritage ancien de ce préfixe. On constate en effet que le serveur whois d'ARIN, lui, renvoie chez Cogent (notez la date) :

% whois -h whois.arin.net 154.45.216.7
...
NetRange:       154.45.0.0 - 154.45.255.255
CIDR:           154.45.0.0/16
OriginAS:       AS174
NetName:        COGENT-154-45-16
NetHandle:      NET-154-45-0-0-1
Parent:         NET-154-0-0-0-0
NetType:        Direct Assignment
RegDate:        1992-02-05
...

Found a referral to rwhois.cogentco.com:4321.

%rwhois V-1.5:0010b0:00 rwhois.cogentco.com
154.45.216.7
network:ID:NET4-9A2DD8001C
network:Network-Name:NET4-9A2DD8001C
network:IP-Network:154.45.216.0/28
network:Postal-Code:75008
network:Country:FR
network:City:Paris
network:Street-Address:11 Rue Marbeuf
network:Org-Name:Qwant
network:Tech-Contact:ZC108-ARIN
network:Updated:2012-03-01 18:16:32
network:Updated-by:Bill Garrison

Quelles conclusions en tirer ? D'abord, que d'être absent (ou mal présent) des bases des RIR, et donc de la plupart des IRR, n'empêche pas un préfixe de fonctionner (le serveur du RIPE lui voit une visibilité quasi-parfaite). Ensuite que le marais (les adresses affectées avant le système des RIR) est mal rangé. Enfin, que l'Internet est quand même très complexe.

Le problème avait été trouvé à l'origine par arapaho. Merci à Jean-Philippe Pick pour son aide pour l'analyse. Merci aussi à Stephen D. Strowes pour son voyage dans le temps, et aux équipes de Cogent et d'AfriNIC pour des réponses rapides et correctes.


L'article seul

RFC 6873: Format for the Session Initiation Protocol (SIP) Common Log Format (CLF)

Date de publication du RFC : Février 2013
Auteur(s) du RFC : G. Salgueiro (Cisco), V. Gurbani (Bell Labs, Alcatel-Lucent), A. B. Roach (Tekelec)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF sipclf
Première rédaction de cet article le 15 février 2013


La question d'un format standard et commun pour la journalisation des événements SIP est exposée et discutée dans le RFC 6872. Ce RFC 6873, lui, spécifie un format standard conforme aux exigences et au modèle de données du RFC 6872. Techniquement, sa principale originalité est d'être un format texte... indexé. Il a donc les avantages des formats textes (lisible sans outil particulier, utilisable avec des outils génériques comme grep ou awk) tout en gardant de bonnes performances si on développe des outils qui lisent ces index.

Le projet d'un format standard pour les journaux de SIP s'appuie évidemment sur le grand succès du CLF des serveurs HTTP. Ce format CLF a facilité la vie de tous les administrateurs système, et a permis le développement de plein d'outils de statistiques et d'analyse. Il a toutefois quelques défauts, le principal étant de performance. Si on cherche un champ de taille variable, comme le nom de la ressource demandée, il faut parcourir chaque ligne jusqu'à ce champ. Or, en SIP, les lignes peuvent être longues (SIP est plus complexe que HTTP et il y a plein de choses à journaliser), d'où le souhait d'un format où on puisse sauter facilement à un champ donné. Les formats binaires permettent cela, mais au prix de la souplesse et de la facilité : il faut en effet des outils spécialisés pour tout accès au journal. Le nouveau format décrit par ce RFC va essayer de vous donner le beurre (le format texte lisible et facile à traiter) et l'argent du beurre (l'indexation, pour sauter directement aux informations intéressantes). Ce format « ASCII indexé » est une innovation : peu de programmes utilisent cette technique. En raison de sa nouveauté dans le monde IETF, ce choix a fait l'objet de chaudes discussions dans le groupe de travail.

La section 4 du RFC décrit ce format : chaque événement est journalisé sous forme d'un enregistrement qui compte deux lignes. La première, qui commence toujours par une lettre, est un ensemble de métadonnées et de pointeurs vers les champs principaux. Tous sont de taille fixe et donc d'accès direct rapide. La seconde, qui commence toujours par un chiffre, comprend les champs eux-mêmes, dans l'ordre indiqué par le RFC. Ces champs sont de taille variable, mais indexés par les pointeurs cités plus haut. Il y a les champs obligatoires (définis par le modèle de données du RFC 6872) comme From: ou bien l'adresse IP source, et les champs facultatifs. Pour les champs obligatoires, toute l'astuce est dans les pointeurs. Ils sont à un emplacement fixe de la première ligne (pour être trouvés facilement) et ils pointent vers l'octet de la deuxième ligne où se trouve le champ. Pour connaître la fin du champ, on regarde simplement le pointeur suivant, qui indique le début du champ suivant. Ainsi, si on veut l'adresse IP de destination, on lit les octets 20 à 23 de la première ligne (006D dans l'exemple suivant), puis les octets 24 à 27 pour avoir le pointeur suivant (007D). Entre ces deux pointeurs (109 à 125 en décimal), on trouve 192.0.2.10:5060. (Pour les champs optionnels, il faut faire une analyse syntaxique classique.) Voici un exemple d'un enregistrement (section 5 du RFC) :

A000100,0053005C005E006D007D008F009E00A000BA00C700EB00F70100
1328821153.010	RORUU	1 INVITE	-	sip:192.0.2.10	192.0.2.10:5060	192.0.2.200:56485	sip:192.0.2.10	-	sip:1001@example.com:5060	DL88360fa5fc	DL70dff590c1-1079051554@example.com	S1781761-88	C67651-11

On note que les champs numériques (les pointeurs) sont encodés en chiffres hexadécimaux, et pas en binaire (pour faciliter l'analyse par des outils orientés texte). Ce petit programme en Python (récupéré sur le Wiki du groupe de travail) permet de décoder l'enregistrement :

% python sip-clf-reader.py sip.log 
String length 257

str=005C CSeq             message[83:92] = 1 INVITE

str=005E Response         message[92:94] = -

str=006D ReqURI           message[94:109] = sip:192.0.2.10

...

Ici, on avait un programme spécifique comprenant ce format. Et si on veut utiliser les outils texte traditionnels ? La section 6 donne quelques détails à ce sujet. La méthode recommandée est de sauter les lignes d'index (elles commencent toujours par une lettre) et de ne traiter que les lignes de données (elles commencent toujours par un chiffre décimal, qui encode l'estampille temporelle). Ensuite, on éclate la ligne de données en champs, ceux-ci étant séparés par une tabulation. C'est moins rapide que les index, mais plus simple pour les utilisateurs de awk.

Merci à Régis Montoya pour sa relecture.


Téléchargez le RFC 6873


L'article seul

RFC 6872: The Common Log Format (CLF) for the Session Initiation Protocol (SIP): Framework and Information Model

Date de publication du RFC : Février 2013
Auteur(s) du RFC : V. Gurbani (Bell Laboratories, Alcatel-Lucent), E. Burger (Georgetown University), T. Anjali (Illinois Institute of Technology), H. Abdelnur, O. Festor (INRIA)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF sipclf
Première rédaction de cet article le 15 février 2013


Un logiciel connecté à l'Internet a tout intérêt à enregistrer ses activités dans un « livre de bord » dont la lecture permettra notamment d'analyser ce qui s'est produit. Une des histoires à succès de la journalisation est celle des serveurs Web qui disposent, depuis longtemps, d'un format de journalisation standard, le Common Log Format (CLF). Ainsi, des logiciels comme Apache et Squid produisent des journaux compatibles, ce qui a permis de développer d'innombrables outils d'analyse et de statistiques pour ce format. Mais le protocole SIP, contrairement à HTTP, n'avait pas un tel format, chaque logiciel SIP journalisait comme cela lui plaisait. Ce fut le travail du groupe SIPCLF de l'IETF que de développer 1) un cadre standard de journalisation, dans ce RFC 6872 2) un format standard utilisant ce cadre, dans le RFC 6873.

Un exemple de journal au format CLF produit par Apache est :

192.0.2.219 - - [03/Feb/2013:07:33:07 +0000] "GET /samknows.html HTTP/1.0" 200 3923 "http://www.bortzmeyer.org/" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.112 Safari/535.1" www.bortzmeyer.org

Mais HTTP a un modèle d'interaction très simple, chaque requête (ici, GET /samknows.html qui veut dire « passe moi la page samknows.html x) étant complète et autonome. SIP est plus complexe et justifie donc une approche plus élaborée (la section 7 détaille cette différence entre les deux protocoles).

La section 3 du RFC synthétise la définition du problème : la variété des formats de journaux utilisés par les logiciels SIP rendent les analyses pénibles (particulièrement lorsqu'on veut analyser un appel qui est passé par plusieurs logiciels). Il faut donc un format commun. Il doit être utilisable par des outils simples en ligne de commande (un format fondé sur XML ne conviendrait donc pas). Il doit être cherchable de manière efficace (un journal SIP peut grossir très vite, c'est un protocole bavard), ce qui n'est pas le cas du CLF des serveurs HTTP, où il faut faire une analyse syntaxique de chaque ligne. Et, enfin, il doit pouvoir être généré facilement par tous les logiciels, sans dépendre de bibliothèques qui ne sont pas forcément disponibles partout (rien que pour cela, la famille ASN.1 ne convient donc pas).

La section 4, elle, est l'anti-cahier des charges, elle expose tout ce que le format commun de journaux SIP n'est pas : ce n'est pas un mécanisme de facturation (il se focalise sur la signalisation et ne voit donc pas l'échange de contenu), ce n'est pas un outil de mesure de la qualité de service, et ce n'est pas un outil d'espionnage, il n'est pas prévu pour aider Big Brother.

Le groupe de travail avait envisagé quatre possibilités, toutes abandonnées, avant de s'attaquer à la définition d'un format commun (section 5) :

  • Utiliser les Call Detail Records traditionnels de la téléphonie. Plutôt conçus pour la facturation, ces CDR ne contiennent pas toute l'information dont on a besoin pour déboguer des problèmes SIP. Par exemple, le CDR contiendra plutôt les coordonnées de l'abonné et pas les champs From: et To: de SIP (qui peuvent être différents de l'abonné). En outre, les CDR sont typiquement générés par des serveurs intermédiaires, alors que le format commun de SIP pourra être utilisé partout (par exemple par les softphones). Enfin, le monde SIP est bien plus large que celui des telcos : des universités, par exemple, utilisent SIP, sans pour autant générer de CDR.
  • Utiliser de la capture de paquets, genre pcap. Ces outils comme Wireshark savent parfaitement décoder le SIP. Mais ce mécanisme ne répond pas à l'exigence « pouvoir utiliser grep » du cahier des charges. Il ne correspond pas forcément à ce que le logiciel SIP peut faire (sur un téléphone Android, le client SIP n'a pas le droit de faire une capture de paquets directement sur l'interface, alors qu'il a analysé tous les champs du paquet et peut donc facilement les journaliser). Et enfin, si on utilise TLS, cette approche peut être impossible, les paquets étant chiffrés.
  • Et syslog (RFC 5424) ? Sa principale limite est qu'il ne spécifie pas le format du contenu des messages. Et toute entité SIP n'a pas forcément un serveur syslog facilement accessible.
  • Il reste IPFIX (RFC 7011). Mais ce n'est pas un outil de journalisation, il ne produit pas ce que l'on cherche ici.

La section 6 revient sur les motivations de ce travail, en faisant une liste complète des scénarios d'usage du futur format commun :

  • Une référence commune entre différents outils SIP. Utilisant le même modèle de données, leurs journaux seront comparables.
  • La possibilité d'écrire des logiciels d'analyse génériques. Pensez à la variété et à la qualité des outils d'analyse de journaux HTTP (comme analog), rendues possibles par le format commun.
  • Corrélation entre événements se situant sur des serveurs différents. Un appel SIP peut passer par pas mal de machines qui, dans le plus compliqué des cas, appartiennent à des domaines administratifs différents.
  • Analyse de tendances, comme la détermination des heures de pointe selon le domaine,
  • Entraîner des IDS comme dans l'article « A Self-learning System for Detection of Anomalous SIP Messages »,
  • Test de matériels et de logiciels SIP, en utilisant des appels réels, journalisés, comme scénarios à rejouer,
  • Analyse d'incident (« l'appel a été coupé au bout de trois minutes, que s'est-il passé exactement ?  »),
  • Et bien d'autres encore.

Armé de ces considérations, le RFC définit ensuite (section 8) le modèle informationnel du journal SIP, c'est-à-dire la liste de ce qu'il faut journaliser (rappelez-vous que la syntaxe du journal n'apparaîtra que dans le RFC 6873). Ce modèle comprend une liste de champs obligatoires et la possibilité de journaliser des champs facultatifs.

D'abord, les champs obligatoires (je donne une liste non exhaustive, voir la section 8.1 du RFC pour la liste complète) :

  • Estampille temporelle,
  • Adresses IP source et destination,
  • Ports source et destination,
  • Expéditeur et destinataire (dans SIP, ce sont les champs From: et To:, qui contiennent des URI),
  • Résultat (status code),
  • Identificateur de la transaction, pour le client et pour le serveur,
  • ...

Comme leur nom l'indique, les champs obligatoires doivent être présents mais, dans certains cas, un champ donné n'a pas de sens pour cet évenement et le format doit alors spécifier un moyen de représenter cette absence.

La section 9 fournit quelques exemples (mais attention, ce sont des exemples pour illustrer le modèle informationnel, pas pour illustrer la syntaxe, qui n'est pas définie par ce RFC, mais dans le RFC 6873). Dans tous les exemples, Alice, en 198.51.100.1:5060, essaie d'appeler Bob, qui a deux téléphones actifs, un en 203.0.113.1:5060 et un en [2001:db8::9]:5060. Alice et Bob ont chacun un fournisseur, respectivement P1 (198.51.100.10:5060) et P2 (203.0.113.200:5060).

Ainsi, lorsque le softphone d'Alice s'enregistre auprès de son fournisseur SIP, le message SIP sera journalisé :

Timestamp: 1275930743.699
Message Type: R
Directionality: s
Transport: udp
CSeq-Number: 1
CSeq-Method: REGISTER
R-URI: sip:example.com
Destination-address: 198.51.100.10
Destination-port: 5060
Source-address: 198.51.100.1
Source-port: 5060
To: sip:example.com
To-tag: -
From: sip:alice@example.com
From-tag: 76yhh
Call-ID: f81-d4-f6@example.com
Status: -
Server-Txn: -
Client-Txn: c-tr-1

On note les champs sans valeur comme Status, puisqu'il s'agit d'une requête, il n'y a pas encore de réponse. Lorsqu'elle arrive, le journal va enregistrer :

Timestamp: 1275930744.100
Message Type: r
Directionality: r
Transport: udp
CSeq-Number: 1
CSeq-Method: REGISTER
R-URI: -
Destination-address: 198.51.100.1
Destination-port: 5060
Source-address: 198.51.100.10
Source-port: 5060
To: sip:example.com
To-tag: reg-1-xtr
From: sip:alice@example.com
From-tag: 76yhh
Call-ID: f81-d4-f6@example.com
Status: 100
Server-Txn: -
Client-Txn: c-tr-1

SIP peut aussi fonctionner en pair-à-pair, sans fournisseur. Ici, Alice appelle Bob :

Timestamp: 1275930743.699
Message Type: R
Directionality: s
Transport: udp
CSeq-Number: 32
CSeq-Method: INVITE
R-URI: sip:bob@bob1.example.net
Destination-address: 203.0.113.1
Destination-port: 5060
Source-address: 198.51.100.1
Source-port: 5060
To: sip:bob@bob1.example.net
To-tag: -
From: sip:alice@example.com
From-tag: 76yhh
Call-ID: f82-d4-f7@example.com
Status: -
Server-Txn: -
Client-Txn: c-1-xt6

et Bob répond positivement (résultat 200) :

Timestamp: 1275930746.100
Message Type: r
Directionality: r
Transport: udp
CSeq-Number: 32
CSeq-Method: INVITE
R-URI: -
Destination-address: 198.51.100.1
Destination-port: 5060
Source-address: 203.0.113.1
Source-port: 5060
To: sip:bob@example.net
To-tag: b-in6-iu
From: sip:alice@example.com
From-tag: 76yhh
Call-ID: f82-d4-f7@example.com
Status: 200
Server-Txn: -
Client-Txn: c-1-xt6

La traditionnelle section sur la sécurité (section 10) appelle à quelques règles de prudence : les journaux contiennent des données personnelles et leur gestion doit se faire en prenant en compte les questions de protection de la vie privée. Pas question donc de mettre des journaux en accès libre. Le modèle d'information décrit dans ce RFC est suffisamment détaillé pour dispenser un attaquant qui aurait accès aux journaux d'écouter le trafic SIP. Le RFC suggère même d'étudier des méthodes de protection plus avancées comme le chiffrement du disque qui contient les journaux et la transmission des journaux uniquement par des canaux sécurisés, par exemple avec TLS.

Autre risque de sécurité, celui d'un dépassement de tampon : les entrées dans un journal SIP peuvent être très longues (surtout avec les champs optionnels) et un analyseur naïf qui utiliserait des structures de données de taille fixe pourrait se faire déborder.

La section 11 contient d'autres conseils utiles, pour les opérateurs cette fois : elle rappelle que les journaux sont facilement de grande taille, qu'un mécanisme de rotation (par exemple avec logrorate) est nécessaire.

Merci à Olivier Festor et Régis Montoya pour leur relecture.


Téléchargez le RFC 6872


L'article seul

Peut-on « débrider » sa connexion YouTube avec le DNS ?

Première rédaction de cet article le 11 février 2013


Une société vient de clamer qu'elle pouvait « débrider gratuitement l'accès à certains sites comme Youtube qui est bridé par votre fournisseur d'accès à internet ». Est-ce possible ? Et, si oui comment font-ils ?

On comprend le modèle d'affaires de cette société. Un grand nombre d'internautes sont en effet très mécontents du peu de fluidité des flux vidéo avec certains services comme YouTube. En effet, le conflit entre les fournisseurs de service comme Google (propriétaire de YouTube) et les FAI (comme Free ou Orange) autour du problème « qui va payer ? » amène parfois à ne pas augmenter la capacité du réseau qui relie le fournisseur de services au FAI, voire à restreindre délibérement cette capacité (« bridage »). (C'est l'une des facettes de la question dite de « neutralité du réseau ».) Depuis de nombreux mois, par exemple, regarder des vidéos YouTube depuis Free est très pénible, avec des arrêts soudains, des dizaines de secondes passées à regarder tourner un indicateur de chargement, etc. Les dirigeants de Free clamant bien fort qu'ils ne résoudront le problème que lorsque Google aura cédé et les paiera, il est logique que les « freenautes » cherchent des solutions, ce que leur FAI ne fait pas.

La société Speed-DNS prétend qu'elle a une telle solution, qu'elle peut « [garantir] une vitesse de streaming aussi importante que chez les autres opérateurs.  ». Or, Speed-DNS est simplement un service de résolveurs DNS. Elle fournit deux résolveurs, identifiés par leurs adresses IP, 178.33.182.34 et 5.135.158.150, qu'on peut utiliser à la place de ceux normalement fournis par son FAI (voir la documentation de Speed-DNS). Quel est l'intérêt ? Un résolveur DNS est un composant quasi-indispensable d'un accès à l'Internet. C'est le serveur auquel on donne un nom de domaine comme www.bouletcorp.com ou www.ati.tn et qui répond par l'adresse IP du serveur correspondant, adresse qui sera utilisée par les machines pour communiquer. Normalement, un résolveur en vaut un autre, car ils donnent tous la même réponse. L'internaute typique se sert donc de ceux fournis par son FAI, configurés automatiquement via la box. Toutefois, depuis quelque temps, deux facteurs ont mené à l'apparition de services de résolveurs DNS publics, distincts de ceux du FAI. Le plus connu est Google Public DNS. D'abord, certains FAI offrent un service médiocre, en fiabilité ou en temps de réponse, poussant certains à aller voir ailleurs un meilleur service (souvent sans mesurer, en faisant une confiance aveugle à la publicité du service). Mais certains FAI font pire. Normalement, un résolveur DNS n'est qu'un relais : il transmet les questions de l'utilisateur aux serveurs DNS faisant autorité (par exemple, pour www.ati.tn aux serveurs de l'ATI) et relaie les réponses vers l'utilisateur. Or, certains FAI modifient les réponses DNS dans le résolveur, pour servir aux utilisateurs de fausses informations. Ce sont les DNS menteurs. Un exemple est le service AdGate de Free (désormais désactivé par défaut, donc ne mentant que si l'utilisateur l'a explicitement réclamé). Ce mensonge peut être imposé par la loi, à des fins de censure, comme le fait l'ARJEL. Utiliser un résolveur DNS public situé dans une autre juridiction peut donc permettre de contourner ces mensonges. (Mais attention, certains résolveurs DNS publics ont leurs propres mensonges.)

Et qu'est-ce que cela change pour YouTube ? Faisons un petit détour vers le fonctionnement de YouTube. Lorsque l'utilisateur se connecte à YouTube, le point de départ est le nom de domaine youtube.com. Via le résolveur DNS, il est ensuite traduit en un groupe d'adresses IP, le navigateur Web va alors se connecter à une de ces adresses (en utilisant HTTP), récupérer une page contenant à son tour des informations sur la source du flux vidéo (où on trouve des noms comme r12---sn-25g7rn7l.c.youtube.com), le navigateur se connectera à ces sources et recevra la vidéo. Le résolveur DNS ne peut rien faire sur le flux vidéo lui-même qui ne passe pas par le DNS. Un résolveur DNS comme celui de Speed-DNS n'a pas de possibilité d'action ici. Que peut-il donc faire ? Speed-DNS répond « on ne va pas dévoiler nos systèmes internes en public ». Qui peut être assez naïf pour avaler un tel argument ? « J'ai mis au point un système pour faire des recherches sur le Web dix fois plus vite qu'avec Google. Je ne vais pas le dévoiler car je ne veux pas me faire piquer l'idée mais il me faut 20 M€ pour le financer, merci de m'envoyer un chèque. »

Pourtant, un résolveur DNS a des possibilités : il peut mentir (pour la bonne cause), en donnant comme adresse IP de YouTube une autre adresse IP que l'officielle. Quel intérêt ? Cette adresse IP pourrait être, par exemple, celle d'un service de relais, comme il en existe déjà pour contourner les bridages.

J'ai mis tout cela au conditionnel : en effet, il faut d'abord tester que l'interrogation des résolveurs DNS de Speed-DNS montre un tel effet. Par exemple, depuis Free, en utilisant l'outil de débogage dig, la réponse renvoyée par le résolveur standard (dans la Freebox) est (j'ai abrégé pour simplifier) :

% dig youtube.com
...
;; ANSWER SECTION:
youtube.com.			74.125.230.229
youtube.com.			74.125.230.225
youtube.com.			74.125.230.230
youtube.com.			74.125.230.231
youtube.com.			74.125.230.233
youtube.com.			74.125.230.224
youtube.com.			74.125.230.227
youtube.com.			74.125.230.228
youtube.com.			74.125.230.232
youtube.com.			74.125.230.226
youtube.com.			74.125.230.238

;; Query time: 40 msec
;; SERVER: 192.168.2.254#53(192.168.2.254)           <--- Le résolveur dans la Freebox
;; WHEN: Mon Feb 11 08:44:20 2013

Alors que celle renvoyée par le résolveur de Speed-DNS est :

% dig @178.33.182.34 youtube.com
...
;; ANSWER SECTION:
youtube.com.			173.194.41.78
youtube.com.			173.194.41.64
youtube.com.			173.194.41.65
youtube.com.			173.194.41.66
youtube.com.			173.194.41.67
youtube.com.			173.194.41.68
youtube.com.			173.194.41.69
youtube.com.			173.194.41.70
youtube.com.			173.194.41.71
youtube.com.			173.194.41.72
youtube.com.			173.194.41.73
...
;; Query time: 58 msec
;; SERVER: 178.33.182.34#53(178.33.182.34)
;; WHEN: Mon Feb 11 08:52:08 2013

D'autres adresses, miraculeusement plus rapides ? Non. Comme on peut le tester avec whois, ces adresses sont également chez Google et une recherche de leur connectivité avec traceroute montrent qu'on les atteint par la même route, en passant par les mêmes tuyaux. L'adresse donnée par le résolveur de Free :

% traceroute  74.125.230.229 
traceroute to 74.125.230.229 (74.125.230.229), 30 hops max, 60 byte packets
 1  192.168.2.254 (192.168.2.254)  0.460 ms  0.469 ms  0.380 ms
 2  88.189.152.254 (88.189.152.254)  22.790 ms  23.970 ms  24.443 ms
 3  78.254.1.62 (78.254.1.62)  25.469 ms  25.563 ms  25.525 ms
 4  rke75-1-v900.intf.nra.proxad.net (78.254.255.42)  26.754 ms  26.797 ms  28.618 ms
 5  cev75-1-v902.intf.nra.proxad.net (78.254.255.46)  28.611 ms  29.653 ms  29.885 ms
 6  p16-6k-1-po12.intf.nra.proxad.net (78.254.255.50)  30.920 ms  26.093 ms *
 7  th2-crs16-1-be1002.intf.routers.proxad.net (212.27.57.217)  27.883 ms  25.887 ms  29.845 ms
 8  cbv-9k-1-be1002.intf.routers.proxad.net (212.27.59.9)  31.298 ms  31.328 ms  32.510 ms
 9  74.125.50.116 (74.125.50.116)  91.574 ms google-pni-3.routers.proxad.net (212.27.40.102)  92.001 ms 74.125.50.116 (74.125.50.116)  93.148 ms
10  72.14.238.228 (72.14.238.228)  34.098 ms  35.280 ms  35.603 ms
11  209.85.242.51 (209.85.242.51)  49.916 ms  50.083 ms  49.745 ms
12  par08s10-in-f5.1e100.net (74.125.230.229)  38.188 ms  39.238 ms  23.775 ms

Et celle donnée par Speed-DNS :

% traceroute  173.194.34.8
traceroute to 173.194.34.8 (173.194.34.8), 30 hops max, 60 byte packets
 1  192.168.2.254 (192.168.2.254)  0.578 ms  0.467 ms  0.419 ms
 2  88.189.152.254 (88.189.152.254)  24.557 ms  25.586 ms  25.731 ms
 3  78.254.1.62 (78.254.1.62)  27.030 ms  27.066 ms  27.057 ms
 4  rke75-1-v900.intf.nra.proxad.net (78.254.255.42)  28.425 ms  28.408 ms  29.838 ms
 5  cev75-1-v902.intf.nra.proxad.net (78.254.255.46)  29.904 ms  30.903 ms  30.968 ms
 6  * p16-6k-1-po12.intf.nra.proxad.net (78.254.255.50)  60.155 ms *
 7  th2-crs16-1-be1002.intf.routers.proxad.net (212.27.57.217)  60.847 ms  25.848 ms  34.256 ms
 8  cbv-9k-1-be1002.intf.routers.proxad.net (212.27.59.9)  34.233 ms  35.785 ms  35.815 ms
 9  google-pni-3.routers.proxad.net (212.27.40.102)  94.137 ms 72.14.216.98 (72.14.216.98)  95.981 ms google-pni-3.routers.proxad.net (212.27.40.102)  95.775 ms
10  72.14.238.234 (72.14.238.234)  38.538 ms  109.822 ms  39.354 ms
11  209.85.242.45 (209.85.242.45)  42.286 ms  42.052 ms  42.013 ms
12  par03s02-in-f8.1e100.net (173.194.34.8)  42.321 ms  23.875 ms  23.746 ms

On voit qu'on suit la même route, on passe par les mêmes endroits (google-pni-3.routers.proxad.net est à l'interconnexion de Google et de Free, PNI veut dire Private Network Interconnection et elle est toujours surchargée). Et la cible se trouve probablement dans le même bâtiment (dans par03s02-in-f8.1e100.net, par désigne sans doute Paris, vus les temps de réponse en milli-secondes indiqués ensuite).

Mais attention, rappelez-vous la description du fonctionnement de YouTube : ce n'est pas lors de la connexion avec le serveur Web de YouTube que des problèmes peuvent se produire, c'est lors de l'envoi de la vidéo, qui se fait sur une connexion différente et via des noms différents. Testons ceux-ci. Sans Speed-DNS :

% dig A r12---sn-25g7rn7l.c.youtube.com
...
;; ANSWER SECTION:
r12---sn-25g7rn7l.c.youtube.com. --->	r12.sn-25g7rn7l.c.youtube.com.
r12.sn-25g7rn7l.c.youtube.com. 173.194.20.49
...
;; Query time: 34 msec
;; SERVER: 192.168.2.254#53(192.168.2.254)
;; WHEN: Mon Feb 11 09:11:29 2013

Et avec Speed-DNS :

% dig @178.33.182.34 A r12---sn-25g7rn7l.c.youtube.com
...
;; ANSWER SECTION:
r12---sn-25g7rn7l.c.youtube.com.  178.33.182.34
...
;; Query time: 37 msec
;; SERVER: 178.33.182.34#53(178.33.182.34)
;; WHEN: Mon Feb 11 09:12:37 2013

Cette fois, on voit un effet, l'adresse IP renvoyée est chez OVH, pas chez Google (c'est la même adresse que le serveur de noms de Speed-DNS). Si on configure sa machine pour utiliser les serveurs de noms de Speed-DNS, et qu'on examine son trafic avec tcpdump, on voit en effet que, lors du visionnage d'une vidéo YouTube, un important trafic TCP sur le port 80 a lieu avec 178.33.182.34 : le trafic vidéo a été détourné vers la machine de Speed-DNS à OVH, contournant ainsi le bridage. Rien de miraculeux ou d'innovant, donc, c'est exactement la même chose que les services de VPN qu'on achète ou qu'on fait soi-même.

Maintenant, est-ce que cela accélère les choses ? Une seule machine à OVH, qui sert aussi bien de serveur DNS que de relais vidéo ne va pas pouvoir encaisser beaucoup de trafic. Ça marche pour l'instant car il y a peu de clients, mais, en pratique, il reste à voir si cela tiendra la charge.

Il y a d'autres choses à raconter sur Speed-DNS, sur l'état de leur réseau ou sur les autres caractéristiques de leurs résolveurs mais, ici, je me suis focalisé sur leur prétention à accélérer YouTube.


L'article seul

Un peu d'Arch Linux

Première rédaction de cet article le 10 février 2013


Il existe des dizaines (des centaines ?) de systèmes d'exploitation autour du noyau Linux et des logiciels GNU (notez que je n'aime pas le terme de distribution Linux, souvent employé). Il y a les très connus (comme Ubuntu ou Fedora), les marginales et, entre les deux, des systèmes comme Arch Linux, qui a une petite communauté d'utilisateurs fidèles.

Certains petits cerveaux ricanent de ce nombre élevé de systèmes différents, comme les dictateurs ricanent du nombre élevé de partis politiques dans une démocratie. Mais le grand nombre de systèmes d'exploitation utilisant Linux n'est pas seulement une conséquence de la liberté et du succès. C'est aussi parce que ces systèmes sont différents, optimisant tel ou tel aspect au détriment des autres. Pour ne pas être déçu d'un système qu'on a essayé, il faut donc se renseigner avant, sur le système qu'on va installer, pour être sûr qu'il corresponde à ce que l'on veut. Donc, Arch Linux est optimisé pour 1) la légéreté en nombre et taille des logiciels 2) la souplesse (on peut facilement faire les choses différemment). Le tout, vous vous en doutez, est atteint en sacrifiant la facilité d'utilisation. Comme le dit la documentation, Simple design and implementation shall always trump simple user interface. Arch Linux n'est pas pour les gens effrayés ou simplement débutants en Unix. Ce n'est pas à tort qu'on dit souvent qu'Arch Linux est la nouvelle Slackware.

Ses caractéristiques le rendent particulièrement adapté pour les environnements limités (vieux PC sur lesquels Ubuntu rame épouvantablement, engins à faibles ressources), pour les bricoleurs et pour les étudiants en informatique.

L'installation étant particulièrement... peu conforme aux standards d'aujourd'hui (même Debian et NetBSD sont mille fois plus simples à installer), je vais commencer par une machine déjà installée. Pour avoir une telle machine, on peut prendre un engin pour lequel il existe déjà des images toutes faites d'Arch Linux (c'est le cas du Raspberry Pi, une plate-forme pour lequel Arch Linux est bien adapté) ou bien louer un VPS chez un fournisseur qui a des images Arch Linux (c'est le cas de l'excellent Linode). Une telle solution permet de débuter avec Arch Linux sans se confronter à l'installation (qui est ardue). (À partir d'ici, je vais mettre des liens vers les excellentes documentations du site officiel. Je commence par le texte décrivant les principes d'Arch Linux puis par le bon guide du débutant qui, une fois l'installation faite, explique les étapes suivantes.)

Parmi les points qui différencient le plus les différents systèmes GNU/Linux se trouve le gestionnaire de paquetages. Celui d'Arch Linux se nomme pacman. Il dispose des commandes classiques d'un tel outil :

  • Chercher un paquetage par son nom pacman -Ss $PACKAGE,
  • Installer un paquetage pacman -S $PACKAGE,
  • Avoir des informations sur un paquetage installé pacman -Qi $PACKAGE,
  • Trouver quel paquetage a installé un fichier donné pacman -Qo $FILE,
  • Et bien sûr mettre tout le système à jour pacman -Syu.

Sur ce dernier point, notez bien une importante caractéristique d'Arch Linux : il n'y a pas de versions d'Arch Linux, Arch Linux utilise un principe connu sous le nom de rolling release qui consiste à n'avoir qu'une seule version, toujours en cours de changement. Lorsqu'on gère une machine Arch Linux, et qu'on fait un pacman -Syu tous les matins, il y a quasiment toujous au moins un changement, parfois assez disruptif (comme l'arrivée de systemd il y a quelques mois). Si on utilise des machines Arch Linux en production, il est donc recommandé de suivre les canaux d'information soigneusement, avant toute mise à jour.

Question mise à jour, un autre point à noter est que les dépôts « officiels » d'Arch Linux ne contiennent pas tout (je n'y ai pas trouvé Icinga) et sont moins riches que ceux de Debian, par exemple. Pour compenser cela, il existe un dépôt supplémentaire géré directement par les utilisateurs (et donc, pas forcément bien testé, ni très sûr), l'AUR. L'utilisation de l'AUR n'étant pas forcément aisée, des tas de programmes ont été développés pour aider. Personnellement, j'utilise pacaur, qui a l'avantage de reprendre les commandes de pacman et de traiter le dépôt officiel et l'AUR ensemble. Un seul pacaur -Syu suffit donc à mettre tout à jour. Lorsqu'il rencontre un paquetage qui est en source dans l'AUR, il lance la compilation, autrement, il installe le binaire.

Voilà, l'administration quotidienne d'une Arch Linux n'est donc pas très compliquée, il faut juste penser à suivre l'actualité pour ne pas faire une mise à jour désastreuse. Et si on est nostalgique de Gentoo et qu'on veut recompiler soi-même certains paquetages ? (Cela m'est arrivé sur une machine Linode, ou sur un Raspberry Pi, car Net-SNMP ne fonctionne pas, se plaignant de l'absence de bus PCIpcilib: Cannot open /proc/bus/pci, ce qui impose l'utilisation d'un paquetage spécial, et d'une entrée IgnorePkg = net-snmp dans /etc/pacman.conf pour qu'il ne soit pas écrasé lors des mises à jour.) Ce processus de compilation est bien documenté. En gros, on va dans le répertoire où se trouve le fichier PKGBUILD, on l'édite selon ses goûts et on fait makepkg -s.

Et l'installation initiale ? Eh bien, elle est fidèle aux principes d'Arch Linux, par exemple A freshly installed Arch Linux system contains only basic core components with no automatic configuration performed. L'installation est très bien documentée mais il n'existe pas de logiciel qui vous guide. Il faut suivre pas à pas le guide d'installation. Mëme si tout marche bien, vous vous retrouvez avec un Unix très sec (même pas de mot de passe pour le compte root si vous avez sauté cette partie de la documentation d'installation) et où plein de choses devront être configurées, du fuseau horaire au clavier en passant par le client DHCP. Le pire étant sans doute l'installation du chargeur de démarrage pour lequel le guide d'installation vous dit juste de voir la documentation du chargeur choisi... (Lire la page concernant Grub est assez rude. D'autres systèmes ont des documentations compliquées mais, si on ne le lit pas, cela marche quand même. Pas Arch Linux.)

Pire, le programme d'installation est plus intelligent pour lui-même que pour le système qu'il installe. Ainsi, en installant sur un vieux portable muni d'une carte Ethernet PCMCIA, le programme d'installation la reconnait et lance le réseau sans problème mais, ensuite, il installe un système qui n'a pas les modules PCMCIA et qui n'a donc pas de réseau jusqu'à ce que l'ingénieur système passe le configurer manuellement.

Bon, heureusement, on n'installe pas sa machine tous les jours et, comme je l'ai indiqué, il existe des images toutes faites : si vous voulez apprendre Arch Linux ainsi, une machine virtuelle Linode est certainement une bonne solution. Et, une fois installé, Arch Linux est après tout très agréable.


L'article seul

RFC 6864: Updated Specification of the IPv4 ID Field

Date de publication du RFC : Février 2013
Auteur(s) du RFC : J. Touch (USC/ISI)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF intarea
Première rédaction de cet article le 9 février 2013


Le champ ID (internet identification field) de l'en-tête des paquets IPv4 sert à plusieurs usages mais le plus connu est pour identifier les fragments d'un même datagramme original, afin de réassembler ce datagramme. La norme officielle de ce champ pose des contraintes qui ne peuvent tout simplement pas être respectées avec les réseaux modernes. Donc, toutes les mises en œuvre d'IP violaient la norme, avant que ce RFC 6864 ne les ramènent dans la légalité en changeant la norme, par le relâchement de ces contraintes. Par ailleurs, cet excellent RFC, très bien écrit, est une lecture très recommandée pour celui ou celle qui veut comprendre les détails de la fragmentation dans IPv4.

La principale contrainte était que le champ ID devait être unique pour tout tuple {adresse source, adresse destination, protocole de transport}, pendant une période qui est la durée de vie attendue des paquets. Avec les capacités des réseaux modernes, ce champ, limité à 16 bits, ne pouvait tout simplement pas rester unique aussi longtemps. Notre RFC change donc cette contrainte pour la limiter aux paquets effectivement fragmentés (une minorité, en général). Notez qu'IPv6 n'a pas ce problème, à la fois parce que son champ ID est plus grand (RFC 2460, section 4.5) et parce que cette contrainte limitée avait été définie dès le début.

Si vous voulez les détails du calcul, avec ses 16 bits, le champ ID peut stocker 65 536 valeurs. La durée de vie des paquets dans le réseau est la MDL (maximum datagram lifetime, typiquement deux minutes, cf. RFC 791 et RFC 1122 qui ne donnent pas directement de valeur précise). Avec une MTU typique de 1 500 octets, en supposant que les datagrammes IP ont la taille de cette MTU (moins 20 octets pris par l'en-tête) cela ferait (1 480 * 8) * (65 536 / (2 * 60)) = 6,465 Mb/s au maximum ! Avec une MTU irréaliste (le maximum permis par IP, 65 535 octets), on n'irait encore qu'à 286 Mb/s. (Si vous aimez la précision, notez qu'on pourrait, pour avoir ces 286 Mb/s, envoyer des datagrammes de 65 535 octets sur un réseau dont la MTU n'est que de 1 500 octets. Mais, alors, tous les paquets seraient fragmentés et le coût de réassemblage et les problèmes liés feraient que l'opération serait sans doute une mauvaise idée.) Le calcul complet figure dans le RFC 4963. Notez que tous ces RFC donnent des valeurs de plusieurs minutes pour le MDL, valeurs qui me semblent complètement irréalistes. Je n'ai jamais vu un datagramme se promener dans l'Internet pendant deux minutes entières avant d'arriver ! (Voir la discussion en section 3.2.) Ceci dit, même avec une MDL de 3 secondes, on n'arriverait encore qu'à 255 Mb/s (pour la MTU typique), ce qui n'est pas suffisant. Des interfaces Ethernet à 1 Gb/s sont aujourd'hui banales.

Les réseaux modernes vont évidemment bien plus vite que cela et il est donc clair que les mises en œuvre d'IP violent cette contraine d'unicité. Typiquement, elles réutilisent l'ID bien avant l'expiration du délai maximum (section 5.1), ou bien elles utilisent un ID constant dès que le paquet n'est pas fragmenté (ROHC en tient compte pour comprimer ce champ, cf. section 5.4).

Avant de revenir sur les changements de ce RFC, retournons au fonctionnement de la fragmentation (section 3). Celle-ci survient lorsqu'un datagramme est plus grand que la MTU du prochain lien à traverser. Le datagramme est alors fragmenté, chaque fragment est un paquet IP routé indépendemment, mais tous les fragments d'un même datagramme ont la même valeur du champ ID. Vu par tcpdump, voici une réponse DNS de 3,5 ko fragmentée, les trois fragments du datagramme original ayant l'ID 60977 (indiqué juste après le TTL) :

16:32:35.631159 IP (tos 0x0, ttl 64, id 60977, offset 0, flags [+], proto UDP (17), length 1500)
    217.70.190.232.53 > 88.189.152.187.44168: 41314*- q: ANY? sources.org. 23/0/1 sources.org. [1d] SOA ns3.bortzmeyer.org. hostmaster.bortzmeyer.org. 2013010100 7200 3600 604800 43200, sources.org. [1d] RRSIG [...]
16:32:35.631169 IP (tos 0x0, ttl 64, id 60977, offset 1480, flags [+], proto UDP (17), length 1500)
    217.70.190.232 > 88.189.152.187: udp
16:32:35.631173 IP (tos 0x0, ttl 64, id 60977, offset 2960, flags [none], proto UDP (17), length 419)
    217.70.190.232 > 88.189.152.187: udp

On note que les numéros de port, ainsi que l'analyse du contenu du paquet, ne sont possibles que pour le premier fragment (le seul qui contient les en-têtes UDP et DNS). D'autres paquets de la même source vers la même destination, auront un ID différent :

16:42:17.601777 IP (tos 0x0, ttl 64, id 60988, offset 0, flags [+], proto UDP (17), length 1500)
    217.70.190.232.53 > 88.189.152.187.54895: 15361*- q: ANY? sources.org. 23/0/1 sources.org. [1d] SOA ns3.bortzmeyer.org. hostmaster.bortzmeyer.org. 2013010100 7200 3600 604800 43200, sources.org. [1d] RRSIG, [...]
16:42:17.601787 IP (tos 0x0, ttl 64, id 60988, offset 1480, flags [+], proto UDP (17), length 1500)
    217.70.190.232 > 88.189.152.187: udp
16:42:17.601792 IP (tos 0x0, ttl 64, id 60988, offset 2960, flags [none], proto UDP (17), length 419)
    217.70.190.232 > 88.189.152.187: udp

En IPv4, la fragmentation peut être faite par la source des datagrammes, ou bien par un routeur intermédiaire, lorsqu'il détecte que le lien suivant a une MTU trop faible. L'émetteur ne sait donc pas forcément si son paquet sera fragmenté. En IPv6, par contre, seule la source peut fragmenter et elle sait donc si le paquet sera fragmenté ou pas.

Pour représenter la fragmentation, IPv4 a quatre champs, ID, déjà cité, le bit DF (Don't fragment, qui interdit aux routeurs de fragmenter), la distance depuis le début du datagramme (fragment offset, 0, 1480 puis 2960 dans les exemples plus haut) et le bit MF (More fragments, s'il vaut zéro, cela signifie que ce fragment est le dernier dans le datagramme original, il est noté par un signe + dans la sortie de tcpdump). En IPv6, ce n'est plus dans l'en-tête mais dans un en-tête d'extension (fragment header), qui ne comporte que trois champs : le bit DF a disparu car, en IPv6, il est toujours à 1 (un routeur intermédiaire n'a pas le droit de fragmenter). Cet en-tête de fragmentation n'est présent que si le paquet est effectivement fragmenté. Contrairement à IPv4, IPv6 ne gaspille pas d'identificateur (ID) pour les paquets non fragmentés. IPv4 doit mettre un identificateur dans tous les paquets, même non fragmentés, car il ne peut pas être sûr qu'un routeur plus loin ne va pas décider de fragmenter.

En outre, en IPv6, le champ ID fait 32 bits et permet donc de stocker bien plus de valeurs. Bref, notre RFC ne couvre que le cas d'IPv4, IPv6 n'a pas de problèmes. Même si tous les paquets sont fragmentés, le champ ID plus grand permettrait à IPv6 de pomper 18,8 Tb/s (en supposant des datagrammes de la taille maximale permise par IP). Si les paquets ne sont pas fragmentés, il n'y a plus de limite.

Donc, que faire pour IPv4, afin de réconcilier la norme et la pratique ? La section 4 expose les nouvelles règles pour le champ ID. L'idée de base est que tous les paquets ne sont pas fragmentés. En fait, avec la PMTUD (RFC 1191), la plupart ne le sont pas. Donc, l'obligation d'unicité du champ ID n'est maintenue que pour les paquets fragmentés ou susceptibles de l'être. La grande majorité des paquets TCP, aujourd'hui, grâce à la PMTUD, ne seront pas fragmentés (ils ont le bit DF, Don't fragment) et n'ont donc pas d'obligation d'un identificateur unique.

Ce RFC introduit le concept de « datagramme atomique ». Un datagramme atomique est un datagramme qui n'est pas fragmenté (MF = 0 et distance au début du datagramme = 0) et qui ne le sera pas (DF = 1). En pseudo-code ressemblant à du C, (DF==1)&&(MF==0)&&(frag_offset==0). Les datagrammes non-atomiques sont tous les autres (ils sont déjà fragmentés ou bien, n'ayant pas le bit DF à un, ils le seront peut-être plus tard). Aujourd'hui, dans le trafic TCP habituel, quasiment tous les datagrammes sont atomiques. La nouvelle règle de non-unicité ne s'applique qu'aux datagrammes non-atomiques. Pour les datagrammes atomiques, IP peut mettre le champ ID à n'importe quelle valeur (section 4.2). Pour les autres, il faut continuer à garder ID unique pendant la MDL (section 4.3). Cela a des conséquences sur les sources qui émettent beaucoup de datagrammes non-atomiques, typiquement les gros serveurs DNS (cf. RFC 6891, des réponses DNS plus grosses que la MTU sont courantes et les serveurs ne font pas de PMTUD en UDP). Ces sources, pour réussir à respecter l'unicité des ID peuvent se trouver dans l'obligation de s'auto-limiter et donc de ne pas envoyer trop de paquets (section 5.2).

À noter qu'il y a d'autres usages possibles pour le champ ID que la fragmentation et le réassemblage. Il a été envisagé d'utiliser ce champ pour détecter des datagrammes dupliqués (chose qui est possible dans un routeur congestionné, cf. RFC 1122, section 3.2.1.5), ce qui diminuerait le travail de protocoles de transport comme TCP qui, actuellement, doivent gérer ce problème. Il a aussi été proposé de se servir d'ID pour des activités de diagnostic. Aucun de ces projets n'est allé très loin et, de toute façon, ils ne marcheraient pas en IPv6 qui n'a de champ ID que pour les datagrammes effectivement fragmentés.

Comme la nouvelle règle ne marche que pour la fragmentation, les autres usages du champ ID sont désormais interdits : plus question d'essayer d'utiliser ce champ pour autre chose, puisqu'il n'est officiellement plus unique. Ce champ doit donc être ignoré si le datagramme est atomique.

Le reste ne change pas. Par exemple, le bit DF garde exactement la même signification (« ne fragmente surtout pas ce paquet »).

En pratique, qu'est-ce que cela va changer (section 5) ? Rappelez-vous qu'en pratique, la nouvelle règle est depuis longtemps la règle de fait et que l'Internet ne s'est pas écroulé. Donc, notre RFC estime qu'il ne faut pas s'attendre à des problèmes, sinon, ceux-ci auraient été signalés il y a des années.

Une autre solution au problème du champ ID trop court a été mentionnée plus haut : réutiliser les valeurs bien avant l'expiration du MDL, d'autant plus qu'on a vu que celui-ci est typiquement très grand. L'inconvénient de cette approche est que, si des paquets fragmentés traînent et arrivent ensuite à peu près en même temps que des fragments d'un autre datagramme, utilisant le même identificateur, le réassemblage va produire des paquets qui ne correspondent pas à l'original, en fusionnant les deux paquets (RFC 4963). Les sommes de contrôle vont peut-être détecter le problème, mais le RFC recommande d'utiliser des contraintes d'intégrité dans les applications, pour être sûr. Si on a de telles contraintes bien fortes, on peut réutiliser les identificateurs plus vite.

Autre problème potentiel, avec les middleboxes qui réécrivent les paquets, par exemple les routeurs NAT. Elles ne doivent pas bêtement copier le champ ID mais en générer un correctement. Comme le routeur NAT typique réécrit l'adresse source de N machines en un nombre bien plus petit d'adresses (une seule pour le petit routeur NAT à la maison, un peu plus pour un CGN), le risque de casser l'unicité est élevé : si deux machines sur le réseau local communiquent avec la même destination externe et émettent des datagrammes avec le même ID, une réécriture bête de l'adresse IP source cassera l'unicité. Les CGN ont davantage d'adresses externes mais aussi bien davantage de trafic et le risque est donc encore plus élevé avec eux.

On a vu que ce RFC changeait l'ancienne norme (impossible à respecter) pour l'aligner avec la pratique. La section 6 donne la liste exacte des RFC modifiés : RFC 791, la norme IPv4 originale, et RFC 1122 notamment.

La fragmentation a des tas de conséquences sur la sécurité, d'où la section 7 qui examine les résultats de la nouvelle règle. Par exemple, elle rendra plus difficile le comptage des machines situées derrière un routeur NAT, même si ce n'était pas son objectif (cf. S. Bellovin, A Technique for Counting NATted Hosts).


Téléchargez le RFC 6864


L'article seul

RFC 6869: vCard KIND:device

Date de publication du RFC : Février 2013
Auteur(s) du RFC : G. Salgueiro, J. Clarke, P. Saint-Andre (Cisco)
Chemin des normes
Première rédaction de cet article le 9 février 2013


Le format vCard (RFC 6350) de stockage de données structurées à propos d'une entité a surtout été utilisé pour des personnes (pour faire des carnets d'adresses) et des organisations. Le format standard définit une propriété KIND (section 6.1.4 du RFC 6350) qui indique quel est le type d'entité décrit. À l'origine, KIND pouvait avoir les valeurs individual (valeur par défaut), group, org ou location. Ce nouveau RFC ajoute la valeur device qui permet d'indiquer qu'une vCard décrit un engin, par exemple un routeur, à des fins d'inventaire et de gestion du matériel.

KIND avait déjà été étendu pour décrire les logiciels (type application, RFC 6473) et voici donc qu'il passe au matériel. Attention, il y a une restriction : pour l'instant, ces « device » ne sont que les engins effectivements connectés à l'Internet, du commutateur au Raspberry Pi, en passant par l'imprimante et par des engins plus exotiques mais qui ont tous en commun d'avoir une connexion réseau et donc de participer à l'« Internet des Objets ». Les engins purement mécaniques comme un ascenseur ou une génératrice sont donc exclus, en attendant qu'ils acquièrent une connexion Internet.

En revanche, les machines virtuelles sont incluses, contrairement à ce qui se passait en X.521 / RFC 4519 qui était restreint aux machines physiques.

Un des scénarios d'usage de ce nouveau RFC est d'inscrire la vCard décrivant l'engin dans celui-ci, lors de la fabrication, permettant ainsi de récupérer facilement et de manière standard les informations utiles. Si la mémoire où est stockée la vCard est réinscriptible, on peut aussi envisager d'y stocker des informations opérationnelles. Mais comment récupérera t-on la vCard ? Pour l'instant, aucun mécanisme standard n'est normalisé, ce RFC ne spécifie que le format. Notez que plusieurs vCards pourront être présentes dans un engin, par exemple une de type device pour l'engin, une de type org pour l'entreprise qui l'a fabriqué, etc. La propriété RELATED (section 6.6.6 du RFC 6350) pourra alors être utilisée pour relier ces vCards.

Quelles propriétés vCard auront un sens pour un engin ainsi identifié ? La section 2 en donne une liste indicative mais un exemple vaut mieux qu'un long discours, un routeur installé au 60 Hudson géré par l'opérateur example.net :

BEGIN:VCARD
VERSION:4.0
KIND:device
FN:core-rtr1-nyc1.example.net
GEO:geo:40.717593,-74.00854
TZ:America/NewYork
EMAIL:noc@example.net
IMPP:PREF=1:xmpp:noc@example.net
IMPP:PREF=2:irc:example@freenode.net
ADR:;;60 Hudson Street;New York City;NY;;USA
END:VCARD

On notera que FN (Full Name) est un nom de domaine.

À noter que le RFC utilise une autre syntaxe pour l'exemple de la section 3, en XML, en suivant le format xCard du RFC 6351.

Cette valeur device est désormais enregistrée dans le registre IANA.


Téléchargez le RFC 6869


L'article seul

Explorer le contenu du DNS dans le passé avec DNSDB

Première rédaction de cet article le 7 février 2013
Dernière mise à jour le 7 octobre 2013


Le DNS peut être vu comme une grande base de données répartie sur toute la planète. Cette base contient des données, les enregistrements (resource records dans la langue de George Martin, d'où le sigle RR que vous verrez plus bas). Ces enregistrements peuvent changer dans le temps, parfois assez vite, et on souhaiterait souvent revenir en arrière. L'adresse IP de google.ro a-t-elle changé le 28 novembre 2012 ? Qu'est-il arrivé à meteofrance.com le 20 novembre 2012 ? Quand est apparu l'enregistrement d'une adresse IPv6 pour ovh.com ? Le service DNSDB de la société Farsight (créé originellement à l'ISC) permet de répondre à ces questions. C'est un véritable Internet Archive pour le DNS.

D'abord, un avertissement : DNSDB n'est pas ouvert publiquement. Les données que ce service contient peuvent être sensibles, et intéresser des pabos. C'est pour cela que l'accès à DNSDB est soumis à une autorisation préalable. Il faut montrer patte blanche. Discuter autour d'une bière avec un employé de Farsight lors d'une réunion IETF ou OARC peut aider aussi.

Une fois que votre candidature est approuvée, vous pouvez accéder au service, en parler publiquement (cet article dans mon blog ne viole donc pas les conditions d'utilisation) et même citer des exemples de données. Mais, évidemment, pas question de copier la base et de l'emporter (un avertissement technique au passage : la base est grosse et, même si on en avait une copie, il faudrait être un dieu de NoSQL pour arriver à y accéder en des temps raisonnables).

Bien, une fois qu'on a un accès, essayons d'abord avec l'interface Web : dnsdb-form.jpg On va demander l'histoire de l'enregistrement de type A (adresse IPv4) google.ro. Il y a bien sûr de nombreuses réponses mais celle qui nous intéresse est celle du 28 novembre : dnsdb-google-ro.jpg On voit que google.ro, pendant quelques heures, pointait vers l'adresse IP d'un hébergeur néerlandais qui n'a rien à voir avec Google. Apparemment, le registre du .ro avait été piraté et google.ro redirigé.

Mais d'où est-ce que DNSDB tire ces informations ? Il s'appuie sur plusieurs sources, notamment le SIE, un réseau de sondes DNS installées en divers endroits, qui capturent passivement le trafic DNS et l'envoient à DNSDB.

Naturellement, on n'est pas forcé d'utiliser le cliquodrome Web. Il existe une API REST. Il suffit de demander en ligne un mot de passe (API key, évidemment non affichée ici). Testons-la avec curl pour regarder le problème de meteofrance.com :

% curl --header "X-API-Key: 1234" \
      https://api.dnsdb.info/lookup/rrset/name/meteofrance.com/NS
...
;;  bailiwick: com.
;;      count: 29
;; first seen: 2012-11-20 12:32:48 -0000
;;  last seen: 2012-11-20 15:38:22 -0000
meteofrance.com. IN NS ns1.pendingrenewaldeletion.com.
meteofrance.com. IN NS ns2.pendingrenewaldeletion.com.
...
;;; Returned 6 RRsets in 0.06 seconds
;;; ISC DNSDB

Ah, le problème est clair. Le 20 novembre, le domaine meteofrance.com a expiré (paiement non effectué) et le bureau d'enregistrement a mis le domaine sur ses propres serveurs de noms, le temps que le client se réveille (ce qui s'est passé trois heures plus tard, comme vous pouvez le voir).

Si on n'aime pas faire du curl directement, Farsight fournit des scripts qui permettent d'interroger l'API plus facilement. On met le mot de passe dans ~/.isc-dnsdb-query.conf et :

% isc-dnsdb-query rrset ovh.com/AAAA
;;  bailiwick: ovh.com.
;;      count: 10519
;; first seen: 2011-06-08 10:20:48 -0000
;;  last seen: 2011-08-19 16:40:23 -0000
ovh.com. IN AAAA 2001:41d0:1:1b00:213:186:33:34

;;; Returned 1 RRsets in 0.01 seconds
;;; ISC DNSDB

On peut voir qu'OVH a une adresse IPv6 en juin 2011 mais ne l'a pas conservée.

Attention au passage, si vous faites des analyses historiques, DNSD est un service récent. Essayons avec un domaine ancien et connu :

% isc-dnsdb-query rrset www.ripe.net              
;;  bailiwick: ripe.net.
;;      count: 207148
;; first seen: 2010-06-24 06:30:27 -0000
...

Le RIPE existait évidemment avant 2010. Mais cette date est celle du plus ancien enregistrement dans la base.

DNSDB accepte aussi les jokers à l'extrémité d'un nom. Imaginons qu'on cherche tous les enregistrements DANE existants (RFC 6698). DNSDB ne connaît pas ce type mais on peut l'indiquer par son numéro :

% isc-dnsdb-query rrset '_443._tcp.*/type52'  
;;  bailiwick: torproject.org.
;;      count: 3
;; first seen: 2013-02-08 07:54:42 -0000
;;  last seen: 2013-02-10 07:29:16 -0000
_443._tcp.www.torproject.org. IN TYPE52 \# 67 03 01 02 4d f6 66 72 94 fc 1d fd 6a 95 da 7b d8 95 9b 71 7b 68 21 3e 25 39 dd ec ae b0 9d e0 b7 55 a1 b9 72 70 7e e4 5f aa 4d 48 91 cc f2 2b 11 03 c7 29 10 56 95 e2 8a e8 91 33 1e 0c 56 e6 35 fc ff 57 
...
;;  bailiwick: os3sec.org.
;;      count: 9
;; first seen: 2013-01-19 22:57:17 -0000
;;  last seen: 2013-02-06 02:52:42 -0000
_443._tcp.os3sec.org. IN TYPE52 \# 35 03 00 01 18 e3 71 b8 ad 85 a1 7c ba a1 17 a8 af 44 10 1e 57 b8 8d 7a 99 44 4f df 4b 4f 90 c0 a7 3a 8f db 
...

Toutes les recherches ci-dessus ont été faites à partir du nom de domaine (la partie gauche d'un enregistrement DNS). Mais on peut aussi, depuis l'interface Web ou bien via l'API, chercher sur le contenu, sur la partie droite d'un enregistrement. Pour cela, il faut remplacer rrset par rdata et indiquer si on cherche une adresse IP ou un nom ou un contenu quelconque. Ici, je cherche tous les noms qui pointent vers l'adresse IP du serveur Web du ministère des Finances :

% isc-dnsdb-query  rdata ip 193.17.19.153
vae.gouv.fr. IN A 193.17.19.153
www.kezeco.economie.gouv.fr. IN A 193.17.19.153
taxepro.economie.gouv.fr. IN A 193.17.19.153
www.dpa.finances.gouv.fr. IN A 193.17.19.153
semaine.industrie.gouv.fr. IN A 193.17.19.153
www.semaine-industrie.gouv.fr. IN A 193.17.19.153
;;; Returned 6 RRs in 0.05 seconds
;;; ISC DNSDB

En pratique, cette option est très utile pour mesurer le degré de corruption d'une adresse IP. Si on prend une adresse IP citée dans un spam, on découvre en général plein de noms qui pointent vers la même adresse :

% isc-dnsdb-query  rdata  ip 83.206.207.181
tracking.cofidis.be. IN A 83.206.207.181
tr.service-mail.carrefour.fr. IN A 83.206.207.181
tr.denplan.co.uk. IN A 83.206.207.181
mp-dhrd.com. IN A 83.206.207.181
mail.dailyreduc.com. IN A 83.206.207.181
affiliates-solution.com. IN A 83.206.207.181
tr.affiliates-solution.com. IN A 83.206.207.181
www.affiliates-solution.com. IN A 83.206.207.181
tracking.bp01.net. IN A 83.206.207.181
trpreviews.bp01.net. IN A 83.206.207.181
tr1.bp06.net. IN A 83.206.207.181
bp08.net. IN A 83.206.207.181
bp09.net. IN A 83.206.207.181
bp10.net. IN A 83.206.207.181
bp11.net. IN A 83.206.207.181
...

(La liste continue pendant longtemps... Le spammeur avait manifestement enregistré une longue liste de domaines pour éviter les listes noires.)

Un service ressemblant à DNSDB (en moins riche) est http://dnshistory.org/.


L'article seul

RFC 6820: Address Resolution Problems in Large Data Center Network

Date de publication du RFC : Janvier 2013
Auteur(s) du RFC : T. Narten (IBM), M. Karir (Merit Network), I. Foo (Huawei Technologies)
Pour information
Réalisé dans le cadre du groupe de travail IETF armd
Première rédaction de cet article le 30 janvier 2013


Lorsque des dizaines de milliers, voire des centaines de milliers de machines, sont connectées au même réseau (ce qui peut être le cas dans un grand data center), certains protocoles TCP/IP, pas forcément prévus pour cela, peuvent avoir des problèmes. C'est le cas d'ARP et de NDP, protocoles utilisés pour trouver l'adresse MAC d'une machine voisine. ARP n'avait pas été prévu pour les data centers modernes et ses limites se font parfois sentir. ND pose pas mal de problèmes similaires. D'où ce document qui définit précisement le problème.

Il n'y aura par contre pas de solution de si tôt : le groupe de travail armd, qui devait travailler sur ce sujet, a été dissous immédiatement après avoir produit ce RFC de description du problème. Il ne semblait pas qu'il soit possible de travailler sur des solutions et l'IESG a donc choisi de dissoudre le groupe alors qu'il était loin du résultat. Il reste cet intéressant RFC 6820 qui sera lu avec plaisir par tous les passionnés de réseaux informatiques. (Un autre document, le RFC 7342, décrit les pratiques existantes.)

ARP (RFC 826) et ND (RFC 4861) s'attaquent tous les deux (le premier pour IPv4 et le second pour IPv6) au problème de la résolution d'adresses sur le réseau local. Une machine veut parler à une autre machine dont l'adresse IP indique qu'elle est sur le même réseau local. Pas besoin de routage, donc, on peut lui envoyer directement un paquet mais, pour cela, il faut d'abord trouver son adresse MAC. ARP et ND procèdent de façon très proche : ils diffusent un paquet à tout le monde « qui est 2001:db8:1::af:41 ? » et la machine qui se reconnait répond. Cela veut dire que ce paquet de demande va être transmis à toutes les machines du réseau local, jusqu'aux routeurs qui marquent la limite du « domaine de broadcast » (l'ensemble des machines touchées par la diffusion « L2 », c'est-à-dire utilisant les mécanismes de la couche 2). Des détails comme les VLAN compliquent encore le tableau. Pour notre RFC, un « domaine de broadcast L2 » est l'ensemble des liens, répéteurs et commutateurs traversés pour atteindre tous les nœuds qu'on touche avec une diffusion.

(Il existe une légère différence entre ARP et ND, ND utilisant le multicast et pas le broadcast mais, en pratique, cela ne change pas grand'chose : ce point est traité plus loin.)

Depuis longtemps, on sait que les grands domaines de diffusion (réseaux « plats », sans routeurs) créent des tas de problèmes. La totalité des machines du réseau doit traiter les paquets de diffusion. Une machine méchante ou détraquée qui envoie des paquets de diffusion en boucle peut sérieusement perturber un réseau. Dans certains cas (« tempêtes de diffusion », provoquées par exemple par une boucle non détectée dans la topologie du réseau), ces paquets diffusés suscitent la création d'autres paquets diffusés et, là, on peut arrêter complètement le réseau. La sagesse des administrateurs réseaux est donc depuis longtemps « ne faites pas de grands domaines de diffusion ; partitionnez en mettant des routeurs au milieu »). Par exemple, si on architecture son data center en mettant un sous-réseau IP par armoire, la charge résultant d'ARP et de ND sera confinée à une seule armoire. Et les éventuelles tempêtes de diffusion resteront dans une armoire. Le problème est que cette configuration est plus rigide : avec les techniques de gestion modernes (buzzwords : cloud, élasticité, agilité, etc), on souhaite pouvoir déplacer une machine très facilement, sans la renuméroter. Les grands réseaux L2 plats permettent cela. Au contraire, les réseaux très partitionnés nécessitent de changer l'adresse IP de la machine selon sa position physique dans le data center, faisant perdre en souplesse de gestion. Même problème lorsqu'on veut ajouter des nouvelles machines : avec un réseau plat, on configure les machines et on les installe là où il y a de la place. Avec un réseau très partitionné, on doit les configurer en fonction de l'endroit où elles vont être installées, ajoutant ainsi une contrainte de gestion.

Et la virtualisation, très utilisée dans les data centers actuels, pousse encore plus dans ce sens. Avec la virtualisation, déplacer une machine ne nécessite même plus d'opérations physiques : on copie la VM, c'est tout. Si l'alimentation électrique d'une machine physique menace de défaillir, on copie toutes les VM hébergées dans l'armoire vers d'autres machines physiques, puis on peut arrêter l'armoire tranquillement. Une architecture où chaque armoire est son propre sous-réseau ne permet plus cela : changer d'armoire veut dire changer d'adresse IP, donc sérieusement impacter le service.

Autre conséquence de la virtualisation : le nombre de machines augmente. Il est courant aujourd'hui d'avoir plusieurs dizaines de machines virtuelles par machine physique. Demain, ce nombre sera probablement plus élevé. Les problèmes de passage à l'échelle d'ARP et de ND vont donc devenir plus aigus lorsqu'une VM émettra un paquet ARP qui devra être traité par des milions de machines situées dans le même data center (des data centers de 100 000 machines physiques existent déjà, ce qui fait bien davantage de VM).

Le désir de souplesse et d'agilité dans la gestion des machines virtuelles (VM) pèse aussi sur l'architecture du réseau : il est plus difficile de prédire les flux de données entre machines (ça change tout le temps) et on ne peut donc pas architecturer le réseau autour des flux d'aujourd'hui, par exemple pour conserver le trafic à l'intérieur d'une seule armoire, ou pour éviter de passer par plusieurs commutateurs.

Les sections 4 et 5 se penchent sur les spécificités des deux protocoles ARP et ND. ARP souffre du fait d'être un très vieux protocole, nettement sous-spécifié (par exemple, aucun RFC ne précise de stratégie de retransmission lorsqu'un paquet est perdu). Les mises en œuvre d'ARP sont très variables dans leur comportement. Certaines sont par exemple bien plus bavardes que d'autres, vidant les caches même lorsque ce n'est pas nécessaire, ce qui entraîne davantage de requêtes.

ND est mieux placé qu'ARP, car plus récent. Ceci dit, pour la plupart des problèmes listés dans ce RFC, ND et ARP sont proches. La principale différence est qu'ARP utilise le broadcast et ND le multicast. En théorie, cela permet que les requêtes n'aillent pas dans tout le réseau, seulement dans les parties où il y a des machines IPv6. En pratique, je suis sceptique : combien de commutateurs filtrent ainsi ? Mais, même si cela ne protège pas le réseau, cela protège les machines purement IPv4, qui peuvent ignorer ces sollicitations dès l'arrivée sur la carte Ethernet. Évidemment, si toutes les machines parlent IPv6, cet avantage disparait : tout le monde droit traiter les requêtes ND, comme tout le monde droit traiter les requêtes ARP.

Dernière chose à garder en tête avant de voir la liste des problèmes, l'architecture du data center (section 6). Un data center typique est hiérarchique : des armoires, connectées à un réseau d'accès, lui-même connecté à un réseau d'agrégation, lui-même connecté au cœur. L'armoire compte plein de serveurs et le réseau d'accès est, soit un commutateur réseau interne (ToR pour Top of Rack car il est souvent en haut de la baie), soit on utilise un commutateur situé à l'extrémité de la rangée d'armoirees (EoR pour End of Row).

Ensuite, le réseau d'agrégation qui, dans le cas le plus fréquent, est composé de commutateurs connectant les commutateurs ToR (souvent plusieurs centaines) entre eux.

Le cœur, lui, comprend les équipements qui connectent les commutateurs du réseau d'agrégation, ainsi que les liens avec l'extérieur.

Maintenant, la question d'architecture qui va le plus impacter notre problème : jusqu'où va le domaine de diffusion d'un serveur ? Jusqu'au réseau d'accès, jusqu'au réseau d'agrégation, ou bien jusqu'au cœur ? Comme vu plus haut, la première solution est plus sûre (les problèmes seront concentrés dans une armoire ou dans un relativement petit groupe d'armoires), la seconde plus flexible et la troisième offre le maximum de flexibilité... et de risques.

Pour profiter de la structure hiérarchique du data center, on souhaite que le trafic entre deux machines connectées au même réseau d'accès reste local et n'aille pas sur le réseau d'agrégation. Idem entre l'agrégation et le cœur. Si le data center est occupé par une seule organisation, où le trafic réseau est bien connu et compris, cela peut être possible. Par exemple, si on héberge une ferme de serveurs Web dynamiques, dépendant d'un SGBD, on prendra soin de mettre les serveurs de base de données proches du frontal HTTP, puisqu'ils auront beaucoup à parler entre eux.

Si le data center est public (utilisé par des tas de clients différents, n'ayant pas de lien entre eux, par exemple Amazon EC2, OVH ou Gandi), on ne peut plus espérer connaître les flux réseau. Bref, le type d'usage envisagé va peser sur l'architecture.

Enfin, après ces préliminaires, la section 7 expose la liste des problèmes ARP/ND identifiés. D'abord, le traitement par les routeurs. Ceux-ci doivent écouter le trafic ARP et traiter chaque paquet, ne serait-ce que pour mettre le cache ARP à jour (comme l'impose le RFC 826). Ce traitement se fait en général sur le « chemin lent » (slow path) du routeur, c'est-à-dire en remontant au CPU généraliste de la machine, sans pouvoir utiliser les plus rapides ASIC dont on se sert pour la transmisison de paquets. Ce CPU est limité et, avec les machines actuelles, il ne faut pas espérer plus de quelques milliers de paquets ARP par seconde, ce qui peut être insuffisant dans certains environnements.

Une des techniques utilisées par les routeurs est d'ignorer très tôt les requêtes ARP où l'adresse du routeur n'apparait pas. Cela viole le RFC 826 mais cela peut être nécessaire.

Une autre optimisation est de limiter le nombre de requêtes qui concernent le routeur en envoyant périodiquement de l'ARP gratuit (RFC 5227), pour garder les caches des autres machines peuplés (à noter que cela ne marche pas si la machine n'avait pas déjà une entrée dans son cache ARP).

Autre problème pour le routeur, chaque fois qu'on doit envoyer un paquet à une machine pour laquelle le routeur n'a pas d'entrée dans son cache ARP, il faut effectuer un traitement assez lourd (mettre le paquet IP en attente, comme imposé par les RFC 1122 et RFC 1812, envoyer la requête ARP, attendre et réémettre si nécessaire, peut être envoyer une réponse ICMP destination unreachable) et qui est typiquement géré par le slow path du routeur, sa partie la plus lente. Si le data center contient un grand réseau à plat, et que le routeur doit parler à des dizaines de milliers de machines (et donc faire de l'ARP avec elles), cela peut être une charge sérieuse. (Ce n'est pas le nombre d'interfaces physiques du routeur qui compte mais le nombre totale de machines avec qui il parle en couche 2.)

Ensuite, le cas du protocole ND d'IPv6. Il est très proche d'ARP et bien des problèmes sont les mêmes. La principale différence est qu'il utilise le multicast et que donc, dans certaines circonstances, ses paquets pourront être ignorés, diminuant la charge sur les équipements réseau.

Mais, par contre, le RFC 4861, section 7.3.1, impose des vérifications régulières de la validité des entrées dans le cache. La méthode de vérification n'est pas spécifiée (on a le droit de se servir des accusés de réception TCP pour cela). Mais cela pousse certaines machines à envoyer des demandes ND répétées, parfois une toutes les trente-cinq secondes. Et il n'y a pas d'équivalent de l'ARP gratuit, le RFC 4861, section 7.3.1, disant que la réception d'une réponse ND ne doit pas valider une entrée du cache (au contraire, cela peut générer un test ND, précisement ce qu'on tentait d'éviter). C'est parce que la réception d'une « réponse » ne prouve que le chemin retour, pas forcément l'aller.

La plupart des réseaux étant aujourd'hui en IPv4 et IPv6, les problèmes quantitatifs s'additionnent. La situation ne s'arrangera que lorsqu'on pourra arrêter IPv4, ce qui est une perspective encore très éloignée.

Derniers équipements à souffrir (le RFC ne considère pas le cas des machines terminales), les commutateurs. Pour n'envoyer les paquets que sur le bon port physique (au lieu de le diffuser partout), le commutateur doit garder en mémoire une table des adresses MAC. Si le réseau « couche 2 » est très grand, cette table le sera aussi.

Si vous voulez approfondir le sujet et notamment voir toutes les données quantitatives, lisez le document draft-karir-armd-statistics, et le RFC 7342.


Téléchargez le RFC 6820


L'article seul

RFC 6839: Additional Media Type Structured Syntax Suffixes

Date de publication du RFC : Janvier 2013
Auteur(s) du RFC : T. Hansen (AT&T Laboratories), A. Melnikov (Isode)
Pour information
Réalisé dans le cadre du groupe de travail IETF appsawg
Première rédaction de cet article le 30 janvier 2013


Tout le monde connait les « types de contenu » (media types, aussi appelés types MIME pour des raisons historiques), comme application/pdf ou text/plain. On sait qu'ils ont un type (comme application ou text, dans les exemples ci-dessus) et un sous-type (pdf ou plain ci-dessus) qui précise le format, à l'intérieur de la catégorie définie par le type. On sait moins que le sous-type peut avoir une structure : on peut voir un format générique et un format plus spécifique, séparés par un +, comme dans application/xhtml+xml ou image/svg+xml. Cette structuration, introduite à l'origine par le RFC 3023, pour XML, est ici généralisée à d'autres formats et normalisée en détail. (Pour +xml, une mise à jour a été faite ensuite dans le RFC 7303.)

Cette technique vient du fait que certains formats ont deux couches : un format décrivant la syntaxe de base et plusieurs formats (plutôt appelés vocabulaires, ou même langages, dans le monde XML) qui définissent des règles sémantiques différentes, mais tous utilisant la même syntaxe de base. L'exemple typique est XML. Ainsi, les fichiers TEI (RFC 6129) sont en XML et un processeur XML généraliste saura en faire quelque chose (par exemple vérifier leur validité syntaxique). Mais TEI n'est pas que XML : c'est aussi la définition d'un certain nombre d'éléments XML légaux et de leurs relations (le schéma). Un fichier TEI peut donc être étiqueté application/xml mais son type de contenu officiel, application/tei+xml, donne davantage d'informations (cf. section 2, sur l'intérêt de ces suffixes). Si on prend un autre vocabulaire XML, le Atom du RFC 4287, c'est aussi du XML mais les éléments acceptés sont complètement différents. Son type de contenu aura donc aussi le suffixe +xml mais le type sera distinct, ce sera application/atom+xml.

La section 3 liste les sous-types à suffixe possibles (mais cette liste va grandir par la suite, cf. RFC 6838, section 6). Pour chaque suffixe, sont notamment indiquées les règles relatives à son encodage (pour savoir si la ressource doit être transportéee comme du texte ou comme du binaire), et les règles de sécurité. Parmi les suffixes possibles, il y a, entre autres :

  • +json pour le format JSON du RFC 7159. comme vnd.oftn.l10n+json (format de la bibliothèque Javascript l10n) ou comme les réponses de l'API de GitHub. Comme XML, JSON peut être encodé en UTF-8 (il est alors considéré comme texte, cf. RFC 2045) ou UTF-32 (il est alors vu comme du binaire).
  • +ber pour le format BER et +der pour le format DER, tous les deux d'encodage d'ASN.1 (norme UIT ITU.X690.2008). Un exemple est dssc+der, du format du RFC 5698 (qui peut aussi se représenter en XML). À noter que BER présente des risques particuliers en terme de sécurité. Encodage TLV, il permet de construire des fichiers avec des longueurs invalides, permettant de dépasser les limites des données et de déclencher un débordement de tampon chez des décodeurs naïfs. On peut aussi faire des dépassements de pile puisque BER permet d'emboîter des données récursivement.
  • +fastinfoset est la norme Fast Infoset, un encodage binaire de XML, qui ne semble pas avoir été un grand succès (bien que résolvant un reproche parfois fait à XML, celui que son encodage par défaut est trop bavard).
  • +zip est le fameux format de compression et d'archivage ZIP. (Aucun n'a apparemment encore été enregistré.)

La section 4 reprend le suffixe +xml, déjà décrit dans le RFC 3023 et l'adapte aux exigences du RFC 6838.

Le registre IANA de ces suffixes est désormais en ligne.


Téléchargez le RFC 6839


L'article seul

RFC 6838: Media Type Specifications and Registration Procedures

Date de publication du RFC : Janvier 2013
Auteur(s) du RFC : N. Freed (Oracle), J. Klensin, T. Hansen (AT&T Laboratories)
Réalisé dans le cadre du groupe de travail IETF appsawg
Première rédaction de cet article le 30 janvier 2013


Tout professionnel de l'Internet voit passer les fameux types de contenu (media types, souvent appelés types MIME) comme audio/ogg ou text/json. Comment sont enregistrés ces types ? Suivant quelles procédures ? Si je veux un type pour mon super format que j'ai inventé moi, comment je fais ? Ce nouveau RFC, qui remplace l'ancienne norme (RFC 4288), donne la réponse à toutes ces questions.

Ces types de contenu sont utilisés dans de nombreux protocoles multimédia. Les deux les plus connus sont HTTP et le format du courrier électronique (RFC 2045 et RFC 5322), le nom de « type MIME » venant d'ailleurs du courrier, même si ces types sont utilisés bien ailleurs. Lorsqu'un client HTTP interroge un serveur, celui-ci se sert ainsi de ces types pour lui indiquer le format des données envoyées :

% curl -v http://www.bortzmeyer.org/images/defile-fete-cheval-2008-4.png > /dev/null
...
< Content-Length: 2094295
< Content-Type: image/png
...

Ces types sont composés de deux parties, le type proprement dit et le sous-type, séparés par une barre. Ainsi, dans le cas ci-dessus, image/png, le type est image (une image) et le sous-type est PNG (le format de l'image). Pour assurer l'unicité d'un type, ils sont enregistrés à l'IANA et c'est la gestion de ce registre qui est le cœur de ce RFC.

Les noms enregistrés sont regroupés en arbres, un arbre étant identifié par une facette indiquée dans le sous-type par le texte précédant le point. S'il n'y a pas de point (comme dans tous les exemples données jusqu'à présent), il s'agit de l'arbre standard, qui stocke les noms d'intérêt général. Un exemple de nom dans un autre arbre est image/vnd.microsoft.icon qui est dans l'arbre « Vendeurs » (vnd) et désigne le format ICO.

L'enregistrement dans l'arbre standard est, comme on s'en doute, le plus difficile. Le format en question doit être normalisé par l'IETF ou une autre SDO reconnue par l'IESG (politique « Norme nécessaire » du RFC 5226). Un expert appointé par l'IANA est chargé de réviser ces enregistrements pour s'assurer que tout est complet. Au cas où un changement de l'enregistrement soit nécessaire, c'est la SDO originale qui peut seule décider (section 5.5).

Notez aussi que le sous-type doit normalement désigner un format qui permette l'interopérabilité. Si un fichier est étiqueté image/MACHIN, un logiciel qui lit ce format MACHIN doit pouvoir lire tous les fichiers de ce format, sans que l'émetteur n'ait à s'angoisser sur les éventuelles variantes acceptées ou pas (cf. section 4.5).

Après l'arbre standard, le plus important est sans doute l'arbre « vendeur » (notez que le terme inclut les organisations non-commerciales) où se trouvent les types liés à un fournisseur de logiciel particulier. Les sous-types dans cet arbre commencent par la facette vnd comme par exemple application/vnd.amiga.ami. Le contrôle du changement, cette fois, revient au vendeur en question (bien que l'enregistrement lui-même puisse être fait par un tiers). À noter qu'aucune vérification publique n'est nécessaire (ce sont des types pour un produit privé, après tout) mais qu'une telle vérification est quand même recommandée (sur la liste media-types, voir plus loin). Dans tous les cas, la demande sera examinée par l'expert nommé par l'IANA.

Comme indiqué plus haut, « vendeur » (et son abréviation vnd) n'implique pas forcément une entreprise commerciale. Par exemple, Debian a enregistré vnd.debian.copyright ce qui, au dire de Charles Plessy, le développeur Debian qui s'en est chargé, est désormais très simple avec la nouvelle procédure de notre RFC.

Et s'il n'y a pas du tout de vendeur, même pas une fondation ou association établie ? Si Jean Durand, développeur avec un compte sur GitHub, veut un type de contenu pour le format d'images qu'il a développé ? Pas de panique, Jean peut utiliser l'arbre « personnel ». Son sous-type aura alors la facette prs comme dans application/prs.plucker. Comme pour l'arbre « vendeur », l'examen public sur la liste media-types est recommandé mais pas indispensable.

Enfin, il y avait un arbre « privé » avec la facette x. Il n'y avait pas d'enregistrement dans cet arbre, chacun pouvait y mettre ce qu'il voulait avec zéro formalité. Ces préfixes X ayant créé quelques problèmes (collisions entre deux noms, noms qui deviennent populaires et qui sont alors « enregistrés de fait »), ils sont aujourd'hui abandonnés (RFC 6648) et l'utilisation de l'arbre x très découragée.

Bon, maintenant, je peux l'envoyer, ma demande à l'IANA, se demande notre programmeur qui veut enregistrer « son » type ? Pas encore, il faut encore lire toute la section 4 qui précise ce qu'on peut et qu'on ne peut pas enregistrer. Par exemple, le type doit désigner un format pas des trucs qui ressemblent à un format mais n'en sont pas comme un encodage de transfert. C'est pour cela qu'on ne trouvera pas Base64 dans le registre des types de contenu.

Les noms doivent évidemment obéir à la syntaxe standard (section 4.2) et audio/$%#& n'est donc pas acceptable. C'est d'autant plus vrai que certains protocoles qui utilisent les types de contenu peuvent avoir des règles strictes sur les caractères acceptés.

À noter que le sous-type peut avoir une structure : ainsi, les sous-types XML peuvent s'écrire FORMAT+xml comme par exemple application/svg+xml pour SVG. Cette structure (définie dans le RFC 6839, et comportant un format spécifique, un plus et un suffixe qui indique le format général) permet de garder toute l'information. Un logiciel générique XML peut ainsi faire quelque chose d'un fichier SVG, même s'il ne connait pas SVG.

Depuis, d'autres formats ont suivi ce système (on trouve des sous-types se terminant par +json pour JSON) et un registre de ces formats génériques a été créé par le RFC 6839.

Il y a ensuite plein de règles spécifiques à certains types. Ainsi, le type text est conçu pour du contenu qui est lisible par un humain, sans disposer d'un logiciel particulier. Pour le logiciel qui reçoit un document, c'est une distinction importante : un document text/UNKNOWNUNKNOWN est un sous-type inconnu, pourra toujours être montré à l'utilisateur et ce sera mieux que rien. Avec les images (image/SOMETHING) ou le son (audio/SOMETHING), cela n'aurait pas de sens.

C'est ainsi que text/troff (RFC 4263) désigne du texte formaté avec troff ; si ce format d'enrichissement prévoit quelques « décorations » au texte, il reste néanmoins lisible sans processeur troff.

Le texte brut, sans aucun caractère spécial, est text/plain (RFC 2046). Tous les sous-types de text/ peuvent avoir un paramètre supplémentaire (voir la section 4.3 sur le concept de paramètres), charset, qui indique à la fois un jeu de caractères et un encodage (le terme de charset est donc malheureux mais il est trop tard pour le changer). Les charsets sont eux-même enregistrés en suivant le RFC 2978. Attention, certains sous-types contiennent l'indication de charset dans le texte lui-même (c'est le cas de XML) et ne doivent donc pas utiliser le paramètre charset (cf. RFC 6657). Dans tous les cas, s'il y a un paramètre charset, il doit dans la plupart des cas désormais être obligatoire (pas de valeur implicite). Si, malgré tout, une valeur par défaut est définie, cela doit être UTF-8 (RFC 6657 qui a remplacé l'ancienne règle, qui privilégiait US-ASCII).

image/ et audio/ ne posent pas de problèmes particuliers. Par contre, pour video/, le RFC rappele qu'une vidéo inclut souvent du contenu d'autres types (par exemple une piste audio synchronisée) et que cela doit être pris en compte lorsqu'on enregistre un sous-type.

Un type bien plus général, application/, est utilisé pour tout le reste. Ce sont les formats spécifiques à une application, par exemple application/msword pour le format privé de Microsoft Word, que tant de gens s'obstinent à vous envoyer sans s'être demandé si vous aviez payé votre taxe à Steve Ballmer. Mais application/ sert aussi pour les cas où le format n'est pas lisible directement (contrairement à text/) mais ne rentre pas dans les catégories comme image/ ou audio/. C'est ainsi qu'il existe un application/pdf pour les fichiers PDF.

Enfin, un type un peu spécial, multipart/ est là pour le contenu composite (RFC 2046). Si le protocole permet de mettre plusieurs objets de type différents dans un message, celui-ci va être étiqueté multipart/QUELQUECHOSE. On verra alors multipart/signed (deux parties, le contenu lui-même et une signature, par exemple en PGP), multipart/mixed (plusieurs parties distinctes, chacune ayant son type et sous-type), multipart/alternative (plusieurs parties de sous-types différents mais normalement équivalentes, le logiciel choisira le format qu'il préfère), etc.

Le RFC prévoit la possibilité d'enregister de nouveaux types (et pas seulement des sous-types). Il faudra pour cela un RFC sur le chemin des normes et notre RFC 6838 prévoit qu'un tel enregistrement sera plutôt rare. Un exemple est la création du type font/ par le RFC 8081.

Est-ce qu'un sous-type peut être enregistré pour un format breveté ? Oui (autrement, on n'aurait pas audio/mpeg), mais en suivant les règles habituelles de l'IETF, notamment de divulgation des brevets connus par un participant (RFC 8179 et RFC 5378).

Il faut aussi penser à la sécurité (section 4.6). La demande d'enregistrement d'un type de contenu doit comporter une section sur la sécurité de ce format, indiquant quels sont les risques connus. Quels formats peuvent créer des problèmes ? Ceux où le format est en fait un langage complet, permettant des actions comme ouvrir un fichier, sont les principaux. C'est ainsi qu'application/postscript a fait souvent parler de lui (voir son analyse de sécurité détaillée dans la section 4.5.2 du RFC 2046). Un tel « contenu actif » est toujours risqué.

Une fois qu'on a digéré toutes ces règles, ainsi que celles qui se trouvent dans le RFC et que je n'ai pas reprises ici, on peut passer à la rédaction de sa demande d'enregistrement d'un sous-type. La section 5 expose les procédures. La méthode canonique (mais il existe des variantes) est de rédiger sa demande (le gabarit, qui précise quelles informations doivent être données, figure en section 5.6), puis la soumettre d'abord à la liste media-types@ietf.org pour avoir un avis de la communauté. Ensuite, si l'enregistrement est dans l'arbre standard, on envoie la demande à l'IANA qui vérifiera que le format est bien décrit dans une norme stable (un RFC ou son équivalent dans une autre SDO). Pour les autres arbres, on écrit à l'IANA, ou bien on utilise le formulaire Web. Les demandes seront ensuite examinées par l'expert désigné, actuellement Ned Freed, avec Mark Baker en secours . Au cas où on n'aimerait pas sa décision, on peut toujours tenter un appel auprès de l'IESG.

Une autre procédure, en section 6, décrit le mécanisme d'enregistrement des suffixes de sous-types (comme +xml ou +json, voir le registre, créé par le RFC 6839).

La nouvelle liste de discussion pour un premier examen des demandes d'enregistrement a été créée le 17 septembre 2012. Elle se nomme media-types@ietf.org et remplace l'ancienne ietf-types.

Les amateurs d'histoire peuvent lire la section 1.1 de ce RFC : elle rappelle la naissance de ces types de contenu, dans le seul contexte du courrier électronique, lorsque celui-ci est devenu multimédia, en 1992, avec le RFC 1341. Notez que le courrier est asynchrone. Cela veut dire qu'il n'est pas possible de négocier un type de données entre les deux machines. L'émetteur doit lancer son message sans connaître le récepteur et étiqueter correctement le contenu est donc crucial. Pour limiter les risques d'interopérabilité (l'émetteur choisit un type très rare et le récepteur ne le connait pas), le choix avait été fait de limiter sévèrement le nombre de types, par le biais d'une procédure d'enregistrement très restrictive (RFC 2048, puis son successeur le RFC 4288, voir aussi la section 4.9 de notre RFC 6838). Aujourd'hui, les types sont souvent utilisés dans des protocoles synchrones comme HTTP, où la négociation est possible (le serveur HTTP sait ce qu'accepte le client, grâce à l'en-tête Accept:), ces anciennes règles n'ont donc plus de sens. D'où la libéralisation que marque notre nouveau RFC.

Outre celle-ci, les grands changements depuis le RFC 4288 sont (cf. annexe B) :

  • Spécification formelle des suffixes de sous-types (comme +xml) et création d'un registre de ces sous-types,
  • Changement des règles pour les noms commençant par x-, suite au RFC 6648,
  • Mise à jour des règles pour le type text/ pour tenir compte du RFC 6657.

Téléchargez le RFC 6838


L'article seul

RFC 6851: Internet Message Access Protocol (IMAP) - MOVE Extension

Date de publication du RFC : Janvier 2013
Auteur(s) du RFC : A. Gulbrandsen, N. Freed (Oracle)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF imapmove
Première rédaction de cet article le 29 janvier 2013


Le protocole d'accès aux boîtes aux lettres IMAP, normalisé dans le RFC 3501, ne prévoyait pas officiellement de moyen de déplacer un message d'une boîte à une autre. Il fallait que le client IMAP réalise une série de commandes à la place, et le déplacement n'était donc pas atomique. Plusieurs serveurs IMAP avaient mis en œuvre une commande atomique non officielle, MOVE, et ce RFC la normalise.

Avant ce RFC, en effet, la meilleure méthode officielle pour déplacer un message d'une boîte IMAP à une autre était un COPY (copier le message vers la nouvelle boîte), puis STORE (marquer le message comme devant être détruit), suivis d'un EXPUNGE (détruire les messages marqués). Plusieurs logiciels clients avaient ce service, pour que l'utilisateur puisse déplacer un message. Le problème est que ce n'était pas atomique. Par exemple, si le serveur IMAP redémarrait entre le COPY et le STORE, le message était dupliqué, et se retrouvait dans les deux boîtes. Sans même supposer un redémarrage, IMAP permet un accès simultané par plusieurs clients et le second client peut alors voir la boîte dans un état invalide (message copié mais pas encore détruit de l'ancienne boîte). Enfin, certains serveurs ont un mécanisme efficace pour déplacer un message sans copier les données (pensez à un serveur Unix qui stocke chaque message dans son fichier et peut donc faire un rename() facilement) et il était donc souhaitable de permettre son utilisation.

Bref, la section 3 décrit la nouvelle commande, MOVE, qui prend comme argument les numéros des messages à déplacer et le nom de la nouvelle boîte (il y a aussi un UID MOVE qui désigne les messages par leur identificateur, l'UID, et pas par leur numéro dans une séquence). À noter que, comme MOVE prend comme argument un groupe de messages, l'atomicité n'est garantie que pour chaque message (soit il est déplacé, soit il ne l'est pas, il ne peut pas être dupliqué), pas pour le groupe (certains messages peuvent être déplacés et d'autres pas).

Comme toute extension d'IMAP, MOVE est annoncé dans les capacités du serveur, au début de la connexion (les capacités possibles sont dans un registre IANA).

La section 4 décrit les interactions de MOVE avec d'autres extensions IMAP. Par exemple, les quotas du RFC 2087 (MOVE peut réussir là où un COPY aurait échoué, s'il y a un quota actif), ou bien les ACL du RFC 4314 (pour déplacer un message, il faut avoir le droit d'écrire dans la nouvelle boîte, et de détruire dans l'ancienne). Pendant qu'on parle de sécurité, le RFC rappelle aussi (section 6) qu'un MOVE peut avoir des interactions avec certaines politiques de stockage dans les boîtes (par exemple, si l'antispam met les spams dans une boîte nommée SPAM, un MOVE hors de cette boîte n'est pas innocent).

Il parait qu'il existe déjà plusieurs mises en œuvre de MOVE, aussi bien dans des clients que dans des serveurs IMAP. Mais je ne connais pas lesquelles. J'ai testé avec des Courier et des Zimbra récents et ils ne semblent pas avoir cette extension. Pour Dovecot, c'est annoncé pour la 2.2.


Téléchargez le RFC 6851


L'article seul

RFC 6852: Affirmation of the Modern Paradigm for Standards

Date de publication du RFC : Janvier 2013
Auteur(s) du RFC : R. Housley (IETF Chair), S. Mills (IEEE-SA President), J. Jaffe (W3C CEO), B. Aboba (IAB Chair), L. St.Amour (ISOC President and CEO)
Pour information
Première rédaction de cet article le 26 janvier 2013


Au cours des préparatifs de la réunion WCIT, organisée par l'UIT à Dubaï en décembre 2012, une des propositions faites au sein de la bureaucratie UIT était de rendre obligatoires, d'une manière ou d'une autre, les normes techniques émises par l'UIT. Ce projet n'a finalement apparemment pas été adopté mais il avait déclenché une réaction des autres SDO, qui ne voyaient pas pourquoi l'UIT aurait un tel privilège. Trois de ces SDO, l'IEEE, l'IETF et le W3C ont signé en commun une déclaration, dite OpenStand, dont ce RFC reprend le texte.

On comprend l'UIT : ses normes techniques (comme X.25 ou X.400) sont aujourd'hui bien oubliées et, dans l'Internet d'aujourd'hui, il ne reste guère de normes UIT qui soient utilisées (X.509 et ASN.1 doivent être parmi les rares exceptions, et encore, X.509 est menacé par le RFC 6698). Obtenir par un traité international, puis par la loi, ce que les acteurs du réseau lui ont refusé est donc tentant. L'un des principaux points de la déclaration tripartite des autres SDO est donc que l'adoption des normes doit rester fondée sur le volontariat : on déploie sur le réseau réel les normes qui ont un sens, et pas n'importe quel délire issu des comités Théodule de l'UIT, déconnectés de la réalité depuis longtemps.

La déclaration tripartite OpenStand a été signée le 29 août 2012, sans discussion à l'intérieur de l'IETF, dont les membres ont découvert le texte a posteriori. Comme la déclaration était le résultat d'un accord multilatéral, il ne pouvait plus être modifié par la suite. Le RFC reprend son texte littéralement, et tout le processus normal de discussion d'un RFC a donc été court-circuité : il y a bien eu des appels à commentaires mais les commentaires ont été complètement ignorés.

D'autres organisations ont signé depuis cette déclaration, on peut en trouver la liste sur le site officiel d'OpenStand.

Que dit cette déclaration (section 2) ? Après un préambule où n'est mentionné que le business (comme si l'Internet ne servait pas à une myriade d'autres activités, comme le notait le commentaire #193), les global markets et la concurrence, la déclaration affirme cinq points. Le premier est une sorte de clause de « non-ingérence dans les affaires des autres SDO », où chaque signataire s'engage à respecter les règles des autres. Le deuxième est l'adhésion à cinq principes :

  • Un processus de développement des normes qui repose sur des processus clairs et documentés, sans arbitraire,
  • La recherche d'un accord aussi large que possible, prenant en compte l'intérêt de tous,
  • La visibilité publique des travaux en cours, avec par exemple des appels à commentaires qui soient publics (on notera que le développement de la déclaration OpenStand n'a pas suivi cet excellent principe),
  • Un équilibre entre les parties prenantes, de manière à éviter le poids excessif d'un groupe précis (l'UIT est dominée par les États, alliés aux opérateurs telco traditionnels, mais les autres SDO ont en commun qu'elles sont réservées aux professionnels, le simple utilisateur n'est pas représenté),
  • Une ouverture à tous les volontaires qui veulent participer.

Le troisième point de la déclaration est un pot-pourri de points souhaitables dans les normes techniques produites (par exemple qu'elles permettent l'interopérabilité, la résilience, le passage à l'échelle, etc).

Le quatrième est le plus hypocrite : la disponibilité des normes techniques. Or, si des dinosaures comme l'ISO ou l'AFNOR ne publient toujours pas leurs normes sur l'Internet, si des organisations comme l'ETSI imposent des restrictions ridicules (enregistrement préalable, limite à trois normes accessibles), l'UIT, après de très longues hésitations, a fini par passer au vingt-et-unième siècle et ses normes sont désormais gratuitement accessibles. Par contre, un des signataires d'OpenStand, l'IEEE, ne le fait toujours pas... Il avait été question de mettre dans la déclaration tripartite une phrase comme « The text of standards is made accessible to all, free of charge or at low cost », voire, plus flou, un mot sur l'importance d'une distribution free des normes (avec la délicieuse ambiguité de l'anglais sur le mot free) mais cela a été écarté, sinon l'IEEE ne signait pas. C'est sur ce point que le caractère politicien d'OpenStand est le plus clair.

Le même point mentionne la délicate question de l'appropriation intellectuelle, qui affecte tant de normes. Les différences de politique entre les trois signataires (et même à l'intérieur de chaque signataire, notamment l'IETF), font que la déclaration reste très vague, acceptant aussi bien les techniques complètement libres que celles plombées par un brevet, à la seule condition, très générale, que les licences soient FRAND.

Enfin, le cinquième point de la déclaration est l'importance d'une adoption volontaire des normes, fondée sur leur mérite technique et pas sur une décision autoritaire, comme indiqué au début de cet article.


Téléchargez le RFC 6852


L'article seul

RFC 6833: LISP Map Server Interface

Date de publication du RFC : Janvier 2013
Auteur(s) du RFC : V. Fuller, D. Farinacci (cisco)
Expérimental
Réalisé dans le cadre du groupe de travail IETF lisp
Première rédaction de cet article le 24 janvier 2013


Comme pour tous les protocoles de séparation de l'identificateur et du localisateur, le nouveau-né LISP, normalisé dans le RFC 6830, doit faire face au problème de la correspondance (mapping) entre les deux informations. Comment trouver un localisateur, en ne connaissant que l'identificateur ? LISP n'a pas encore de solution ferme, bien qu'un protocole, ALT, normalisé dans le RFC 6836, ait été choisi pour l'instant. Comme il y a une probabilité non négligeable que LISP change de protocole de correspondance, voire en utilise plusieurs en parallèle, la stabilité du logiciel des routeurs imposait une interface stable avec le système de résolution des identificateurs en localisateurs. C'est ce que fournit notre RFC 6833, qui spécifie l'interface, vue du routeur, et qui ne devrait pas changer, même si ALT était remplacé par un autre système de correspondance/résolution.

LISP prévoit deux sortes de machines impliquées dans la résolution d'identificateurs (les EID) en localisateurs (les RLOC). Ces deux machines sont les Map-Resolver et les Map-Server. Pour ceux qui connaissent le DNS, on peut dire que le Map-Server est à peu près l'équivalent du serveur faisant autorité et le Map-Resolver joue quasiment le même rôle que celui du résolveur. Toutefois, il ne faut pas pousser la comparaison trop loin, LISP a ses propres règles. Pour résumer en deux phrases, un routeur LISP d'entrée de tunnel (un ITR), ayant reçu un paquet à destination d'une machine dont il connait l'identificateur (l'EID), va interroger un Map-Resolver pour connaître le localisateur (le RLOC, auquel l'ITR enverra le paquet). Pour accomplir sa tâche, le Map-Resolver fera suivre les requêtes au Map-Server, qui la transmettra finalement au routeur de sortie du tunnel (l'ETR), qui est la vraie source faisant autorité.

C'est entre le Map-Resolver et le Map-Server que se trouvent les détails du système de correspondance. Ils peuvent être connectés par ALT (RFC 6836, actuellement le mécanisme « officiel »), par CONS (RFC pas encore publié), par NERD (idem) ou bien par tout autre système de résolution, existant ou encore à créer (ils ne peuvent pas être connectés avec simplement LISP, puisqu'on aurait alors un problème d'œuf et de poule, LISP ayant besoin de ALT qui aurait besoin de LISP...). Rappelez-vous que notre RFC 6833 ne décrit qu'une interface, celle des ITR et ETR avec les Map-Resolver et Map-Server. Il est donc relativement court.

Comme avec toute technique nouvelle, il est prudent d'apprendre le vocabulaire (section 2, puis section 3 pour un survol général du système). Il y a deux types d'acteurs, les Map-Server et les Map-Resolver que nous avons déjà vu, et trois types de messages, Map-Register (un ETR l'envoie au Map-Server pour indiquer les RLOC des EID dont il est responsable), Map-Request (un ITR l'envoie à un Map-Resolver pour obtenir les RLOC ; le Map-Resolver fait suivre jusqu'au Map-Server, puis à l'ETR) et enfin Map-Reply, la réponse au précédent. Notons que ces types de messages ont leur description complète (avec leur format) dans le RFC 6830. Notez aussi que Map-Resolver et Map-Server sont des fonctions, et que les deux peuvent être assurée par la même machine, qui serait à la fois Map-Resolver et Map-Server (dans le DNS, un tel mélange est déconseillé).

La section 4 de notre RFC plonge ensuite dans les détails. Accrochez-vous. Voyons d'abord le premier routeur LISP que rencontrera le paquet. On le nomme ITR pour Ingress Tunnel Router. Les routeurs précédents traitaient l'adresse de destination du paquet comme une adresse IP ordinaire. L'ITR, lui, va la traiter comme un identificateur (EID pour Endpoint IDentification). L'EID n'est pas routable sur l'Internet.Il faut donc encapsuler le paquet en LISP pour l'envoyer dans le tunnel. La nouvelle adresse IP de destination est le localisateur (RLOC pour Routing LOCator). Pour trouver le localisateur, l'ITR va demander à un ou plusieurs Map-Resolver. Il a été configuré (typiquement, à la main) avec leurs adresses IP (qui doivent être des localisateurs, pour éviter un amusant problème d'œuf et de poule; notez que plusieurs Map-Resolver peuvent avoir la même adresse, grâce à l'anycast). L'ITR ne connait que le protocole de résolution, envoi d'une Map-Request et récupération d'une Map-Reply (en termes DNS, l'ITR est un stub resolver). L'ITR ne connait donc pas les protocoles utilisés en interne par le système de correspondance, il ne connait pas ALT (ou ses concurrents). Cette communication avec le Map-Resolver peut être testée et déboguée avec l'outil lig (RFC 6835).

La réponse du Map-Resolver ne sera pas forcément positive. L'ITR recevra peut-être une Negative-Map-Reply, envoyée en réponse si un Map-Resolver ne trouve pas de localisateur pour l'identificateur qu'on lui a passé. Cela veut dire que le site final n'utilise pas LISP, et qu'il faut alors router le paquet avec les méthodes habituelles d'IP. (Il n'est évidemment pas prévu que tout l'Internet passe à LISP du jour au lendemain, le routeur LISP doit donc aussi pouvoir joindre les sites non-LISP.)

Si la réponse est positive, l'ITR peut alors encapsuler le paquet et le transmettre. Comment le Map-Resolver a-t-il trouvé la réponse qu'il a envoyé ? Contrairement aux routeurs LISP comme l'ITR, le Map-Resolver et le Map-Server connaissent le système de correspondance utilisé (si c'est ALT, ils sont tous les deux routeurs ALT) et c'est celui-ci (non traité dans ce RFC) qu'ils utilisent pour savoir s'il y a une réponse et laquelle.

Et, à l'autre bout du tunnel, que s'était-il passé ? Le routeur de fin de tunnel (l'ETR, pour Egress Tunnel Router), avait été configuré par un administrateur réseaux avec une liste d'EID dont il est responsable. Pour que le reste du monde connaisse ces EID, il les publie auprès d'un Map-Server en envoyant à ce dernier des messages Map-Register. Pour d'évidentes raisons de sécurité, ces messages doivent être authentifiés (champ Authentication Data du message Map-Register, avec clés gérées à la main pour l'instant, avec SHA-1 au minimum, et le SHA-256 de préférence), alors que les Map-Request ne l'étaient pas (la base de données consultée par les routeurs LISP est publique, pas besoin d'authentification pour la lire, seulement pour y écrire). Ces Map-Request sont renvoyés périodiquement (le RFC suggère toutes les minutes) pour que le Map-Server sache si l'information est toujours à jour. Ainsi, si un ETR est éteint, l'information obsolète dans les Map-Server disparaîtra en trois minutes maximum (des messages peuvent être perdus, le RFC demande donc de patienter un peu en cas de non-réception). Cela veut aussi dire que LISP ne convient pas forcément tel quel pour les situations où on exige une mobilité très rapide.

Notez que je ne décris pas tous les détails (comme la possibilité pour un ETR de demander un accusé de réception au Map-Server, chose que ce dernier ne fait pas par défaut), voyez le RFC si vous êtes curieux.

Arrivés là, nous avons un Map-Server qui connait les EID que gère l'ETR. Désormais, si ce Map-Server reçoit une demande Map-Request, il peut la faire suivre à l'ETR (si vous connaissez le DNS, vous avez vu que le Map-Register n'est pas tout à fait l'équivalent des mises à jour dynamiques du RFC 2136 : avec ces dernières, le serveur de noms qui a reçu la mise à jour répondra ensuite lui-même aux requêtes). Le Map-Server ne sert donc que de relais, il ne modifie pas la requête Map-Request, il la transmet telle quelle à l'ETR. Le rôle des Map-Resolver et des Map-Server est donc simplement de trouver l'ETR responsable et de lui faire suivre (sans utiliser l'encapsulation LISP) les requêtes, pas de répondre à sa place. Cela se fera peut-être dans le futur lorsque des mécanismes de cache seront ajoutés. Pour le moment, les Map-Resolver n'ont pas de cache, grosse différence avec le DNS (section 3). La question, qui a suscité beaucoup de discussions dans le groupe de travail, est laissée pour des études futures.

La section 5 couvre les questions encore ouvertes. LISP étant un protocole expérimental, celles-ci sont nombreuses. Par exemple, les paramètres quantitatifs (fréquence des enregistrements, limites de retransmission, durée de vie des informations) sont actuellement fixés de manière un peu arbitraire. Le niveau de sécurité des enregistrements doit-il être durci, ou au contraire est-il déjà trop élevé pour être facilement déployable ? Ces questions ne pourront recevoir de réponse ferme qu'avec l'expérience en production.

La section 7 fait le tour des questions de sécurité liées au service de résolution. Celles-ci ont été chaudement discutées dans le groupe de travail mais le problème reste très ouvert. Comme les requêtes sont faites avec le format de paquets de LISP, elles héritent des services de sécurité de LISP comme le nonce qui permet de limiter les risques d'usurpation. Par contre, comme pour les protocoles utilisés dans l'Internet actuel, il n'y a pas de vraie protection contre les annonces faites à tort (un Map-Server qui annoncerait un EID qui n'est pas à lui). C'est un problème très proche de celui de la sécurité de BGP et qui utilisera peut-être le même genre de solutions.

Le RFC dit qu'il existe quatre mises en œuvre. Outre l'outil de débogage lig (RFC 6835), il y a celle de Cisco pour ses routeurs, mais je ne connais pas les autres, sans doute dans des Unix.


Téléchargez le RFC 6833


L'article seul

RFC 6830: Locator/ID Separation Protocol (LISP)

Date de publication du RFC : Janvier 2013
Auteur(s) du RFC : D. Farinacci (cisco), V. Fuller (cisco), D. Meyer (cisco), D. Lewis (cisco)
Expérimental
Réalisé dans le cadre du groupe de travail IETF lisp
Première rédaction de cet article le 24 janvier 2013


Le protocole LISP (qui n'a rien à voir avec le langage de programmation du même nom), vise à résoudre un problème documenté dans le RFC 4984 : les difficultés que rencontre le système de routage de l'Internet devant les pressions imposées par la croissance du réseau, et par le désir des utilisateurs de ne pas être lié à un unique fournisseur d'accès. Actuellement, tout changement de routage sur n'importe quel site se propage à tous les autres routeurs de la DFZ. Un tel système ne passe pas réellement à l'échelle (il ne peut pas croitre indéfiniment). LISP propose une solution (encore expérimentale actuellement), dans un ensemble de RFC dont ce RFC 6830 est le principal.

Avant de plonger dans ce RFC, voyons les motivations pour LISP et ses principes essentiels (si vous préférez les lire dans le RFC et pas dans mon article, c'est en section 4). Aujourd'hui, les adresses IP ont deux rôles, localisation (où suis-je connecté au réseau) et identité (qui suis-je). Une adresse IP est un localisateur car changer de point d'attachement (par exemple parce qu'on change de FAI) vous fait changer d'adresse IP, et c'est un identificateur car c'est ce qui est utilisé par les protocoles de transport comme TCP pour identifier une session en cours : changer d'adresse IP casse les connexions existantes.

Le principal problème de cet approche concerne le routage. Un routage efficace nécessiterait une cohérence entre les adresses et la topologie du réseau, par exemple que deux sites proches sur le réseau aient des adresses proches. Mais on n'a pas cette cohérence actuellement. On notera qu'IPv6 ne résolvait pas ce problème, et délibérement (le cahier des charges d'IPv6 ne prévoyait pas de changer le modèle de routage).

Résultat, les routeurs doivent gérer bien plus de routes que nécessaire, augmentant leur prix (en attendant le jour où, même en payant, on n'arrivera pas à manipuler autant de routes, avec leurs changements fréquents). Le RFC 4984 insistait sur ce problème en affirmant que « The workshop participants believe that routing scalability is the most important problem facing the Internet today and must be solved, although the time frame in which these problems need solutions was not directly specified. »

Cette croissance de la table de routage peut être suivie sur le célèbre site de Geoff Huston. Notez que la taille n'est pas le seul aspect, le rythme de changement (le nombre d'updates BGP par seconde) est au moins aussi important.

LISP vise donc à résoudre ce problème par une technique connue sous le nom de séparation du localisateur et de l'identificateur (son nom, « Locator/ID Separation Protocol », en dérive d'ailleurs, bien qu'il soit loin d'être le seul protocole dans cette catégorie). Au lieu que tous les préfixes IP aillent dans la DFZ, seuls les localisateurs, les RLOC (Routing LOCators) y iront. Les identificateurs, les EID (Endpoint IDentifiers) seront dans un nouveau système, le système de correspondance (mapping), qui permettra de trouver un RLOC à partir d'un EID. LISP est donc l'application d'un vieux principe de l'informatique : « Tout problème peut être résolu en ajoutant un niveau d'indirection. »

À quoi ressemblent RLOC et EID ? Physiquement, ce sont juste des adresses IP (v4 ou v6), avec une nouvelle sémantique.

Par rapport aux autres solutions de séparation de l'identificateur et du localisateur (la plus achevée étant HIP), LISP s'identifie par les points suivants :

  • Solution dans le réseau, pas dans les machines terminales. Seuls des routeurs (mais pas tous les routeurs de l'Internet) seront modifiés pour gérer LISP.
  • Déployable de manière incrémentale (il n'est pas nécessaire que tout le monde passe à LISP).
  • Pas de cryptographie (et donc pas plus de sécurité que l'IP d'aujourd'hui).
  • Indépendant de la famille IP utilisée (v4 ou v6).
  • Outre une solution au problème du passage à l'échelle du système de routage, LISP se veut aussi utilisable pour la mobilité et la virtualisation de réseaux (imaginez une machine virtuelle migrant d'un centre d'hébergement à un autre sans changer d'identificateur...).

Comment se passe l'envoi d'un paquet avec LISP ? Supposons qu'une machine veuille écrire à www.example.com. Elle utilise le DNS comme aujourd'hui, pour trouver que l'adresse est 2001:db8:110:2::e9 (c'est un EID, un identificateur, mais la machine n'a pas besoin de le savoir, les machines terminales ne connaissent pas LISP et ne savent même pas qu'elles l'utilisent). Elle envoie le paquet à son routeur habituel. À un moment dans le réseau, le paquet va arriver dans un routeur LISP (qui, lui, a été modifié pour gérer LISP). Il va alors chercher le RLOC (le localisateur). Il demande au système de correspondance (l'équivalent LISP du DNS) qui va lui dire « le RLOC de 2001:db8:110:2::e9 est 198.51.100.178 » (notez au passage que RLOC et EID peuvent être des adresses v4 ou v6). (L'information est stockée dans un cache du routeur, pour le prochain paquet.) Le paquet est alors encapsulé dans un paquet LISP qui est transmis en UDP (port 4341) à 198.51.100.178. (En raison de ces deux étapes, correspondance puis encapsulation, LISP fait partie des protocoles nommés Map and Encap.) 198.51.100.178 décapsule et le paquet suit ensuite un chemin normal vers la machine 2001:db8:110:2::e9. Pendant le trajet dans le tunnel, le paquet aura donc deux en-têtes, l'interne (celui placé par la machine d'origine et qui utilise des EID dans les champs « Adresse IP source » et « Adresse IP destination ») et l'externe (celui placé par le routeur d'entrée du tunnel, et qui utilise des RLOC).

Si le système de correspondance avait répondu négativement « Ce n'est pas un EID, je n'ai pas de RLOC pour 2001:db8:110:2::e9 » (Negative map reply) ? Cela aurait voulu dire que le site cible n'utilise pas LISP et, dans ce cas, on lui transmet le paquet par les mécanismes habituels d'IP.

Ainsi, pour prendre le scénario d'usage principal de LISP, un site qui veut être multi-homé n'aura pas besoin de BGP et d'annoncer ses routes dans la DFZ. Il aura ses identificateurs, ses EID, et les paquets entrant ou sortant de son réseau seront encapsulés en LISP (le système de correspondance peut renvoyer plusieurs RLOC pour un EID, avec des préférences différentes, pour faire de l'ingénierie de trafic). Pour les routeurs de la DFZ, ce seront juste des paquets IP ordinaires. Seules les deux extrémités du tunnel sauront que LISP est utilisé.

Le système de correspondance de LISP n'est pas encore définitif : plusieurs choix sont possibles mais il existe un système privilégié, ALT (RFC 6836). Comme le DNS, il fonctionne en tirant les informations nécessaires (pas en les poussant vers tout le monde, comme le fait BGP), ce qui devrait lui donner une bonne capacité de croissance. De toute façon, LISP spécifie une interface vers le système de correspondance (RFC 6833) et les différents systèmes ont juste à mettre en œuvre cette interface pour qu'on puisse en changer facilement. Ainsi, ALT pourra être remplacé par un de ses concurrents, CONS, EMACS ou NERD (leurs noms sont des références au langage de programmation). NERD est documenté dans le RFC 6837.

LISP est aujourd'hui essentiellement promu par Cisco, qui a monté un réseau mondial de test, qui compterait 140 sites. LISP est considéré comme expérimental, comme l'indique le statut de ce RFC (et la section 15 de notre RFC, qui liste les problèmes connus). Ses effets sur l'Internet ne sont pas encore complètement maîtrisés. LISP est à l'heure actuelle un protocole très controversé. (Ces avertissements ont été ajoutés au document peu de temps avant son adoption comme futur RFC.)

Ce RFC est un gros morceau (d'autant plus que d'autres parties de LISP sont dans d'autres RFC). Je ne vais pas le couvrir en entier. Mais quelques points méritent d'être gardés en tête :

  • Un paquet dont l'adresse de destination est un EID ne peut être acheminé que via LISP. L'EID n'est pas routé sur l'Internet habituel. (Les EID peuvent être des adresses RFC 1918, par exemple.)
  • Pour éviter que la base des EID ne pose les mêmes problèmes de croissance que la DFZ d'aujoud'hui, les EID seront agrégés, mais cela sera fait de manière indépendante de la topologie : si on change de FAI, cette agrégation ne changera pas.

Pour les fanas de format de paquets, la section 5 décrit l'encapsulation. LISP est indépendant de la famille d'adresses, donc on peut avoir un paquet IP où les EID sont IPv4 qui soit tunnelé avec des RLOC IPv6 ou bien le contraire. Devant le paquet normal, LISP va ajouter un en-tête IP standard pour les RLOC, où la source sera l'ITR (routeur d'entrée du tunnel) et la destination l'ETR (routeur de sortie du tunnel), puis un en-tête UDP (l'UDP a davantage de chances de passer les middleboxes que de l'IP mis directement dans l'IP), avec le port de destination à 4341, puis un en-tête spécifique à LISP et enfin le paquet original. Donc, pour résumer :

  • En-tête du paquet original (inner header en terminologie LISP) : les adresses IP source et destination sont des identificateurs, des EID,
  • En-tête vus par les routeurs situés entre l'ITR et l'ETR (outer header) : les adresses IP source et destination sont des localisateurs, des RLOC.

L'en-tête spécifique à LISP contient notamment (section 5.3 si vous voulez tout connaître) :

  • Cinq bits de contrôle, nommés N, L, E, V et I
  • Si le bit N est à 1, un champ Nonce (section 6.3.1). Il s'agit d'un nombre tiré au hasard : si le destinataire d'un paquet peut le renvoyer, cela prouve qu'il avait reçu le message original (et qu'on parle donc bien au bon destinataire : ce numnique sert à éviter les attaques en aveugle).
  • Si le bit L est à 1, un champ Locator Status Bits, qui indique l'état (joignable ou pas) des machines situées sur le site de départ du paquet.

Comme toutes les solutions à base de tunnel, LISP va souffrir de la mauvaise gestion de la PMTUD dans l'Internet d'aujourd'hui (cf. RFC 4459), l'en-tête LISP supplémentaire réduisant la MTU (cf. section 5.4 pour des solutions possibles).

La section 5 décrivait les paquets de données, ceux encapsulant les données envoyées par le site original. La section 6 couvre les paquets de contrôle, utilisés par LISP pour ses propres besoins, notamment le système de correspondance (cf. RFC 6833 pour les détails). On y retrouve l'utilisation d'UDP :

  • Map Requests, où le port de destination est 4342,
  • Map Replies,
  • et quelques autres qui partagent des formats proches.

Il est évidemment essentiel qu'on sache si son correspondant est joignable ou pas. Comment cette « joignabilité » est-elle vérifiée ? La section 6.3 énumère les mécanismes disponibles. Entre autres :

  • Les Locator Status Bits où un ITR (le routeur LISP à l'entrée du tunnel) indique si les sites qu'il contrôle sont joignables. Si on souhaite répondre à un message transmis en LISP, c'est une information cruciale.
  • Les classiques messages ICMP comme Host Unreachable. Comme ils ne sont pas authentifiés, les croire aveuglément est dangereux. Mais les ignorer totalement serait dommage.
  • La réception récente d'un message Map Reply est une bonne indication que le site à l'autre bout fonctionne.

Mais on peut aussi tester explicitement, par le mécanisme Echo Nonce de la section 6.3.1. Le testeur émet un message LISP avec les bits N (numnique présent) et E (écho demandé), met le numnique à une valeur aléatoire (RFC 4086), et envoie le paquet. L'ETR à l'autre bout doit normalement renvoyer ce numnique dans son prochain paquet. Notons que cela teste la bidirectionnalité de la connexion. Si on n'obtient pas de réponse, cela peut signifier que la connexion est complètement coupée ou tout simplement qu'elle ne marche que dans un seul sens. Mais, surtout, l'absence de réponse peut indiquer le cas où l'ETR qui reçoit le trafic pour un site n'est pas le même routeur que l'ITR qui génère le trafic sortant. Dans ce cas, l'absence de réponse n'est pas un problème. Enfin, le routeur en face peut tout simplement être configuré pour ignorer les demandes d'écho.

Une autre solution pour tester est donc d'utiliser les messages du système de correspondance EID->RLOC, les Map Request et Map Reply. Ces messages ont un bit P (pour probe) qui indique que le demandeur est intéressé par la joignabilité du site demandé.

LISP impose donc des traitements supplémentaires, par rapport à ceux de l'IP classique. Est-ce que cela ne ralentit pas trop les routeurs ? La section 7 explore le problème et explique pourquoi LISP ne nécessite pas de changement du matériel de forwarding (les ASIC du routeur). La plupart des routeurs ont déjà du code prévu pour gérer des tunnels (encapsuler et décapsuler) rapidement.

Comment sera déployé LISP ? La section 8 décrit plusieurs scénarios possibles mais il faut regarder le futur RFC sur le déploiement de LISP pour avoir les détails. Principal problème : combien d'ITR et d'ETR pour un opérateur ? Grâce aux tunnels, on peut n'avoir qu'un seul ITR et un seul ETR pour tout le trafic. Cela poserait évidemment des problèmes de redondance et de performance. Mais avoir beaucoup de xTR peut poser des problèmes d'administration. Si les ITR sont largement automatiques (leur cache des correspondance EID->RLOC est bâti dynamiquement), avoir beaucoup d'ETR risque d'être compliqué à maintenir (car l'ETR doit avoir dans sa configuration une liste des EID qu'il va gérerà).

On peut aussi se demander si le premier routeur LISP utilisé par les clients doit être dans le réseau du FAI ou bien s'il ne devrait pas être dans le CPE (section 8.3).

Toujours dans la série des problèmes pratiques, que devient l'indispensable outil de débogage traceroute (section 9) ? Si les routeurs ne faisaient rien de spécial, un traceroute depuis un site LISP vers un autre montrerait le tunnel entre l'ITR et l'ETR comme un seul saut. Pour qu'on voit les routeurs dans le tunnel, il faut que LISP bricole un peu : les messages ICMP time exceeded générés dans le tunnel arriveront à l'ITR (c'est son adresse qui est la source des paquets encapsulés). L'ITR doit donc, pour faire des jolis traceroute, regarder le contenu du message ICMP, extraire le message original et donc l'adresse originale, puis envoyer un ICMP Time Exceeded à la vraie source.

Ça, c'était pour IPv6. En IPv4, c'est un peu plus compliqué car le paquet ICMP d'erreur ne contient pas la totalité du message-sonde de traceroute, même pas le maximum possible. L'ITR doit donc maintenir un cache des requêtes traceroute qu'il voit passer, indexé par un numéro qui sera utilisé comme port source dans les requêtes encapsulées. Ainsi, lors de la réception du ICMP Time Exceeded, l'ITR pourra retrouver la vraie source.

Pour ceux qui s'intéressent à la question de la mobilité, la section 10 y est consacrée. Un des avantages de la séparation de l'identificateur et du localisateur est justement de faciliter la mobilité. Un site ou une machine peut garder son EID en changeant de RLOC. Plusieurs cas :

  • Si c'est tout le site qui bouge (un changement de FAI, par exemple, c'est une forme de mobilité, après tout), les machines du site ne voient rien, elles gardent leur EID et n'ont rien à faire. Il faut juste enregistrer la correspondance entre les EID et les nouveaux RLOC.
  • Si c'est juste une machine qui bouge, on est dans le domaine de Mobile IP (RFC 6275 et RFC 4866). LISP peut aider mais ses interactions avec Mobile IP sont encore en cours d'exploration.

Un des gros problèmes que pose la séparation de l'identificateur et du localisateur est la sécurité : nouvelles attaques (par exemple contre le système de correspondance), nouveaux pièges (une machine qui utiliserait le vrai RLOC mais mentirait sur l'EID, par exemple), tout cela n'est pas encore bien connu et explique largement pourquoi les RFC sur LISP n'ont que le statut Expérimental. En attendant davantage d'expérience concrète , la section 12 examine les risques théoriquement présents dans LISP.

Comme avec toutes les techniques de tunnel, un émetteur peut facilement tricher sur l'adresse source interne (celle qui sera utilisée après décapsulation par l'ETR). Pour se protéger, un ITR devrait n'encapsuler un paquet que si l'adresse source est un EID qu'il contrôle. Et un ETR ne devrait transmettre un paquet que si la destination est un EID sous sa responsabilité.

Le test de la réversibilité (via les numniques, cf. section 3)) est essentiel contre ces risques. Sans ce test, un ETR pirate pourrait par exemple envoyer un Map Reply en réponse aveugle à un Map Request, et le voir accepté, avec des données mensongères (naturellement, l'ITR n'accepte que des Map Replies qui sont en réponse à un Map Request de sa part). Avec ce système de numnique que le récepteur doit mettre dans sa réponse, un attaquant aveugle (qui n'est pas situé sur le chemin des paquets et ne peut donc pas les observer) aura donc peu de chances de réussir à faire accepter ses paquets.

En revanche, un attaquant situé sur le chemin, et qui peut observer les paquets qui passent, a la possibilité de commettre bien plus de dégâts. Mais c'est déjà le cas avec les protocoles actuels (par exemple, les numéros de séquence difficiles à deviner du RFC 6528 ne protègent pas TCP contre des attaquants situés sur le chemin).

Les attaques par déni de service sont évidemment possibles avec LISP : une des précautions recommandées est de limiter le trafic des Map Requests et Map Replies. Autre attaque par déni de service, un ITR peut être victime d'une machine qui essaie de remplir la table des correspondances EID->RLOC du routeur. Il est donc important d'envisager ce cas, par exemple en permettant de garder dans le cache les entrées les plus fréquemment accédées (pour éviter qu'elles ne soient retirées automatiquement pour faire de la place). Mais il n'existe pas de solution miracle contre ce problème d'envahissement de cache.

On l'a dit, LISP a actuellement le statut Expérimental. La section 15 résume les problèmes connus à l'heure actuelle, et qui devront être traités pour obtenir un changement de statut :

  • Recherche sur d'autres systèmes de correspondance EID->RLOC, au cas où ALT (RFC 6836) ne convienne pas.
  • La gestion du cache des correspondances EID->RLOC, notamment en cas de fort usage (attaque par défi de service, par exemple) reste à explorer.
  • Un RFC existe au sujet de l'interconnexion de LISP avec les sites non-LISP (RFC 6832) mais il n'y a guère d'expérience pratique.
  • Traditionnellement, les protocoles Internet séparaient strictement le contrôle et les données : un simple paquet IP ne pouvait pas modifier les routes, par exemple. Ce n'est plus tout à fait le cas avec LISP : un paquet de données arrivant à un ETR peut mettre à jour le cache de celui-ci (section 6, sur le gleaning). Il reste à voir quelles conséquences cela aura.
  • L'Internet est un système très complexe, et les conséquences de LISP sur toutes les parties de ce système ne sont pas encore assez connues.
  • Le RFC 6115 (section 2.2) avait formulé des critiques sur LISP, qui n'ont pas encore fait l'objet d'un traitement (montrer que la critique était injustifiée, ou bien modifier LISP pour en tenir compte).

Le fonctionnement de LISP est schématisé sur ce dessin : lisp-basic Alice a l'identificateur (EID) 2001:db8:1::1 et veut écrire à Bob qui a le 2001:db8:2::42 (dans la plupart des cas, Alice aura trouvé l'adresse de Bob dans le DNS, comme aujourd'hui). Ni Alice, ni Bob n'ont à connaître LISP, chacun croit utiliser de l'IP normal. Alice envoie donc un paquet standard, à destination de 2001:db8:2::42. Mais, sur le trajet, il y a un ITR, un routeur LISP. Celui-ci va chercher (dans le système de correspondance, non montré ici) le RLOC (le localisateur) de Bob (ou, plus exactement, de son site). Une fois qu'il a trouvé 2001:db8:ff::666, il encapsule le paquet derrière un en-tête LISP et envoie ce paquet à l'ETR, l'autre routeur LISP en face, 2001:db8:ff::666. Les routeurs de l'Internet, entre l'ITR et l'ETR, ne connaissent pas LISP non plus et routent ce qui leur semble un paquet IP normal. Arrivé à l'ETR, le paquet est décapsulé et poursuit son chemin par du routage IP classique. Sur tout le schéma, seuls l'ITR et l'ETR sont des nouveautés LISP.

Modifions légèrement le schéma pour y mettre le système de correspondance : lisp-mapping On y voir l'ITR demander à son résolveur « Quel est le localisateur de 2001:db8:2::42 ? » et son résolveur lui répondre. Le résolveur avait demandé au serveur qui avait reçu de l'ETR un enregistrement disans « Le localisateur de 2001:db8:2::42 est 2001:db8:ff::666 ». Entre le résolveur et le serveur se trouve le cœur du système de correspondance. LISP en a plusieurs possibles, comme le ALT du RFC 6836.

Où trouve-t-on du code LISP aujourd'hui ?

Comme pour tous les protocoles fondés sur le principe de la séparation de l'identificateur et du localisateur, il est toujours utile, si on veut en comprendre les principes, de (re)lire l'article fondateur de Chiappa, « Endpoints and Endpoint names: A Proposed Enhancement to the Internet Architecture ». Autres articles à lire :


Téléchargez le RFC 6830


L'article seul

RFC 6837: NERD: A Not-so-novel EID to RLOC Database

Date de publication du RFC : Janvier 2013
Auteur(s) du RFC : E. Lear (Cisco)
Expérimental
Première rédaction de cet article le 24 janvier 2013


Dès qu'on sépare, dans un protocole réseau, le localisateur de l'identificateur, on a créé la nécessité d'une base de données pour mettre les deux en correspondance : une fois qu'on a l'identificateur, il faut bien trouver le localisateur. Et cette base doit être accessible depuis le réseau. Le protocole LISP n'impose pas une base particulière : son architecture permet de tester plusieurs types de base et le système NERD (Not-so-novel EID to RLOC Database) est une de ces bases.

En pratique, LISP, décrit dans le RFC 6830, a un mécanisme de correspondance identificateur->localisateur favori, ALT (RFC 6836). Mais la base de données des correspondances est accédée via une interface standard (RFC 6833) et, derrière cette interface, on peut placer d'autres systèmes. NERD est nettement moins avancé qu'ALT (pas de mise en œuvre existante, juste un projet individuel) mais est intéressant parce qu'il explore une solution très différente. Le principe de NERD est de stocker la totalité des correspondances (ce n'est qu'un gros fichier, après tout, et relativement statique), et de la distribuer via les mécanismes habituels de distribution de fichiers (typiquement HTTP).

Question état d'avancement de NERD, il est amusant de noter que NERD était en fait le premier mécanisme de correspondance identificateur->localisateur proposé pour LISP. Pour diverses raisons, notamment organisationnelles à l'IETF, le RFC n'est publié que maintenant.

L'auteur estime que la méthode proposée fonctionne jusqu'à environ cent millions d'entrées dans la base. Que devra contenir cette base ? La correspondance entre les identificateurs (EID pour endpoint identifiers) et les localisateurs (RLOC pour routing locators). Qu'est ce que consulte un routeur LISP lorsqu'il doit transmettre un paquet ? Ce paquet est à destination de l'identificateur 2001:db8:1337::1:af ? Regardons dans la base des correspondances, chic, on trouve que le localisateur correspondant en 192.0.2.254. Encapsulons le paquet et envoyons-le à 192.0.2.254 qui se débrouillera ensuite (et, au passage, vous avez vu que les EID et les RLOC ont la forme physique d'une adresse IP et qu'un EID IPv6 peut avoir un RLOC IPv4 et réciproquement).

La plupart des autres systèmes de base de données de correspondance sont « à la demande ». C'est lorsque le routeur doit transmettre un paquet qu'il va se mettre en chasse de la correspondance. L'inconvénient est que cela va prendre du temps et que le premier paquet d'une communication risque fort de ne pas patienter assez longtemps. La perte du premier paquet d'une session (typiquement un TCP SYN) est particulièrement gênante car l'application attendra longtemps. Avec NERD, au contraire, le routeur a en permanence toute l'information. (Ce point du « premier paquet perdu » est développé dans la section 7.2, qui explique en quoi NERD traite ce problème mieux que ALT.)

Pour concevoir NERD, l'auteur a supposé acquis les points suivants (section 1.1) :

  • Les données changent peu et uniquement lors d'opérations explicites d'un humain (par exemple, un site acquiert un nouveau FAI et donc un nouveau moyen d'être joint), pas lors d'événements techniques comme la panne d'un routeur ou d'un lien.
  • Les données sont globales (identiques pour tout l'Internet) contrairement aux métriques de certains protocoles de routage (le coût d'une route, par exemple, dépend de la position).
  • La mobilité des machines ou des réseaux (qui nécessite des changements fréquents des correspondances) ne sera pas traitée par NERD.

Ensuite, NERD définit quatre choses :

  • Un format pour la base de données,
  • Un format pour la distribution des mises à jour,
  • Un mécanisme de distribution, qui sera généralement HTTP (RFC 7230),
  • Un mécanisme de bootstrapping (NERD a besoin du réseau mais le réseau a besoin de NERD...).

Pour représenter les changements, un mécanisme aussi simple que le format patch traditionnel aurait pu être utilisé. Mais NERD utilise un format spécifique à la base de données LISP.

La section 2 explique comment fonctionne NERD :

  • Une Autorité (volontairement, le RFC ne spécifie pas qui serait l'Autorité : peut-être un RIR) génère la base et la signe avec la clé privée dont la partie publique est dans son certificat X.509. (L'annexe A décrit comment signer avec OpenSSL : openssl smime -binary -sign -outform DER -signer yourcert.crt -inkey yourcert.key -in database-file -out signature.)
  • La base est ensuite envoyée à un groupe de serveurs HTTP que les routeurs LISP connaissent.
  • Les routeurs récupèrent la base et vérifient la signature (avec OpenSSL, openssl smime -binary -verify -inform DER -content database-file -out /dev/null -in signature). À partir de là, le routeur LISP peut fonctionner, il connait les correspondances identificateur->localisateur.
  • L'Autorité peut générer des changements, reflétant les modifications de la base.
  • De temps en temps, les routeurs reviennent interroger les serveurs pour demander les changements. Ceux-ci sont également signés. Une fois vérifiés, le routeur « patche » sa base avec les changeents.

Ainsi, un routeur d'entrée d'un tunnel LISP n'a jamais à attendre une résolution d'EID en RLOC. Il a toujours la totalité des informations. Ce gain en temps se paie par une consommation plus élévée de mémoire.

La section 2.3 discute qui pourrait être Autorité. NERD est compatible avec plusieurs mécanismes comme une Autorité unique et centrale (l'IANA ?), comme une oligarchie d'Autorités (les RIR), ou comme un système très décentralisé avec des tas d'Autorités différentes en concurrence.

Quant au format de la base, il figure en section 3. Il est fort simple, un en-tête avec les métadonnées. Parmi elles, la signature cryptographique au vieux format PKCS#7 du RFC 2315, un numéro de version permettant de voir si la base est plus récente qu'une copie locale, etc. Le format de la signature pourrait passer à CMS (RFC 5652) dans le futur. Le certificat doit contenir un DNS-ID (voir RFC 6125) qui sera le nom identifiant l'Autorité.

Et les données ? Une simple liste d'identificateurs (EID) suivi chacun d'une liste de ses localisateurs (RLOC), encodée dans un format binaire décrit en section 3.1. Les changements (section 3.2) suivent un format simple : si un EID a des RLOC, il est ajouté à la base (ou il remplace complètement les valeurs existantes, s'il y en avait : ajouter un seul RLOC à un EID nécessite donc de diffuser tous les RLOC), sinon (si sa liste des RLOC est vide), il est retiré de la base.

La section 4 spécifie les URL à utiliser. La récupération initiale de la base nerd.arin.net, à partir d'un serveur www.example.com se fait avec http://www.example.com/eiddb/nerd.arin.net/current/entiredb et la récupération d'un changement se fait avec http://www.example.com/eiddb/nerd.arin.net/current/changes/1105500 où 1105500 est le numéro de version de l'actuelle copie locale du routeur. Si le serveur n'a pas les changements depuis 1105500 (par exemple parce que c'est une trop vieille version), il a le droit de faire une redirection HTTP vers une autre version. Le routeur aura donc peut-être plusieurs étapes pour se mettre à jour. Attention, www.example.com ne doit pas mener à un identificateur LISP, sinon on rencontrerait un amusant problème de circularité (voir aussi la section 8.1).

Est-ce réaliste en pratique ? La section 5 analyse quantitativement les « dépenses » liées à NERD. D'abord, la taille de la base. Elle dépend évidemment des hypothèses faites. Pour une hypothèse basse, 100 000 EID et une moyenne de 4 RLOC par EID, la base ferait dans les 9 méga-octets. Un bien petit fichier selon les critères d'aujourd'hui. Ceci dit, une hypothèse haute, avec 100 millions d'EID et 8 RLOC par EID donnerait une base de 17 giga-octets, nettement plus difficile à distribuer. Il est difficile de prévoir qu'elle est l'hypothèse réaliste. Par exemple, il y a aujourd'hui dans les 400 000 routes dans la table de routage globale, donc LISP, s'il est un succès, aura certainement plus de 400 000 EID. Le RFC compte sur un déploiement progressif, estimant que, même si l'hypothèse haute est atteinte, cela ne sera pas avant de nombreuses années, et les routeurs auront alors davantage de RAM.

Des calculs similaires donnent une idée du nombre de serveurs HTTP qui seront nécessaires pour distribuer une telle base, et ses changements, sans devoir attendre des heures.

Et pour jouer le rôle des Autorités ? Notez que ce RFC parle très peu de l'avitaillement de la base (enregistrement d'EID et changement de leurs RLOC). Voir les sections 2.3 et 5.4 qui donnent une idée de ce que serait le travail de ces Autorités et les caractéristiques (notamment de sécurité) qu'elles doivent avoir.

Les sections 6 et 7 sont consacrées aux alternatives non retenues. Pourquoi n'avoir pas utilisé XML pour le format ? (Principale raison : taille de la base, avec l'encodage habituel de XML.) Et pourquoi n'avoir pas spécifiéé d'autres mécanismes de distribution que ce système de miroirs HTTP ?

Un tel mécanisme aurait pu être celui de NNTP (RFC 3977). Il a largement montré ses capacités à distribuer rapidement une grande quantité de données et le RFC ne dit pas clairement pourquoi il n'a pas été retenu.

Plus éloigné du principe de NERD aurait été l'utilisation du DNS pour récupérer l'information de correspondance entre EID et RLOC. Les avantages du DNS sont que le partage administratif des responsabilités et l'infrastructure technique sont déjà en place. Il a déjà été envisagé de l'utiliser pour le routage (RFC 1383). Notre RFC suggère quelque chose du genre :

; Deux RLOC pour 10.0.128.0/23
$ORIGIN 0.10.nerd.arpa.
128   EID2RLOC   mask 23 priority 10 weight 5 172.16.5.60
      EID2RLOC   mask 23 priority 15 weight 5 192.168.1.5

Mais le DNS n'est pas temps réel et, bien que cela ne soit pas forcément une gêne pour l'application (qui attend le résultat de la résolution DNS), c'est plus embêtant lorsque cette attente est dans le système de routage, laissant l'application dans l'ignorance de ce qui se passe. Et puis l'utilisation du DNS pour LISP ferait peser une contrainte sur les serveurs de noms (ne pas les numéroter avec des EID, qui obligeraient à avoir LISP pour trouver la base de données LISP).

Voilà, si vous aimez les jolis transparents avec des images et des citations érudites, l'auteur du RFC a mis en ligne son court exposé sur NERD.

Il n'y a apparemment pas de mise en œuvre de NERD aujourd'hui, ni côté Autorités, ni dans les routeur (les serveurs, eux, seraient des serveurs HTTP standard). Disons que NERD est une solution de rechange si ALT ou les autres mécanismes de correspondance ne tiennent pas leurs promesses. Après tout, LISP est expérimental...


Téléchargez le RFC 6837


L'article seul

RFC 6836: LISP Alternative Topology (LISP+ALT)

Date de publication du RFC : Janvier 2013
Auteur(s) du RFC : V. Fuller (Cisco), D. Farinacci (Cisco), D. Meyer (Cisco), D. Lewis (Cisco)
Expérimental
Réalisé dans le cadre du groupe de travail IETF lisp
Première rédaction de cet article le 24 janvier 2013


Dans tous les systèmes de séparation de l'identificateur et du localisateur, le gros problème à résoudre est celui de la correspondance entre les deux. Sur le papier, cette séparation semble une idée simple et qui apporte des tas de bénéfices (multi-homing facile, plus besoin d'adresses PI, plus de rénumérotation des réseaux, etc), mais, dès qu'on rentre dans les détails, on se heurte au problème de la correspondance : comment trouver le localisateur lorsqu'on ne connait que l'identificateur, et de manière raisonnablement sécurisée ? Le protocole LISP a donc lui aussi ce problème et l'une des approches proposées (LISP est encore expérimental) est ALT (ALternative Topology) dont le principe est de créer un réseau virtuel des routeurs LISP, avec le mécanisme de tunnels GRE, leur permettant d'échanger en BGP ces informations de correspondance entre identificateurs et localisateurs. Avec ALT, route et résolution de noms sont fusionnés. De même que BGP dans l'Internet habituel peut être vu comme une résolution préfixe->nexthop, ALT est une résolution identificateur->localisateur faite en utilisant le routage.

Donc, le problème est le suivant : un ITR (premier routeur LISP qui traite un paquet) reçoit un paquet à destination d'un EID (un identificateur), il doit trouver l'ETR (dernier routeur LISP avant que le paquet ne repasse dans le routage habituel) à qui le passer et pour cela connaître son RLOC (le localisateur). Pour cela, l'ITR interroge un Map Resolver qui lui donnera la correspondance EID->RLOC. Mais comment le Map Resolver a-t-il trouvé l'information qu'il va servir ? Il existe plusieurs méthodes et notre RFC décrit l'une d'elles, ALT (ALternative Topology).

Pour éviter de réinventer la roue, ALT repose donc sur BGP (RFC 4271). Mais le protocole BGP n'est pas utilisé entre les routeurs habituels mais uniquement entre les routeurs ALT. Le réseau de ces routeurs est un réseau virtuel, construit avec des tunnels GRE (RFC 2784). Une fois le réseau virtuel, l'overlay, construit, les routeurs ALT vont se communiquer en BGP la liste des préfixes EID, qui va ainsi se propager partout. Les routes ainsi publiées mèneront à l'origine de l'annonce, un Map Server LISP qui connait l'ETR à qui demander la correspondance entre EID et RLOC. Notez donc bien qu'ALT ne distribue pas réellement les correspondances EID->RLOC mais les routes permettant de joindre celui qui connait la correspondance. Comme cela, il pourra recevoir une requête Map Request de LISP.

L'ITR typique, qui se retrouve avec un paquet IP destiné à un EID (l'identificateur) dont il ne connait pas le RLOC (le localisateur) ne fait en général pas partie de ALT. Il écrit à un Map Resolver (en utilisant l'interface standard décrite dans le RFC 6833) qui, lui, utilisera ALT (section 4.1). La réponse sera gardée dans un cache de l'ITR, pour accélerer les requêtes suivantes.

De même, ce n'est pas en général un ETR qui est membre de ALT pour diffuser les correspondances EID->RLOC mais un Map Server, auprès duquel les ETR enregistreront leurs préfixes.

Comme tous les protocoles de correspondance (par exemple le DNS), ALT réussit donc à résoudre le problème de l'œuf et de la poule : pour trouver un RLOC, on a besoin d'écrire à la machine qui le connait mais, pour cela, il nous faut son RLOC... Dans ALT, le problème d'œuf et de poule est résolu en créant ce réseau virtuel, qui ne repose que sur les EID (les identificateurs). Ce réseau virtuel ne sert qu'à la résolution d'identificateur en localisateur, il ne transporte pas de données.

On l'a vu, ALT réutilise des techniques très classiques et bien connues, déjà mises en œuvre dans tous les routeurs (BGP et GRE). Cela ne veut pas dire que les routeurs ALT seront les mêmes routeurs que ceux qui transmettent actuellement le trafic Internet. Bien au contraire, le RFC recommande de dédier des routeurs à cette tâche ALT.

Comme tous les RFC sur LISP, ce RFC 6836 rappelle que le protocole est expérimental. On ne sait pas encore trop comment LISP, et ALT, réagissent à des problèmes comme :

  • Le délai de résolution pour le premier paquet à destination d'un identificateur inconnu (les protocoles situés au dessus pourraient s'impatienter, ALT est largement piloté par la demande, le résolveur n'a donc aucune garantie d'avoir toutes les informations à l'avance).
  • Pour éviter le problème ci-dessus, LISP permet de transporter des données utilisateur (celle du premier paquet de la session) dans la demande de résolution d'identificateur en localisateur. Est-ce que cela vaut la peine de compliquer ainsi le protocole ?
  • Comment bâtir un graphe ALT ? Actuellement, la construction du graphe des routeurs BGP se fait à la main, via les achats de transit et les accords de peering. Y a-t-il une meilleure méthode ?
  • Et, naturellement, les risques de sécurité. Comment se passera la première attaque DoS contre LISP ?

Bref, il y a besoin de pratiquer pour répondre à ces questions, et c'est la raison des déploiements actuels de LISP.

Donc, après ces principes de base, place à la construction et au fonctionnement de ALT. D'abord, révisons le vocabulaire (section 2). Les termes les plus importants  :

  • ALT (Alternative Logical Topology) : le réseau overlay bâti avec BGP et qui connecte tous les routeurs ALT. Étant un réseau virtuel, créé avec des tunnels, ses performances ne sont pas extraordinaires et il ne sert donc qu'à transmettre les Map Requests, surtout pas à faire circuler le trafic normal.
  • EID (Endpoint IDentifier) : les identificateurs de LISP. Ils sont regroupés en préfixes par les routeurs ALT, pour limiter le nombre d'annonces à transporter (comme l'agrégation dans BGP, cf. RFC 4632).
  • RLOC (Routing LOCator) : les localisateurs de LISP. En pratique, des adresses IP.
  • Map Server : un routeur ALT permettant l'enregistrement de préfixes EID par les ETR (routeurs non-ALT). C'est donc lui l'origine des EID dans ALT. Rappelez-vous que ALT fusionne résolution et routage. Un serveur d'identificateurs est un routeur. Le Map Server recevra des Map Requests, qu'il transmettra à ces ETR.
  • Map Resolver : un routeur ALT qui reçoit des demandes de résolution (Map Requests) d'un ITR et les transmet dans le réseau ALT.
  • ITR (Ingress Tunnel Router) : un routeur LISP qui encapsule les paquets IP pour les transmettre à un ETR où ils seront décapsulés. Pour cela, il a besoin d'émettre des Map Requests vers un résolveur.
  • ETR (Egress Tunnel Router) : un routeur LISP qui décapsule les paquets LISP avant de les transmettre en IP classique. Il est également chargé de faire suivre les requêtes de résolution d'EID en RLOC (Map Requests).

Comment tous ces jolis sigles sont-ils utilisés ? La section 3 décrit le modèle ALT. Il reprend les mécanismes de LISP, Deux types de paquets LISP peuvent entrer dans le réseau virtuel ALT : les Map Requests, demande de résolution d'un EID en RLOC, et les Data Probes, équivalents aux précédentes mais incluant en plus des données à faire suivre (le but est d'éviter à un routeur de garder en mémoire les données en attendant la réponse à la requête de résolution).

Comment est-ce que les informations rentrent dans le système ? La méthode de loin la plus courante (façon de parler puisque LISP est encore très peu déployé, disons la méthode dont on pense qu'elle sera la plus courante) est pour les ETR d'enregistrer les EID dont ils ont la charge auprès d'un Map Server (RFC 6833), qui les propagera alors dans ALT. Mais on verra peut-être aussi des routes statiques depuis les routeurs ALT vers les ETR ou bien des montages plus exotiques.

Et, pour envoyer un paquet à destination d'un EID, lorsqu'on est ITR ? La méthode « la plus courante  » est que l'ITR écrive à son Map Resolver, comme une machine Internet ordinaire écrit à son résolveur DNS pour trouver les adresses IP associées à un nom. Mais on aura peut-être la aussi des routes statiques (« si tu ne sais pas, envoie tous les paquets à tel ETR ») et d'autres configurations.

Donc, LISP n'impose pas un modèle unique mais recommande néanmoins fortement un modèle où les routeurs ALT sont au centre, communiquant entre eux, et où les ITR et ETR sont à l'extérieur de système de résolution, ne faisant pas d'ALT eux-mêmes mais transmettant les requêtes via les Map Resolver (questions des ITR) et les Map Server (réponses des ETR), dont les interfaces sont normalisées dans le RFC 6833. Un des avantages de ce modèle recommandé est qu'il permettra de tester d'autres systèmes que ALT et peut-être de le remplacer plus facilement (rappelez-vous que tout LISP est expérimental et que la partie « résolution d'identificateurs » est la plus expérimentale de toutes, donc très susceptible de changer).

Tout ce mécanisme ne gère pas le cas de la communication avec des sites non-LISP (tout l'Internet actuel) couvert dans le RFC 6832.

On l'a déjà dit, une des plus grosses discussions lors du développement de LISP avait été « le problème du premier paquet ». Lors d'une nouvelle connexion vers un identificateur, par exemple avec TCP, si le localisateur correspondant n'est pas dans les caches des routeurs, l'opération de résolution, a priori relativement lente, va obliger à garder le premier paquet dans les tampons de sortie du routeur, ou bien à jeter ce premier paquet. La première solution consomme de la mémoire et facilite les attaques par déni de service sur le routeur (un méchant pourrait commencer plein de connexions vers des EID injoignables, juste pour épuiser les ressources du routeur). La seconde est la seule réaliste (c'est ce qu'utilisent les routeurs du cœur de l'Internet pour les résolutions ARP, par exemple). Mais elle fait perdre un paquet crucial, celui d'ouverture de connexion. Cela obligera donc l'émetteur à attendre l'expiration d'un délai de garde, puis à réémettre, introduisant ainsi une latence considérable. C'est pourquoi des solutions où l'entiereté de la base des correspondances identificateur->localisateur serait gardée en mémoire de chaque routeur (ou, plus exactement, de chaque résolveur), avaient été proposées. ALT n'a pas suivi cette voie et propose donc autre chose : un type de paquets spécial, le Data Probe permet à la fois de demander une résolution (comme le fait un paquet Map Request) et de transmettre le premier paquet. Cette solution a été très contestée (elle viole le principe « le réseau virtuel ne sert qu'à la résolution ») et l'une des choses qui sera suivie avec le plus d'attention dans le déploiement de ALT est l'utilisation des Data Probes. La principale crainte est que ces Data Probes, potentiellement bien plus gros que les Map Requests soient un bon vecteur de DoS pour le réseau virtuel ALT, qui n'est pas du tout conçu pour un tel trafic (cf. section 3.3). Le RFC recommande donc que les Data Probes ne soient pas activés par défaut et que le réseau limite vigoureusement leur débit.

La section 4 détaille l'architecture de ALT, présentée plus haut. Le RFC présente ALT comme push/pull mais je le décrirai personnellement comme étant plutôt pull, comme le DNS, plutôt que push comme BGP. Pour tenir la charge dans un très grand réseau, une approche pull passe mieux à l'échelle. Dans ALT, la partie pull est la résolution elle-même (Map Request et réponse), la construction du réseau virtuel étant plutôt push.

Les tunnels sont construits avec GRE (RFC 2784) mais ce n'est pas fondamental pour l'architecture d'ALT, qui pourrait utiliser d'autres types de tunnels dans le futur. (GRE est faible, question sécurité, par exemple.) L'avantage de GRE est qu'il est bien connu et bien maîtrisé. Deux routeurs ALT qui veulent communiquer doivent donc créer un tunnel entre eux (ip tunnel add tun0 mode gre remote 10.2.3.4 local 172.16.0.76 ttl 255 sur Linux, interface tunnel 0 \ tunnel source 10.2.3.4 \ tunnel destination 172.16.0.76 sur un Cisco, etc). Puis ils établissent une session BGP au dessus de ce tunnel. Ces sessions devront utiliser des nouveaux numéros de système autonome, pour éviter toute collision avec le graphe BGP actuel, celui des routeurs du cœur de l'Internet (section 6.1). Par contre, le RFC laisse ouverte la question de savoir s'il faut un nouveau SAFI (Sub-Address Family Identifier, RFC 4760, qui sert aujourd'hui à distinguer les préfixes IPv4 de ceux IPv6). Cela serait souhaitable pour éviter qu'un préfixe EID soit injecté accidentellement dans la DFZ ou réciproquement. Mais cela compliquerait le déploiement, surtout avec les anciens routeurs qui ne connaitraient pas ce SAFI.

Comment sont alloués les identificateurs, les EID ? Attribués de manière hiérarchique, comme les adresses IP d'aujourd'hui, ils sont relativement statiques. On ne change pas d'EID quand on change d'opérateur réseau, par exemple. La topologie d'ALT, fondée sur les EID, n'a donc rien à voir avec celle de l'Internet, fondée sur les adresses IP avant LISP, et sur les localisateurs (RLOC) une fois LISP déployé. Et elle est bien plus stable. Des phénomènes ennuyeux du monde BGP comme le route flapping (un routeur qui annonce et retire frénétiquement un préfixe, faisant ainsi travailler tous les routeurs de la DFZ avant d'être amorti) seront donc probablement rares dans ALT (section 7.3).

Une note personnelle de gouvernance au passage : cela veut dire que la hiérarchie dans ALT ne suit pas des relations de business et il n'est donc pas sûr que l'agrégation de plusieurs préfixes EID dans un même Map Server se passe bien, puisque ces préfixes sont alloués à des organisations n'ayant aucun point commun (même pas le même opérateur). C'est clairement une des questions les plus ouvertes d'ALT, à l'heure actuelle (section 7.4). Si un routeur ALT a reçu de l'information sur les EID 10.1.0.0/24, 10.1.64.0/24, 10.1.128.0/24 et 10.1.192.0/24, peut-il et doit-il agréger en un seul 10.1.0.0/16 ?

Les fanas de sécurité liront avec intérêt la section 10, qui lui est entièrement consacré. En gros, ALT a la même sécurité que BGP. Il a donc les mêmes vulnérabilités (un routeur ALT méchant peut annoncer n'importe quel préfixe EID, même s'il ne lui « appartient » pas) et on peut envisager les mêmes solutions (comme la protection des sessions BGP du RFC 5925, et pourquoi pas, demain, BGPsec).

Sinon, si vous êtes plus intéressé par les performances que par la sécurité, vous pouvez consulter un exposé sur l'évaluation des performances d'ALT,

Il existe apparemment trois mises en œuvre différentes de ALT, dont une dans les routeurs Cisco.

Parmi les alternatives à ALT, il y a plusieurs propositions en cours de discussion à l'IETF, avec des jolis noms comme CONS, NERD ou DDT. Une solution évidente aurait été de choisir plutôt le système de correspondance le plus utilisé actuellement dans l'Internet, le DNS. Il existe des problèmes techniques avec le DNS mais la principale raison pour laquelle il n'a même pas été sérieusement considéré est que les gens qui travaillent quotidiennement sur des routeurs, et qui ont l'habitude de BGP et autres protocoles de routage, ne connaissent pas le DNS et ne l'aiment pas (ils l'assimilent souvent à un service de couche 7, loin de leurs problèmes opérationnels et envahis d'avocats). Comme tous les choix techniques, celui du système de correspondance a donc également une forte composante culturelle.


Téléchargez le RFC 6836


L'article seul

RFC 6835: LISP Internet Groper (LIG)

Date de publication du RFC : Janvier 2013
Auteur(s) du RFC : D. Farinacci, D. Meyer (Cisco)
Pour information
Réalisé dans le cadre du groupe de travail IETF lisp
Première rédaction de cet article le 24 janvier 2013


De même que dig est la référence, connue de tous, des outils de débogage du DNS, le nom de lig va peut-être devenir célèbre dans le monde des opérateurs réseaux. lig est également un outil de débogage : il sert à interroger la base de correspondance identificateur->localisateur du protocole de routage LISP (RFC 6830, et sans lien avec le langage de programmation).

En quoi consiste LISP ? C'est une architecture de séparation de l'identificateur et du localisateur sur l'Internet (RFC 6830). Actuellement, l'adresse IP sert à deux choses : elle identifie une machine unique dans l'Internet (identificateur), et elle indique où envoyer les paquets à destination de cette machine (localisateur). LISP sépare ces deux fonctions. Et, comme toute architecture de séparation identificateur/localisateur, LISP nécessite une correspondance (mapping) entre les deux. Si on n'a que l'identificateur (EID - Endpoint ID - dans la terminologie LISP), il faut trouver le localisateur (RLOC - Routing Locator - en termes LISP) pour pouvoir envoyer les paquets. C'est le rôle du système de correspondance. Et lig permet d'interroger cette base de correspondances, pour voir son contenu et déboguer ainsi des problèmes.

Il existe plusieurs systèmes possibles pour cette correspondance, comme les très expérimentaux CONS ou NERD. Mais le plus répandu est le système officiel, ALT (RFC 6836). Comme il existe un protocole standard de communication avec le système de correspondance, « LISP Map-Server » (dont l'interface est normalisés dans le RFC 6833), lig va pouvoir interroger tous les systèmes, ALT et les autres. Voici un exemple simple, où on demande le RLOC de l'EID 153.16.4.1 :

% lig 153.16.4.1   
Send map-request to eqx-ash-mr-ms.rloc.lisp4.net for 153.16.4.1 ...
Received map-reply from 216.129.110.58 with rtt 0.11500 secs

Mapping entry for EID '153.16.4.1':
153.16.4.0/24, via map-reply, record ttl: 1440, auth, not mobile
  Locator                                 State     Priority/Weight
  216.129.110.58                          up        1/100     

Et on trouve que c'est 216.129.110.58, qui va donc recevoir les paquets encapsulés à destination de 153.16.4.1.

Pour suivre le RFC, ou même simplement cet article, il vaut mieux apprendre par cœur le vocabulaire, en section 2. Les termes que je trouve les plus importants :

  • Map-Server: un élement de l'infrastructure réseau qui connait la correspondance entre identificateurs (EID) et localisateurs (RLOC). C'est typiquement une grosse machine qui sera dans le réseau de l'opérateur et utilisera les systèmes cités plus haut (comme ALT) pour publier son bout de la base des correspondances. Chaque Map-Server ne connait qu'une partie de la base, celle-ci étant répartie.
  • Map-Resolver: c'est le composant qui interroge les Map-Servers. Il sera sans doute séparé de l'ITR (voir plus loin), son client. C'est ce Map-Resolver qu'interroge lig.
  • RLOC: le Routing LOCator est l'adresse IP de l'ETR (voir plus loin). Une fois le RLOC connu, grâce au Map-Server, l'ITR peut lui envoyer les paquets LISP. (Le RLOC peut être vu comme le localisateur de la destination. LISP, contrairement à HIP, n'est pas de bout en bout mais est une solution dans l'infrastructure, qui n'implique que les routeurs. Donc, le localisateur est attaché à un routeur, pas à la destination.)
  • EID: le Endpoint Identifier identifie la destination. On l'a typiquement trouvé dans le DNS.
  • EID-to-RLOC cache: les protocoles permettant de gérer la base des correspondances entre EID et RLOC sont typiquement assez complexes, et on ne souhaite pas les faire tourner sur un routeur, qui a d'autres responsabilités. Ils vont donc être exécutés sur le Map-Server, que le routeur va interroger via le Map-Resolver. Mais ce trafic d'interrogation va être intense, potentiellement une requête à chaque paquet que le routeur transmettra. Le routeur doit donc avoir un cache des correspondances les plus récentes. Contrairement à la base que stocke le Map-Server, ce cache est de petite taille, incomplet, et change très vite (les entrées y sont typiquement créées et détruites avec les flux réseau).
  • ITR : l'Ingress Tunnel Router est le routeur d'entrée du tunnel LISP (rappelons que LISP fonctionne en encapsulant les paquets IP dans un tunnel qui va de l'ITR à l'ETR).
  • ETR : l'Egress Tunnel Router est le routeur de sortie du tunnel LISP.
  • xTR ; lorsqu'on souhaite parler ensemble des ITR et des ETR, on utilise souvent le terme de xTR. Par exemple, « Un déploiement possible de LISP est de mettre les xTR dans le routeur directement connecté au client. »

La section 3 donne le principe général de fonctionnement de lig et sa syntaxe. lig se comporte un peu comme un ITR qui a reçu un paquet IP dont la destination est un EID, et qui se demande à quel RLOC envoyer le paquet. lig prend donc en argument un EID, fabrique un paquet LISP de type Map-Request, l'envoie, et attend une réponse Map-Reply. Là, contrairement au routeur, il se contentera d'afficher cette réponse à l'utilisateur. Il indiquera également le RTT de la requête et l'état de l'ETR (LISP surveille en permanence l'état des tunnels, cf. RFC 6830, section 6.3 « Reachability », pour éviter d'envoyer les paquets à un trou noir).

Outre l'EID, lig prend deux paramètres optionnels, l'EID source (au cas où la réponse en dépendrait) et l'adresse d'un Map-Resolver à interroger (dans le premier exemple, le résolveur était indiqué via la variable d'environnement LISP_MAP_RESOLVER).

On peut se servir de lig, comme dans l'exemple plus haut, pour savoir quel est le localisateur d'un EID donné, mais on peut aussi l'utiliser pour se liguer soi-même, en interrogeant les serveurs pour vérifier que le site où on est a bien enregistré son préfixe EID.

La section 4 présente les deux implémentations de lig actuelles. Celle présente dans les routeurs Cisco (dans des versions expérimentales du code, seulement) est en section 4.1. La syntaxe générale (où les crochets indiquent une mention facultative) et où les termes entre chevrons sont des variables) est lig <destination-EID> [source <source-EID>] [to <Map-Resolver>]. Un exemple d'utilisation, tiré du RFC, est :

router# lig abc.example.com
     Send map-request to 10.0.0.1 for 192.168.1.1 ...
     Received map-reply from 10.0.0.2 with rtt 0.081468 secs

     Map-cache entry for abc.example.com EID 192.168.1.1:
     192.168.1.0/24, uptime: 13:59:59, expires: 23:59:58,
                     via map-reply, auth
       Locator          Uptime    State  Priority/Weight  Packets In/Out
       10.0.0.2         13:59:59  up     1/100            0/14

Et si on veut tester son propre EID (se liguer soi-même), sans avoir à le taper, on peut remplacer le <destination-EID> par self (ou self6 pour IPv6). Par exemple :

router# lig self
     Send loopback map-request to 10.0.0.1 for 192.168.2.0 ...
     Received map-reply from 10.0.0.3 with rtt 0.001592 secs

     Map-cache entry for EID 192.168.2.0:
     192.168.2.0/24, uptime: 00:00:02, expires: 23:59:57
                     via map-reply, self
       Locator       Uptime    State  Priority/Weight  Packets In/Out
       10.0.0.3      00:00:02  up     1/100            0/0

En section 4.2 figure la version en logiciel libre de lig, qui tourne notamment sur machines Unix et est disponible en https://github.com/davidmeyer/lig. Sa syntaxe est un peu différente, lig [-m <Map-Resolver>] <destination-EID>. Elle ne permet pas de sélectionner l'adresse source. Voici un exemple sur une machine Debian :

% lig -m l3-london-mr-ms.rloc.lisp4.net  153.16.10.254                  
Send map-request to l3-london-mr-ms.rloc.lisp4.net for 153.16.10.254 ...
Received map-reply from 173.36.254.163 with rtt 0.23900 secs

Mapping entry for EID '153.16.10.254':
153.16.10.0/24, via map-reply, record ttl: 1440, auth, not mobile
  Locator                                 State     Priority/Weight
  173.36.254.163                          up        1/100     

On y voit que les paquets à destination de l'EID 153.16.10.254 doivent être encapsulés dans LISP par l'ITR et transmis à l'ETR en 173.36.254.163. Si vous essayez avec une adresse qui n'est pas un EID, vous recevez une réponse négative (Negative cache entry) :

% lig -m l3-london-mr-ms.rloc.lisp4.net  10.1.2.3       
Send map-request to l3-london-mr-ms.rloc.lisp4.net for 10.1.2.3 ...
Received map-reply from 195.50.116.18 with rtt 0.01200 secs

Mapping entry for EID '10.1.2.3':
10.1.0.0/16, via map-reply, record ttl: 15, not auth, not mobile
  Negative cache entry, action: forward-native

Et si vous ne recevez rien :

% lig -m l3-london-mr-ms.rloc.lisp4.net  153.16.10.254     
Send map-request to l3-london-mr-ms.rloc.lisp4.net for 153.16.10.254 ...
Send map-request to l3-london-mr-ms.rloc.lisp4.net for 153.16.10.254 ...
Send map-request to l3-london-mr-ms.rloc.lisp4.net for 153.16.10.254 ...
*** No map-reply received ***

Alors le plus probable est que vous êtes derrière un pare-feu fasciste qui bloque les réponses. Pensez à autoriser le port UDP 4342, par exemple sur Linux :

# iptables --insert INPUT --protocol UDP --sport 4342 -j ACCEPT

(ou peut-être, sur un pare-feu avec état, l'état RELATED mais je n'ai pas testé.) tcpdump ne connait pas encore LISP donc vous ne verrez que deux paquets non analysés (notez que la réponse est venue d'une autre adresse IP que celle interrogée...) :

14:56:11.873961 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto UDP (17), length 88)
    217.70.190.232.50793 > 206.223.132.89.4342: UDP, length 60
14:56:12.051870 IP (tos 0xc0, ttl 110, id 31203, offset 0, flags [none], proto UDP (17), length 80)
    173.36.254.162.4342 > 217.70.190.232.57375: UDP, length 52

On peut aussi utiliser un looking glass (cf. section 5) comme http://lispmon.net/lig.cgi, pour interroger sur un EID particulier. Si on veut une vision générale de l'état de LISP, on peut regarder http://www.lisp4.net/status (état des résolveurs) et http://www.lisp4.net/lisp-site (liste de sites LISP et de résolveurs).


Téléchargez le RFC 6835


L'article seul

Ma politique concernant les données de mes lecteurs

Première rédaction de cet article le 23 janvier 2013


Cela fait chic d'avoir une « privacy policy », vous savez, un de ces longs textes en jargon pseudo-légal, que personne ne lit et qui disent, pour la plupart, quelque chose du genre « BigCompany tient beaucoup à votre vie privée et la considère comme très importante. Nous ferons ce que nous voudrons avec vos données, pendant une durée illimitée, et nous vendrons vos données à qui paie. » Donc, il m'en fallait une pour ce blog.

D'abord, tous les accès faits à ce blog sont journalisés, dans le classique format commun. Chaque accès ressemble à :

[2001:db8:0:1:79c9:574:b16a:437d]:60529 - - [23/Jan/2013:19:57:20 +0000] "GET / HTTP/1.1" 200 93561 "-" "... (Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_1) AppleWebKit/534.48.3 (KHTML, like Gecko) Version/5.1 Safari/534.48.3)" www.bortzmeyer.org

Vous noterez que cela me donne l'adresse IP (que l'on peut considérer, dans certains cas, comme une donnée personnelle), le type de navigateur (ce qui donne déjà beaucoup d'informations) et, c'est plus original, le port source (ici, 60529), en application du RFC 6302. Si vous voulez voir tout ce que votre navigateur m'envoie sans sollicitation, regardez https://www.bortzmeyer.org/apps/http (ou sa documentation).

Ces données sont ensuite conservées pendant quelques mois. Je les lis parfois et je m'amuse à repérer les questions posées aux moteurs de recherche. Je ne transmets ces données à personne, sauf s'il demande avec une arme à feu, ou si c'est un copain et, dans ce cas, uniquement pour le faire rigoler.

Certaines parties de ce site Web sont dynamiques : une application écoute mais elles n'envoient pas de cookies du RFC 6265 (et donc n'en reçoivent jamais), et ne gèrent pas de base d'utilisateurs (donc, pas de risque que celle-ci soit compromise). Donc, les seules données un peu personnelles sont les adresses IP des clients dans le journal.


L'article seul

DNS Looking Glass: motivations and explanations

First publication of this article on 20 January 2013
Last update on of 1 March 2013


There was a time where getting information about the content stored in the DNS was easy: just fire dig from any machine in the Internet and ask your question. It has never been a perfect solution (because of caching and because of different network connectivity) but it worked most of the time: the DNS was supposed to give the same data to anyone. Now, several recent changes make this solution too limited. We need DNS Looking Glasses.

What are these changes?

  • Answers can be different depending on the source IP address of the query, for instance to direct users to a closer server.
  • Cache poisoning may have the effect that the users of some resolvers/caches will see a different set of data.
  • DNSSEC can have an effect. Today, some resolvers validate and some do not. If a DNS zone administrator makes a mistake, validating resolvers will experience a problem but not the users of non-validating resolvers.
  • Lying resolvers can rewrite answers for their users.
  • Legal requirments on DNS censorship (both in dictatorships and in democracies) may make some data unavailable (or modified) from some places.

It means we need DNS Looking Glasses, points of observation to look at the DNS data from a different viewpoint. Such looking glasses are already very common to observe BGP but not for the DNS. People typically use open resolvers, DNS resolvers open for everyone, for that purpose (for instance, scientific papers analyzing the DNS are often based on surveys with open resolvers). But they create various security problems and that's why the RFC 5358 recommends their closing.

Therefore, I present here three things:

  • A proposal for the format of requests and responses of these DNS looking glasses.
  • A free program implementing this format.
  • An actual service with this software that you can query.

The service is available using the REST paradigm, at https://dns.bortzmeyer.org/$DOMAIN[/$TYPE] where DOMAIN is the domain name and TYPE a DNS record type (such as AAAA or MX). For instance, https://dns.bortzmeyer.org/example.com/AAAA will get you the AAAA record for the name example.com. There is no Web form, you have to construct the URL and send it with a HTTP client (which can be a Web browser or a program like curl; you do not need a DNS client like dig or drill). Of course, people are welcome to write such a form. The complete documentation of this service is available online (for instance, you can change the output format, it does not have to be HTML).

Since the DNS looking glass uses a structured output format, it is quit easy to develop a program which will query the existing looking glasses instances and ask them a question. Such programs are available in the subdirectory usages/ of the distribution. For instance, the program get-ip asks for the IP addresses of its argument:

% ./get-ip www.ietf.org
http://dns-lg.tetaneutral.net/: [64.170.98.30 2001:1890:126c::1:1e]
http://dns.bortzmeyer.org/: [64.170.98.30 2001:1890:126c::1:1e]
http://dns-lg.dk-hostmaster.dk/: [64.170.98.30 2001:1890:126c::1:1e]
http://dnslg.generic-nic.net/: [64.170.98.30 2001:1890:126c::1:1e]
http://dns-lg.vs.uni-due.de/: [64.170.98.30 2001:1890:126c::1:1e]

Here, you see the same results from all the instances?. If you don't, it does not always mean there is someone with nefarious aims in the middle. Some services do send different DNS replies, depending where you ask, in order for instance to balance the load geographically:

% ./get-ip pool.ntp.org
http://dns-lg.tetaneutral.net/: [193.52.136.2 213.251.172.92 88.190.219.242 91.121.92.90]
http://dns-lg.dk-hostmaster.dk/: [217.198.219.102 80.196.238.30 94.126.0.23 80.71.132.103]
http://dns.bortzmeyer.org/: [199.7.177.206 204.235.61.9 64.16.214.60 72.8.140.240]
http://dns-lg.vs.uni-due.de/: [176.9.47.150 188.174.232.178 89.238.66.126 89.238.75.57]
http://dnslg.generic-nic.net/: [193.52.136.2 213.251.172.92 88.190.219.242 188.165.211.5]

The program is freely available (under a free software license) at the FramaGit hosting service. You can install it on your own machines (it requires Python and a few non-standard packages, as well as a WSGI-able server such as Apache or Nginx). This way, we will have many looking glasses around the planet (remember they will not all see the same thing, which is the reason we need several).

By the way, FramaGit (a GitLab) provides an issue tracker and the recommended way to report bugs, send patches or give advices is to use this tracker. (It requires a FramaGit account but it is easier for me to rely on an existing, and nice, tool.) Do not forget to read the existing issues to be sure yours is not a duplicate.

The proposal for the request and response format is in the sources of the above program (specially the "Format-specific things" section of the README). It may be implemented by other programs, free or not. Do note that, at this time (june 2012), it is not yet stable and certainly not "standard" in any way. The output XML format follows partially the format of Internet-Drafts draft-mohan-dns-query-xml for the outer elements (plus some extensions) and of draft-daley-dns-schema for the resource data. (Other output formats are available, see the documentation.)

Here are some existing DNS looking glasses: most are Web-only, with no API to automatize them or to provide an alternative interface, and no structured output:


L'article seul

DNS Looking Glass: usage of the online service

First publication of this article on 20 January 2013
Last update on of 2 February 2013


This text describes how to use the DNS Looking Glass service hosted at https://dns.bortzmeyer.org/, http://dnslg.generic-nic.net/ or http://dns-lg.nlnetlabs.nl/ (and other future services using the same software, although they may have different installation settings).

You use this program through REST requests (if you do not know REST, do not worry; basically, it means we use ordinary HTTP requests, with structured output formats). The URL for the requests will be https://dns.bortzmeyer.org/$DOMAIN[/$TYPE][/$CLASS] where DOMAIN is the domain name and TYPE a DNS record type (such as AAAA or MX).

More formally, following the language of URI Templates (RFC 6570), the URLs of this service are https://dns.bortzmeyer.org/{+domain}/{querytype}/{queryclass}{?format,server,buffersize,dodnssec,tcp,reverse}. (Or replace https://dns.bortzmeyer.org by another prefix such as http://dnslg.generic-nic.net or http://dns-lg.nlnetlabs.nl/.)

There is a non-standard pseudo-querytype ADDR to request both A and AAAA records, specially for the links in the HTML output. And you can use ANY to request any type the server may know about.

Some typical examples:

Records containing Unicode are not a problem, as shown with https://dns.bortzmeyer.org/mailclub.tel/TXT.

You can use this program from an ordinary Web browser, which will request the proper format. The program uses HTTP content negotiation to get the better output format. But, if you prefer, you can add manually the option format=FORMAT where FORMAT is XML, HTML, TEXT, ZONE or JSON. So, for instance, to get the IPv6 address of www.example.com in XML, it will be https://dns.bortzmeyer.org/www.example.com/AAAA?format=XML. If you use a command-line client like curl, you can add a HTTP header to indicate the format you want (here, JSON):

% curl -s -H 'Accept: application/json' https://dns.bortzmeyer.org/xxx/SOA

The HTML option's format is not documented yet. It is mostly for human consumption, not for parsing by a program.

The XML output format follows partially Internet-Drafts draft-mohan-dns-query-xml for the outer elements (plus some extensions) and of draft-daley-dns-schema for the resource data. (Note that the query format does not follow the first draft's syntax.)

The JSON option's format is documented in the file JSON.txt in the program's distribution.

The Text option's format is not documented. It is intended for human reading. If you need a structured format (to parse it from a program), use XML or JSON. If you prefer text-based formats, for instance for processing with common Unix command-line tools (awk, grep, etc), the best solution is probably the Zone format.

The Zone option's format follows section 5 of RFC 1035, with tabs as separators.

You can add an option to select the name server to query (the default one is chosen by the server, it is the default resolver(s) of the machine): server=IP-ADDRESS (IP address only, names are not supported).

This option is necessary when you want to query the name and version of a name server. Funny examples are https://dns.bortzmeyer.org/version.bind/TXT/CH?server=176.31.113.162 or https://dns.bortzmeyer.org/version.bind/TXT/CH?server=78.193.86.178.

To activate DNSSEC in the responses (to send the DO bit), use option dodnssec=1 in the URL. This option will allow you to see the AD (Authentic Data) flag.

To use TCP (instead of UDP) for the request, use option tcp=1 in the URL.

By default, the server queries the name servers with EDNS0 and a buffer size of 4096 bytes. To change that, use the option buffersize with the value you want. Setting it to 0 will disable EDNS.

For finding a domain name from an IP address, you can do requests with the .arpa domain name, for instance https://dns.bortzmeyer.org/241.5.5.192.in-addr.arpa/PTR but you can also use the option reverse to ask for the address to be turned into an arpa domain name, for instance https://dns.bortzmeyer.org/192.5.5.241?reverse=1.

To avoid abuse, there is a rate-limiter so, if you receive HTTP status code 429 (see RFC 6585), it means you have been too aggressive. Slow down your requests.

You can also use the DNS looking glass from a program: see the subdirectory usages/ of the distribution for samples.

Note that the service does not use HTTPS today so you cannot really use it to detect censorship if the environment is really hostile (for instance if Aladeen mangles the DNS answers and also the unprotected HTTP traffic).


L'article seul

Journée d'étude FULBI sur le Web de données

Première rédaction de cet article le 18 janvier 2013


La FULBI est une association de bibliothécaires et autres professionnels de l'information et de la documentation. Elle organise tous les ans une journée d'études sur un thème donné et le thème de la réunion du 17 janvier 2013 était le Web des données.

Il y avait plusieurs exposés très intéressants. Emmanuelle Bermès (Centre Pompidou) a joué le rôle de la formatrice : expliquer le Web des données pour ceux et celles qui ne seraient pas déjà dedans. Son accroche était que l'usager est comme un petit enfant, très impatient, et qu'il faut lui donner l'information très vite, et lui apporter là où il est (allusion probable au fait que certains professionnels de l'infodoc avaient snobé le Web pendant longtemps, préférant leurs catalogues rigides et leurs systèmes informatiques non-interopérables. « Le Web est un modèle d'interopérablité. On ne s'en rend plus compte parce qu'on est habitué, mais c'est rare en informatique »).

Ensuite, pour accéder à cette information, il faut qu'elle ait pu être digérée par les machines. « Vous regardez une page Wikipédia, instinctivement, vous la structurez, vous repérez le menu, le titre, etc, le tout en analysant la mise en page, ce que la machine ne peut pas faire ». D'autre part, face à un formulaire de recherche, le moteur de recherche est face à un mur, il ne sait même pas quelle question poser. Il faut donc donner accès au catalogue. Le Web de données vise à répondre à ces deux questions, structuration de l'information et accès au catalogue, permettant d'énumérer toutes les données (problème dit du Web profond).

Au passage, l'oratrice avait promis d'expliquer la différence entre Web de données et Web sémantique mais j'ai raté cette explication. Elle note à juste titre que le Web sémantique n'a rien de sémantique : pas d'IA, pas de traitement automatique des langues.

Emmanuelle Bermès a longuement parlé des URI (une de ses spécialités, pour laquelle elle avait fait un excellent exposé à JRES), puis de RDF (mais ne vous inquiétez pas RDFS/OWL et SPARQL étaient aussi cités). Les URI sont vitaux en RDF car chaque entité (personne, lieu, concept, etc) est identifiée par un URI (qui doit être pérenne : contrairement aux vendeurs de vent comme ceux des DOI, elle affirme que les URI peuvent être pérennes). « Le bonheur, l'amour (et le malheur aussi) ont des URI ».

Autres technologies mentionnées et qui semblaient intéressantes : Open Graph Protocol et le site de dépôt de schémas schema.org.

(Deux avis personnels : pour le problème du Web profond, le plus simple est de traduire automatiquement toute la base de données en HTML avec liens, et on n'a plus qu'à laisser faire le moteur de recherche. Et, pour RDF, c'est au Web ce qu'est IPv6 au réseau : des années qu'il existe et qu'il va vraiment décoller « l'année prochaine ». J'ai posé la question des microformats à l'oratrice, mais elle ne les voit pas vraiment comme une alternative à RDF, car ils permettent moins de choses.)

Lionel Maurel, lui, a parlé (sans diapos) de la question du droit des données publiques. Je vais essayer de résumer mais attention, je ne suis pas juriste donc les erreurs dans ce résumé sont les miennes, pas celles de Lionel Maurel.

L'Open Data n'a pas de cadre juridique particulier pour l'instant. Le cadre juridique de l'accès aux informations publiques est la loi du 17 juillet 1978 (celle qui créait la CADA). Les bases non publiques dépendent du droit des bases de données (qui ressemble au droit d'auteur). La loi de 1978 pose le principe de la réutilisabilité, par défaut. L'administation n'a pas le droit de refuser la réutilisation des données (y compris à des fins commerciales). Ce principe est très fort mais, en pratique, est limité par des tas de choses :

  • documents secrets (exemple Défense Nationale),
  • données produites par les EPIC comme l'INA ou l'IGN (justement ceux qui ont des données...),
  • données personnelles,
  • l'État peut faire payer, au tarif qu'il décide (pas de régulateur pour le prix),
  • défense d'altérer les données (je trouve ce point très contestable, car il revient à donner un droit de veto contre toute modification),
  • le droit d'auteur garde toujours le dessus (une bibliothèque publique ne peut pas distribuer en Open Data les livres récents qu'elle vient de numériser).

D'autres restrictions à ce principe de publication sont plus consensuelles :

  • citer la source,
  • pas d'obligation de publier activement. Si les données sont sur du papier dans le sous-sol, l'État n'est pas obligé de les numériser.

Lionel Maurel a résumé cela en disant que le droit permettait à un établissement public de faire presque tout ce qu'il voulait. Ceux qui sont dynamiques et ouverts peuvent publier. Les rétrogrades fermés ne sont pas obligés de publier.

Et les licences ? Celles du logiciel libre ou les CC n'étaient pas parfaitement adaptées. La ville de Paris a utilisé ODBL (licence copyleft), plus adaptée aux bases de données mais qui ne mentionne pas la loi de 1978. La licence IP du Ministère de la Justice français est, elle, explicitement adaptée à la loi de 1978. Idem pour la Licence Ouverte, d'Etalab. Et, pendant ce temps, Creative Commons a créé CC0 (équivalent au domaine public).

À noter que l'État (mais pas les collectivités locales) est, lui, obligé de publier depuis une circulaire Fillon, et via Etalab. Parmi les exceptions à cette obligation (le droit, c'est comme le français, c'est plein d'exceptions) :

  • Le cas où les données sont vendues (Légifrance),
  • Les données « culturelles », ce qui permet au Louvre de ne pas diffuser les siennes.
  • Le cas de la recherche publique n'est pas clair...

Enfin, une dernière faiblesse du dispositif légal français, il n'y a pas d'obligation d'un format ouvert ou même interopérable. C'est ainsi que la grand majorité des données sur http://data.gouv.fr/ sont dans un format purement Microsoft.

Au niveau européen, la directive PSI est en cours de révision (et pourrait être publiée dans les mois qui viennent). Elle prévoit l'obligation de formats ouverts, et une limite au prix qu'on peut faire payer (le coût marginal).

Lionel Maurel a terminé par un hommage à Aaron Swartz, militant des données ouvertes.

Troisième exposé que j'ai beaucoup apprécié, celui de Stéphane Pouyllau (CNRS) sur son expérience d'informaticien au service des chercheurs en SHS pour les aider à publier leurs données (pas les articles, les données qui sont à la base de ces articles). À l'heure actuelle, en SHS, les données sont typiquement en vrac sur portable du chercheur, ou, dans le meilleur des cas, classées selon ses principes à lui et donc peu réutilisables (l'orateur a dit cela plus diplomatiquement). Chaque laboratoire ou MSH a développé un outil de documentation, utilisé uniquement en interne. Il y a donc bien trop d'outils. D'une manière plus générale, il y a peu d'interaction entre les chercheurs (qui aiment bien développer un outil NIH) et les professionnels de la documentation. (« On n'a pas pensé à leur demander » a dit un chercheur interrogé, après que l'orateur lui ait demandé pourquoi diable il avait utilisé Drupal pour bâtir un catalogue bibliographique, au lieu d'outils plus adaptés.)

L'orateur a plaidé pour une structuration (il disait plutôt « normalisation ») des données à la base. Vaste chantier.

Enfin, j'ai aimé l'exposé de Romain Wenz sur http://data.bnf.fr, le service de distribution de données structurées de la BNF, avec une jolie démonstration en utilisant le pirate/écrivain/cartographe Exquemelin (sans doute le seul pirate dans le catalogue BNF...) Les données incluent notamment des liens entre auteurs, œuvres... data.bnf.fr, c'est « Facebook pour les morts ». (Voici la fiche d'Exquemelin.)

L'orateur a insisté sur l'importance de connaître son public, qui fait ainsi souvent un usage déroutant des données mises à sa disposition. C'est ainsi que 25 % des lecteurs du Roman de la Rose sur Gallica déclaraient qu'ils cherchaient des idées de déguisement (le livre est riche en illustrations de costumes).

Par contre (attention, à partir d'ici, je suis négatif), l'exposé de Caroline Goulard (Dataveyes) était nettement moins intéressant : mauvaise oratrice (cafouillage à la mise en route de la vidéo de pub, vidéo elle-même sans intérêt, récriminations contre le navigateur qui lui semblait trop lent, etc), vocabulaire approximatif (open data pour parler de toute entreprise qui donne accès à ses données, même avec une licence ultra-restrictive), et très peu de visualisation de données, ce qui était pourtant le titre (prometteur) de son exposé. Par contre, j'y ai découverte les jolies visualisations du New York Times comme celle sur le budget états-unien.


L'article seul

RFC 6811: BGP Prefix Origin Validation

Date de publication du RFC : Janvier 2013
Auteur(s) du RFC : P. Mohapatra (Cisco Systems), J. Scudder (Juniper Networks), D. Ward (Cisco Systems), R. Bush (Internet Initiative Japan), R. Austein (Dragon Research Labs)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF sidr
Première rédaction de cet article le 18 janvier 2013


Il manquait un élément dans les normes de la sécurisation du routage avec RPKI+ROA, une description de la façon exacte dont on valide une annonce BGP lorsqu'on a des ROA (Route Origin Authorizations) pour ce préfixe. Ce RFC comble ce manque. Jusqu'à présent, en suivant les RFC, on pouvait distribuer des certificats authentifiant le titulaire d'un préfixe IP (la RPKI) et on pouvait émettre des autorisations, pour un AS, d'annoncer un préfixe (les ROA). Désormais, on peut utiliser RPKI et ROA pour avoir une solution de sécurité complète.

Cette solution traite le cas des détournements BGP dont le plus célèbre est celui de YouTube par Pakistan Telecom. Elle permet de s'assurer de la validité de l'origine d'une annonce de route. Dans un routeur BGP, les annonces reçues des autres routeur, dans un message BGP UPDATE, ressemblent à 192.0.2.0/24 : 64497 64499 65550, ce qui indique que ce préfixe 192.0.2.0/24 a pour origine l'AS 65550 (on lit de droite à gauche) qui l'a ensuite transmis à l'AS 64499, qui l'a ensuite envoyé à 64497. Cette liste d'AS est transmise d'un routeur BGP à l'autre dans les attributs AS_PATH et AS4_PATH. La technique décrite dans ce RFC permet d'authentifier l'origine (et elle seule), ce qui traite le cas de la plupart des accidents (comme la bavure de Pakistan Telecom) mais pas forcément celui des attaques délibérées.

Depuis plus d'un an, une RPKI réelle est en cours de déploiement. Elle contient des certificats permettant de prouver la titularité d'adresses IP et de numéros d'AS (RFC 3779). Ces certificats servent ensuite à la signature des ROA. Dans le modèle actuellement privilégié, RPKI et ROA sont distribués à des machines validantes chez les opérateurs et les routeurs BGP récupèrent une liste des ROA validés auprès de ces machines, avec le protocole RTR du RFC 6810 (cette séparation permet de réduire le travail, notamment cryptographique, des routeurs). Notre RFC appelle cette liste la liste des VRP (Validated ROA Payload).

Armé de ces VRP, un routeur peut, pour chaque annonce BGP, la classer en :

  • Pas trouvée : aucun VRP ne couvre cette route (fin 2012, c'est le cas de la très grande majorité des routes, puisque le déploiement de la RPKI est encore récent),
  • Valide : au moins un VRP couvre cette route, et indique l'AS effectivement reçu,
  • Invalide : au moins un VRP couvre cette route mais l'AS ne correspond à aucun d'entre eux (oui, il peut y avoir plusieurs ROA pour un préfixe).

À noter que certains VRP ne peuvent jamais correspondre à une annonce légale, par exemple, si l'AS d'origine est zéro (RFC 7607). Cette propriété est utilisée pour indiquer que certains préfixes ne doivent jamais être annoncés (RFC 6491).

Tirés d'une documentation du RIPE-NCC, voici un exemple avec un routeur Cisco, montrant ces trois états :


isco-rpki-rtr>sh ip bgp 93.175.146.0/24
BGP routing table entry for 93.175.146.0/24, version 8995350
Paths: (1 available, best #1, table default)
...
  64510 3333 12654, (received & used)
...
      path 51012284 RPKI State valid

cisco-rpki-rtr>sh ip bgp 93.175.147.0/24
BGP routing table entry for 93.175.147.0/24, version 8995351
Paths: (1 available, no best path)
...
  64510 3333 12654, (received & used)
...
      path 510122C8 RPKI State invalid

cisco-rpki-rtr>sh ip bgp 84.205.83.0/24
BGP routing table entry for 84.205.83.0/24, version 5427340
Paths: (1 available, best #1, table default)
...
  64510 3333 12654, (received & used)
...
      path 2609454C RPKI State not found

Le RFC parle de « couvrir » un préfixe, pas d'être égal à un préfixe car le calcul est fait en tenant compte du caractère hiérarchique des adresses. Ainsi, un ROA pour 192.0.2.0/24 couvre une annonce pour 192.0.2.128/26. L'algorithme en pseudo-code figure en section 2.1.

Et une fois qu'on a déterminé l'état Non trouvé ou Valide ou Invalide, qu'en fait-on ? Un point important de notre RFC (section 3) est que la décision est locale. Chaque routeur décide de ce qu'il fait du résultat de la validation (c'est analogue à la façon dont fonctionnent d'autres techniques de sécurité comme DNSSEC ou X.509 : la norme précise la technique, pas la décision). Le routeur peut se contenter d'envoyer une trap SNMP pour les routes invalides, il peut changer la préférence locale selon le résultat de la validation, ou bien il peut carrément rejeter les routes invalides (section 5).

Naturellement, avant de configurer son routeur pour prendre des décisions radicales, l'administrateur réseaux s'assurera que la validation se passe bien, que la machine validante se met bien à jour, n'a pas de faux positifs, est bien sécurisée, etc (section 8).

Insistons : cette technique ne valide que l'origine de l'annonce, pas le chemin d'AS complet (en anglais, c'est une Origin validation, pas une Path validation). Un attaquant malin qui veut fabriquer des fausses annonces BGP va donc s'assurer de mettre l'origine correcte, avant d'injecter l'annonce. Le RFC note donc que cette technique est plutôt une sauvegarde contre les « attaques du singe du milieu » (le singe étant supposé moins intelligent que l'homme du milieu) plutôt qu'une technique de sécurité au sens classique. D'autres techniques sont en cours de développement pour assurer la validation du chemin, mais c'est un problème bien plus complexe.

Fin 2012, les routeurs de Cisco et de Juniper (et sans doute d'autres) mettent déjà en œuvre ce RFC et permettent de configurer le sort des routes en fonction de leur validité.

On notera que Cisco prétend avoir un brevet sur cette technique : IPR #1569, où Cisco ne s'engage pas à permettre des licences gratuites.


Téléchargez le RFC 6811


L'article seul

RFC 6810: The RPKI/Router Protocol

Date de publication du RFC : Janvier 2013
Auteur(s) du RFC : R. Bush (Internet Initiative Japan), R. Austein (Dragon Research Labs)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF sidr
Première rédaction de cet article le 18 janvier 2013


Le protocole décrit dans ce RFC fait partie de la grande famille des RFC sur la RPKI, un ensemble de mécanismes permettant de sécuriser le routage sur l'Internet. Il traite un problème bien particulier : comme la validation des annonces de route, potentiellement complexe en cryptographie, se fait typiquement sur une machine spécialisée, le cache validateur, comment communiquer le résultat de ces validations au routeur, qui va devoir accepter ou rejeter des routes ? C'est le rôle d'un nouveau protocole, RTR (RPKI/Router Protocol), un protocole très simple. (Ce RFC décrit la version 0 du protocole, une version plus récente, la 1, est normalisée dans le RFC 8210.)

L'opérateur Internet a donc deux acteurs qui font du RTR entre eux, le cache validateur qui récupère les ROA (Route Origin Authorization, cf. RFC 6482) par rsync, les valide cryptographiquement et garde en mémoire le résultat de cette validation (pour des exemples d'utilisation de deux programmes mettant en œuvre cette fonction, voir mon article sur les logiciels de la RPKI), et le routeur (Cisco, Juniper, Unix avec Quagga, etc). Ce dernier joue un rôle critique et on ne souhaite pas trop charger la barque en lui imposant les opérations assez lourdes du validateur. Dans la plupart des déploiements de la RPKI, le routeur ne fait donc que récupérer des résultats simples (« ce préfixe IP peut être annoncé par cet AS »). Le jeu de données que connait le cache validateur a un numéro de série, qui est incrémenté dès qu'il y a une modification (RFC 1982). Le cache peut donc facilement savoir si un de ses clients routeur est à jour en comparant son numéro de série avec celui du routeur. Le numéro de série est spécifique à un cache donné, il n'a pas de signification globale. Le routeur ne validant pas, le cache qu'il utilise doit donc être une machine de confiance.

Un autre acteur, externe à l'opérateur, est la RPKI, l'ensemble des informations de routage publiées (RFC 6481), et qui sont transportées en général en rsync et validées par les signatures cryptographiques qu'elles portent.

Le routeur va ouvrir une connexion avec un ou plusieurs caches et transmettre le numéro de série de ses données. Le cache va lui envoyer les données plus récentes que ce numéro (ou bien rien, si le routeur est à jour). Le cache dispose aussi d'un mécanisme de notification pour dire à tous les routeurs connectés « j'ai du nouveau ». La section 8 décrit plus en détail le processus avec plusieurs caches.

La section 5 décrit le format des paquets : chacun, outre le classique champ version, a un type, indiqué par un entier de 8 bits (requête, réponse, etc), le numéro de série de l'envoyeur et un identifiant de session, qui identifie le serveur du cache (pour détecter une remise à zéro d'un cache, par exemple), la longueur du préfixe annoncé et bien sûr le préfixe lui-même.

Les types de paquets les plus utiles (la liste complète est dans un registre IANA) :

  • Serial Notify (type 0) qui sert au cache à envoyer une notification non sollicitée par les routeurs « J'ai du nouveau ».
  • Serial Query (type 1) où le routeur demande au cache validateur quelles informations il possède, depuis le numéro de série indiqué par le routeur.
  • Cache Response (type 3), la réponse à la requête précédente, composée de :
  • IPv4 prefix (type 4) et IPv6 prefix (type 6) qui indiquent un préfixe IP avec les numéros de systèmes autonomes autorisés à l'annoncer.
  • End of Data (type 7) : comme son nom l'indique.
  • Error (type 10), envoyé lorsque le précédent message avait déclenché un problème.

Le dialogue typique entre un routeur et un cache validateur est décrit en section 6 (le RFC détaille aussi le dialogue de démarrage, ici, je ne montre que celui de fonctionnement régulier) :

  • Le routeur demande des données avec un Serial Query,
  • Le validateur envoie successivement un Cache Response, plusieurs IPvX Prefix, puis un End of Data.

Les codes d'erreur possibles sont décrits dans la section 10 et font désormais l'objet d'un registre IANA. On y trouve par exemple 0 (données corrompues), 1 (erreur interne dans le client ou le serveur), 2 (pas de nouvelles données ; ce n'est pas à proprement parler une erreur).

La question du transport des données entre le cache et le routeur est celle qui a fait l'objet du plus grand nombre de débats à l'IETF. Elle est traitée dans la section 7. Le principal problème est le suivant : comme le but de l'opération RPKI+ROA est d'augmenter la sécurité du routage, il faut que chaque maillon de la chaîne soit sécurisé. Il ne servirait pas à grand'chose de déployer une telle usine à gaz de validation si la liaison entre le routeur et le cache permettait à un intermédiaire de changer les données en cours de route. Il était donc tentant de normaliser une technique de sécurité particulière pour le transport, comme par exemple TLS. Malheureusement, il n'existe pas à l'heure actuelle de technique accessible sur tous les routeurs. L'IETF ayant toujours soin de normaliser des protocoles réalistes, qui puissent être mis en œuvre et déployés, le choix a été fait de ne pas imposer une technique de sécurisation particulière. L'interopérabilité en souffre (un cache et un routeur peuvent ne pas avoir de protocole de sécurité en commun) mais c'était la seule option réaliste. (J'ajoute que, si le but de la séparation du routeur et du validateur était de dispenser ce dernier des calculs cryptographiques, il ne serait pas logique de lui imposer ensuite une session protégée cryptographiquement avec le validateur.)

Le RFC se contente donc de donner une préférence à AO (TCP Authentication Option, cf. RFC 5925) en signalant qu'elle sera la technique préférée, dès lors qu'elle sera disponible sur tous les routeurs (ce qui est très loin d'être le cas en 2012). Les algorithmes du RFC 5926 doivent être acceptés.

En attendant AO, et pour s'assurer qu'il y aura au moins un protocole commun, le RFC spécifie que routeurs et caches doivent pouvoir se parler en utilisant du TCP nu, sans sécurité, vers le port 323. Dans ce cas, le RFC spécifie que routeur et cache validateur doivent être sur le même réseau (idéalement, sur le même segment, cf. section 11) et que des mécanismes, par exemple de contrôle d'accès physiques, empêchent les méchants de jouer avec ce réseau.

Au cas où AO ne soit pas disponible (la quasi-totalité des routeurs aujourd'hui) et où le transport non sécurisé soit jugé nettement trop faible, le RFC présente plusieurs transports sécurisés possibles. Par exemple, SSH, avec une sécurisation des clés obtenue par un moyen externe (entrée manuelle des clés, par exemple). Le sous-système SSH à utiliser est nommé rpki-rtr. Notez que, si SSH n'a pas été rendu obligatoire, alors que quasiment tous les routeurs ont un programme SSH, c'est parce que ce programme n'est pas toujours disponible sous forme d'une bibliothèque, accessible aux applications comme RTR.

Autre alternative de sécurisation évidente, TLS. Le RFC impose une authentification par un certificat client, comportant l'extension subjectAltName du RFC 5280, avec une adresse IP (celle du routeur qui se connecte, et que le serveur RTR, la cache validateur, doit vérifier). Le client RTR, lui (le routeur), utilisera le nom de domaine du serveur RTR (le cache) comme entrée pour l'authentification (cf. RFC 6125). N'importe quelle CA peut être utilisée mais notre RFC estime qu'en pratique, les opérateurs créeront leur propre CA, et mettront son certificat dans tous leurs routeurs.

Notez que ce problème de sécurité ne concerne que le transport entre le routeur et le cache validateur. Entre les caches, ou bien entre les caches et les serveurs publics de la RPKI, il n'y a pas besoin d'une forte sécurité, l'intégrité des données est assurée par la validation cryptographique des signatures sur les objets.

Ce RFC spécifie un protocole, pas une politique. Il pourra y avoir plusieurs façons de déployer RTR. La section 9 donne un exemple partiel de la variété des scénarios de déploiement, notamment :

  • Le petit site (« petit » est relatif, il fait quand même du BGP) qui sous-traite la validation à un de ses opérateurs. Ses routeurs se connectent aux caches validateurs de l'opérateur.
  • Le grand site, qui aura sans doute plusieurs caches en interne, avec peut-être un repli vers les caches de l'opérateur en cas de panne.
  • L'opérateur qui aura sans doute plusieurs caches dans chaque POP (pour la redondance).

Pour limiter la charge sur les serveurs rsync de la RPKI (voir RFC 6480), il est recommandé d'organiser les caches de manière hiérarchique, avec peu de caches tapant sur les dépôts rsync publics, et les autres caches se nourrissant (et pas tous en même temps) à partir de ces caches ayant un accès public.

Bien que ce protocole RTR ait été conçu dans le cadre de la RPKI, il peut parfaitement être utilisé avec d'autres mécanismes de sécurisation du routage, puisque RTR se contente de distribuer des autorisations, indépendemment de la manière dont elles ont été obtenues. On peut donc imaginer du RTR avec Rover.

Aujourd'hui, qui met en œuvre RTR ? Il existe en logiciel libre une bibliothèque en C, RTRlib. Elle a fait l'objet d'un bon article de présentation (avec schéma pour expliquer RTR). Elle peut tourner sur TCP nu mais aussi sur SSH. RTRlib permet d'écrire, très simplement, des clients RTR en C, pour déboguer un cache/validateur, ou bien pour extraire des statistiques. Un client simple en ligne de commande est fourni avec, rtrclient. Il peut servir d'exemple (son code est court et très compréhensible) mais aussi d'outil de test simple. rtrclient se connecte et affiche simplement les préfixes reçus. Voici (avec une version légèrement modifiée pour afficher la date) son comportement (en face, le RPKI Validator du RIPE-NCC) :

% rtrclient tcp localhost 8282
...
2012-05-14T19:27:42Z + 195.159.0.0         16-16        5381
2012-05-14T19:27:42Z + 193.247.205.0       24-24       15623
2012-05-14T19:27:42Z + 37.130.128.0        20-24       51906
2012-05-14T19:27:42Z + 2001:1388::         32-32        6147
2012-05-14T19:27:42Z + 2001:67c:2544::     48-48       44574
2012-05-14T19:27:42Z + 178.252.36.0        22-22        6714
2012-05-14T19:27:42Z + 217.67.224.0        19-24       16131
2012-05-14T19:27:42Z + 77.233.224.0        19-19       31027
2012-05-14T19:27:42Z + 46.226.56.0         21-21        5524
2012-05-14T19:27:42Z + 193.135.240.0       21-24         559
2012-05-14T19:27:42Z + 193.247.95.0        24-24       31592
...

Autre bibliothèque pour développer des clients RTR, cette fois en Go, ma GoRTR. Le programmeur doit fournir une fonction de traitement des données, qui sera appelée chaque fois qu'il y aura du nouveau. GoRTR est fournie avec deux programmes d'exemple, un qui affiche simplement les préfixes (comme rtrclient plus haut), l'autre qui les stocke dans une base de données, pour étude ultérieure. Par exemple, on voit ici que la majorité des préfixes annoncés autorisent une longueur de préfixe égale à la leur (pas de tolérance) :

essais=> SELECT count(id) FROM Prefixes WHERE serialno=(SELECT max(serialno) FROM Prefixes) AND 
   maxlength=masklen(prefix);
 count 
-------
  2586
(1 row)

essais=> SELECT count(id) FROM Prefixes WHERE serialno=(SELECT max(serialno) FROM Prefixes) AND 
   maxlength>masklen(prefix);
 count 
-------
  1110
(1 row)

Autrement, Cisco et Juniper ont tous les deux annoncé que leurs routeurs avaient un client RTR, et qu'il a passé des tests d'interopérabilité avec trois mises en œuvre du serveur (celles de BBN, du RIPE et de l'ISC). Un Internet-Draft sur ces tests d'interopérabilité est draft-ymbk-rpki-rtr-impl. Quant aux serveurs, un exemple est fourni par le logiciel RPKI du RIPE-NCC qui fournit un serveur RTR sur le port 8282 par défaut.

Aujourd'hui (18 janvier 2013), un client RTR récupère 3696 préfixes (ce qui est plus que le nombre de ROA puisqu'un ROA peut comporter plusieurs préfixes). C'est encore très loin de la taille de la table de routage globale et il reste donc à voir si l'infrastructure suivra. (Sur ma station de travail, le validateur, écrit en Java, rame sérieusement.)

Pour les curieux, pourquoi est-ce que l'IETF n'a pas utilisé Netconf (RFC 6241) plutôt que de créer un nouveau protocole ? Les explications sont dans une discussion en décembre 2011. Le fond de la discussion était « les informations de la RPKI sont des données ou de la configuration » ? La validation est relativement statique mais reste quand même plus proche (fréquence de mise à jour, notamment) des données que de la configuration.

Si vous voulez tester un client RTR, BBN fournit un serveur public : rtr-test.bbn.com:12712 (TCP nu). Les données sont bidon et générées automatiquement. Voici le genre de choses qu'affiche rtrclient :

% rtrclient tcp rtr-test.bbn.com 12712
...
2012-05-14T19:36:27Z + 236.198.160.184     18-24  4292108787
2012-05-14T19:36:27Z + 9144:8d7d:89b6:e3b8:dff1:dc2b:d864:d49d 105-124 4292268291
2012-05-14T19:36:27Z + 204.108.12.160       8-29  4292339151
2012-05-14T19:36:27Z + 165.13.118.106      27-28  4293698907
2012-05-14T19:36:27Z + 646:938e:20d7:4db3:dafb:6844:f58c:82d5   8-82  4294213839
2012-05-14T19:36:27Z + fd47:efa8:e209:6c35:5e96:50f7:4359:35ba  20-31  4294900047
...

Les auteurs de la RTRlib gèrent également un serveur RTR public, accessible en rpki.realmv6.org:42420.

Une étude comparée des mises en œuvre de RTR a été publiée en février 2014 dans le RFC 7128.


Téléchargez le RFC 6810


L'article seul

RFC 6861: The Create-Form and Edit-Form Link Relations

Date de publication du RFC : Janvier 2013
Auteur(s) du RFC : I. Dzmanashvili
Pour information
Première rédaction de cet article le 17 janvier 2013


Depuis la création du registre des types de liens par le RFC 5988, de nombreux types ont été enregistrés, pour qualifier les relations existant entre une ressource Web, et les ressources vers lesquelles elle a un lien. Ce nouveau RFC décrit deux nouveaux types, pour indiquer un lien vers un formulaire permettant de créer ou de modifier une ressource.

Prenons une encyclopédie en ligne comme Wikipédia. Chaque article est modifiable par les lecteurs. Trouver le lien menant au formulaire de modification est une opération différente sur chaque site. Pour faciliter cette tâche, on peut mettre dans l'article un lien typé edit-form et le navigateur pourra alors facilement mettre un bouton standard « Modifier cette ressource ». Même si, pour les humains, ce n'est pas forcément indispensable, ces liens typés peuvent être très utiles pour les programmes, qui peuvent ainsi automatiquement détecter et suivre le lien menant vers le formulaire. (Attention toutefois, avertit le RFC, si le lien pointe vers un autre domaine : il ne faut pas forcément suivre aveuglément tous les liens.)

Ce RFC est très court car ces deux types sont simples à définir. Le premier, create-form, permet d'indiquer un formulaire pour créer une ressource inexistante (il est donc intéressant lors d'une réponse « 404 », indiquant que la ressource demandée n'a pas été trouvée, mais aussi pour ajouter une entrée à une collection). Voici un exemple en HTML :


<ul>
       <li>Endives au gratin</li>
       <li>Hachis parmentier</li>
       ...
</ul>
<a href="/recipe/create" rel="create-form">[Ajouter une nouvelle recette]</a>

Comme tous les liens typés du RFC 8288 (successeur du RFC 5988), ils ne sont pas limités à HTML et peuvent être mis dans une réponse HTTP (ce qui permet leur utilisation pour des ressources non-HTML) :

HTTP/1.0 404 Not found
Server: Experimental 0.0
Link: </files/upload>; rel="create-form"; title="Create it"
Date: Mon, 14 Jan 2013 07:35:01 GMT

L'autre type, edit-form, permet de modifier une ressource existante. En HTML :


<ul>
      <li>
        Endives au gratin
        <a href="/recipe/endivegratin/edit" rel="edit-form">[Modifier]</a>
      </li>
      <li>
        Hachis parmentier
        <a href="/recipe/hachisparmentier/edit" rel="edit-form">[Modifier]</a>
      </li>
      ...
</ul>

Et sous forme d'un en-tête HTTP :

HTTP/1.0 200 OK
Server: Experimental 0.0
Link: </recipe/fiadone/edit>; rel="edit-form"; title="Modifier la recette"
Date: Mon, 14 Jan 2013 07:36:42 GMT

Notez qu'il existe déjà un type edit (décrit par le RFC 5023 et donc spécifique à APP mais qu'on trouve parfois dans des pages HTML).


Téléchargez le RFC 6861


L'article seul

RFC 6859: Update to RFC 3777 to Clarify Nominating Committee Eligibility of IETF Leadership

Date de publication du RFC : Janvier 2013
Auteur(s) du RFC : B. Leiba (Huawei)
Première rédaction de cet article le 15 janvier 2013


Un petit RFC bureaucratique, décrivant un léger changement dans les règles d'éligibilité au NomCom, le comité qui nomme à des postes au sein de la galaxie IETF. Désormais, les membres de l'IAOC rejoignent la liste des non-éligibles. (Ce RFC a depuis été fusionné avec d'autres pour former le RFC 7437.)

Le RFC 3777 décrivait le fonctionnement de ce NomCom (Nominating Committee). Il dressait une liste des comités dont les membres ne peuvent pas être au NomCom, afin d'éviter l'auto-sélection. Par exemple, les membres de l'IESG ne peuvent pas être au NomCom, ce qui est logique puisque celui-ci contribue à la nomination de l'IESG. Même chose pour l'IAB.

Depuis le RFC 3777, l'IAOC a été créée (RFC 4071) et ses membres sont également partiellement choisis par une procédure où le NomCom est présent. Notre RFC décrète donc que, désormais, la liste des non-éligibles inclut l'IAOC (mettant ainsi à jour la règle 15 de la section 4 du RFC 3777). Depuis, le RFC 7437 a rassemblé tous les changements en un seul RFC faisant autorité sur le NomCom.

On notera que les présidents des groupes de travail, les membres des directions transversales et d'autres comités ne sont pas concernés : aujourd'hui comme hier, ils peuvent siéger au NomCom.


Téléchargez le RFC 6859


L'article seul

RFC 6772: Geolocation Policy: A Document Format for Expressing Privacy Preferences for Location Information

Date de publication du RFC : Janvier 2012
Auteur(s) du RFC : H. Schulzrinne (Columbia University), H. Tschofenig (Nokia Siemens Networks), J. Cuellar (Siemens), J. Polk (Cisco), J. Morris, M. Thomson (Microsoft)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF geopriv
Première rédaction de cet article le 11 janvier 2013


Toute information sur la position physique d'une personne ou d'une machine (la géolocalisation) est évidemment très sensible et il est normal que les considérations de protection de la vie privée jouent un grand rôle dès qu'on parle de géolocalisation. Le RFC 6280 fixait un cadre général pour la protection de la vie privée face à cette géolocalisation. Ce nouveau RFC étend les techniques des RFC 4119 et RFC 4745 pour permettre d'exprimer les autorisations concernant la géolocalisation, en fonction de la position : ce qu'on peut faire de l'information, à qui on peut la transmettre, etc.

Le principe est que le document suivant le format de ce RFC va poser des conditions (« si je suis en tel lieu », cf. section 4) et que, en fonction de ces conditions, on aura des actions (non spécifiées ici) et surtout des transformations (section 6), qui vont changer les valeurs spécifiées par le langage du RFC 4119 : autoriser ou interdire la retransmission de l'information, modifier la durée d'expiration, indiquer un texte décrivant une politique, et enfin délibérement faire perdre de la précision, afin de protéger sa vie privée. Ainsi, pour les localisations civiles (exprimées par rapport aux constructions humaines et pas par rapport à la Terre), on peut utiliser le vocabulaire du RFC 5139 pour spécifier que la localisation doit être limitée en précision à une rue, une ville, voire un pays.

Tirés de la section 7, voici quelques exemples (comme vous le voyez, la syntaxe est du XML, le schéma figure en sections 8 et 9) :


   <?xml version="1.0" encoding="UTF-8"?>
   <ruleset xmlns="urn:ietf:params:xml:ns:common-policy"
     xmlns:gp="urn:ietf:params:xml:ns:geolocation-policy">

     <rule id="AA56i09">
       <conditions>
         <gp:location-condition>
           <gp:location
             profile="civic-condition"
             xml:lang="en"
             label="Siemens Neuperlach site 'Legoland'"
             xmlns="urn:ietf:params:xml:ns:pidf:geopriv10:civicAddr">
             <country>DE</country>
             <A1>Bavaria</A1>
             <A3>Munich</A3>
             <A4>Perlach</A4>
             <A6>Otto-Hahn-Ring</A6>
             <HNO>6</HNO>
           </gp:location>
         </gp:location-condition>
       </conditions>
       <actions/>
       <transformations/>
     </rule>
   </ruleset>

Qu'est-ce que cela dit ? Que si la localisation civile actuelle est « 6, Otto-Hahn-Ring, dans le quartier de Perlach à Munich », alors, on ne fait rien de particulier (les éléments <actions> et <transformations> sont vides). Les conditions auraient pu être exprimées en géodésique et pas en civil, par exemple :


<gs:Circle srsName="urn:ogc:def:crs:EPSG::4326">
               <gml:pos>-33.8570029378 151.2150070761</gml:pos>
               <gs:radius uom="urn:ogc:def:uom:EPSG::9001">1500
               </gs:radius>
             </gs:Circle>

(C'est l'opéra de Sydney.)

Maintenant, avec une transformation qui interdit la retransmission, change la durée de vie de l'information, et limite la précision géodésique à 500 mètres :


<transformations>
         <gp:set-retransmission-allowed>false
         </gp:set-retransmission-allowed>

         <gp:set-retention-expiry>86400</gp:set-retention-expiry>

         <gp:provide-location
           profile="geodetic-transformation">
           <lp:provide-geo radius="500"/>
         </gp:provide-location>
</transformations>

Attention, si la protection de votre vie privée est cruciale, lisez bien la section 13, qui expose les limites de la protection qu'offrent ces techniques. Par exemple, imaginez que, lorsque vous êtes chez vous, vous réduisez la précision à 200 mètres, pour empêcher qu'on localise votre maison. Imaginons maintenant que le logiciel vous place donc au hasard quelque part dans un cercle de rayon 200 m centré sur votre maison. Un attaquant malin pourrait relever votre position pendant quelques jours, faire l'intersection de ces informations, et trouver la maison avec une bonne précision... Une bonne mise en œuvre de ce RFC devrait donc servir toujours la même information à un demandeur donné, mais, si vous étiez programmeur, vous auriez pensé à ce piège ? Aléatoire n'est dons pas synonyme de sécurité, bien au contraire.

Même sans cela, des informations externes peuvent guider celui qui cherche à vous pister. Si la précision est de mille mètres pendant votre déplacement de Paris à Lyon, l'observateur pourra remarquer que vous utilisez le TGV et réduire ainsi drastiquement l'imprécision.

Pire, le danger peut venir des règles de protection de la vie privée elle-même. Si la configuration par défaut est d'une précision de 100 m, et que quelqu'un indique une dégradation à 1000 m en certains endroits, il indique que ces endroits sont particulièrement sensibles et donc intéressants pour une personne mal intentionnée envers lui.


Téléchargez le RFC 6772


L'article seul

RFC 6841: A Framework for DNSSEC Policies and DNSSEC Practice Statements

Date de publication du RFC : Janvier 2013
Auteur(s) du RFC : F. Ljunggren (Kirei AB), AM. Eklund Lowinder (.SE), T. Okubo (ICANN)
Pour information
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 11 janvier 2013


Comme pour toutes les techniques de sécurité informatique, DNSSEC n'est efficace que si son déploiement s'accompagne de bonnes pratiques de sécurité. Il ne suffit pas de générer une clé et de signer la zone ! Pour prendre un exemple caricatural, si on signe sa zone DNS avec DNSSEC, mais que la partie privée de la clé est stockée, en mode 644 (lecture pour tous), sur un serveur sur lequel tous les employés du registre, les stagiaires et les consultants ont un compte, alors DNSSEC n'apportera guère de sécurité. Il est donc nécessaire de prendre certaines précautions. Un DPS (DNSSEC Policies and DNSSEC Practice Statement) est un document qui liste les politiques et les pratiques d'un utilisateur de DNSSEC, y compris ces précautions.

Il a deux usages principaux. L'un est plutôt externe, communiquer au reste du monde, notamment aux utilisateurs du nom de domaine en question, les pratiques du registre, pour que ces utilisateurs, le régulateur, les autorités de cyber-sécurité (comme l'ANSSI en France) et les autres parties prenantes puissent se faire une idée du niveau de sécurité de DNSSEC dans cette zone. Et le deuxième usage est plus interne, documenter des choix effectués. Si un DPS peut n'être vu que comme un exercice bureaucratique de plus, il peut aussi être une utile check-list pour s'assurer qu'on maîtrise bien tous les composants de la chaîne de sécurité et qu'on n'a rien oublié dans sa réflexion.

Ce RFC fait la liste de tout ce que peut contenir un DPS, de manière à guider les auteurs de tels documents. Par contre, il ne dit pas quels sont les bons choix (en partie parce que ceux-ci dépendent des caractéristiques particulières de la zone signée), cela sera « vous devez indiquer si vous utilisez NSEC ou NSEC3 », pas « NSEC3 est meilleur que NSEC ». Ce RFC s'inspire d'un document équivalent fait pour X.509, le RFC 3647 mais ne le copie pas, DNSSEC étant très différent de X.509.

En pratique, ce RFC sera sans doute surtout utilisé par les gérants de TLD mais il peut être utile à d'autres, notamment les zones les plus critiques, ou tout simplement ceux qui veulent améliorer leur sécurité (au prix d'un certain travail).

D'abord, une distinction entre politique DNSSEC (DNSSEC policy) et déclaration de pratiques DNSSEC (DNSSEC Practice Statement) en section 3 du RFC. La première est de plus haut niveau, plus générale, elle exprime le cahier des charges, ce qu'on veut atteindre comme objectif. Si une évaluation de la sécurité d'une zone est faite, par rapport à certaines menaces, c'est par rapport à cette politique DNSSEC. (La politique DNSSEC la plus simple est « on ne signe pas avec DNSSEC » mais elle est typiquement insuffisante face aux menaces d'aujourd'hui.) La seconde, la déclaration de pratiques DNSSEC, est plus concrète, décrivant les mécanismes qu'on déploie pour s'approcher de cet objectif. Si la politique DNSSEC dit ce qu'il faut faire, la déclaration de pratiques DNSSEC dit ce qui est fait. Attention, une déclaration de pratiques DNSSEC est typiquement un document public et on déclare donc ce qui est utile au public, et pas ce qui est confidentiel.

On notera que les deux documents peuvent être écrits par deux acteurs différents. On peut imaginer, par exemple, un régulateur écrivant la politique DNSSEC (les objectifs de sécurité) et le registre qui a obtenu la délégation de la zone écrivant la déclaration de pratiques DNSSEC (ce qu'il va faire pour atteindre ces objectifs).

La déclaration de pratiques étant plus concrète, elle est aussi plus détaillée et, typiquement, bien plus longue que la politique DNSSEC.

Si vous voulez voir des exemples de DPS existantes (je vais en citer plusieurs, à titre d'exemple), l'ISOC maintient une bonne liste. Ce sont plutôt des déclarations de pratiques que des politiques. On y trouve surtout des TLD (j'ai utilisé pour les exemples la DPS de .FR et celle de .NL) mais aussi des domaines comme in-addr.arpa (DPS du RIPE-NCC en ligne sur leur site) ou bien sûr comme la racine. Notons qu'elles ne sont pas forcément en anglais. Celle de .CL a deux versions mais celle en espagnol est la seule à faire autorité.

Alors, justement, que peut-on mettre dans ces documents ? La section 4 fait la liste des points qu'il peut être souhaitable de couvrir. Je ne vais pas les répéter ici, consultez le RFC 6841 si vous voulez tout savoir. Parmi les points qu'on peut noter, l'importance d'identifier dans le document à qui il s'adresse (section 4.1.3) : au gouvernement, au régulateur, aux gérants des serveurs récursifs, aux titulaires de noms de domaine, à tous à la fois ?

Un sujet de discussion dans la communauté DNSSEC a toujours été la publication des clés. DNSSEC reposant sur l'architecture arborescente du DNS, il n'y a en théorie besoin de publier qu'une seule clé, celle de la racine. Toutefois, on peut avoir de bonnes raisons de publier la clé d'un sous-domaine, par exemple pour être indépendant de la racine, ou bien parce qu'on a une relation plus forte avec le gérant de la zone qu'avec celui de la racine. Pour prendre un exemple imaginaire, on pourrait voir gouv.fr signé et chaque ministère mettre la clé de gouv.fr dans ses résolveurs, de manière à ce que la communication au sein du gouvernement français ne dépende pas du tout d'une organisation extérieure. Dans un cas comme celui-ci, la section 4.2.2 rappelle qu'il faut inclure dans ses documents publics les mécanismes de publication, et notamment la méthode que doivent utiliser les gérants de résolveurs validant pour s'assurer de l'authenticité des clés (récupération sur un serveur HTTPS, signature des clés avec PGP, etc). D'autres informations importantes peuvent être ajoutées comme la fréquence de renouvellement des clés et la technique qui sera utilisée pour prévenir d'un tel renouvellement. Par exemple, le .CL utilise une liste de diffusion « NIC Chile mantendrá una lista de correo electrónico, de suscripción pública, donde se anunciarán con anticipación los inicios y términos de los rollovers de KSK: anuncios-dnssec@listas.nic.cl ».

À titre d'exemple, voyez la publication des clés de la racine et sa documentation, ou bien celle de .FR ou du RIPE-NCC. Au contraire, les clés de .UK ne font pas l'objet d'une publication (à part dans le DNS).

La déclaration de pratiques doit exposer comment sont délégués les enregistrements DS. DNSSEC ne servirait à rien si, par exemple, on pouvait ajouter ou modifier une DS via un canal non-sécurisé. De même, un registre peut avoir des méthodes pour tester que la DS soumise l'a bien été par le gérant de la zone (par exemple, Zonecheck, depuis la version 3, peut vérifier que la zone est bien signée avec une clé correspondant à la DS indiquée). Ces méthodes sont alors décrites dans ce document. Enfin, le document peut indiquer comment on retire une DS de la zone (certains registres peuvent le faire dès qu'un problème technique est signalé, rendant alors la zone non sécurisée, mais, au moins, utilisable). Par exemple, .FR dit « Un enregistrement DS peut-être supprimé par une demande du bureau d'enregistrement via EPP ou un formulaire web sécurisé par TLS. » mais a aussi une possibilité de suppression par le titulaire « Un Titulaire d'un nom de domaine sous une extension géré par l'Afnic qui se trouve incapable de joindre le bureau d'enregistrement correspondant à ce nom, pourra utiliser une procédure exceptionnelle de suppression de DS, similaire à la procédure de demande d'urgence du auth_info. ».

La sécurité n'est pas l'affaire que de technique. Les sections 4.4 et 4.5 rappelent qu'il y a aussi toute une organisation nécessaire et qu'elle aussi doit être décrite dans la document : accès physique aux locaux (si vous utilisez des empreintes rétiniennes, c'est là qu'il faut en parler, idem pour les autres mesures high-tech prises pour assurer la sécurité du système, bref tous les gadgets James Bond utilisés dans le registre), procédures à suivre pour les opérations, etc. Par exemple, il est fréquent que les opérations de sécurité (comme le démarrage du processus de signature) reposent sur un schéma « M parmi N ». Cela veut dire que N personnes sont habilitées à effectuer les opérations et que M d'entre elles (avec M ≤ N) doivent être présentes. La déclaration de pratiques DNSSEC est l'endroit où on donne les valeurs de M et de N (section 4.4.2).

Et comment décide-t-on que ces personnes sont « qualifiées » ? La section 4.4.3 dit que cela doit être marqué noir sur blanc : qualifications requises, enquêtes effectuées, sanctions prévues contre les employés qui violent les procédures, etc. La racine va assez loin dans l'examen de ses employés « Check of credit/financial records to the extent allowed by national laws for the individual's country of residence ». .FR dit « Le recrutement interne ou externe est effectué par la fonction RH de l'Afnic, qui vérifie les antécédents et les qualifications des candidats, prend en compte : Le curriculum vitae des candidats, Emplois précédents, Références, Les diplômes obtenus. Pour être admissible à l'un des rôles de confiance, ces contrôles ne peuvent pas révéler un critère d'incapacité. » Et .NL s'appuie sur les mécanismes de certification du pays « All persons that fulfill a role in the DNSSEC ceremony must have a "Certificate of Good Conduct" ("Verklaring omtrent Gedrag") issued by the Dutch government. ».

C'est aussi à cet endroit qu'on devrait indiquer si les manœuvres de sécurité sont effectuées uniquement par les employés du registre ou bien peuvent l'être par le stagiaire envoyé par une SSII. Ainsi, .NL précise « No person outside of the specified Trusted Roles (4.2.1) can get access to the signer systems.If necessary, tasks can be performed with the guidance of an external contractor. At no time is the contractor allowed to be the person performing the tasks on the system. » alors que la racine est plus ouverte « In limited circumstances, independent contractors or consultants may be used to fill Trusted Roles. Any such contractor or consultant is held to the same functional and security criteria that apply to any ICANN employees in a comparable role. Independent contractors and consultants who have not completed or passed the background check procedures specified in DPS section 4.3 are permitted access to ICANN's secure facilities only to the extent they are escorted and directly supervised by Trusted Persons at all times. ».

Une part du travail d'évaluation des risques concerne évidemment les PCA et PRA, en section 4.4.5.

Au passage, la section 4.4.1 concernait les risques physiques. Aux Pays-Bas, comme leur nom l'indique, le risque principal est l'inondation, ce qui explique cette mention dans le DPS du RIPE-NCC : « Additionally, we have a back-up site outside of Amsterdam at around 30 metres above sea level. » et, dans le DPS de .NL : « Several sites are located above sea level. ».

Les audits, pour vérifier si le système correspond réellement à ce qui est décrit dans la déclaration de pratiques DNSSEC, font l'objet de la section 4.7. Un avis personnel : comme toujours en sécurité, ils peuvent être traités comme un moyen concret de déterminer le vrai niveau de sécurité, ou bien simplement comme une série de processus, style ISO 27001, ayant peu de liens avec la réalité (« process over result »).

La génération des clés cryptographiques doit être particulièrement soignée (c'est souvent le point faible des processus cryptographiques). Chez les registres importants, elle fait en général l'objet de cérémonies solennelles, avec des auditeurs qui notent gravement toutes les étapes dans un gros livre, et deux caméras qui enregistrent le tout. La déclaration de pratiques DNSSEC doit indiquer comment se fait cette génération (sur un serveur Unix connecté à l'Internet ? au sein d'un HSM ?) et quelles précautions sont prises (la salle où se fait la génération est-elle une cage de Faraday, pour empêcher les attaques Tempest ?) Rappelez-vous, comme pour le reste de ce RFC, que ce RFC 6841 dit juste quels sont les points à couvrir, il ne prend pas position sur, par exemple, la question de savoir si un HSM vaut la peine ou pas. Le RFC dit juste « décrivez le système qui générera les clés ». La réponse « le responsable écrit à la main une série de chiffres sortis de sa tête, et qui lui semble cool et aléatoire » est acceptable, car elle permettra aux auditeurs de se faire une idée de la sécurité du système.

Une fois la clé générée, il faut garder en sécurité la partie privée (section 4.5.2). La mettre dans un fichier en mode 0644 (lecture pour tous) sur un serveur Web public (cf. section 4.5.6) est certainement une très mauvaise idée. Mais, ensuite, il y a plusieurs choix possibles, le choix dépendant en partie des moyens financiers du registre. Un fichier en mode 0600 (lisible uniquement par le propriétaire), propriété de root, sur une machine Unix bien gérée (cf. section 4.5.5), semble assez sûr mais il y a des risques : si un attaquant vole la machine physique, il met le disque dans une autre machine et il peut tout lire. Voilà pourquoi il existe des boîtiers assurant une certaine protection contre le vol physique. La norme FIPS-140 décrit leurs différents niveaux. Il faut noter que ce n'est qu'à partir du niveau 4 que le boîtier est tamper-zeroize, c'est-à-dire qu'il garantit l'effacement des clés en cas d'ouverture non autorisée (« coupe le fil bleu »). Les HSM des niveaux 2 et 3 ne garantissent que la résistance à l'ouverture (qui n'est jamais infinie) ou le tamper-evident (si quelqu'un a ouvert le boîtier, cela se verra). Il faut donc prêter attention, pas juste à l'étiquette FIPS-140 mais aussi au niveau exact. Et, naturellement, comme toute technique de sécurité, il faut une évaluation globale, pour s'assurer de la cohérence du système. Il ne serait pas très utile d'avoir un HSM FIPS-140 niveau 4 si la base de données du registre permettait à n'importe qui d'écrire n'importe quoi dedans. Le RIPE-NCC dit « Systems used for signing the zones are FIPS 140-2 Level 2-certified » alors que la racine met la barre plus haut « For RZ KSK generation and RZ KSK private component operations and storage, ICANN uses hardware security modules that are validated at FIPS 140-2 level 4 overall. ». Même chose pour .FR : « Le Système utilise un module de Sécurité matérielle ( HSM ) conforme aux exigences du standard FIPS 140-2 Niveau 4 ». Le .CL ne fait pas référence à FIPS-140 mais dit « La "máquina firmadora off-line" se encuentra en una caja fuerte bajo control directo de NIC Chile, y los Ministros de Fe conocerán la clave para abrirla. Cuando no esté en uso, la "máquina firmadora off-line" se mantendrá en una bolsa sellada para asegurar que no ha sido intervenida. ».

Autres questions sur la gestion de la partie privée : y a-t-il un séquestre ? Des sauvegardes (si on n'en fait pas, on minimise les risques de copie non autorisée mais on risque d'être très embêté en cas de destruction accidentelle de la clé) ? Et, si oui, on veut bien des détails. Pour .FR, la DPS annonce « L`Afnic n'a pas recours à l'entiercement des clés » et « Les clés créées sont : recopiées en format chiffré sur les cartes de sauvegarde (SMK) spécifiques au HSM exploité par l'Afnic. [...] Les clés sont sauvegardées de façon sûre et synchronisée après chaque génération de clé. ».

L'activation de la clé privée, pour commencer les signatures, dépend souvent de choses que possèdent les personnes autorisées. Il faut donc écrire noir sur blanc ce que sont ces choses : une carte à puce ? Un PIN ? Une partie de la clé privée (pour les cas où elle est divisée) ? Plusieurs choses ?

Enfin, la journalisation correcte des événements nécessite un estampillage temporel correct et la section 4.5.7 rappelle qu'il faut penser à décrire comment on obtient l'heure et avec quel niveau de sécurité. Le RIPE-NCC affirme « The signer systems securely sychronise their system clocks with a trusted time source inside our network ». Tout aussi vague, la racine dit « The ceremony administrator will manually set the signer system clock and the wall clock to current UTC time drawn from a reliable time source. ». Et .NL : « The registry utilizes its default NTP-policy for timestamping. Time stamps are conducted using UTC and are standardized for all log information and validity time for signatures. ». Bien sûr, aucune de ces trois déclarations n'est précise. Mais, bon, c'est une question difficile quand on rédige une DPS : trop de détails, et on risque de se lier les mains et de ne plus être à jour rapidement. Pas assez, et la déclaration ne sert pas à grand'chose.

Tout aussi technique, la section 4.6 concerne le processus de signature de la zone : quel algorithme de cryptographie utiliser (aujourd'hui, c'est RSA pour l'écrasante majorité des zones DNSSEC mais d'autres sont possibles, voir par exemple les RFC 6605 et RFC 5933), quelle longueur pour les clés, quel TTL pour les enregistrements, etc. On dit aussi ici si on utilise NSEC ou NSEC3 (RFC 5155) pour prouver la non-existence d'un nom. .NL annonce ses TTL ainsi « DNSKEY: 7200 seconds \ NSEC3: equal to minumum[sic] field of SOA record (RFC5155) \ RRSIG: equal tot[sic] TTL of RRset covered, 7200 in practice » et la longueur « RSA algorithms with a key length of 2048 bits are currently used for KSK and 1024 bits for ZSK. ». La racine dit « DNSKEY 48 hours \ NSEC same as SOA minimum (24 hours) \ RRSIG same as the covered RR (varies) ».

Un gros morceau de cette section est le problème récurrent du remplacement des clés. Le sujet est sensible mais, en tout cas, il faut documenter les choix effectués.

Et, comme la sécurité n'est pas une question purement technique, que les registres peuvent avoir des obligations contractuelles, il faut aussi penser aux risques légaux et (section 4.8) documenter quelle est la loi qui s'applique au registre et ses éventuelles obligations contractuelles. La racine dit « This DPS shall be governed by the laws of the State of California » (problème classique de gouvernance Internet, la racine, ressource mondiale, est contrôlée par un seul État). Par contre, la DPS de .JP (dans sa traduction anglaise non officielle) « When operating JP DNSSEC Service, the Registry follows the laws of Japan and the rules defined by the Registry (No English translation is available). ». Et celle de .FR dit « La Loi française s'applique au présent document ».

La section 5 est simplement une suggestion de plan pour la rédaction d'une déclaration de pratiques DNSSEC. La plupart des déclarations que j'ai lues reprennent ce plan tel quel (certes, le RFC vient juste de paraître, mais il est issu d'Internet-Drafts bien plus anciens, le processus de publication ayant été très lent). Une étude faite au sein du CENTR en février 2011 a montré notamment que, sur les 19 registres répondants, 17 connaissait cet Internet-Draft et 13 l'avaient utilisé comme check-list pour écrire leur propre DPS.

Merci à Florian Maury pour sa relecture (ce qui ne veut pas dire qu'il est d'accord avec moi sur tout.)


Téléchargez le RFC 6841


L'article seul

Faire réaliser des mesures par les sondes Atlas

Première rédaction de cet article le 8 janvier 2013


Le réseau des sondes Atlas, créé et géré par le RIPE-NCC, couvre l'Europe de petites machines connectées à l'internet et qui effectuent en permanence des mesures diverses. Les Atlas ne savaient faire au début que des mesures commandées par le RIPE-NCC. Depuis quelque temps, les utilisateurs peuvent également commander des mesures selon leur goût, un système connu sous le nom d'UDM, User-Defined Measurements.


L'article complet

RFC 6819: OAuth 2.0 Threat Model and Security Considerations

Date de publication du RFC : Janvier 2013
Auteur(s) du RFC : T. Lodderstedt (Deutsche Telekom AG), M. McGloin (IBM), P. Hunt (Oracle Corporation)
Pour information
Réalisé dans le cadre du groupe de travail IETF oauth
Première rédaction de cet article le 8 janvier 2013


Le protocole d'autorisation sur le Web OAuth version 2 est riche, voire complexe. Son cadre général est décrit dans le RFC 6749. Et ce nouveau RFC documente les questions de sécurité liées à OAuth v2. Quelles sont les menaces ? Quels sont les risques ? Et comment OAuth gère-t-il ces risques ?

Le document reste assez abstrait car les détails, notamment les probabilités d'une attaque réussie, dépendent de la façon dont OAuth est utilisé. OAuth v2 n'est pas réellement un protocole mais plutôt un cadre général dans lequel peuvent être décrits plusieurs protocoles, qui n'auront pas la même utilisation, ni les mêmes vulnérabilités. En prime, ce mécanisme complexe n'est pas au cœur de mon domaine de compétence personnel, et je vais devoir me contenter de survoler le RFC. Il n'était à l'origine que la section Security Considerations du RFC 6749 mais il a grossi suffisamment pour devenir un document autonome, très détaillé.

Donc, d'abord, en section 2, le cadre général. Par exemple, l'analyse des risques de ce RFC suppose que l'attaquant a un accès complet au réseau et peut écouter à sa guise, voire changer les paquets. On considère également possible que deux des parties impliquées peuvent s'allier pour tromper la troisième. OAuth a trois - ou quatre, dans la v2 - acteurs, le client, le serveur et le propriétaire. Dans la v2, le serveur a été séparé en deux, le serveur d'autorisation et le serveur de ressources. La section 2.3 fait la liste de tout ce que connaissent les différentes parties, Le serveur d'autorisation connait ce qui sert à authentifier (par exemple les condensats des mots de passe des propriétaires). Le serveur de ressources connait les données qu'on veut protéger. Le client (l'application qui cherche à accéder aux données), par contraste, connait nettement moins de choses : le but principal d'OAuth était justement de permettre au propriétaire de donner un accès limité à des clients tiers, à qui il ne fait pas forcément une confiance aveugle.

OAuth repose largement sur des jetons (tokens), un petit bout de données qui sert à prouver qu'on est légitime. Avec certains de ces jetons (par exemple les jetons au porteur, bearer tokens), la seule possession du jeton suffit. Il est donc important de ne pas permettre à un tiers de les copier (donc, il faut communiquer en HTTPS, comme avec un cookie, cf. section 4.3.1, et aussi section 4.6.7 pour un moyen plus rigolo de faire fuiter les jetons).

Les jetons peuvent avoir une durée de vie limitée (RFC 6749, section 4.2.2), et cela permet à un utilisateur OAuth de retirer sa confiance à un client. Les jetons qu'a obtenu ce dernier avant la révocation de la confiance ne lui serviront pas éternellement.

La section 4 est le cœur du RFC. Elle expose toutes les menaces auxquelles a pu penser le groupe de travail, avec les solutions existant dans le cadre OAuth. Je ne vais pas la reprendre intégralement (pas moins de cinquante menaces ont été identifiées), juste en expliquer quelques-unes prises au hasard.

Par exemple (section 4.1.1), OAuth permet de stocker certains secrets (comme des jetons de rafraîchissement) dans le client, pour éviter de devoir passer par une autorisation explicite de l'utilisateur. La possession de ces secrets permet évidemment de se faire passer pour un client légitime. Certains programmeurs peuvent être tentés de planquer ces secrets dans un client distribué en binaire, en croyant naïvement que cela empêchera les hackers de les trouver. Le RFC rappelle donc à juste titre que la rétro-ingéniérie retrouvera rapidement ces secrets, même si le code source du client n'est pas distribué. La protection est donc simple : pas de secret dans un client public (section 5.3.1).

Même si les clients n'ont pas de secret codé en dur dans leur code, une fois qu'ils ont été utilisés, des secrets se retrouveront dans leur mémoire. En volant un engin qui fait tourner le client (un smartphone, par exemple), le méchant se retrouvera en possession des secrets. Les solutions sont dans les systèmes de verrouillage mais aussi dans les possibilités de révocation d'OAuth (encore faut-il que l'utilisateur y pense, lorsque son smartphone a été volé).

Autre menace, le hameçonnage. Comme OAuth dépend beaucoup des redirections HTTP (par exemple du site Web qu'on veut visiter vers le site Web d'autorisation), un utilisateur peut se faire tromper si la redirection est faite vers un site Web qui ressemble au site d'autorisation habituel. Autre façon de hameçonner, le client malveillant peut aussi, au lieu d'utiliser le navigateur Web normal du système, présenter à l'utilisateur humain sa propre interface, en la remplissant d'indicateurs rassurants, petit cadenas et tout. Le client, dans OAuth, ne devrait jamais avoir accès aux informations d'authentification de l'utilisateur (comme le mot de passe) mais ces techniques de hameçonnage le permettent. La seule solution est la vigilance de l'utilisateur, qui ne devrait se servir que de clients honnêtes. (Oui, je sais que c'est plus facile à écrire dans un RFC qu'à faire respecter en pratique. Le RFC suggère des contrôles de sécurité des applications avant de les mettre dans les dépôts comme l'App Store mais on sait que de tels contrôles ne sont pas faits.) Si le client est un navigateur Web, on sait que ces logiciels très complexes ont déjà eu de nombreuses failles de sécurité, permettant à un méchant de les détourner de leur rôle.

Outre le hameçonnage par le client (l'application qui tourne sur la machine de l'utilisateur), il y a un risque de hameçonnage par le serveur d'autorisation. Si celui auquel on accède n'est pas celui qu'on croit (par des trucs comme l'empoisonnement DNS ou ARP), et qu'on lui confie son mot de passe, on est fichu. L'utilisation de HTTPS est donc nécessaire.

OAuth soulève aussi des problèmes d'ergonomie : le serveur d'autorisation informe (voire permet de choisir) sur les permissions exactes qui seront données au client. Cette liste n'est pas toujours comprise par l'utilisateur, qui risque de donner au client trop de droits (section 4.2.2). Voici un exemple d'une application qui demande beaucoup de droits (car c'est un client Twitter généraliste) : twitter-authorisations.jpg

D'une manière générale, comme l'analyse la section 5.5, l'utilisateur manque d'expertise pour répondre intelligemment à des questions comme « il y a un problème de sécurité [ici, texte incompréhensible par l'utilisateur], voulez-vous continuer ? ». De même, la plupart des bonnes pratiques de sécurité (par exemple, l'utilisation obligatoire de seulement certains logiciels, soigneusement validés) vont être une gêne pour l'utilisateur. OAuth n'offre pas de solution ici, mais il est probable qu'il n'en existe pas : c'est le conflit classique entre sécurité et utilisabilité.

Certaines attaques ne sont pas réellement spécifiques à OAuth et visent le processus d'authentification de l'utilisateur, par exemple en essayant, auprès d'un serveur d'autorisation, des dictionnaires entiers de mots de passe pour essayer d'en trouver un qui marche. Les contre-mesures classiques s'appliquent ici, comme les si pénibles CAPTCHA (section 5.1.4.2.5) ou comme le verrouillage automatique des comptes après N essais infructueux (section 4.4.3.6).

Naturellement, le même processus d'authentification de l'utilisateur est vulnérable aux attaques Web classiques comme le clickjacking. Un navigateur Web moderne est rempli de tellement de fonctions différentes, visant en général à faire joli, qu'il est difficile de vérifier la totalité des risques de sécurité. Si un site Web charge la page du serveur d'autorisation dans un iframe transparent, au-dessus de ses propres boutons, il peut faire en sorte que l'utilisateur, croyant cliquer sur les boutons visibles, donne en fait une autorisation OAuth. Il existe plusieurs contre-mesures (section 4.4.1.9) mais des tas d'autres vulnérabilités attendent certainement, dissimulées dans les millions de lignes de code des navigateurs.

L'enfer étant pavé de bonnes intentions, ce sont aussi les solutions de sécurité, conçues pour résoudre une vulnérabilité, qui peuvent être utilisées pour monter une attaque. Ainsi, un méchant peut utiliser OAuth pour faire en sorte que des clients se connectent au serveur d'autorisation en masse. Cela oblige l'attaquant à faire une connexion HTTP mais, en échange, il obtient des connexions HTTPS, bien plus coûteuses (cf. « SSL handshake latency and HTTPS optimizations » de J. Sissel), vers le serveur d'autorisation. De même, si vous vous y connaissez en sécurité, vous avez peut-être noté que le verrouillage automatique des comptes après N essais ratés, proposé plus haut, permet une belle attaque par déni de service en autorisant n'importe qui à verrouiller un compte (cf. section 5.1.4.2.3).

Comme indiqué au début, je suis loin d'avoir listé toutes les menaces, notamment celles reposant sur de subtiles propriétés d'OAuth. N'écrivez pas un logiciel OAuth en suivant uniquement cet article, lisez bien tout le RFC !

Et les solutions à ces problèmes ? La section 5 regroupe les bons principes à suivre lorsqu'on développe ou déploie du OAuth. Chiffrer le trafic, avec TLS ou IPsec (OAuth vérifie l'authenticité et l'intégrité des requêtes mais, utilisé seul, ne fait rien pour la confidentialité), vérifier l'identité du serveur d'autorisation, etc.

Il y a aussi des mesures moins techniques, liées à l'interaction avec un humain, l'utilisateur. Il doit toujours être maintenu « dans la boucle », en lui demandant avant et en l'informant après de ce qui a été fait en son nom (section 5.1.3).

La section 5.1.4 se penche sur le problème de la conservation des « lettres de créance » (credentials), ces différentes informations que le serveur d'autorisation doit stocker en mémoire pour authentifier les utilisateurs. Elle rappelle l'importance de suivre les meilleures pratiques de ce domaine (comme documenté par OWASP). Cela va des protections contre les injections SQL (requêtes paramétrées, accès à la base de données sous un utilisateur non privilégié, etc) à la nécessité de ne pas stocker les mots de passe en clair. En 2012, garder des mots de passe en clair dans une base de données (qui se fera forcément copier un jour ou l'autre par un attaquant quelconque) est une faute grave. La méthode sûre la plus souvent utilisée est de ne stocker qu'un condensat du mot de passe mais cela ne suffit pas toujours, face aux attaques par dictionnaire, facilitées notamment par les tables arc-en-ciel. Ainsi, la copie de la base de mots de passe condensés de LinkedIn avait eu des conséquences sérieuses car les condensats n'étaient pas salés (section 5.1.4.1.3).

Si on génère des secrets qui n'ont pas besoin d'être manipulés par des êtres humains (comme les jetons), il faut bien penser à les faire longs et réellement aléatoires (RFC 4086).

Voilà, il existe encore plein de solutions décrites dans cette section, notamment sur les problèmes spécifiques à OAuth (sur lesquels je suis passé un peu rapidement, car je ne connais pas assez ce protocole). Si vous programmez un logiciel OAuth, il va évidemment falloir les lire.


Téléchargez le RFC 6819


L'article seul

Comment Free bloque les pubs

Première rédaction de cet article le 5 janvier 2013
Dernière mise à jour le 12 février 2013


Beaucoup de gens se sont exprimés depuis l'annonce par Free de leur nouveau service de blocage des publicités (désactivé temporairement le 7 janvier, puis réactivé ensuite). La plupart se sont focalisés sur les aspects politiques ou économiques. Comme je n'ai guère trouvé de détails techniques, j'ai profité d'une connexion Free pour regarder comment cela marchait.

Attention, à l'heure actuelle (février 2013), le « service » n'est pas activé par défaut. Si on le fait, on découvre que la liste noire est actuellement vide. Donc, ces tests ne peuvent pas être reproduits dans l'immédiat. Cet article reflète donc la situation lors de la première phase, aux environs du nouvel an 2013.

D'abord, première déception, après avoir redémarré la Freebox pour mettre à jour le logiciel, je vois toujours les publicités, sur tous les sites que je regarde. Je lis alors quelques tweets (et un courrier anonyme), qui expliquent que le filtrage des publicités utilise le DNS. Ah, je comprends, j'utilise un résolveur DNS qui n'est pas celui de Free, donc je vois toujours les pubs. Testons la fonction DNS de la Freebox. Celle-ci indique aux machines du réseau local, avec le protocole DHCP (et également avec les annonces du RFC 8106), les adresses des serveurs de noms à utiliser pour résoudre un nom comme www.owni.fr en une adresse IP. On peut changer la valeur indiquée, en passant par le panneau de contrôle de la Freebox v6.

Revenons aux résolveurs officiels. Sur une machine Unix, l'examen du fichier /etc/resolv.conf nous dira ce que la Freebox v6 nous a dit :

% cat /etc/resolv.conf
# Generated by dhcpcd from eth0
...
nameserver 192.168.2.254

On a donc un résolveur, 192.168.2.254, la Freebox elle-même. Celle-ci utilise un relais DNS, dnsmasq, qui transmet aux « vrais » résolveurs de Free (la Freebox v5 utilisait un système différent).

On va interroger ce résolveur. L'outil sérieux le plus courant pour le débogage DNS, l'outil qui est au DNS ce que ping est au réseau, est dig. Pour changer un peu, on va se servir de son concurrent drill, qui fait partie de l'excellente (mais peu connue) bibliothèque ldns. drill n'a pas davantage particulier sur dig dans ce cas, c'est juste pour changer et pour ne pas connaître qu'un seul outil. Il fait partie du paquetage ldns sur Arch Linux ou ldnsutils sur Debian.

D'abord, demandons à ce relais/résolveur dans la Freebox l'adresse IPv4 d'une régie publicitaire bien connue, DoubleClick :

% drill @192.168.2.254 doubleclick.net A
...
doubleclick.net.	1411	IN	A	212.27.40.246

Ah, on voit ici la triche. whois nous indique que 212.27.40.246 n'est pas une adresse de DoubleClick mais de Proxad, le réseau de Free. La Freebox abrite donc un DNS menteur. La vraie adresse de DoubleClick peut être obtenue en demandant à un résolveur honnête (ici, l'ODVR de l'OARC) :

% drill @2001:4f8:3:2bc:1::64:21 doubleclick.net A
...
doubleclick.net.	300	IN	A	70.32.146.212

Cette fois, on obtient bien une adresse de DoubleClick (plus exactement de sa maison mère, Google).

Et que se passe-t-il lorsque le navigateur Web de M. Michu, client de Free, se connecte à cette adresse en croyant qu'il va récupérer un bandeau de pub à afficher ? Voyons avec curl :


% curl -v http://212.27.40.246/fcggddgdf
...
< HTTP/1.1 200 OK
< Server: nginx
< Date: Sat, 05 Jan 2013 20:17:13 GMT
< Content-Type: text/plain
< Content-Length: 0

Pour tous les chemins demandés (j'ai tapé fcggddgdf au hasard), on récupère un fichier de taille nulle, donc rien ne sera affiché. Si je teste avec un navigateur sur une machine qui utilise le résolveur indiqué par Free, je ne vois pas les pubs.

Au passage, le serveur HTTP qui sert ces fichiers vides semble être sur la Freebox elle-même :

% traceroute  212.27.40.246
traceroute to 212.27.40.246 (212.27.40.246), 30 hops max, 60 byte packets
 1  212.27.40.246 (212.27.40.246)  0.409 ms  0.328 ms  0.366 ms

Donc, résumons, la Freebox inclut un résolveur DNS menteur, qui donne, pour certains noms (ceux des grandes régies publicitaires, probablement), une réponse mensongère. Celle-ci pointe vers un serveur de fichiers vides.

Voici pour la partie technique. À part l'intérêt intellectuel de savoir, cela permet de comprendre les limites du service :

  • Comme souvent avec le filtrage par DNS, il y a surblocage, on ne peut pas regarder la page d'accueil du service DoubleClick, par exemple.
  • Il y a aussi sous-blocage : la liste des noms de domaines bloqués (et que Free ne communique pas à ses clients, ce qui est tout à fait anormal) n'est jamais complète et des publicités échapperont donc à ce filtre.
  • Le panneau de contrôle de la Freebox v6 (pas celui du compte Free) permet de désactiver ce filtrage (qui était activé par défaut à l'origine). J'ai testé et le DNS menteur redevient sincère immédiatement. Mais, de toute façon, il suffit d'utiliser un autre résolveur que celui de Free (au moins pour les systèmes où un tel réglage est possible, par exemple Debian). C'est plus ou moins facile mais cela marche, en tout cas tant que le port 53 n'est pas filtré ou détourné.

À noter qu'une façon de ne pas utiliser les résolveurs menteurs de Free est d'avoir son propre résolveur. Dans ce dernier cas, le conseil donné en général (et mis en œuvre automatiquement par des logiciels comme dnssec-trigger) est d'utiliser les résolveurs du FAI comme forwarders, afin de profiter du cache partagé et d'épargner ainsi les serveurs faisant autorité. Ce conseil n'est plus bon si le forwarder est un menteur, puisqu'il peut alors empoisonner le résolveur local.

Une autre façon de contourner les résolveurs menteurs de Free est... d'utiliser les résolveurs de Free. Les vrais résolveurs, pas le relais/cache dnsmasq de la Freebox, disent la vérité. Regardons ceux annoncés avec les RA (Router Advertisment) du RFC 8106) :

% drill @2a01:e00::1  A doubleclick.net
...
doubleclick.net.	1632	IN	A	70.32.146.212

Et avec ceux qui sont utilisés par les Freebox v5 :

% drill @212.27.40.241  A doubleclick.net
...
doubleclick.net.	1800	IN	A	70.32.146.212

C'est donc bien dans la Freebox que se trouve la fonction menteuse.

Quelques lectures pour approfondir le sujet. D'abord, sur les aspects techniques :

Sur les aspects politiques et économiques :


L'article seul

RFC 1958: Architectural Principles of the Internet

Date de publication du RFC : Juin 1996
Auteur(s) du RFC : Brian E. Carpenter (CERN, European Laboratory for Particle Physics)
Pour information
Première rédaction de cet article le 2 janvier 2013


Ce très court RFC posait en 1996 les bases de l'architecture de l'Internet... longtemps après que celui-ci soit largement déployé. C'est une application du principe « faire tourner d'abord, documenter après » qui a été justement un des principes fondamentaux de l'Internet.

Ce document est surtout une synthèse de deux articles essentiels, celui de David Clark, « The Design Philosophy of the DARPA Internet Protocols » (Proc SIGCOMM 88, ACM CCR Vol 18, Number 4, August 1988) et celui de J.H. Saltzer, D.P. Reed et David Clark, « End-To-End Arguments in System Design » (ACM TOCS, Vol 2, Number 4, November 1984) qui expose très bien les raisons pour lesquelles il ne faut pas de réseau intelligent et pourquoi tout le travail difficile doit être fait aux extrémités, dans les machines terminales.

Ce RFC 1958 affiches des ambitions modestes : son but était de décrire les principes fondamentaux de l'architecture de l'Internet or, dès le résumé, le RFC note que l'Internet n'a pas été bâti en suivant des grands principes, mais a évolué. Cette capacité à évoluer a fait son succès et tout texte sur les principes ne peut donc être qu'un cliché momentané, pas un texte sacré de principes immuables.

En 1996, date de publication du RFC, la capacité de l'épine dorsale du réseau avait été multipliée par 1 000 depuis les débuts d'ARPANET et son nombre de machines par 1 000 000. Depuis, ces chiffres ont évidemment encore augmenté. Face à de tels changements quantitatifs, il faut s'attendre à ce que les principes qualitatifs aient également changé. Comme le note le RFC « la seule constante de l'Internet, c'est le changement ». On est loin des beaux plans académiques tellement jolis sur le papier mais jamais mis à l'épreuve des faits. L'Internet, comme un être vivant (la comparaison est de moi, elle n'est pas dans le RFC), n'a pas été conçu par un démiurge parfait et c'est pour cela qu'il est si réussi.

La comparaison qu'utilise le RFC est celle d'une ville : de même qu'on ne peut pas détruire une ville pour la refaire « en mieux », on ne peut pas refaire l'Internet de zéro. La ville change tout le temps mais n'a jamais été conçue à partir de zéro (contrairement à ce que voudraient faire aujourd'hui les raseurs de table).

Le RFC appelle donc à la prudence : il est difficile de prévoir le futur. Et à l'humilité. À noter qu'il ne suit pas toujours ses propres règles. Ainsi, la section 1 parle sans hésiter du « besoin de qualité de service », besoin qui, en 2013, est toujours aussi flou (cf. RFC 5290).

La section 2 commence la liste des principes, après avoir répondu à ceux qui disent, en n'exagérant qu'à moitié, qu'il n'existe pas d'architecture de l'Internet, juste des traditions. Les premiers principes (section 2.1) : la connectivité est un but en soi (contrairement aux experts qui expliquaient doctement qu'il ne servait à rien d'avoir des tuyaux sans contenus, ou aux marketeux qui s'obstinaient à vendre des applications intégrées, et pas juste de la connectivité), l'outil principal d'interconnexion est IP et les fonctions un tant soi peu avancées doivent être dans les extrémités, pas dans le réseau. La connectivité est un but en soi car ce sont les utilisateurs du réseau qui fourniront contenu et applications. (Mon avis est que ceux qui disent le contraire sont ceux qui voudraient verrouiller l'usage de l'Internet en définissant les usages qu'on peut en faire.)

À l'époque de ce RFC, Internet était récemment devenu un réseau mono-protocole, tout fonctionnait avec IPv4. Quelques années auparavant, de nombreux concurrents (de DECnet à UUCP) existaient encore. Depuis, l'Internet est redevenu multi-protocoles, avec IPv6. Notre RFC estime (section 2.2) qu'il ne devrait y avoir qu'un seul protocole au niveau 3, sauf lors d'une transition vers une nouvelle version (le cas actuel) ou si un nouveau protocole est franchement meilleur (personne n'a encore proposé un tel protocole).

La section 2.3 expose et défend le fameux principe de bout en bout. Ce principe dit que, toutes les fois où on hésite sur le meilleur endroit pour placer une fonction, on doit la mettre dans les machines terminales et pas dans le réseau. Une des principales justifications de ce principe est qu'il permet à une session en cours de survivre à un redémarrage du réseau, puisque les routeurs ne conservent pas d'état. C'est pour cela que le datagramme est meilleur que le circuit.

Bien sûr, les équipements du réseau ont quand même un état : le routeur connait les routes actuelles, par exemple, et il a un cache ARP. Mais cet état doit être auto-réparable : au cas où le routeur redémarre, il doit pouvoir reconstituer son état seul, et que les applications qui l'utilisaient continuent comme si rien ne s'était passé.

Ce principe de bout en bout est également crucial pour la sécurité : une application ne doit pas avoir à faire confiance au réseau (même si le RFC ne le dit pas, l'attaquant peut être le FAI), elle doit pouvoir assurer sa propre sécurité (point traité dans la section 6.2).

Une opinion au passage : ce principe de bout en bout a un autre avantage, bien plus important mais peu mentionné dans le RFC. Ce principe permet l'innovation. Aucun routeur, aucun câble sous-marin n'a dû être modifié pour permettre des inventions comme le Web (apparu quelques années avant ce RFC). Si l'Internet avait été géré par des technocrates français, il aurait fallu réunir une commission avant l'introduction de toute nouvelle application, et le Web n'aurait jamais été déployé. Il n'est donc pas étonnant que le principe de bout en bout soit surtout combattu par ceux qui regrettent le bon temps où le même groupe de technocrates concevait le réseau et toutes les applications.

Depuis la publication de ce RFC, ce principe de bout en bout est aujourd'hui très sérieusement remis en cause par la multiplication des middleboxes, routeurs NAT, pare-feux et autres engins qui, volontairement ou parce qu'ils ont été programmés avec les pieds, bloquent aujourd'hui de nombreuses possibilités du modèle de bout en bout (par exemple, déployer un nouveau protocole de transport comme SCTP est devenu quasiment impossible).

Une des rares incursions de ce RFC dans la politique est en section 2.4 : personne n'est propriétaire de l'Internet, personne ne peut l'éteindre. Et c'est une bonne chose (même si c'est parfois agaçant).

La section 3 porte sur tout un tas de problèmes de conception d'un grand réseau mondial. Par exemple, il est essentiel de penser au passage à l'échelle (section 3.3). Et de ne pas seulement regarder les fonctions offertes par le réseau mais aussi leur coût (section 3.4), en euros et en performance (un certain nombre de plans alternatifs promettent beaucoup mais oublient de chiffrer les conséquences). Plus généralement, le mieux est l'ennemi du bien : il vaut mieux une solution partielle que d'attendre une solution parfaite et complète (section 3.7).

La longue expérience des praticiens de l'Internet au moment de la publication de ce RFC a aussi mené à d'autres principes : par exemple, que les réglages manuels sont une source d'ennuis sans fin et qu'il faut donc que tout soit automatique (section 3.8). Et il faut éviter les dépendances circulaires (section 3.11), par exemple que le routage dépende du DNS puisque celui-ci dépend du routage... (Des techniques comme Rover ont été critiquées pour cela, pas forcément à juste titre).

C'est dans cette section que le RFC 1958 rappelle un principe souvent cité et souvent discuté, le principe de robustesse (section 3.9). Présent bien avant (je crois que le premier RFC qui le citait explicitement est le RFC 791), il est ici défini comme « soyez strict en envoyant et tolérant en recevant ». L'idée est qu'un programme a intérêt à coller aux moindres détails de la spécification lorsqu'il envoie des données (pour maximiser les chances d'être compris) mais à interpréter cette spécification de manière ouverte lorsqu'il reçoit des données (permettre que le réseau fonctionne est plus important que de pinailler sur la qualité de l'implémentation d'en face).

Et le dernier principe de cette nouvelle section : on ne normalise pas tant qu'on n'a pas deux mises en œuvre distinctes d'un protocole (section 3.14). Notez bien que ce n'est qu'un principe, pas une loi et qu'en pratique, celui-ci est loin d'être toujours respecté.

La section 4 est consacrée aux questions, toujours chaudement disputées, du nommage et de l'adressage. Elle pose des principes comme (section 4.1) d'utiliser des noms plutôt que des adresses (pour leur stabilité), et n'avoir qu'un seul espace de nommage (section 4.2, qui fait écho au RFC 2826).

Plus rétrograde, le principe 4.3 qui demande que les noms soient uniquement en US-ASCII. Aujourd'hui, où les IDN existent et sont utilisés depuis longtemps, cela sent son époque...

La section 5 porte sur les questions non strictement techniques : acceptation des technologies brevetées (section 5.1), ne pas tenir compte des restrictions à l'exportation (section 5.2, un problème typique des années 1990 où la diffusion des logiciels de cryptographie était bien plus dure qu'aujourd'hui). Il y a aussi un principe (section 5.4) sur l'importance de n'utiliser que des techniques complètement internationalisées, ce qui est franchement contradictoire avec le principe 4.3...


Téléchargez le RFC 1958


L'article seul

Articles des différentes années : 2024  2023  2022  2021  2020  2019  2018  Précédentes années

Syndication : Flux Atom avec seulement les résumés et Flux Atom avec tout le contenu.

Un article de ce blog au hasard.