Je suis Charlie

Autres trucs

Accueil

Seulement les RFC

Seulement les fiches de lecture

Mon livre « Cyberstructure »

Ève

Les RFC (Request For Comments) sont les documents de référence de l'Internet. Produits par l'IETF pour la plupart, ils spécifient des normes, documentent des expériences, exposent des projets...

Leur gratuité et leur libre distribution ont joué un grand rôle dans le succès de l'Internet, notamment par rapport aux protocoles OSI de l'ISO organisation très fermée et dont les normes coûtent cher.

Je ne tente pas ici de traduire les RFC en français (un projet pour cela existe mais je n'y participe pas, considérant que c'est une mauvaise idée), mais simplement, grâce à une courte introduction en français, de donner envie de lire ces excellents documents. (Au passage, si vous les voulez présentés en italien...)

Le public visé n'est pas le gourou mais l'honnête ingénieur ou l'étudiant.


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

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 9562).

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

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 9558).

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

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

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

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

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

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

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

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

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

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 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 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 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 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 6940: REsource LOcation And Discovery (RELOAD) Base Protocol

Date de publication du RFC : Janvier 2014
Auteur(s) du RFC : C. Jennings (Cisco), B. Lowekamp (Skype), E. Rescorla (RTFM, Inc.), S. Baset, H. Schulzrinne (Columbia University)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF p2psip
Première rédaction de cet article le 17 janvier 2014


Le groupe de travail IETF p2psip travaille à permettre la communication (par exemple téléphonique) entre utilisateurs de SIP sans passer par un fournisseur SIP, mais en se débrouillant en pair-à-pair. Pour cela, le groupe a choisi une approche modulaire et a d'abord développé un protocole de communication pair-à-pair, qui va servir de socle aux futures utilisations. Ce protocole se nomme RELOAD (pour REsource LOcation And Discovery), et fait l'objet de ce très long RFC, le premier du groupe p2psip.

L'enjeu est d'importance : le système fermé Skype a obtenu beaucoup d'utilisateurs en s'appuyant partiellement sur des techniques pair-à-pair. Le SIP traditionnel, où deux correspondants ne communiquent que via leurs fournisseurs SIP respectifs devait être amélioré en exploitant ces capacités pair-à-pair. Échanger des paquets RTP directement est facile. Se trouver et initier la communication l'est moins. Pour le faire en pair-à-pair, il n'existait pas de protocole ouvert et normalisé. On notera d'ailleurs que RELOAD est le premier protocole pair-à-pair (au sens moderne parce que, objectivement, IP a toujours été pair-à-pair) normalisé par l'IETF.

RELOAD est suffisemment général pour pouvoir être utilisé dans le futur par d'autres systèmes que SIP. Qu'est-ce qu'il fournit comme service que les autres protocoles existants ne fournissaient pas ?

  • Une gestion de la sécurité, avec un serveur central d'inscription qui laisse entrer (ou pas) les pairs. Si vous pensez qu'un tel serveur n'est pas pair-à-pair, vous avez raison. Si vous pensez qu'on peut s'en passer, vous avez tort.
  • La possibilité d'être utilisé par des applications différentes (par exemple SIP et XMPP),
  • Des fonctions de passage à travers les NAT (un point pénible pour SIP et ses équivalents),
  • La possibilité d'utiliser plusieurs algorithmes pour la gestion de l'overlay (le réseau virtuel entre les pairs). Le pair-à-pair est en effet un domaine encore relativement récent et il serait imprudent de croire qu'on connait le bon algorithme d'overlay et qu'on peut ignorer tous les autres. RELOAD permet des réseaux structurés (comme les DHT) et des non structurés. À des fins d'interopérabilité, RELOAD impose la possibilité d'utiliser la classique DHT Chord (ainsi, deux mises en œuvre de RELOAD sont sûres d'avoir au moins un algorithme en commun) mais permet aux overlays d'en utiliser d'autres. La section 3.5 détaille cette particularité de RELOAD. Les systèmes possibles sont stockés dans un registre IANA.
  • Une distinction entre pairs et clients, qui permet de profiter de RELOAD sans y participer comme pair. Le même protocole est utilisé (section 3.2 pour les détails). L'annexe B du RFC explique plus en détail pourquoi on autorise les « simples » clients, notamment parce que certaines machines n'ont pas assez de ressources pour assurer les tâches (routage et stockage) d'un pair (machines sur batterie, par exemple).

Si vous voulez vous cultiver sur Chord, l'article original est « Chord: A Scalable Peer-to-peer Lookup Protocol for Internet Applications » (IEEE/ACM Transactions on Networking Volume 11, Issue 1, 17-32, Feb 2003, 2001) et Wikipédia en anglais a un bon article.

Une instance RELOAD est donc un overlay (un réseau virtuel utilisant un algorithme donné) où chaque nœud (pair ou simple client) a un identificateur, le Node-ID. Cet overlay forme un graphe où tout nœud n'a pas forcément directement accès à tout autre nœud, et les pairs doivent donc se préparer à router les messages (les simples clients en sont dispensés).

L'instance RELOAD offre deux services, la transmission de messages et le stockage de données (données de petite taille, a priori, celles nécessaires à la communication). Chaque donnée a un identificateur, le Resource-ID, qui utilise le même espace de nommage que les Node-ID. Il y a ensuite une relation entre les Node-ID et les Resource-ID par exemple, qu'un nœud est responsable de toutes les données dont le Resource-ID est compris entre son Node-ID et le Node-ID précédent (si vous connaissez les DHT, ce genre de concept vous est familier. Sinon, cela peut être le moment de s'arrêter pour lire des choses sur les DHT.) La relation exacte dépend de l'algorithme d'overlay utilisée. Celle donnée en exemple est valable pour Chord.

Pour accomplir ses tâches, RELOAD a plusieurs composants. De haut en bas (si cela ressemble au modèle en couches, c'est exprès, sauf que ces couches sont entassées sur l'overlay, pas sur un réseau physique) :

  • L'application, par exemple SIP (la liste des applications est dans un registre IANA).
  • Un composant de transport des messages, qui assure des fonctions comme la fiabilité de bout en bout. Ce composant permet donc d'envoyer un message de n'importe quel pair de l'overlay à n'importe quel autre.
  • Un composant de stockage des données.
  • Un greffon de gestion de la topologie. RELOAD utilise le terme de topology plugin, pour mettre en avant le fait qu'il est modifiable : on peut remplacer le greffon par défaut, qui utilise Chord, par un autre.
  • Un composant de gestion des liens entre pairs, qui s'occupera notamment du difficile problème de la traversée des NAT, grâce à ICE (RFC 8445 et section 6.5.1.3).
  • Et plusieurs composants de transport sur les liens, entre deux pairs. Un exemple est un composant utilisant TLS (RFC 5246) sur TCP. Un autre composant au même niveau pourrait être DTLS (RFC 6347) sur UDP. Contrairement au composant de transport des messages, le premier cité, qui avait une responsabilité de bout en bout, ces composants de transport sur un lien ne sont responsables que d'envoyer des octets d'un pair à un pair voisin (voisin dans l'overlay, pas du point de vue IP...)

La sécurité est traditionnellement le point faible des DHT (et du pair-à-pair en général). (Voir l'excellent exposé d'Eric Rescorla.) Le principe de base de la sécurité de RELOAD est que chaque pair aura un certificat délivré par une instance centrale (qui ne sera responsable que de l'inscription des pairs : elle ne participera ni au routage, ni à l'envoi des messages, ni au stockage,). Chaque message, et chaque objet stocké, sera signé avec ce certificat et toutes les communications de bas niveau chiffrées (par exemple avec TLS). Une machine qui veut rejoindre l'overlay doit se connecter en HTTPS au serveur central, qui lui attribuera un Node-ID (dans le champ subjectAltName du certificat RFC 5280). Le serveur central demandera probablement une authentification (par exemple nom et mot de passe). Ce serveur et les vérifications qu'il fait sont le cœur de la sécurité de RELOAD. La machine joindra ensuite le réseau virtuel (les détails sur la façon dont elle le fait dépendent de l'algorithme utilisé pour le maintien de l'overlay).

Ne vous inquiétez pas forcément de ces obligations de sécurité : elles ne sont valables que pour un overlay installé sur le grand Internet public. Si vous avez un environnement restreint et sécurisé (disons un groupe de machines formant un réseau ad hoc local), vous avez le droit de vous en dispenser et de vous contenter de certificats auto-signés par les pairs, où le Node-ID est simplement un condensat de la clé publique. Une telle façon de fonctionner laisse le réseau très vulnérable aux attaques Sybil mais peut convenir si vous savez que vous êtes « entre vous ». Autre possibilité de simplification de la sécurité : RELOAD a un mode où les pairs s'authentifient, non pas par un certificat, mais par un secret partagé (par exemple RFC 4279).

Voici donc les grands principes de RELOAD. Je ne vais pas ensuite détailler les 186 pages du RFC, juste quelques points que je trouve intéressants. Le mécanisme de routage est présenté en section 3.3. Par défaut, RELOAD utilise du récursif symétrique (section 6.2). La requête enregistre les nœuds par lesquels elle est passée (dans la Via List) et la réponse suivra le même chemin en sens inverse. Si la topologie a changé entre-temps, la réponse sera perdue et ce sera aux couches supérieures de réémettre. (Il existe une alternative à ce stockage du chemin dans le message lui-même : si les pairs intermédiaires peuvent stocker des données, ils peuvent garder la mémoire des routes suivies, au lieu d'utiliser la Via List.)

L'inscription initiale dans l'overlay est un problème intéressant, car on voudrait que cela soit simple pour l'utilisateur, par exemple qu'il n'ait pas à rentrer 50 paramètres dans son client SIP. L'idée est que le nouveau pair n'a à connaître que le nom de l'overlay (un FQDN) et peut-être des informations d'authentification. Une requête SRV dans le DNS à partir du nom du réseau (précédé de _reload-config._tcp) donne le nom du serveur de configuration, qu'on contacte en HTTPS en lui demandant la ressource .well-known/reload-config (RFC 8615 pour .well-known). Ce serveur envoie alors tous les détails de configuration de l'overlay, en XML, un exemple figure en section 11 et à la fin de cet article. (Une machine peut aussi avoir cette configuration dans un fichier local.) C'est alors que le futur pair connait le nom du serveur d'inscription et peut le contacter pour apprendre son Node-ID.

Le stockage pair-à-pair dans RELOAD (section 4.1) permet de stocker différents types (kind) d'objets. Un type peut être défini comme stockant un scalaire, un tableau ou un dictionnaire (section 7.2 pour les détails). Tous les objets stockés sont signés par le déposant, qui pourra ainsi vérifier que ses pairs ne se sont pas moqués de lui. (Voir mon article « Assurer l'authenticité des données stockée dans une DHT».) À noter qu'un pair ne peut pas stocker des objets sous des noms arbitraires. Typiquement (cela dépend de l'application), il ne peut stocker que sous son propre nom (alice@example.com pour du SIP), ce qui fait qu'il ne pourra pas noyer tous les nœuds de la DHT sous des objets à stocker.

Une des choses les plus nécessaires pour communiquer en pair-à-pair est la découverte. Trouver quelqu'un ou quelque chose dans l'immensitude de l'Internet est difficile (alors que c'est trivial en centralisé, d'où le succès de services comme Facebook). Il existe actuellement plusieurs Internet-Drafts décrivant de futurs services de découverte qui tourneront au dessus de RELOAD.

Le format des messages RELOAD est décrit en section 6.3 : format binaire, avec les premiers en-têtes, qui sont obligatoires, à une position fixe (pour une analyse plus rapide) et les suivants, qui sont optionnels, encodés en TLV (pour la souplesse et l'extensibilité). Chaque message est auto-suffisant, un peu comme un datagramme. Sa première partie, le Forwarding Header, est la seule qui ait besoin d'être examinée par les routeurs intermédiaires. Les deux autres, le Message Content et le Security Block (les signatures), ne concernent que la machine de destination.

Notre RFC utilise une syntaxe analogue à celle du C pour décrire le format des messages (un peu comme le fait le RFC 5246). Principal point à noter pour lire cette syntaxe (la section 6.3.1 fournit tous les détails) : les termes entre chevrons sont des valeurs de taille variable. Par exemple data<0..15> désigne de zéro à quinze octets de données.

Le Forwarding Header contient les Via Lists vues plus haut et les destinations (la plupart du temps, il n'y en a qu'une seule mais RELOAD permet d'indiquer une liste de destinations à parcourir successivement : pour comparer avec le datagramme IP, disons que la liste des destinations est une fusion de l'adresse IP de destination et de l'option Source route). Cela donne :

 struct {
          ...
          uint32             overlay; /* Un condensat du nom */
          ...
          uint8              ttl;
          ...
          uint32             length;
          ...
          uint16             via_list_length; /* Pour le routage
	  symétrique */
          uint16             destination_list_length;
          ...
          Destination        via_list[via_list_length];
          Destination        destination_list
                               [destination_list_length];
          ...
        } ForwardingHeader;

Pour cet en-tête, qui doit être lu très vite par les routeurs intermédiaires, RELOAD utilise l'encodage {longueur, tableau}. Les autres termes de longueur variable utiliseront un encodage moins rapide à analyser mais plus propre. Le type Destination est, en résumant, un Node ID ou Resource ID (rappelez-vous que ces ID ont la même forme - dépendante du type d'overlay - et sont tirés du même espace).

La deuxième partie du message, Message Content, est largement opaque :


struct {
     uint16                 message_code;
     opaque                 message_body<0..2^32-1>;
     MessageExtension       extensions<0..2^32-1>;
   } MessageContents;

C'est donc surtout une suite d'octets, 2^32 au maximum. Le code indique la sémantique du message (demande de stockage de données, « ping », annonce d'un nouveau pair, etc) et la liste des codes est dans un registre IANA.

La troisième et dernière partie du message, le Security Block, est une liste de certificats X.509 et une signature :


struct {
      GenericCertificate certificates<0..2^16-1>;
      Signature          signature;
   } SecurityBlock;

Tous les messages doivent être signés et les signatures vérifiées à la réception.

Les responsabilités du greffon de gestion de la topologie figurent dans la section 6.4. Elles sont décrites sous forme de messages abstraits, à incarner pour chaque algorithme d'overlay. Un exemple, le message Join lorsqu'un nouveau pair arrive :


struct {
            NodeId                joining_peer_id;
            opaque                overlay_specific_data<0..2^16-1>;
         } JoinReq;

Les protocoles de communication entre deux nœuds devront fournir des mécanimes d'authentification du Node ID, d'intégrité et de confidentialité, par exemple en s'appuyant sur TLS (section 6.6.1). Le RFC suggère d'explorer la possibilité d'utiliser HIP (RFC 7401 et section 6.6.1.1) qui a toutes les propriétés voulues. Ils doivent aussi respecter les principes du RFC 8085, i.e. ne pas noyer les destinataires sous les retransmissions.

Le stockage des données fait l'objet de la section 7. On stocke des objets qui ont cette forme :

 struct {
          uint32                  length;
          uint64                  storage_time;
          uint32                  lifetime;
          StoredDataValue         value;
          Signature               signature;
        } StoredData;

On voit qu'ils sont signés, et ont une durée de vie maximale.

On l'a dit, RELOAD utilise par défaut la DHT Chord et toutes les mises en œuvre de RELOAD doivent connaître Chord, pour assurer l'interopérabilité. Le mécanisme utilisé par RELOAD est légèrement différent du Chord original et la section 10 détaille ces différences. Les deux principales :

  • Chord ne permettait qu'un seul prédécesseur et un seul successeur par nœud, alors que plusieurs sont possibles avec Chord-RELOAD,
  • Le routage dans Chord était itératif (le nœud de départ devait contacter directement celui d'arrivée, les autres pairs ne servaient qu'à indiquer où le trouver), il est devenu récursif (les autres pairs transmettent le message, difficile de faire autrement avec les NAT). L'annexe A du RFC discute en détail les raisons de ce choix.

Les grands principes de Chord sont gardés : nœuds organisés en un anneau (le dernier nœud dans l'ordre des Node ID est donc le précédesseur du premier), utilisation de SHA-1 (tronqué aux 128 premiers bits dans Chord-RELOAD) pour trouver le Resource ID à partir des données, table de routage composée, non seulement des voisins immédiats, mais aussi de pointeurs (les fingers) vers un certain nombre de non-voisins (pour des raisons de performance, car cela évite de parcourir la moitié de l'anneau, mais aussi de résilience, pour survivre à la perte des voisins), etc

Un exemple de fichier de configuration d'un réseau virtual (overlay) figure en section 11 :


<overlay>
      <configuration instance-name="overlay.example.org" sequence="22"
          expiration="2002-10-10T07:00:00Z" ext:ext-example="stuff" >
          <!-- Le greffon de topologie par défaut : -->
          <topology-plugin>CHORD-RELOAD</topology-plugin>
          <!-- Le certificat qui va signer tout : -->
          <root-cert>
              MIIDJDCCAo2gAwIBAgIBADANBgkqhkiG9w0BAQUFADBwMQswCQYDVQQGEwJVUzET...
          </root-cert>
          <!-- Les serveurs à contacter pour avoir Node-ID et
	  certificat : -->
          <enrollment-server>https://example.org</enrollment-server>
          <enrollment-server>https://example.net</enrollment-server>
          <!-- Les pairs à contacter pour rejoindre l'overlay : -->
          <bootstrap-node address="192.0.0.1" port="6084" />
          <bootstrap-node address="192.0.2.2" port="6084" />
          <bootstrap-node address="2001:db8::1" port="6084" />
          <!-- Les paramètres spécifiques à la DHT : -->
          <chord:chord-update-interval>
              400</chord:chord-update-interval>
          <chord:chord-ping-interval>30</chord:chord-ping-interval>
          <chord:chord-reactive>true</chord:chord-reactive>
         <!-- Et bien d'autres choses encor... -->
    </overlay>

6084 est le port par défaut pour RELOAD (section 14.2). La grammaire pour ce fichier de configuration est normalisée (en Relax NG) en section 11.1.1.

Pour contacter les serveurs d'inscription (enrollment server), le protocole à utiliser est en section 11.3. L'IETF a choisi de ne pas réutiliser les protocoles existants (RFC 5272 et RFC 5273) car ils sont trop complexes. À la place, le futur pair fait juste une requête HTTPS POST dont le contenu comprend du PKCS#10 (contenant la demande de certificat, cf. RFC 2311). Cette requête doit aussi contenir les informations d'authentification du pair (par exemple un nom et un mot de passe). En échange, le serveur enverra un certificat dont le sujet (le nom) sera un Node ID, choisi au hasard (RFC 4086 ; c'est important car certaines attaquent contre les DHT nécessitent que l'attaquant choisisse son Node ID). En outre, le champ subjectAltName doit contenir le nom que l'utilisateur sera autorisé à présenter à l'application (pour SIP, ce sera un nom de type machin@truc.example). Certaines autorisations (par exemple d'accès aux données stockées) dépendront de ce nom.

La faiblesse traditionnelle des DHT (ou du pair-à-pair en général) est la sécurité (RFC 5765). Sans chef pour contrôler les échanges, que faire si un méchant s'insère dans le réseau pair-à-pair pour l'espionner, modifier les données, ou bien empêcher le réseau de fonctionner ? La section 13 revient en détail sur les questions de sécurité. Le fond du problème est qu'on dépend des pairs (pour envoyer des messages à d'autres pairs ou bien pour stocker des données) et qu'on n'a pas de relation bien définie avec ces pairs. Sur un réseau public comme l'Internet, les pairs peuvent être n'importe qui, y compris des méchants. Si la majorité des pairs sont dans ce cas, on est fichu, aucun algorithme astucieux ne peut marcher dans ces conditions. Il faut donc agir sur l'inscription (enrollment). C'est ce que fait RELOAD (section 13.3) en imposant le passage par un serveur d'inscription pour obtenir un certificat, puis en imposant de prouver la possession d'un tel certificat (en signant les messages avec la clé).

RELOAD permet des certificats auto-signés mais, dans ce cas, l'overlay peut être vite noyé sous les pairs malveillants (ce qu'on nomme une attaque Sybil). La seule sécurité qui reste est le Node ID (qui est dérivé du certificat et est donc cryptographiquement vérifiable). Bref, une telle sécurité ne convient que dans des environnements fermés, où on est sûr de toutes les machines présentes. Un exemple typique est un réseau ad hoc entre les machines des participants à une réunion (et encore, en Wifi, attention à l'attaquant de l'autre côté du mur...). Dans ce cas, on peut même se passer complètement des certificats en choisissant la solution du secret partagé : on le distribue à tous les participants à la réunion et ça roule (section 13.4).


Téléchargez le RFC 6940


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 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 9300), 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 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 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 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 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 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 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 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 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

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

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

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

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

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

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

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

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

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

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

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

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 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 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 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 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 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 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 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 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 6844: DNS Certification Authority Authorization (CAA) Resource Record

Date de publication du RFC : Janvier 2013
Auteur(s) du RFC : P. Hallam-Baker (Comodo), R. Stradling (Comodo)
Chemin des normes
Première rédaction de cet article le 31 août 2017
Dernière mise à jour le 26 octobre 2017


Ce RFC a quelques années mais n'avait connu que peu de déploiement effectif. Cela va peut-être changer à partir du 8 septembre 2017, où les AC ont promis de commencer à vérifier les enregistrements CAA (Certification Authority Authorization) publiés dans le DNS. Ça sert à quoi ? En gros, un enregistrement CAA publié indique quelles AC sont autorisées à émettre des certificats pour ce domaine. Le but est de corriger très partiellement une des plus grosses faiblesses de X.509, le fait que n'importe quelle AC peut émettre des certificats pour n'importe quel domaine, même si ce n'est pas un de ses clients. Notez qu'il a depuis été remplacé par le RFC 8659.

C'est donc une technique très différente de DANE (RFC 6698), les seuls points communs étant l'utilisation du DNS pour sécuriser les certificats. DANE est déployé chez le client TLS, pour qu'il vérifie le certificat utilisé, CAA est surtout dans l'AC, pour limiter le risque d'émission d'un certificat malveillant (par exemple, CAA aurait peut-être empêché le faux certificat Gmail du ministère des finances.) Disons que CAA est un contrôle supplémentaire, parmi ceux que l'AC doit (devrait) faire. Les clients TLS ne sont pas censés le tester (ne serait-ce que parce que l'enregistrement CAA a pu changer depuis l'émission du certificat, la durée de vie de ceux-ci étant en général de plusieurs mois). CAA peut aussi servir à des auditeurs qui veulent vérifier les pratiques d'une AC (même avertissement : le certificat a pu être émis alors que l'enregistrement CAA était différent.)

La section 3 de notre RFC présente l'enregistrement CAA (la syntaxe détaillée est en section 5). Il a été ajouté au registre des types d'enregistrements sous le numéro 257. Il comprend une série d'options (flags) et une propriété qui est sous la forme {clé, valeur}. Un nom peut avoir plusieurs propriétés. Pour l'instant, une seule option est définie (un registre existe pour les options futures), « issuer critical » qui indique que cette propriété est cruciale : si on ne la comprend pas, le test doit être considéré comme ayant échoué et l'AC ne doit pas produire de certificat.

Les propriétés possibles sont, à l'heure actuelle (d'autres pourront être ajoutée dans le registre IANA) :

  • issue, la principale, qui indique une AC autorisée à émettre des certificats pour ce domaine (l'AC est indiquée par son nom de domaine),
  • issuewild, idem, mais avec en plus la possibilité pour l'AC d'émettre des certificats incluants des jokers,
  • iodef, qui indique où l'AC doit envoyer d'éventuels rapports d'échec, pour que le titulaire du nom de domaine puisse les corriger. Un URL est indiqué pour cela, et le rapport doit être au format IODEF (RFC 7970).

Voici par exemple quel était l'enregistrement CAA de mon domaine personnel :


% dig CAA bortzmeyer.org
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 61450
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 3, AUTHORITY: 7, ADDITIONAL: 7
...
;; ANSWER SECTION:
bortzmeyer.org.		26786 IN CAA 0 issue "cacert.org"
bortzmeyer.org.		26786 IN CAA 0 issuewild "\;"
...

  

Il indique que seule l'AC CAcert peut créer un certificat pour ce domaine (et sans les jokers). Bon, c'est un peu inutile car CAcert ne teste pas les enregistrements CAA, mais c'était juste pour jouer. Je n'ai pas mis d'iodef mais il aurait pu être :

bortzmeyer.org. CAA 0 iodef "mailto:security@bortzmeyer.org"
  

Et, dans ce cas, l'AC peut écrire à security@bortzmeyer.org, avec le rapport IODEF en pièce jointe.

Attention, l'enregistrement CAA est valable pour tous les sous-domaines (et ce n'est pas une option,contrairement à, par exemple, HSTS du RFC 6797, avec son includeSubDomains). C'est pour cela que j'ai dû retirer l'enregistrement ci-dessus, pour avoir des certificats pour les sous-domaines, certificats faits par une autre AC.

Des paramètres peuvent être ajoutés, le RFC cite l'exemple d'un numéro de client :

example.com.   CAA 0 issue "ca.example.net; account=230123" 
  

Une fois les enregistrements CAA publiés, comment sont-ils utilisés (section 4) ? L'AC est censée interroger le DNS pour voir s'il y a un CAA (on note que DNSSEC est recommandé, mais n'est pas obligatoire, ce qui réduit le service déjà faible qu'offre CAA). S'il n'y en a pas, l'AC continue avec ses procédures habituelles. S'il y a un CAA, deux cas : il indique que cette AC peut émettre un certificat pour le domaine, et dans ce cas-là, c'est bon, on continue avec les procédures habituelles. Second cas, le CAA ne nomme pas cette AC et elle doit donc renoncer à faire un certificat sauf s'il y a une exception configurée pour ce domaine (c'est la deuxième faille de CAA : une AC peut facilement passer outre et donc continuer émettre de « vrais/faux certificats »).

Notez que le RFC ne semble pas évoquer la possibilité d'imposer la présence d'un enregistrement CAA. C'est logique, vu le peu de déploiement de cette technique mais cela veut dire que « qui ne dit mot consent ». Pour la plupart des domaines, la vérification du CAA par l'AC ne changera rien.

Notez que, si aucun enregistrement CAA n'est trouvé, l'AC est censé remonter l'arbre du DNS. (C'est pour cela que SSL [sic] Labs trouve un enregistrement CAA pour mercredifiction.bortzmeyer.org : il a utilisé le CAA du domaine parent, bortzmeyer.org.) Si example.com n'a pas de CAA, l'AC va tester .com, demandant ainsi à Verisign si son client peut avoir un certificat et de qui. Cette erreur consistant à grimper sur l'arbre avait déjà été dénoncée dans le RFC 1535, mais apparemment la leçon n'a pas été retenue.

Enfin, la section 6 du RFC analyse les différents problèmes de sécurité que peut poser CAA :

  • Le respect de l'enregistrement CAA dépend de la bonne volonté de l'AC (et CAA ne remplace donc pas DANE),
  • Sans DNSSEC, le test CAA est vulnérable à des attaques par exemple par empoisonnement (le RFC conseille de ne pas passer par un résolveur normal mais d'aller demander directement aux serveurs faisant autorité, ce qui ne résout pas le problème : le programme de test peut se faire empoisonner, lui aussi, d'autant plus qu'il prend sans doute moins de précautions qu'un résolveur sérieux),
  • Et quelques autres risques plus exotiques.

Comme indiqué au début, le CA/Browser Forum a décidé que le test des CAA serait obligatoire à partir du 8 septembre 2017. (Cf. la décision.) Parmi les rares enregistrements CAA dans la nature, on trouve celui de Google, qui autorise deux AC :


% dig CAA google.com
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 55244
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
...
;; ANSWER SECTION:
google.com.		86400 IN CAA 0 issue "pki.goog"
google.com.		86400 IN CAA 0 issue "symantec.com"
...

  

(Le TLD .goog est apparemment utilisé par Google pour son infrastructure, .google étant plutôt pour les choses publiques.) Notez que gmail.com, lui, pourtant souvent détourné par des gouvernements et des entreprises qui veulent surveiller le trafic, n'a pas d'enregistrement CAA. Le célèbre SSL [sic] Labs teste la présence d'un enregistrement CAA. S'il affiche « DNS Certification Authority Authorization (CAA) Policy found for this domain », c'est bon. Regardez le cas de Google.

Le type CAA est relativement récent (quatre ans quand même), donc il crée des problèmes amusants avec les serveurs DNS bogués comme ceux de BNP Paribas, qui timeoutent lorsque le type demandé n'est pas A :


% dig CAA mabanqueprivee.bnpparibas

; <<>> DiG 9.10.3-P4-Debian <<>> CAA mabanqueprivee.bnpparibas
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 42545
                                       ^^^^^^^^

  

Quelques lectures et ressources pour finir :


Téléchargez le RFC 6844


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

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 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 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 9300, 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 9301) 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 9301) 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 9301), 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 9301. 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 9300, 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 9300). 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 9301), 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 9300, sections 10 et 11 « 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

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. (Ce RFC a depuis été remplacé par le RFC 9301.)

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 (expérimentale, à l'époque), dans un ensemble de RFC dont ce RFC 6830 est le principal. Depuis, il a été remplacé par le RFC 9300.

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 6821: Improving Peer Selection in Peer-to-peer Applications: Myths vs. Reality

Date de publication du RFC : Décembre 2012
Auteur(s) du RFC : E. Marocco, A. Fusco (Telecom Italia), I. Rimac, V. Gurbani (Bell Labs, Alcatel-Lucent)
Pour information
Réalisé dans le cadre du groupe de recherche IRTF PeerToPeerResearchGroup
Première rédaction de cet article le 22 décembre 2012


Le trafic du pair-à-pair peut, on le sait, représenter une bonne part de l'activité d'un réseau, malgré les efforts de l'industrie du divertissement pour diaboliser cette technique. Il y a donc depuis plusieurs années de gros efforts de recherche pour optimiser ce trafic, notammment via l'amélioration de la sélection des pairs. Si je veux télécharger la saison 1 de Being human, et que trois pairs ont les données, auquel demander ? Le bon sens répond « au plus proche ». Mais le concept de « plus proche » est plus flou qu'il n'y parait, et, de toute façon, le logiciel pair-à-pair installé sur ma machine n'a pas forcément accès à toutes les informations nécessaires pour déterminer « le plus proche ». Il existe plusieurs solutions pour résoudre ce problème, mais notre RFC se penche plutôt sur le méta-problème : la sélection des pairs améliore-t-elle les choses ?

Tellement de choses ont été dites à ce sujet que l'ingénieur ou l'étudiant débutant qui se penche sur l'optimisation du pair-à-pair peut avoir une impression de grande confusion. Ce RFC choisit donc l'approche « retours aux faits ». Parmi toute la littérature scientifique et technique existante, peut-on trancher sur la question de l'intérêt de la sélection des pairs ?

Je préviens tout de suite que le titre de ce RFC, inutilement sensationnaliste, ne correspond pas à son contenu : le RFC ne dynamite pas de mythes, il examine un certain nombre de questions posées par la sélection des pairs et, pour chacune, en se basant sur des mesures ou des simulations déjà effectuées et publiées, fait une synthèse de leurs conclusions.

A priori, l'intérêt de la sélection est grand : comme les machines, dans un réseau pair-à-pair, ne connaissent pas la topologie sous-jacente (elles ne savent pas si les pairs sont proches ou lointains, s'ils sont joignables par des liens de peering gratuits ou par du transit payant, etc), elles risquent de ne pas choisir le meilleur pair. Une des conséquences fâcheuses sera l'utilisation d'inter-connexions lointaines, au lieu de rester dans le réseau du FAI. Il est donc logique que cette idée de sélection « intelligente » des pairs ait fait l'objet de nombreux travaux (résumés dans le RFC 6029 ; sinon, voir les articles « Can ISPs and P2P systems co-operate for improved performance? » d'Aggarwal, V., Feldmann, A., et C. Scheidler, ou « Taming the Torrent: A practical approach to reducing cross-ISP traffic in P2P systems » de Choffnes, D. et F. Bustamante, ou encore « P4P: Explicit Communications for Cooperative Control Between P2P and Network Providers » de Xie, H., Yang, Y., Krishnamurthy, A., Liu, Y., et A. Silberschatz) et qu'un groupe de travail de l'IETF, ALTO, travaille entièrement sur ce sujet (voir ses RFC 5693 et RFC 6708). (À noter que j'avais fait un exposé sur ces techniques en 2010.) L'évaluation de ces techniques n'est pas évidente, notamment de leur passage à l'échelle lorsque le réseau comprend des dizaines de millions de pairs.

Notre RFC suit le schéma suivant pour synthétiser la littérature existante :

  • Décrire une croyance (un mythe, dit le RFC, terme très exagéré),
  • Lister les faits (études, mesures, simulations, etc) disponibles,
  • Discuter ces données,
  • Conclure à la véracité ou à la fausseté de la croyance.

Naturellement, cette synthèse n'est valable qu'aujourd'hui : les progrès de la science pourront changer les conclusions. Ah et, sinon, question terminologie, en l'absence d'une norme unique du pair-à-pair, ce RFC utilise largement le vocabulaire de BitTorrent (section 2), comme le terme d'essaim pour désigner un groupe de pairs ayant les données convoitées.

Place maintenant aux croyances et à leur évaluation. La première : « la sélection des pairs permettra de diminuer le trafic entre domaines ». Les différents essais ou simulations montrent des réductions allant de 20 à 80 % (la variation importante donne une idée de la difficulté à estimer cette réduction). 70 % pour la simulation de Xie, H., Yang, Y., Krishnamurthy, A., Liu, Y., et A. Silberschatz déjà citée. 34 % en sortie et 80 % en entrée pour les mesures du RFC 5632. Et jusqu'à 99,5 % si le trafic est fortement localisé (beaucoup de pairs dans le même domaine) selon « Pushing BitTorrent Locality to the Limit » de Stevens Le Blond, Arnaud Legout et Walid Dabbous.

Bref, cette croyance est tout à fait justifiée (comme la plupart de celles citées par le RFC). On peut vraiment espérer une réduction du trafic entre opérateurs.

Cette réduction profite aux opérateurs, qui voient baisser leur facture d'interconnexion. Une autre croyance fait espérer des gains pour les utilisateurs : « la sélection des pairs se traduira par une amélioration des performances », en clair, on attendra moins longtemps pour charger la dernière ISO d'Ubuntu.

Les simulations de Xie, H., Yang, Y., Krishnamurthy, A., Liu, Y., et A. Silberschatz montrent une diminution du temps de transfert de 10 à 23 %. Celles de « Applicability and Limitations of Locality-Awareness in BitTorrent File-Sharing » par Seetharaman, S., Hilt, V., Rimac, I., et M. Ammar (article que je n'ai pas réussi à trouver en ligne et qui ne semble pas avoir été publié « officiellement ») montraient que le gain n'est pas systématique. Les mesures du RFC 5632 indiquent une augmentation du débit de 13 à 85 %. L'expérience de Choffnes, D. et F. Bustamante déjà citée a vu 31 % de gain de débit en moyenne (mais une perte dans certains cas).

La conclusion est donc plutôt « ça dépend ». En général, il y a une amélioration mais dans certains cas (capacité du lien montant faible, peu de pairs disponibles à proximité), on peut voir une dégradation. Donc, la croyance est probablement justifiée mais pas dans tous les cas.

Et l'occupation du lien réseau montant ? Cela pourrait être un effet négatif d'une meilleure sélection des pairs. Ils sont plus proches, donc on envoie plus vite les données, saturant le canal montant, souvent très petit sur les liens asymétriques comme l'ADSL ou DOCSIS. Cette crainte est-elle justifiée ?

Les mesures du RFC 5632 ne montrent pas un tel effet. Théoriquement, cela serait pourtant possible (si la sélection des pairs menait à choisir une machine mal connectée mais proche plutôt qu'une machine lointaine et ayant de fortes capacités réseau, la machine mal connectée verrait son lien montant plus utilisé). Mais, en pratique, cela ne semble pas le cas.

Autre croyance parfois entendue : la sélection des pairs va avoir une influence sur les accords de peering. Ceux-ci sont souvent fondés sur le volume de trafic échangé. Si la sélection des pairs améliore la localité, le trafic entre opérateurs va baisser, le faisant passer en dessous du seuil qu'exigent certains opérateurs pour peerer avec eux. Mais, sur ce point, on ne dispose pas de mesures ou de simulations. On ne peut faire pour l'instant qu'une analyse théorique.

Par exemple, si les deux opérateurs ont une base d'utilisateurs très différente (mettons qu'un opérateur a beaucoup de clients offrant du contenu et l'autre pas du tout), non seulement le trafic entre eux va baisser, mais il peut baisser nettement plus dans une direction que dans l'autre, remettant en cause un accord de peering fondé sur la réciprocité.

Curieusement, le RFC affirme que, si les opérateurs sont très similaires (même base d'utilisateurs, mêmes technologies d'accès), il n'y aura sans doute pas beaucoup de changement. Pourtant, comme indiqué plus haut, la seule baisse du trafic entre eux, même symétrique, peut changer les conditions du peering.

Le RFC rappele que des opérateurs ont déjà tenté d'injecter des paquets vers un autre opérateur, pour obtenir artificiellement des chiffres élevés de trafic, avant de pouvoir demander un peering (« The art of Peering: The peering playbook » de Norton). Ce n'est pas très subtil car ce trafic purement unidirectionnel apparait vite comme suspect. En revanche, avec des techniques de sélection des pairs, le même FAI peu scrupuleux pourrait faire mieux, en redirigeant systématiquement ses utilisateurs vers l'opérateur avec qui il espère négocier un accord de peering, créant ainsi un trafic nettement plus réaliste.

En conclusion (fondée sur un raisonnement purement théorique, contrairement à la grande majorité des croyances étudiées dans ce RFC), il est probable que la sélection des pairs amène à changer les accords de peering.

Et sur le transit, y aura-t-il un impact ? Là aussi, on peut imaginer des transitaires peu scrupuleux qui, en utilisant les techniques de sélection de pairs comme ALTO, redirigeront le trafic vers des clients payants, plutôt que vers des opérateurs pairs gratuits. Là encore, on ne dispose pas d'études à ce sujet. Mais, vue l'importance de la question pour le monde des opérateurs, le RFC recommande que l'on se penche sur la question. Des cas comme Sprint contre Cogent ou Cogent contre AOL illustrent bien l'extrême sensibilité du problème.

Un effet de bord négatif d'une bonne sélection des pairs avait été envisagé dans l'article Stevens Le Blond, Arnaud Legout et Walid Dabbous ci-dessus (mais les mesures faites ne montraient pas cet effet). Si la sélection marche trop bien, l'essaim de pairs va se fragmenter en plusieurs essaims, un par FAI, avec peu de communications entre eux, ce qui annulerait une partie de l'intérêt du pair-à-pair. En effet, les simulations de Seetharaman, S., Hilt, V., Rimac, I., et M. Ammar ont montré que cela pouvait se produire.

Le RFC conclut que l'effet dépend de l'algorithme utilisé. Si BitTorrent semble assez résistant à ce problème, comme montré par les mesures de Stevens Le Blond, Arnaud Legout et Walid Dabbous, d'autres algorithmes peuvent avoir le problème. Et que la croyance peut donc être justifiée dans certains cas. Attention donc, si vous concevez un algorithme de pair-à-pair à ne pas mettre tous vos œufs dans le même panier en ne sélectionnant que des pairs très proches.

Dernière croyance étudiée, celle que des caches P2P chez les FAI, combinés avec la sélection des pairs, va améliorer les choses. Un problème classique de tous les caches réseau est de les trouver, et de ne les utiliser que s'ils apportent réellement un gain. Avec la sélection des pairs, le problème est théoriquement résolu : le cache est un pair comme un autre et est sélectionné s'il est « plus proche ».

Une étude chez un FAI a montré (« Are file swapping networks cacheable? Characterizing p2p traffic » de Nathaniel Leibowitz, Aviv Bergman, Roy Ben-Shaul et Aviv Shavit) que le cache pouvait potentiellement gérer 67 % du trafic pair-à-pair. Cette croyance est donc plausible.


Téléchargez le RFC 6821


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

RFC 6817: Low Extra Delay Background Transport (LEDBAT)

Date de publication du RFC : Décembre 2012
Auteur(s) du RFC : S. Shalunov (BitTorrent Inc), G. Hazel (BitTorrent Inc), J. Iyengar (Franklin and Marshall College), M. Kuehlewind (University of Stuttgart)
Expérimental
Réalisé dans le cadre du groupe de travail IETF ledbat
Première rédaction de cet article le 20 décembre 2012


Alors que tant d'efforts de recherche ont été dépensés pour faire des réseaux informatiques et des protocoles qui permettent d'aller plus vite, d'attendre moins longtemps avant de voir la page d'accueil de TF1, le groupe de travail LEDBAT (Low Extra Delay Background Transport ) de l'IETF travaillait à un tout autre projet : un protocole de transport de données qui aille moins vite, de façon à être un bon citoyen du réseau, à n'utiliser celui-ci que lorsqu'il est vide et qu'on peut donc faire passer ses bits sans gêner personnne. Ce RFC décrit l'algorithme LEDBAT, un algorithme « développement durable ».

LEDBAT n'est donc pas un protocole complet, mais un algorithme de contrôle de la fenêtre de congestion, ce mécanisme par lequel les protocoles de transport évitent de saturer le réseau. Le plus connu et le plus utilisé de ces mécanismes est celui de TCP (RFC 5681) et ses objectifs sont d'utiliser le réseau à fond et d'assurer une relative égalité entre les flots de données qui se concurrencent sur ce réseau. LEDBAT, au contraire, vise avant tout à céder la place aux autre flots, non-LEDBAT.

Mais pourquoi diable voudrait-on être si généreux ? Cela peut être parce qu'on estime les autres flots plus importants : si je télécharge Plus belle la vie pendant que je passe un coup de téléphone via SIP, je souhaite que le téléchargement ne prenne pas de capacité si SIP en a besoin (c'est la différence entre applications d'« arrière-plan » comme le transfert de gros fichiers et d'« avant-plan » comme un coup de téléphone ou une session SSH interactive). Ou bien cela peut être pour profiter de réductions offertes par le réseau : après tout, un routeur ou une fibre optique ne coûtent pas plus cher à l'usage, que les octets circulent ou pas (contrairement à un autoroute ou une voie ferrée). Il serait donc logique que les transports « charognards », comme LEDBAT, qui n'utilisent la capacité réseau que lorsque personne n'en veut, reçoivent une récompense financière, par exemple une réduction des prix (parlez-en à votre FAI).

Pour les détails sur les motivations de LEDBAT et les raisons pour lesquelles des technqiues comme le shaping ne conviennent pas, voir le premier RFC du groupe LEDBAT, le RFC 6297. Ici, je vais me focaliser sur l'algorithme spécifié par LEDBAT et qui répond au cahier des charges : céder la place le plus vite possible.

Le principe de cet algorithme est simple : utiliser les variations du temps de voyage des paquets pour détecter l'approche de la congestion et refermer alors la fenêtre de transmission. TCP utilise essentiellement le taux de pertes de paquets comme indicateur (ou les marques ECN du RFC 3168). Les routeurs ayant des tampons d'entrée-sortie, lorsque la ligne de sortie est saturée, les paquets commencent à s'entasser dans ce tampon. Lorsqu'il est plein, le routeur jette des paquets (et TCP va alors réagir). On voit que l'augmentation du temps de voyage (dû au séjour dans le tampon) précède la perte de paquets. En réagissant dès cette augmentation, LEDBAT atteint son objectif de céder la place à TCP. (À noter qu'il existe des variantes de TCP qui utilisent également le temps de voyage comme indicateur de l'approche de la congestion, par exemple TCP Vegas, documenté dans « TCP Vegas: New techniques for congestion detection and avoidance » de Brakmo, L., O'Malley, S., et L. Peterson, mais voir le RFC 6297 pour un tour d'horizon général.)

Où est-ce que LEDBAT va être mis en œuvre ? Cela peut être dans un protocole de transport, par exemple comme une extension de TCP, ou bien dans l'application. LEDBAT est un algorithme, pas un protocole précis. Il peut être utilisé dans plusieurs protocoles, du moment que ceux-ci permettent l'estampillage temporel des paquets, pour que les deux machines qui communiquent puissent mesurer le temps de voyage (section 4.1).

La section 2 décrit l'algorithme exact. LEDBAT a une fenêtre de congestion, notée cwnd qui indique combien d'octets l'émetteur peut envoyer avant un nouvel accusé de réception. L'émetteur met dans chaque paquet le moment où il a envoyé ce paquet. Le récepteur regarde l'heure, en déduit le temps de voyage (aller simple, puisque l'encombrement n'est pas forcément le même dans les deux sens, une mesure aller-retour ne servirait pas à grand'chose) et retransmet cette indication à l'émetteur. Lorsque celui-ci voit le temps de voyage augmenter (signe que les tampons des routeurs se remplissent), il diminue la fenêtre de congestion. L'émetteur notamment utilise deux paramètres, TARGET et GAIN. TARGET est l'augmentation du temps de voyage en dessous de laquelle LEDBAT ne fait rien. GAIN (qui vaut entre 0 et 1) indique le facteur d'échelle entre l'augmentation du temps de voyage et la réduction de la fenêtre de congestion. Plus il est élevé, plus LEDBAT réagit rapidement et vigoureusement. Un GAIN de 1 est équivalent à TCP Reno. À noter qu'on pourrait avoir deux valeurs de GAIN, une pour augmenter la fenêtre de congestion et une pour la diminuer. En mettant un GAIN plus grand pour la diminution de la fenêtre, on garantit que LEDBAT cédera très vite la place dès le plus petit signal d'un ralentissement. (Pour les amateurs de pseudo-code, une description de l'algorithme avec cette technique figure dans le RFC.)

Bien sûr, le temps de voyage varie pour tout un tas de raisons et il n'est pas forcément souhaitable de refermer la fenêtre de congestion à chaque dérapage. LEDBAT filtre donc les outliers à l'aide d'une fonction FILTER() qui fait partie des paramètres de l'algorithme (elle n'est pas imposée par le RFC, on peut tester plusieurs mécanismes de filtrage des données.) Un filtre sommaire est NULL (aucun filtrage, on accepte toutes les mesures). Un autre plus sophistiqué est EWMA (Exponentially-Weighted Moving Average). Un bon filtre résiste au bruit inévitable, mais reste sensible aux signaux indiquant une vraie congestion.

Le temps de voyage se décompose en temps de transmission sur le câble (qui dépend de la vitesse du médium, par exemple 100 Mb/s pour du Fast Ethernet), temps de propagation (lié à la vitesse de la lumière), temps d'attente dans les tampons et temps de traitement à la destination. Tous ces temps sont constants ou presque, à l'exception du temps d'attente dans les tampons. Ce sont donc ses variations qui déterminent l'essentiel des variations du temps de voyage. Pour estimer ce temps d'attente dans les tampons, LEDBAT calcule un temps de base (section 3.1.1) qui est le temps de voyage minimum observé. Il permet de connaître la valeur minimale en dessous de laquelle le temps de voyage ne pourra pas descendre. Les calculs de fenêtre de congestion se font à partir de (temps de voyage - temps de base), une grandeur qui part donc de zéro (les méthodes du RFC 6298 peuvent être utiles ici). L'algorithme de LEDBAT est linéaire : la fenêtre est réduite ou agrandie proportionnellement à cette grandeur, le facteur de proportionnalité étant le paramètre GAIN. Autre intérêt du concept de temps de base : en cas de changement de la route pendant la session (par exemple, panne d'un lien et re-routage par un chemin plus long), la mesure du temps de base pendant les N dernières secondes permettra de voir que le trajet a changé et que les calculs doivent utiliser le nouveau temps de base. (Le choix de N est un compromis : trop petit et le temps de base va varier souvent, trop grand et il retardera le moment où on détecte un changement de chemin.)

Avec son mécanisme de réduction de la fenêtre de congestion dès que le temps de voyage augmente, LEDBAT ne pousse normalement jamais jusqu'au point où il y aura des pertes de paquets. Néanmoins, celles-ci peuvent quand même survenir, et LEDBAT doit alors se comporter comme TCP, en refermant la fenêtre (section 3.2.2).

La section 4 du RFC discute ensuite de différents points intéressants de LEDBAT. Par exemple, LEDBAT est efficace pour céder rapidement à TCP lorsque celui-ci transfère de grandes quantités de données. Mais cela laisse le problème des applications qui envoient peu de données mais sont très sensibles à la latence, comme la voix sur IP. Si la conversation téléphonique envoie peu de données, il n'y aura jamais de remplissage des tampons, donc pas d'augmentation du temps d'attente dans ceux-ci donc LEDBAT se croira tranquille et enverra autant de données qu'il veut. Au moment où un des interlocuteurs parlera, ses paquets se trouveront donc peut-être coincés derrière un paquet LEDBAT. La seule protection contre ce problème est le paramètre TARGET qui ne doit donc pas être mis trop haut. La norme G.114 de l'UIT suggère 150 ms comme étant le maximum de retard tolérable pour le transport de la voix. LEDBAT doit donc choisir ses paramètres pour réagir avant les 150 ms. Le RFC recommande 100 ms pour le paramètre TARGET qui indique l'augmentation de délai de voyage à partir de laquelle LEDBAT réagit. (Ce paramètre TARGET détermine le temps maximal d'attente supplémentaire dû à LEDBAT.)

Autre point subtil, la compétition entre flots LEDBAT. On sait que TCP assure la « justice » entre flots TCP : si trois flots sont en compétition, chacun aura un tiers de la capacité. LEDBAT, lui, cède à TCP. Si un flot LEDBAT et un flot TCP sont en compétition, TCP aura toute la capacité. Mais si deux flots LEDBAT parallèles se concurrencent ? L'algorithme de LEDBAT ne garantit pas de justice. En général, c'est le flot le plus récent qui va gagner : arrivant tard, dans un réseau déjà bien encombré, il mesure un temps de base très élevé et ne voit donc pas d'augmentation due au temps d'attente dans les tampons, et ne réduit donc pas sa fenêtre de congestion (« Rethinking Low Extra Delay Background Transport Protocols » de Carofiglio, G., Muscariello, L., Rossi, D., Testa, C., et S. Valenti). Pour corriger cet effet, on ne peut compter que sur le bruit : de temps en temps, les tampons se videront, le temps de voyage diminuera, et le récent arrivé corrigera sa mauvaise estimation du temps de base.

La section 5 du RFC considère les points qui sont encore ouverts à expérimentation. Après tout, un protocole comme LEDBAT est quelque chose de très nouveau dans le zoo de l'Internet. Par exemple, l'effet de changement de routes pendant une session LEDBAT, modifiant le temps de base, n'est pas encore vraiment bien connu. Quant à la valeur des paramètres comme TARGET ou GAIN, elle aura certainement besoin d'être ajustée à la lumière de l'utilisation réelle. Enfin, le filtre des mesures, qui permet d'éliminer les mesures jugées anormales, et évite donc à LEDBAT d'ajuster brusquement sa fenêtre de congestion pour rien, aura certainement besoin de réglages, lui aussi.

Et la sécurité de LEDBAT ? La section 6 rappelle que, même si un attaquant arrive à tromper LEDBAT sur les valeurs du temps de voyage, dans le pire des cas, il ne pourra pas le faire se comporter de manière plus gloutonne que TCP. Par contre, il pourra faire une attaque par déni de service en lui faisant croire que le délai de voyage a augmenté et que LEDBAT devrait ralentir. Pour l'instant, il n'y a pas de mécanisme contre cela.

Le bon fonctionnement de LEDBAT dépend de bonnes mesures. Les fanas de métrologie seront donc ravis de l'annexe A, qui parle des causes d'erreur dans les mesures. Le principal problème est que, pour mesurer les temps de voyage aller-simple dont a besoin LEDBAT, il faut des horloges à peu près synchronisées. Si l'émetteur met dans le paquet une heure de départ à 13 heures, 37 minutes et 56,789 secondes, que le récepteur mesure une arrivée à 13 heures, 37 minutes et 57,123 secondes et que le récepteur a 0,5 secondes de retard sur l'émetteur, il mesurera un temps de voyage de 0,334 secondes (alors qu'il est en fait de 0,834 secondes). Reprenant le vocabulaire de NTP (RFC 5905), on peut dire qu'il y a deux sources de problèmes, l'écart des horloges par rapport à une référence et le décalage (la variation de l'écart). L'écart entraine une erreur fixe dans la mesure du temps (comme dans notre exemple ci-dessus). Mais LEDBAT n'utilise pas directement le temps mais la différence entre temps actuel et temps de base. Cette erreur s'annule donc et l'écart des horloges par rapport au temps correct n'est donc pas importante pour LEDBAT.

Plus embêtant est le décalage puisque lui ne s'annulera pas. Si l'horloge du récepteur bat plus vite que celle de l'émetteur, il aura toujours l'impression d'un réseau très encombré, puisque ses mesures de temps de voyage seront toujours supérieures au temps de base qu'il avait mesuré avant. Heureusement, alors que des écarts énormes sont souvent vus sur l'Internet (il est fréquent de voir plusieurs minutes, voire plusieurs heures de différence entre une machine et le temps UTC), les décalages sont typiquement bien plus petits. Les mesures citées par le RFC 5905 indiquent des décalages courants de 100 à 200 ppm, soit 6 à 12 ms d'erreur accumulée par minute. Comme une machine LEDBAT limite sa mémoire (paramètre BASE_HISTORY, pour lequel le RFC recommande actuellement une valeur de dix minutes), et n'utilise donc que des mesures récentes pour évaluer le temps de base, le problème reste donc limité.

Si malgré tout, le problème se pose, il n'affectera que le cas où le récepteur a une horloge plus rapide, et en déduira donc à tort qu'il doit ralentir. Dans le cas inverse (horloge du récepteur plus lente), l'émetteur aura simplement l'impression que le temps de base augmente.

Pour corriger ce problème de décalage, on peut imaginer d'envoyer les estampilles temporelles dans les deux sens, pour que chaque machine puisse calculer ce que devrait voir l'autre, pour pouvoir détecter qu'un pair a une mauvaise mesure. Ensuite, l'émetteur pourrait corriger ses propres calculs por s'adapter à ce récepteur erroné. Il peut même calculer si le décalage est constant (horloge battant trop vite ou trop lentement, mais à une fréquence constante).

Et question mises en œuvre effectives ? LEDBAT a été testé dans des logiciels comme μTorrent Transport Protocol library. Il est l'algorithme utilisé par le microTP de BitTorrent (voir la documentation officielle de µTP). Il est aussi mise en œuvre dans Swift.

Merci à Mathieu Goessens pour sa suggestion et à André Sintzoff pour ses inlassables corrections.


Téléchargez le RFC 6817


L'article seul

RFC 6815: RFC 2544 Applicability Statement: Use on Production Networks Considered Harmful

Date de publication du RFC : Novembre 2012
Auteur(s) du RFC : S. Bradner (Harvard University), K. Dubray (Juniper Networks), J. McQuaid (Turnip Video), 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 1 décembre 2012


Lors de la publication du RFC 2544, sur les tests de performances des équipements réseau, un point n'avait pas été mis assez clairement : comme tous les RFC du BMWG, le RFC 2544 ne concerne que les tests en laboratoire, dans des conditions bien contrôlées, et sans avoir peur de gêner un réseau de production. Comme certains avaient apparemment raté cette limitation, notre RFC 6815 enfonce le clou : ne faites pas les tests du RFC 2544 sur un vrai réseau !

Ce point est clairement précisé dans la charte du groupe de travail BMWG (Benchmarking Methodology Working Group). Les tests produits par ce groupe sont conçus pour des réseaux isolés (section 3 : un réseau isolé est un réseau dont le trafic de test ne sort pas et où le trafic non lié au test ne rentre pas). Il n'est pas prévu de les utiliser pour, par exemple, vérifier des SLA sur un réseau de production.

Mais pourquoi est-ce mal d'utiliser les tests BMWG sur un réseau de production ? La section 4 donne les deux raisons :

  • Dans l'intérêt du test, il ne faut pas que le trafic de test soit mêlé à du trafic sans lien avec le test, si on veut que les résultats soient précis et reproductibles.
  • Dans l'intérêt du réseau de production, il ne faut pas que le trafic de test (qui peut être intense, voir par exemple les tests de la capacité du réseau, qui fonctionnent en essayant de faire passer le plus de données possible) puisse rentrer en concurrence avec le trafic des vrais utilisateurs.

C'est d'ailleurs pour faciliter l'isolation et garder le trafic de test à part qu'il existe des plages d'adresses IP dédiées aux tests, le 198.18.0.0/24 (RFC 2544, annexe C.2.2) et le 2001:2::/48 (RFC 5180, section 8 mais notez que ce RFC comporte une grosse erreur). On peut ainsi facilement filtrer ces plages sur ses routeurs et pare-feux, pour empêcher du trafic de test de fuir accidentellement.

Et si on veut quand même faire des mesures sur des réseaux de production ? Il faut alors se tourner vers un autre jeu de tests, ceux développés par le groupe de travail IPPM. Notez que cela n'est pas par hasard que cet autre jeu ne comporte pas de méthode pour la mesure de la capacité (RFC 5136) : une telle mesure perturbe forcément le réseau mesuré.


Téléchargez le RFC 6815


L'article seul

RFC 6814: Formally Deprecating some IPv4 Options

Date de publication du RFC : Novembre 2012
Auteur(s) du RFC : C. Pignataro (Cisco Systems), F. Gont (UTN-FRH / SI6 Networks)
Chemin des normes
Première rédaction de cet article le 29 novembre 2012


Ce très court RFC est purement administratif et n'aura pas de conséquences pratiques : il note simplement comme officiellement abandonnées neuf des options d'IPv4.

IPv4 (RFC 791, section 3.1) prévoit l'ajout d'options dans l'en-tête d'un paquet (en pratique, elles sont peu utilisées). Parmi les options enregistrées, certaines n'avaient jamais été déployées, ou bien était tombées en désuétude depuis longtemps. Lire ce RFC, c'est donc fouiller le grenier et retrouver des trucs que tout le monde croyait perdus... Le registre des options IP est mis à jour pour que ces options soient formellement retirées (et le RFC correspondant marqué comme « intérêt historique uniquement »). Ce sont :

  • Stream ID (RFC 791), déjà marquée comme inutile par les RFC 1122 et RFC 1812. Elle servait à la compatibilité avec le défunt réseau SATNET, tellement oublié que même Wikipédia n'en parle pas.
  • Extended Internet Protocol (RFC 1385), une tentative pour prolonger la vie d'IPv4 en attendant IPv6.
  • Traceroute (RFC 1393), qui aurait permis (si elle avait été déployée, mais elle nécessitait de modifier tous les routeurs) de faire des traceroute plus économiques (cette option demandait au routeur de renvoyer un paquet d'information à la source).
  • Encode, qui avait un rapport avec le chiffrement mais qui ne semble pas avoir eu de RFC.
  • VISA, une expérience à l'USC qui n'est jamais allé loin.
  • Address Extension (RFC 1475), un autre essai de l'époque où l'IETF cherchait un successeur à IPv4. Cette technique, TP/IX: The Next Internet, avait reçu le numéro 7 et aurait donc été IPv7 si elle avait réussi.
  • Selective Directed Broadcast (RFC 1770), un projet de l'armée qui ne semble pas avoir été utilisé.
  • Dynamic Packet State, une partie de DiffServ, qui n'est jamais devenue un RFC.
  • Upstream Multicast Packet, un truc pour le multicast, jamais décrit dans un RFC, officiellement abandonné par le RFC 5015.

D'autres options, MTU Probe et MTU Reply, avaient déjà été « nettoyées » par le RFC 1191.


Téléchargez le RFC 6814


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 6808: Test Plan and Results Supporting Advancement of RFC 2679 on the Standards Track

Date de publication du RFC : Décembre 2012
Auteur(s) du RFC : L. Ciavattone (AT&T Labs), R. Geib (Deutsche Telekom), A. Morton (AT&T Labs), M. Wieser (Technical University Darmstadt)
Pour information
Réalisé dans le cadre du groupe de travail IETF ippm
Première rédaction de cet article le 6 décembre 2012


Voici le premier RFC à mettre en application la démarche du RFC 6576, qui définissait la méthode pour faire avancer un RFC décrivant des métriques sur le chemin des normes. Si l'IETF avait une grande expérience dans la mesure du déploiement et de la qualité d'un protocole, c'était moins évident pour les métriques, ces grandeurs définies rigoureusement et qu'on cherche à mesurer. Le RFC 6576 ayant déblayé ce terrain, ceci est sa première application : l'étude de l'avancement de la métrique « délai d'acheminement d'un paquet », qui avait été normalisée dans le RFC 2679 et l'est désormais dans le RFC 7679.

Deux mises en œuvre différentes de ce RFC 2679 ont été testées, pour vérifier que leurs résultats, face aux mêmes données, étaient compatibles. C'est le cas et cela plaide en faveur du RFC 2679 : il était clair et non ambigu puisque deux équipes différentes l'ont implémenté de manière compatible. On n'a pas dit « identique » car les métriques permettent une certaine souplesse et, de toute façon, la mesure est un domaine délicat, avec plein de possibilités d'erreur. On ne vérifie donc pas que ces deux programmes donnent les mêmes résultats, mais que leurs résultats sont équivalents, aux erreurs acceptables près.

L'essentiel du RFC est constitué de la description de l'environnement de test, et des mesures effectuées. Les deux implémentations sont NetProbe et Perfas+. NetProbe utilise des paquets UDP de taille variable, et peut produire des distributions de paquets suivant Poisson (RFC 3432) ou bien tout simplement périodiques (RFC 2330). Perfas+, lui (développé par Deutsche Telekom), peut aussi utiliser TCP. Entre deux sites connectés via l'Internet, les expérimentateurs ont monté un tunnel L2TP (RFC 3931), afin de diminuer la variation dans les mesures (autrement, certains équipements sur le trajet auraient pu distribuer le trafic de test sur plusieurs liens, en hachant par exemple les adresses IP des engins de test).

Le trafic passait par netem, un module du noyau Linux qui permet d'ajouter des pertes ou des retards quelconques. (Par exemple, pour le premier test, netem avait été configuré pour ajouter 100 ms de retard, avec une variation uniforme de ±50 ms.)

Les auteurs notent avec honnêteté que les ports des commutateurs étaient en half-duplex, ce qui n'était ni prévu, ni souhaitable (mais ils s'en sont aperçu une fois les mesures faites).

Les tests ont été faits avec des distributions périodiques et de Poisson, des rythmes allant de 1 à 10 p/s et des tailles de 64, 340 et 500 octets, ce que le RFC 2330, section 15, nomme des « paquets standards » (ce qui exclut les fragments).

Des centaines de paquets ont ensuite été envoyés. En conformité avec le RFC 2679 (section 3.8.4), un traceroute a été effectué et ses résultats sont inclus dans le RFC (NetProbe permet de faire le traceroute depuis l'outil, en même temps que la mesure, pour pouvoir analyser a posteriori des résultats surprenants, par exemple des variations inexpliquées).

Étape indispensable (mais pas forcément folichonne) dans une campagne de mesures, l'étalonnage des erreurs est décrite dans la section 4. Par exemple, NetProbe n'utilise pas réellement comme moment d'envoi d'un paquet le wire time défini par le RFC 2330 (il se sert du moment d'acceptation du paquet UDP par le noyau, qui peut être différent si la machine est chargée). L'horloge de la machine est synchronisée avec NTP et la résolution de NTP (typiquement pas mieux qu'une milli-seconde) est également à prendre en compte comme source d'erreur (mais cela peut être amélioré par les méthodes décrites dans la section 4.1 : pour ces mesures, la stabilité de l'horloge est plus importante que sa justesse).

Toutes les sources de l'erreur, après évaluation, ont ensuite été données à R qui nous donne les divers intervalles d'erreur.

Perfas+, lui, utilise un récepteur GPS pour son horloge mais d'autres causes font que ses intervalles d'erreur sont plus larges (et donc moins bons) que ceux de NetProbe.

La section 5 explique ensuite ce que veut dire « équivalent ». En raison de la souplesse de la métrique, et des erreurs dans la mesure, on ne peut pas espérer que les deux logiciels affichent pile les mêmes résultats. On pose donc les limites tolérables, pour une comparaison faite avec Anderson-Darling. (Rappelons que le but de cette expérience n'était pas de mesurer un réseau, mais de savoir si la norme du RFC 2679 était suffisamment bien écrite et précise, et que les implémentations étaient donc équivalentes dans leurs résultats.)

Les tests et leurs résultats figurent en section 6. On note que, dans l'un des tests, un des deux programmes n'a pas réussi le test de l'équivalence avec lui-même (les variations provoquées par le réseau ont été trop grandes). À part ça, toutes les comparaisons Anderson-Darling ont réussi.

La section 7 n'a plus qu'à résumer la conclusion : c'est bon, les deux programmes utilisés sont statistiquement équivalents, ce qui semble indiquer que la norme qu'ils ont tous les deux implémentée était correctement définie. La métrique définie par le RFC 2679 mérite donc d'avancer sur le chemin des normes. Quelques erreurs mineures dans la norme ont été détectées et il est proposé qu'elles soient corrigées dans la prochaine version. (Voir les errata.)

À noter que l'avancement de la métrique sur le chemin des normes a nécessité une nouvelle version du RFC 2679, le RFC 7679.

Une description de l'utilisation de NetProbe sur le réseau d'AT&T est documentée en ligne.


Téléchargez le RFC 6808


L'article seul

RFC 6797: HTTP Strict Transport Security (HSTS)

Date de publication du RFC : Novembre 2012
Auteur(s) du RFC : J. Hodges (PayPal), C. Jackson (Carnegie Mellon University), A. Barth (Google)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF websec
Première rédaction de cet article le 20 novembre 2012


La technique HSTS (HTTP Strict Transport Security), normalisée dans ce RFC (mais déjà largement déployée) vise à résoudre une attaque contre TLS. Si un site Web est accessible en HTTPS, et qu'un méchant arrive à convaincre un utilisateur de se connecter en HTTP ordinaire à la place, le méchant peut alors monter une attaque de l'homme du milieu. Le fait que le site soit protégé par TLS n'aidera pas dans ce cas. Pour éviter cette attaque, HSTS permet à un site de déclarer qu'il n'est accessible qu'en HTTPS. Si l'utilisateur a visité le site ne serait-ce qu'une fois, son navigateur se souviendra de cette déclaration et ne fera plus ensuite de connexions non sécurisées.

Bien sûr, il n'y aurait pas de problème si l'utilisateur utilisait systématiquement des URL https://.... Mais les erreurs ou les oublis peuvent arriver, l'utilisateur peut cliquer sur un lien http://... dans un spam, il peut être victime d'une page Web certes sécurisée mais qui contient des images chargées via un URL http://.... Bref, il y a encore trop de risques. D'où l'idée d'épingler la politique de sécurité du site Web dans le navigateur, en permettant à un site de déclarer au navigateur « je suis sécurisé, ne reviens jamais me voir en HTTP ordinaire » et de compter sur le fait que le navigateur respectera automatiquement cette politique, et s'en souviendra. Cette déclaration se fera par l'en-tête HTTP Strict-Transport-Security:, par exemple Strict-Transport-Security: max-age=7905600.

TLS est normalisé dans le RFC 5246. (Son prédécesseur, SSL, est dans le RFC 6101.) L'utilisation de HTTP au dessus de TLS (HTTPS) est décrite dans le RFC 2818. Un navigateur Web va typiquement appliquer des politiques de sécurité différentes selon que la connexion se fait en HTTP ou en HTTPS. Un exemple typique est fourni par les cookies du RFC 6265 : s'ils ont été envoyés par le serveur avec l'attribut Secure, ils ne seront retransmis par le navigateur que si la connexion est en HTTPS.

Pour vérifier l'identité du serveur en face, les navigateurs valident les certificats présentés par le serveur. Si cette vérification échoue (c'est en général suite à une erreur de l'administrateur du serveur, mais cela est parfois dû à une attaque d'un intermédiaire), le navigateur affiche typiquement un avertissement à l'utilisateur, en lui permettant de continuer de manière non sûre s'il le souhaite (cette possibilité est « officialisée » par la section 3.1 du RFC 2818). Ce mécanisme de click-through security, que le navigateur rend plus ou moins facile, est très critiqué : comme l'utilisateur veut avant tout continuer sa tâche, il va toujours chercher à passer outre l'avertissement de sécurité. C'est même une attitude raisonnable, compte tenu du fait que la plupart des erreurs d'authentification avec TLS ne sont pas des attaques, et aussi compte tenu de la difficulté, même pour un expert, d'analyser ces problèmes et de comprendre ce qui s'est passé. Deux bons articles sur les questions d'interface utilisateur liées à ce problème de sécurité sont « Crying Wolf: An Empirical Study of SSL Warning Effectiveness » de Sunshine, J., Egelman, S., Almuhimedi, H., Atri, N., et L. Cranor, puis « Stopping Spyware at the Gate: A User Study of Privacy, Notice and Spyware » de Good, N., Dhamija, R., Grossklags, J., Thaw, D., Aronowitz, S., Mulligan, D., et J. Konstan. Mais d'autres articles, non cités par ce RFC, prennent un point de vue différent, expliquant qu'ignorer les avertissements de sécurité peut être une attitude rationnelle.

Pour éviter ces risques, l'article de C. Jackson et A. Barth (deux des auteurs du RFC), « ForceHTTPS: Protecting High-Security Web Sites from Network Attacks » proposait une approche où le site Web disait à ses clients qu'ils devaient utiliser HTTPS pour se connecter. Ce RFC utilise une technique différente de celle de l'article mais l'idée est la même.

La section 2 décrit en détail le problème de sécurité. Si vous êtes plutôt intéressé par la solution, il faut sauter à la section 5. Sinon, si on continue dans l'ordre, une analyse des menaces. HSTS gère trois menaces :

  • Les attaques passives. Ce sont celles où l'attaquant ne fait qu'écouter. Par exemple, sur un réseau WiFi typique, écouter est possible, que le réseau soit sécurisé ou pas (« Practical Attacks Against WEP and WPA » de Beck, M. et E. Tews). Il existe même des outils tous faits pour cela comme Aircrack L'attaquant peut alors intercepter des mots de passe, des cookies, etc. Une extension Firefox spectaculaire, Firesheep, permet d'automatiser cette tâche et de se retrouver rapidement connecté au compte Facebook de ses voisins de Starbucks. HTTPS empêche complètement ces attaques passives s'il est utilisé. Par exemple, si un site est accessible normalement à la fois en HTTP et en HTTPS, il suffit d'une seule requête HTTP, faite par accident ou oubli, et les cookies peuvent être copiés.
  • Plus sophistiqué est l'attaquant actif. Il peut agir sur le DNS, ou sur le routage ou tout simplement installer un point d'accès WiFi pirate, ayant le même SSID que le vrai. Il risque plus d'être détecté mais il a ainsi des possibilités bien plus grandes. Notons que l'attaquant actif peut être un État (l'Iran s'en est fait une spécialité) et que, dans ce cas, l'attaque est bien plus facile pour lui, car il contrôle toutes les liaisons du pays. Cette fois, contre ces attaquants actifs, juste faire tourner HTTP sur TLS ne suffit plus : il faut aussi authentifier le serveur distant. Les certificats auto-signés (ou signés par une AC qui n'est pas connue du navigateur) sont dangereux car ils ne protègent pas du tout contre les attaquants actifs. Si l'on accepte les sites présentant un certificat auto-signé (ce que permettent tous les navigateurs, après un sermon sur la sécurité et l'obligation de cliquer sur un lien « je sais ce que je fais »), c'est comme si on n'utilisait pas TLS du tout puisqu'on n'est pas sûr de parler au bon site. (Une protection minimale peut être fournie par des outils comme Certificate Patrol.)
  • Mais il n'y a pas que les attaquants actifs et passifs qui peuvent compromettre la sécurité de HTTP. Il y a aussi les bogues dans les sites Web. Par exemple, si une page a un contenu en Flash, et que ce contenu est chargé via une connexion non sécurisée, l'attaquant passif pourra lire les cookies et l'attaquant actif pourra remplacer le Flash par un autre code, qui fera des tas de choses vilaines chez le client. (Dans une certaine mesure, c'est également faisable avec JavaScript ou même une CSS.) Une protection contre cela est le refus, par le navigateur, de charger du « contenu de contextes de sécurité différents » (page HTML chargée en HTTPS et Flash chargé en HTTP) mais tous ne le font pas (cf. section 12.4), et beaucoup se contentent d'un avertissement qui peut facilement passer inaperçu. (À noter que ce contenu de contextes de sécurité différents est souvent appelé « contenu mixte » mais notre RFC déconseille ce terme, qui a un sens bien précis - et différent - en XML.)

Une analyse de sécurité sérieuse doit indiquer quelles sont les menaces traitées mais aussi celles qu'on ne prétend pas traiter. La section 2.3.2 liste les « non-buts » de HSTS :

  • Le hameçonnage, où un utilisateur va donner à un site Web, authentifié et utilisant HTTPS, mais pas digne de confiance, des informations secrètes. HSTS vous protège si vous essayez d'aller sur https://www.mybank.example/ et qu'un attaquant tente de vous détourner. Mais il ne peut rien faire si, suite à un spam, vous visitez https://s6712.example.net/php/mybank.example...
  • Les failles de sécurité dans le navigateur : HSTS ne protège que si le navigateur est fiable.

Maintenant, place à la solution. L'effet de l'épinglage HSTS sera double :

  • Le client HTTP remplacera tous les URL http://... par des https://... avant de se connecter.
  • Toute erreur de validation sera fatale, sans rémission possible.

Bref, avant de déclarer en HSTS qu'on ne doit être contacté que de manière sécurisée, il faut être sûr de soi...

La section 5 du RFC expose la solution. Comme indiqué plus haut, un serveur HTTPS qui veut être sûr de n'être accédé qu'en HTTPS le déclare en envoyant un en-tête Strict-Transport-Security: (en-tête désormais dans le registre des en-têtes). Évidemment, cet en-tête ne sera utilisé que si la session était sécurisée avec HTTPS (envoyé sur de l'HTTP ordinaire, il sera ignoré). La politique HSTS du site comprend une durée de vie maximale de l'information, et le choix d'inclure ou pas les sous-domaines. Pour la durée de vie, cela se fait avec une valeur max-age en secondes. Le navigateur pourra se souvenir, pendant ce temps, que le site ne doit être accédé qu'en HTTPS. Après, il pourra redemander (cela permet éventuellement de ne plus avoir HSTS, si l'on veut se remettre à autoriser HTTP). Pour les sous-domaines, c'est fait avec une directive includeSubDomains.

La section 6 va davantage dans les détails en couvrant la syntaxe exacte de cet en-tête. Par exemple, un max-age de zéro spécifie que le client HTTP doit tout de suite oublier les choix HSTS : cela revient à dire « j'arrête d'exiger HTTPS ».

Plusieurs sites Web aujourd'hui utilisent déjà HSTS. Par exemple, Gmail annonce une politique d'une durée d'un mois  :

Strict-Transport-Security: max-age=2592000; includeSubDomains

Et l'EFF (qui n'utilise pas l'option includeSubDomains mais a presque la même durée de vie) :

Strict-Transport-Security: max-age=2628000

On l'a vu, la syntaxe est simple. Les sections suivantes portent sur une question plus complexe, le comportement des logiciels lorsqu'ils rencontrent cette option. D'abord, le serveur (section 7). S'il veut utiliser HSTS, il met cette option dans la réponse, si elle est protégée par TLS. Sinon (HTTP ordinaire), le serveur ne doit pas mettre l'en-tête HSTS et le RFC recommande une redirection (code HTTP 301, par exemple) vers un URL https://. Notons que c'est risqué : un attaquant actif peut aussi faire des redirections, si la requête était en HTTP. Voir l'excellente « Transport Layer Protection Cheat Sheet » de Coates, M., Wichers, d., Boberski, M., et T. Reguly.

Et le client HTTP (typiquement un navigateur Web) ? La section 8 lui donne des instructions : si on reçoit l'en-tête HSTS sur une session HTTP ordinaire, l'ignorer (cela peut être une blague, puisque la session n'est pas authentifiée), si on le reçoit sur HTTPS, enregistrer cette information (avec la durée de vie associée). Puis, à la prochaine visite de ce serveur (les règles exactes sont un peu plus compliquées, avec les sous-domaines, et les IDN) :

  • Ne se connecter qu'en HTTPS (si le navigateur reçoit, par frappe de l'utilisateur, ou dans une page HTML, un URL http://..., le réécrire automatiquement en https://...).
  • N'accepter aucune erreur d'authentification (pas de dialogue « voulez-vous quand même continuer même si le certificat X.509 est pourri ? »). Si un serveur met cet en-tête, c'est que son administrateur sait ce qu'il fait et qu'il s'engage à gérer son serveur correctement (pas de certificat expiré, par exemple, cf. l'exemple à la fin).

À noter que l'en-tête HSTS doit être envoyé via le protocole réseau, pas via le contenu du document : le truc HTML <meta http-equiv="Strict-Transport-Security" ...> est explicitement interdit.

Les sections 11 et 12 donnent des avis aux programmeurs sur la bonne façon de mettre en œuvre ce système de sécurité. D'abord, les serveurs (section 11). Le RFC leur rappelle que le serveur ne peut pas savoir si son client respecte l'en-tête qu'on lui envoie. On ne peut donc pas compter uniquement sur HSTS pour traiter les menaces décrites en section 2.

Ensuite, le choix de la durée de vie (via l'attribut max-age). Il y a deux approches : une durée constante ou bien un max-age calculé à chaque fois pour correspondre à une date d'expiration choisie. La première est évidemment plus facile à mettre en œuvre (sur Apache, un Header set Strict-Transport-Security "max-age=604800" dans la configuration ou bien dans un .htaccess suffit). La seconde nécessite un calcul dynamique mais a l'avantage de pouvoir faire correspondre la date d'expiration de HSTS avec une autre date importante (le RFC suggère celle d'expiration du certificat X.509 ; si on ne renouvelle pas le certificat, c'est une bonne chose si HSTS cesse également).

Le RFC met aussi en garde contre les certificats auto-signés ou bien signés par une AC non connue de certains navigateurs (comme CAcert). HSTS interdisant formellement de passer outre un problème X.509 (pas de formulaire « voulez-vous continuer bien que je ne connaisse pas cette AC ? »), si on active HSTS en envoyant l'en-tête Strict-Transport-Security:, et qu'il est accepté, on risque, si on change ensuite de certificat, d'être injoignable par tous les clients (cas où on est passé à un certificat auto-signé) ou par une partie d'entre eux (cas où est est passé à une AC peu connue). Rappelez-vous que HSTS est une déclaration « je suis un parano expert en crypto et je ne ferai jamais d'erreur, n'utilisez que HTTPS ». Réflechissez donc bien avant de l'activer.

Autre piège pour l'administrateur d'un serveur HTTPS, le cas du includeSubDomains. Si on l'utilise, on peut bloquer tout sous-domaine qui ne serait pas accessible en HTTPS. Si vous gérez le domaine d'une grande entreprise, mettons example.com, et que vous mettez un Strict-Transport-Security: max-age=15768000 ; includeSubDomains, alors le petit site Web que vous aviez oublié, http://service.department.example.com/appli, qui n'était accessible qu'en HTTP, deviendra inutilisable pour tous ceux qui utilisent HSTS. Soyez donc sûr de vos sous-domaines avant d'activer cette option. (Le RFC cite l'exemple d'une AC ca.example qui veut permettre l'accès à OCSP en HTTP ordinaire : la directive includeSubDomains pourrait bloquer ocsp.ca.example.) D'un autre côté, sans cette option, vous n'êtes plus sûr de protéger les cookies (cf. section 14.4) puisque ceux-ci peuvent être envoyés à tout serveur d'un sous-domaine. (Avec secure, ce sera forcément en HTTPS mais pas forcément blindé par HSTS.)

Et pour les auteurs de navigateurs Web ? La section 12 leur dispense de sages conseils. D'abord, elle leur rappelle un principe central de HSTS : pas de recours pour les utilisateurs. Si un site est étiqueté en HSTS et qu'il y a un problème d'authentification, il est interdit de permettre aux utilisateurs de passer outre. HSTS est là pour la sécurité, pas pour faciliter la vie des utilisateurs. Le but est d'éviter qu'une attaque de l'Homme du Milieu soit possible parce que l'utilisateur est trop prêt à prendre des risques.

Une suggestion intéressante pour les auteurs de navigateurs est celle de livrer le logiciel avec une liste pré-définie de sites HSTS (grandes banques, etc), comme ils ont aujourd'hui une liste pré-définie d'AC. Cela permettrait de fermer une des faiblesses de HSTS, le fait que la première connexion, si elle n'est pas faite en HTTPS (et sans erreur), n'est pas sécurisée. Après, on peut imaginer que cette liste soit éditable (possibilité d'ajouter ou de retirer des sites) mais permettre de retirer un site est dangereux : un utilisateur inconscient risquerait de virer un site important et de se retrouver ainsi vulnérable. En tout cas, le RFC dit que cette possibilité de retirer un site ne doit pas être accessible à JavaScript, pour éviter qu'un logiciel malveillant dans une page Web ne s'attaque à la sécurité de HSTS.

Tout ce RFC est évidemment consacré à la sécurité mais la traditionnelle section Security considerations (section 14) est néanmoins utile pour évaluer les risques restants. Ainsi, HSTS ne protège pas contre les attaques par déni de service. Il peut même les faciliter : par exemple, un attaquant actif peut envoyer le trafic HTTPS vers un serveur qu'il contrôle et, si l'utilisateur accepte le certificat invalide, le serveur pourra alors mettre un Strict-Transport-Security: non prévu et qui empêchera l'accès au serveur légitime dans certains cas. Autre possibilité, si le navigateur permet à l'utilisateur ou, pire, à du code JavaScript, d'ajouter un site à la liste locale des sites HSTS, les sites pas accessibles en HTTPS deviendront inutilisables.

Autre problème que HSTS ne résout pas complètement : la première connexion. Si, sur une nouvelle machine (dont la mémoire HSTS est vide), vous vous connectez à http://www.example.com/, HSTS ne vous protège pas encore. Si aucun attaquant n'était là pendant la première connexion, vous serez redirigé vers https://www.example.com/, l'en-tête Strict-Transport-Security: définira ce site comme HSTS et tout sera protégé par la suite. Mais, si un attaquant était présent au moment de cette première connexion, HSTS ne pourra rien faire. C'est un des cas où la liste pré-définie de sites HSTS, livrée avec le navigateur, est utile.

Dernier piège, plus rigolo, un attaquant peut découvrir (par une combinaison de noms de domaines qu'il contrôle et d'un script tournant sur le navigateur) si le navigateur a déjà visité tel site HSTS (car, dans ce cas, les liens vers un URL http://... seront automatiquement réécrits en https://...). Cela permet une forme de flicage du navigateur (voir la synthèse « Web Tracking » de N. Schmucker.)

Deux annexes du RFC intéresseront les concepteurs de protocoles. L'annexe A documente les raisons des choix effectués par HSTS. Par exemple, la politique HSTS est indiquée par un en-tête et pas par un cookie car les cookies peuvent être manipulés et modifiés quand ils sont dans la mémoire du navigateur. Autre cas qui a suscité des discussions, le fait que le client HTTPS fasse confiance à la dernière information reçue via Strict-Transport-Security:. Par exemple, si un serveur annonce un max-age d'un an le 18 novembre 2012, puis d'un mois le 19 novembre 2012, l'information expirera-t-elle le 18 novembre 2013 ou bien le 19 décembre 2012 ? Avec HSTS, c'est le dernier en-tête qui gagne, donc l'expiration sera le 19 décembre 2012. C'est peut-être une faiblesse, question sécurité, mais cela permet aux gérants des sites Web de corriger leurs erreurs (comme un max-age excessif).

À propos du max-age, la même annexe explique aussi pourquoi il indique une durée et pas une date d'expiration : c'est pour éviter d'être dépendant de la synchronisation des horloges. Le RFC donne une autre raison, le fait d'être ainsi dispensé de la définition et de l'implémentation d'une syntaxe pour représenter les dates. Cela ne me semble pas convaincant : il existe déjà une syntaxe normalisée et largement implémentée, celle du RFC 3339. Mais, bon , la sécurité préfère des normes simples, X.509 est un parfait exemple des résultats auxquels mènent des normes compliquées.

Quant à l'annexe B, elle explique les différences entre HSTS et la SOP (Same-Origin Policy) du RFC 6454.

Ce RFC normalise une technique déjà largement déployée. Plusieurs sites Web envoient déjà cet en-tête et plusieurs navigateurs le reconnaissent (on trouve deux bonnes listes sur le Wikipédia anglophone).

À noter qu'il y eu des projets plus ou moins avancés de mettre cette déclaration « TLS seulement » dans le DNS (évidemment avec DNSSEC) plutôt que dans HTTP. Cela aurait permis de fermer la faille de la première connexion, et de gérer le cas des autres protocoles sécurisés avec TLS. Deux exemples de cette voie (tous les deux n'ayant pas été poursuivis) : l'Internet-Draft draft-hoffman-server-has-tls et un article de George Ou.

J'ai testé HSTS avec un Chromium « Version 20.0.1132.47 Ubuntu 12.04 (144678) » et tcpdump qui écoute. Tout marche bien. L'en-tête HSTS est ignoré si le certificat n'a pas pu être validé (AC inconnue). Une fois le certificat validé (AC ajoutée au magasin du navigateur), dès que l'en-tête HSTS a été reçu, plus aucune tentative n'est faite en HTTP, le navigateur file sur le port 443 directement.

Quant à Firefox, voici ce qu'il affiche quand un site qui avait auparavant été accessible en HTTPS authentifié ne l'est plus (ici, parce que le certificat a expiré) : firefox-hsts.png

HSTS est également mis en œuvre dans wget (voir la documentation) et c'est activé par défaut.

Merci à Florian Maury pour sa relecture attentive. Un autre article sur HSTS est celui de Cloudflare.


Téléchargez le RFC 6797


L'article seul

RFC 6793: BGP Support for Four-octet AS Number Space

Date de publication du RFC : Décembre 2012
Auteur(s) du RFC : Q. Vohra (Juniper Networks), E. Chen (Cisco Systems)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF idr
Première rédaction de cet article le 19 décembre 2012


Un des nombres trop petits de l'Internet était la taille des numéros de système autonome. En 2007, elle était passée, avec le RFC 4893, de deux à quatre octets. Ce nouveau RFC est juste une révision mineure de cette norme.

Il est assez courant dans l'Internet que des nombres prévus très larges au début s'avèrent ridiculement petits avec la croissance du réseau. C'est bien sûr le cas des adresses IPv4, dont les 32 bits sont bien trop peu pour le nombre de machines connectées aujourd'hui, mais c'est aussi vrai pour les numéros de système autonome (AS pour autonomous system). Chacun de ces numéros identifie un système autonome de routage, au sein duquel une politique de routage cohérente peut s'appliquer. En gros, chaque opérateur a un numéro de système autonome, les plus gros en ayant plusieurs (surtout en cas de fusion ou d'acquisition).

Ces numéros sont notamment utilisés par le protocole de routage BGP (normalisé dans le RFC 4271), pour indiquer le chemin à suivre pour joindre un réseau. La petite fonction shell bgproute permet d'interroger les serveurs de Route Views et affiche les numéros de système autonomes traversés :

% bgproute 80.67.162.1
AS path: 3257 3356 20766 20766
Route: 80.67.160.0/19

On voit que le serveur de Route Views a reçu l'annonce de la part du système autonome 3257 qui l'avait lui même reçu du système autonome 3356.

Ces numéros étaient autrefois stockés sur seulement 16 bits, ce qui ne permettait que 65 535 systèmes en tout, bien trop peu pour l'Internet d'aujourd'hui, qui va des villes chinoises aux hébergeurs brésiliens. Si certains conservateurs, méprisants et élitistes, ont regretté le fait que « n'importe qui, avec une armoire et deux PC avec Quagga » veuille faire du BGP, le fait est que l'Internet touche bien plus de monde et que la population des opérateurs a augmenté. D'où le RFC 4893, qui avait fait passer la taille des numéros d'AS à 32 bits, soit quatre milliards d'opérateurs possibles.

Ces AS de quatre octets s'écrivent en notation ASPLAIN, en écrivant directement le nombre, par exemple 112617 (RFC 5396).

Les nouveaux AS sont ensuite annoncés par l'attribut AS4_PATH, n° 17 dans le registre des attributs.

Le changement lui-même est assez trivial mais, comme souvent sur Internet, le gros du travail était la gestion de la transition. Notre RFC explique avec beaucoup de soin comment un routeur BGP récent va pouvoir parler à un routeur de l'ancienne génération (le routeur doit annoncer sa capacité à gérer les AS de quatre octets avec le capability advertisment n° 65 du RFC 5492). Et comment les chemins d'AS 4-octets pourront être transmis même à travers des « vieux » routeurs, utilisant un mécanisme de tunnel (l'article de Geoff Huston l'explique très bien).

Pour cette transition, le nouveau BGP utilise un numéro d'AS spécial, le 23456, qui sert à représenter tous les AS 4-octets pour les anciens routeurs. Si vous voyez apparaitre ce système autonome, par exemple en tapant un show ip bgp sur un Cisco, c'est que votre logiciel est trop vieux. Ceci dit, cela doit être rare de nos jours, la gestion de ces AS sur quatre octets étant désormais présente dans toutes les mises en œuvre sérieuses de BGP.

Les numéros d'AS sur quatre octets sont distribués par les RIR depuis des années (voir par exemple la politique du RIPE-NCC et sa FAQ). Le RIPE-NCC a publié d'intéressantes statistiques à ce sujet, notamment sur le taux de numéros d'AS 32 bits renvoyés au RIPE-NCC car le titulaire s'est aperçu, après coup, qu'il y avait quelques problèmes techniques, chez lui ou chez ses fournisseurs.

L'annexe A résume les différences par rapport au RFC 4893 : rien de vital, juste un toilettage. Notamment, la gestion d'erreurs, absente du précédent RFC, est spécifiée en détail.


Téléchargez le RFC 6793


L'article seul

RFC 6789: ConEx Concepts and Use Cases

Date de publication du RFC : Décembre 2012
Auteur(s) du RFC : B. Briscoe (BT), R. Woundy (Comcast), A. Cooper (CDT)
Pour information
Réalisé dans le cadre du groupe de travail IETF conex
Première rédaction de cet article le 6 décembre 2012


Premier RFC du groupe de travail CONEX de l'IETF, ce document expose les principes de bases du mécanisme de « publication de la congestion » (CONgestion EXposure). L'idée est d'indiquer dans les paquets la congestion prévue, pour que les équipements réseaux puissent prendre des décisions appropriées. Une fois normalisée (ce RFC 6789 n'est qu'une toute première étape), ce sera une des nombreuses techniques permettant de gérer la congestion dans les réseaux TCP/IP et notamment l'Internet.

Il n'y a pas encore de protocole normalisé pour cette « publication de la congestion » (les deux premiers utiliseront une option IPv6 et une option de TCP). Pour l'instant, notre RFC s'en tient à des usages : à quoi cela pourrait servir. La congestion est clairement une des plaies du réseau. La force de TCP/IP est de multiplexer la capacité des liens au niveau des paquets et pas des circuits. Cela permet une utilisation bien plus efficace du réseau. Mais cela ne crée pas magiquement de la capacité : quand trop de paquets rencontrent trop peu de capacité, la congestion survient. Elle se manifeste par des pertes de paquets (le routeur, n'arrivant pas à suivre, abandonne certains paquets), mais aussi par des retards (si les tampons du routeur amortissent la congestion, ils augmentent les délais d'acheminement), et par le marquage ECN (RFC 3168) de certains paquets.

Le récepteur des données est censé détecter ces signaux (un trou dans la séquence TCP, des RTT qui augmentent, les marques ECN) et il doit alors dire à l'émetteur de ralentir. Ce fonctionnement où seules les machines terminales agissent (les routeurs intermédiaires, à part éventuellement des marques ECN, n'ont pas grand'chose à faire, ils se contentent de router) est typique de l'Internet mais, dans certains cas, exposés dans ce RFC, il est insuffisant.

L'idée de base de ConEx est que l'émetteur mette dans les paquets IP qu'il envoie des indications sur la congestion qu'on lui a signalé. Ainsi, des équipements qui sont purement de niveau 3 sur le trajet peuvent être informés de la congestion (ECN les informe aussi mais ne concerne que les équipements en aval du point où est détectée la congestion, cf. figure 1 du RFC). Ainsi, le réseau pourra avoir une meilleure vision de la congestion, comptant les paquets qui vont rencontrer de la congestion aussi facilement qu'il compte aujourd'hui les paquets ou les octets.

Pourquoi est-ce important de connaître les paquets qui vont circuler dans des parties du réseau où il y a congestion ? Déjà, cela a une importance économique : un réseau ne coûte pas plus cher qu'il soit utilisé ou pas. Un trafic qui emprunte le réseau à un moment où celui-ci est peu chargé ne coûte donc rien à l'opérateur du réseau. Par contre, la congestion coûte cher puisqu'elle est le signe qu'il faut sortir son carnet de chèques pour mettre à jour le réseau, vers des capacités plus grandes. Ainsi, ConEx pourrait être une brique de base pour un système qui pénaliserait uniquement les flots de données qui contribuent à la congestion.

La section 2 présente en détail les concepts et la terminologie ConEx. D'abord, évidemment, la congestion. Tout le monde en parle mais il n'y a pas de définition rigoureuse et unique pour ce concept. Pour une analyse de ce terme, voir « The Evolution of Internet Congestion » de S. Bauer, S., D. Clark et W. Lehr. Dans ConEx, la congestion est définie comme la probabilité de perte de paquet (ou de marquage par ECN). Un autre effet de la congestion, le retard, n'est pas pris en compte (donc, ConEx ne mesurera pas l'effet du bufferbloat).

Deuxième concept, le volume de congestion. Il s'agit du nombre d'octets perdus suite à la congestion. L'idée est de rendre les émetteurs responsables : envoyer 10 Go sur un lien congestionné n'est pas la même chose que d'y envoyer quelques octets. Par exemple, si Alice envoie un fichier d'un Go sur un lien où la probabilité de perte est de 0,2 %, son volume de congestion est de 2 Mo. Si, plus tard dans la journée, elle envoie un fichier de 30 Go alors que la ligne, moins encombrée, ne perd plus que 0,1 % des paquets, elle ajoutera 3 Mo à son volume de congestion (donc, 5 Mo en tout). L'un des intérêts de cette métrique est qu'elle est très facilement mesurable par un routeur : il lui suffit de compter le volume total des paquets qu'il a dû jeter (ou marquer avec ECN, s'il utilise cette technique). C'est donc quasiment la même chose que les compteurs de volume actuels.

Troisième concept important, la congestion aval (Rest-of-path congestion ou downstream congestion dans la langue de Van Jacobson). C'est celle que le flot de données va supporter entre le point de mesure et sa destination (la congestion amont étant évidemment celle entre la source et le point de mesure : aujourd'hui, elle est bien plus difficile à mesurer si on n'utilise pas ECN).

La section 3 décrit ensuite le principal scénario d'usage envisagé pour ConEx. Si vous vous demandez « mais à quoi sert ce truc ? » depuis tout à l'heure, vous allez bientôt avoir une réponse. Soit un opérateur réseau qui a des clients. La plupart consomment peu mais certains sont des acharnés et font passer en permanence des gigaoctets à travers le réseau. L'opérateur voudrait que les mesures désagréables qu'il va prendre pour limiter la congestion frappent en priorité ces gros consommateurs.

Il va pour cela placer un équipement qui regarde les indications de congestion ConEx et va ensuite limiter le trafic en fonction de ces indications (en fonction du volume de congestion). (Les limitations de trafic habituelles visent le débit, pas la participation à la congestion. Or comme on l'a vu, débiter 100 Mb/s sur un réseau vide n'est pas du tout la même chose que de le débiter sur un réseau chargé. Il est donc dommage de limiter le débit dans tous les cas.) L'article « Policing Freedom to Use the Internet Resource Pool » de B. Briscoe, A. Jacquet et T. Moncaster, détaille ce mécanisme. La force de cette méthode est qu'aucune limite, aucune mesure contraignante et désagréable, n'est prise lorsqu'il n'y a pas de congestion (car, dans ce cas, l'usage du résau ne coûte rien). Avec ConEx, un bit n'est plus égal à un bit : celui envoyé pendant la congestion coûte plus cher au réseau et doit donc, d'une certaine façon, être « payé » par l'utilisateur.

Si l'opérateur est un FAI ADSL, un bon endroit pour mettre cette supervision de la congestion et cette limitation du trafic est sans doute le BRAS. (Voir le rapport du DSL Forum « Technical Report TR-059: Requirements for the Support of QoS-Enabled IP Services » mais il ne semble pas en ligne.)

Ainsi, les utilisateurs seront encouragés à utiliser des protocoles que notre RFC appelle « charognards » dans la mesure où ils n'utilisent que la capacité dont personne ne veut (le charognard a une mauvaise image de marque mais c'est bien à tort : il consomme les ressources négligées par tous les autres). Ces protocoles n'envoient du trafic que lorsque le réseau est inutilisé. Leur coût est donc à peu près nul pour l'opérateur. Le RFC 6297 décrit ces protocoles. Pour encourager leur usage, on ne peut pas seulement compter sur des exhortations citoyennes, dont l'écologie montre le peu d'efficacité. Il faut aussi des motivations plus pratiques.

Mais il existe d'autres approches, déjà, pour ce genre de gestion (ralentir les gros consommateurs, ceux qui sortent franchement du rang), non ? La section 3.3 les examine :

  • On l'a vu, il est courant de limiter le débit, ou bien d'imposer un total de données transféré maximum (cette dernière technique est courante en 3G). Cette approche est très grossière car elle mène à sous-utiliser ou sur-utiliser le réseau. S'il n'y a pas de congestion, on va sous-utiliser le réseau, alors qu'il est libre (pire, on décourage l'utilisation de protocoles « charognards » puisque leur utilisateur serait pénalisé pour le volume envoyé, au lieu d'être récompensé pour le soin qu'il met à ne l'envoyer qu'en l'absence de congestion). S'il y a congestion, on risque de sur-utiliser le réseau car, tant que le quota n'est pas atteint, l'utilisateur n'a pas de raison de se gêner.
  • Les techniques de fair queuing visent à égaliser le trafic entre les différents utilisateurs. Agissant en temps réel et n'ayant pas de mémoire, elles favorisent, sur le long terme, les plus gros consommateurs alors qu'on voudrait le contraire.
  • Plus subtile, la technique décrite dans le RFC 6057 ne mesure le débit que lorsqu'il y a congestion et donc effectivement gêne pour le réseau. Mais, lors de la congestion, tout le trafic est compté comme y contribuant et cette technique, comme les deux précédentes, n'encourage absolument pas à utiliser les protocoles « charognards ».
  • Dernière méthode possible, un examen plus ou moins poussé du paquet (allant jusqu'à la DPI) pour décider quelle est l'application utilisée, suivi d'une dégradation du service pour cette application particulière (par exemple BitTorrent). Elle est évidemment incompatible avec des techniques de sécurité comme IPsec et elle soulève de sérieuses questions politiques. ConEx, lui, est neutre par rapport à l'application utilisée.

Toutes ces solutions ont un autre défaut en commun : elles laissent l'utilisateur dans l'incertitude des performances qu'il obtiendra. Le principal intérêt des tarifs forfaitaires pour l'accès Internet (je parle des vrais forfaits, ceux où le prix est connu d'avance, pas de ce que les commerciaux menteurs de la téléphonie mobile appelent « forfait ») est la certitude : pas de mauvaises surprises au moment de l'arrivée de la facture. Mais cette certitude ne porte que sur les prix. Les performances, elles, peuvent varier, par exemple si le trafic émis était tel qu'on est désormais limité. Au contraire, avec Conex, l'utilisateur est en mesure de voir sa propre contribution à la congestion, et peut ajuster son comportement en fonction de cela. (À mon avis, c'est une vision un peu idéale, car elle suppose que le réseau n'agit sur les performances qu'en réponse aux indicateurs ConEx.)

Ce scénario d'usage de la section 3, informer l'opérateur sur la contribution des utilisateurs à la congestion, est le principal but de ConEx à l'heure actuelle. Les versions initiales de ce RFC traitaient sur un pied d'égalité plusieurs scénarios mais le groupe de travail, après bien des discussions, a décidé de prioritiser celui qui semblait le plus prometteur. Ceci dit, la section 4 présente quelques autres cas d'usage :

  • Mesurer la contribution à la congestion non pas par utilisateur mais par opérateur. Comme les indicateurs ConEx sont vus par tous les routeurs intermédiaires (y compris les routeurs de bordure entre opérateurs), chaque opérateur peut savoir ce que chacun de ses voisins va lui apporter comme congestion (et réciproquement). De beaux débats sur la répartition des investissements à prévoir !
  • Avoir de meilleures indications sur l'utilisation globale du réseau, pour mieux planifier l'avitaillement (provisioning) en capacité.

La section 5 se penche ensuite sur le déploiement de ConEx. Ce système ne nécessite pas un accord simultané de tous les acteurs (heureusement). ConEx est donc utile même si certains routeurs du trajet ne marquent pas et même si certains ne lisent pas l'information ConEx.

Par contre, il faut qu'au moins deux acteurs bougent : au moins un routeur doit marquer les paquets et au moins une machine doit réagir et signaler la congestion dans les paquets qu'elle émet. Les développeurs d'une application Ledbat (voir RFC 6297 et RFC 6817), par exemple, peuvent se lancer en espérant que cela motivera les routeurs pour s'y mettre.

Si certains paquets sont marqués par ConEx et d'autres non, que va faire le routeur ? Pour le déploiement de ConEx, il serait préférable que les paquets marqués soient favorisés d'une manière ou d'une autre. Mais comme la raison du marquage est leur contribution à la congestion, ce n'est pas forcément idéal... En outre, cela soulève un problème de sécurité (le marquage n'est pas authentifié et une machine peut mentir) sur lequel ce RFC 6789 est complètement muet (le problème sera traité dans les futurs RFC, plus concrets).

Comme ConEx va tripoter dans la couche 3, cœur de l'Internet, il risque de perturber le fonctionnement d'IP. Il faut donc considérer ConEx comme plutôt expérimental et la section 6 fait la liste des questions encore ouvertes, par exemple :

  • ConEx est actuellement limité à IPv6, l'idée est que le délai de déploiement sera de toute façon tel qu'IPv6 sera largement dominant lorsque ConEx sera généralisé. Était-ce une bonne idée ?
  • ConEx ne fait pas de différence entre l'auto-congestion (un utilisateur qui se gêne lui-même) et la congestion infligée aux autres (lorsqu'on encombre des ressources partagées). Moralement, il serait intéressant de séparer les deux mais n'est-ce pas trop complexe ?
  • ConEx est plus ambitieux qu'ECN et s'appuie sur lui. Mais le déploiement d'ECN est très limité. Est-ce que ConEx sera quand même utile si le déploiement d'ECN en reste où il est maintenant ?

Téléchargez le RFC 6789


L'article seul

RFC 6783: Mailing Lists and non-ASCII Addresses

Date de publication du RFC : Novembre 2012
Auteur(s) du RFC : J. Levine (Taughannock Networks), R. Gellens (Qualcomm)
Pour information
Réalisé dans le cadre du groupe de travail IETF eai
Première rédaction de cet article le 7 novembre 2012


Depuis la sortie du RFC 6530 et de ses petits camarades, il existe désormais une solution normalisée pour avoir du courrier électronique complètement internationalisé, y compris les adresses (arôme@café.fr...). Mais comment est-ce que cela s'applique aux listes de diffusion ? Peut-on avoir des listes où certains membres accepteraient les nouvelles adresses et d'autres non ? Ce RFC, successeur du RFC 5983, se penche sur la question. Pour l'instant, la réponse est pessimiste : il n'y a pas de moyen pratique de faire coexister anciens et nouveaux sur la même liste.

Une liste de diffusion prend un message et le redistribue à N destinataires. Certains de ces N destinataires seront derrière un serveur de messagerie récent, qui gère les adresses internationalisés. Une partie de ceux-ci, en outre, auront des adresses internationalisées. Même si le destinataire, lui, n'a pas une adresse internationalisée, si l'émetteur en a une, ses messages ne pourront pas être remis aux gens qui ont les vieux logiciels.

Il y a donc un problème technique, le fait que des adresses internationalisées soient refusées par certains. Et il y a un problème humain : en communicaton bilatérale, après quelques essais, on peut toujurs trouver une solution technique qui permette la communication. Sur une liste, ce n'est plus possible, l'émetteur ne connait pas les destinataires et réciproquement. Il n'y a pas d'ajustement possible.

Autre problème : idéalement, la liste ne modifie pas le message, à part par l'ajout de certains en-têtes spécifiques aux listes (comme List-Unsubscribe: ou List-Id:, normalisés dans le RFC 2369 et RFC 2919). Toutefois, un certain nombre de listes vont plus loin et, bien que cela soit une source d'ennuis connue, modifient d'autres en-têtes comme Reply-To: voire, pire, From:.

Pour synthétiser, il y a trois services différents qui peuvent marcher ou pas :

  • Avoir une liste dont l'adresse est internationalisée, par exemple évolution-langue@académie-française.fr,
  • Avoir une liste qui accepte l'abonnement de personnes ayant des adresses internationalisées, par exemple étienne@massé.fr,
  • Avoir une liste qui accepte les messages émis depuis des adresses internationalisées.

Ces trois capacités sont relativement indépendantes (la deuxième et la troisième impliquent des logiciels différents donc l'une peut marcher et pas l'autre).

Le plus simple pour une liste qui veut gérer parfaitement l'internationalisation serait de n'avoir que des abonnés qui eux-même ont la gestion complète des adresses en Unicode (option SMTPUTF8 de SMTP, cf. RFC 6531). Pour cela, le mieux est de tester lors de l'inscription, et de refuser l'abonnement de ceux qui ont le vieux logiciel. Pour ce test, si le candidat à l'abonnement s'abonne avec une adresse Unicode, c'est facile : s'il reçoit le message de confirmation, c'est bon. Et s'il s'abonne avec une adresse ASCII ? Alors, le mieux est de tester en tentant de leur envoyer le message « répondez pour confirmer » depuis une adresse Unicode.

Mais pour la majorité des listes, qui voudront accepter des abonnés SMTPUTF8 et d'autres qui ne le sont pas ? (Fin 2012, très peu de serveurs de messagerie, à part en Extrême-Orient, gèrent SMTPUTF8.) Il n'existe pas (ou plus, cf. RFC 5504) de mécanisme de repli automatique d'un message aux adresses Unicode vers un message traditionnel. C'est donc au MLM (Mail List Manager, le logiciel de gestion de la liste, par exemple Mailman) de faire ce repli.

D'abord, le logiciel de gestion de la liste doit déterminer quels abonnés sont SMTPUTF8 et lesquels ne le sont pas. Il y a plusieurs méthodes :

  • Décider que les abonnés avec une adresse Unicode peuvent recevoir du courrier entièrement internationalisé et que les abonnés avec une adresse ASCII ont un logiciel traditionnel (en pratique, cela privera certains de ces abonnés ASCII des bénéfices du courrier internationalisé),
  • Tester, en envoyant un message depuis une adresse Unicode et en demandant confirmation,
  • Demander à l'utilisateur de se classer lui-même comme, aujourd'hui, on lui demande s'il veut recevoir du texte ou de l'HTML.

Ensuite, il faut décider, pour chaque message entrant vers la liste, s'il est internationalisé ou pas. Cela peut se faire en considérant que, si l'option SMTPUTF8 a été utilisée dans la session, le message sera marqué comme « Unicode ». Ou bien on peut examiner les en-têtes du message, à la recherche d'adresses en Unicode.

Les logiciels de gestion de liste réécrivent en général l'émetteur dans l'enveloppe SMTP du message. Ils mettent leur propre adresse (par exemple ima-bounces@ietf.org pour la liste du groupe de travail EAI, ex-IMA) ou même ils mettent une adresse d'origine différente pour chaque abonné, pour mieux gérer les messages de non-remise (technique VERP). Dans les deux cas, l'adresse d'émetteur, qui recevra les messages de non-remise, contient en général le nom de la liste. Dans ce cas, elle sera une adresse Unicode et les serveurs ne connaissant pas le courrier complètement internationalisé ne pourront donc pas envoyer ces avis de non-remise (bounces).

La section 3 contient les recommandations concrètes. D'abord, pour les en-têtes ajoutés comme List-Id:, la recommandation est de les mettre sous une forme purement ASCII, pour limiter les risques, même si cet en-tête prend comme valeur un URI (comme le fait List-Unsubscribe:) et que cet URI a un plan (scheme) qui permet l'Unicode. Il faut dans ce cas utiliser l'« encodage pour-cent ». Donc, pour une liste pause-café@bavardage.fr, on aura :


List-Id: Liste de discussion en Unicode <pause-caf%C3%A9@bavardage.fr>
List-Unsubscribe: <mailto:pause-caf%C3%A9-requ%C3%AAte@bavardage.fr?subject=unsubscribe>
List-Archive: <http://www.example.net/listes/pause-caf%C3%A9/archives>

Dans certains cas, cela ne donnera pas un résultat lisible (par exemple le List-Id: d'une liste en chinois encodé en ASCII ne va pas être tellement utile aux lecteurs...) Mais cet inconvénient semble, aujourd'hui, moins grave que le risque de faire arriver de l'Unicode à des gens qui ne s'y attendent pas. Une meilleure solution devra attendre une nouvelle version des RFC 2369 et RFC 2919.

Le RFC n'a pas de recommandation pour le cas où un auteur d'un message a une adresse Unicode et où le gestionnaire de listes essaie de diffuser le message à un abonné n'ayant que des logiciels anciens, ne gérant pas SMTPUTF8. Il n'y a pas de bonne solution technique, juste des petits arrangements : réserver la liste aux gens pouvant recevoir du courrier internationalisé (cf. plus haut la discussion sur de telles listes), proposer aux abonnés d'enregistrer une adresse ASCII et remplacer le From: par cette adresse avant de transmettre ou enfin remplacer le From: par une adresse de la liste. Reste à programmer cela...

Je ne connais pas encore de « grand » gestionnaire de liste de diffusion qui ait des plans précis pour la mise en œuvre des adresses de courrier internationalisées. Sympa, par exemple, en est toujours au stade de la réflexion sur ce point.

Notre RFC ne contient pas de liste des changements depuis le RFC 5983. Il y a eu réécriture complète puisque le repli automatique et les adresses de secours (alt-address) ont été retirées de la norme finale du courrier internationalisé.


Téléchargez le RFC 6783


L'article seul

RFC 6782: Wireline Incremental IPv6

Date de publication du RFC : Novembre 2012
Auteur(s) du RFC : V. Kuarsingh (Rogers Communications), L. Howard (Time Warner Cable)
Pour information
Réalisé dans le cadre du groupe de travail IETF v6ops
Première rédaction de cet article le 7 novembre 2012


Parfois, je me dis que si on consacrait tous les efforts qui ont été voués à écrire des RFC à propos d'IPv6 à déployer IPv6 au lieu d'expliquer comment le faire, ce protocole aurait remplacé IPv4 depuis longtemps... Toujours est-il que voici un nouveau RFC, consacré à la synthèse de l'état de l'art en matière de déploiement incrémental d'IPv6 pour un opérateur filaire (FAI ADSL ou câble par exemple).

« Incrémental » car peu d'opérateurs ont la possibilité de déployer un réseau purement IPv6. Par contre, je ne sais pas pourquoi le RFC se limite au filaire, la plus grande partie de son texte peut tout à fait s'appliquer aussi bien à un opérateur mobile (genre 3G).

Plein de textes ont déjà été écrits sur ce même sujet mais les choses changent et il est peut-être bon de temps en temps de refaire une synthèse. Donc, l'idée est de prendre par la main un opérateur qui, en 2012, serait toujours en IPv4 pur (c'est donc un opérateur assez retardé techniquement), pour l'amener (à long terme !) en IPv6 pur (cf. section 3.6). Le point important à garder en mémoire est que chaque opérateur est différent et que, s'il existe plusieurs mécanismes de migration d'IPv4 vers IPv6, ce n'est pas uniquement parce que l'IETF aime écrire beaucoup de RFC, c'est surtout parce qu'il n'y a pas un mécanisme qui conviendrait miraculeusement à tous les cas (cf. le RFC 6180 qui décrivait tous ces mécanismes).

Donc, point de départ, un opérateur Internet qui a des clients en IPv4 (et qu'il n'est pas question de migrer immédiatement), qui veut déployer IPv6 mais en ne cassant pas ce qui existe, en minimisant la quantité de travail nécessaire (donc sans déployer de technologies inutiles). En outre, on veut une qualité de service optimum, donc éviter les tunnels, si possible.

Avec un tel cahier des charges, une migration soudaine de tout le réseau d'un protocole vers un autre est hors de question. Il faut une démarche progressive, où IPv6 arrive petit à petit pendant qu'IPv4 continue de fonctionner correctement. Le problème, c'est que, sur le papier, une telle approche progressive (phased approach) est très sympa mais, en pratique :

  • Par suite de la procrastination d'un grand nombre d'acteurs, les adresses IPv4 sont déjà épuisées,
  • Si IPv6 est mis en œuvre dans tous les logiciels et équipements sérieux, depuis de nombreuses années, il n'a pas toujours été utilisé en production avec la même intensité qu'IPv4 et des bogues traînent donc toujours,
  • Le FAI ne contrôle en général pas les équipements des clients (c'est une des différences entre le FAI filaire et le mobile) et ceux-ci peuvent avoir des vieux systèmes, avec peu ou pas de gestion d'IPv6,
  • Le retour à un réseau multi-protocoles (qui n'est pas une nouvelle chose : dans les années 1980, tous les réseaux locaux étaient multi-protocoles) va poser quelques problèmes opérationnels.

Le RFC rappelle que le client final, le mythique « M. Michu », ne demande pas IPv6. Il ne demande pas IPv4 non plus. Il veut un accès à l'Internet, point. C'est aux professionnels de faire en sorte que son accès fonctionne, aussi bien en IPv4 qu'en IPv6. Les deux protocoles coexisteront sur le réseau local pendant encore longtemps (section 3.1 du RFC).

La section 3 du RFC examine plus en détail ces défis pratiques. La pénurie de plus en plus aiguë d'adresses IPv4 va nécessiter du partage d'adresses IP, avec tous ses inconvénients (RFC 6269, et la section 4.2 de notre RFC). Les autres solutions (gratter les fonds de tiroir à la recherche de préfixes oubliés, acheter au marché gris ou noir des adresses vendues sans garantie) ne suffiront sans doute pas.

Mais IPv6 ne peut pas se déployer en cinq minutes. Sans même prendre en compte l'existence de vieux systèmes ne parlant qu'IPv4, l'opérateur qui va déployer IPv6 va devoir prévoir une période d'assimilation des nouvelles pratiques (IPv6 est très proche d'IPv4 mais pas identique). Souvent, les humains ne sont pas au même niveau en IPv6 qu'en IPv4, et c'est pareil pour les logiciels (pas toujours testés au feu). Si la connectivité IPv4 de l'opérateur va dépendre de sa connectivité IPv6 (comme c'est le cas avec certaines techniques comme DS-LiteRFC 6333 - ou NAT64RFC 6146), un problème IPv6 va également toucher IPv4.

Il faut donc faire attention à ne pas déployer IPv6 sans supervision et de réaction adaptés. Trop souvent, des organisations ont mis un peu d'IPv6, se disant que c'était facile et sans conséquences, puis se sont aperçu après qu'un réseau non géré était moins utile : pannes IPv6 non détectées par le système de surveillance, par exemple.

Certaines des techniques de transition n'ont pas aidé, en proposant des mécanismes qui avaient l'avantage de permettre de faire de l'IPv6 rapidement, et l'inconvénient de fournir aux utilisateurs un vécu de moins bonne qualité. C'est le cas notamment avec les tunnels (tous les tunnels ne sont pas forcément mauvais mais, dans l'histoire d'IPv6, il y a eu beaucoup de problèmes à cause de certains tunnels) : ajoutant une complication supplémentaire, forçant le passage par un chemin qui n'est pas toujours optimum, les tunnels ne devraient être utilisés que lorsqu'il n'y a pas d'autre choix, et en toute connaissance de cause. L'objectif est bien de fournir de la connectivité native.

Avec ces défis en tête, la section 4 du RFC rappelle les techniques de transition et de coexistence possibles. La première citée est la catégorie des tunnels automatiques, 6to4 et Teredo, à mon avis la pire (le RFC 6343 documente certains des problèmes avec 6to4 et le RFC 7526 demande qu'il ne soit plus utilisé). Le problème de fond de ces techniques est qu'elles ne fournissent aucun moyen de contrôler le chemin de retour, ou même de savoir s'il existe. Elles ne devraient à mon avis être utilisées que si on veut décourager les gens de faire de l'IPv6

6rd (RFC 5969) bouche certains des trous de 6to4 et c'est la technique qu'a utilisé Free pour distribuer IPv6 sur son réseau, en attendant un hypothétique accès natif. Son principal avantage est qu'il limite l'investissement initial pour l'opérateur, lui permettant de croître progressivement.

DS-Lite (RFC 6333) tunnele l'IPv4 sur un réseau IPv6. Il est surtout intéressant pour un opérateur qui part de zéro (par exemple parce qu'il vient de se créer) et qui peut donc construire un réseau entièrement IPv6 (ce qui peut être difficile avec certains équipements, encore aujourd'hui), tout en ayant des clients IPv4 à satisfaire. Le CPE doit être capable de faire du DS-Lite donc cette solution marche mieux si le FAI contrôle les CPE.

NAT64 (RFC 6146) est pour le cas où les clients sont bien en IPv6 mais où certains services à l'extérieur ne sont accessibles qu'en IPv4. Elle ne semble donc pas d'une grande actualité aujourd'hui, puisque le réseau local purement IPv6 est encore dans le futur (voir RFC 6586). Elle sera plus utile lorsque les réseaux purement IPv6 devront accéder aux derniers dinosaures IPv4.

La technique de coexistence IPv4/IPv6 qui donne les meilleurs résultats, est la double pile (dual stack) où les machines ont les deux protocoles et deux adresses. Pour permettre l'étape suivante (IPv6 pur), elle nécessite un réseau entièrement IPv6 (y compris les services, par exemple le DNS). Elle ne résout pas le problème de l'épuisement des adresses IPv4 donc, pour un opérateur actuel, le vécu IPv4 restera marqué par le partage d'adresses, le CGN et autres horreurs.

À noter que j'ai fait un exposé comparant toutes ces techniques de transition en 2011 à Grenoble.

Après les défis, et les techniques disponibles, la section 5 présente les différentes phases du déploiement. Une organisation qui va passer à IPv6 peut utiliser cette section comme point de départ pour établir son propre plan de migration. Il est important de noter que ce RFC ne fournit pas un plan tout prêt adapté à tout le monde. Il fournit des lignes directrices, mais chacun doit créer son propre plan, en tenant compte de son réseau, de ses clients, de ses moyens humains et financiers. (Une vision plus technique est dans le RFC 6180.)

La section 5 liste successivement plusieurs phases. J'espère qu'en 2012, plus personne n'en est encore à la phase 0 mais on ne sait jamais... La phase 0 commence par la formation : si personne dans l'organisation (ou bien seulement un ou deux geeks) ne connait IPv6, il faut apprendre. Cela peut se faire par des formations formelles, ou en lisant des livres ou des textes sur le Web. Pour le personnel d'exécution, le RFC rappelle qu'il vaut mieux que la formation soit faite juste avant le déploiement, pour qu'elle ne soit pas oubliée lorsque le moment de s'en servir viendra. Cette phase 0 ne doit pas être purement théorique, et il faut aussi pratiquer, dans un laboratoire dédié à cet effet, à la fois pour que les gens apprennent par la pratique, et pour tester si les matériels et logiciels utilisés dans l'organisation n'ont pas de problème avec IPv6.

Armé de cette formation et de cette expérience en laboratoire, les techniciens peuvent alors commencer à planifier le futur routage IPv6 de leur réseau. Est-ce la même tâche qu'en IPv4 ? On peut argumenter dans un sens ou dans l'autre. Le RFC met plutôt l'accent sur les différences mais on peut aussi considérer que le modèle de routage est tellement proche dans les deux protocoles qu'il ne faut pas dramatiser les différences.

Outre la politique de routage, trois autres points doivent retenir l'attention de l'équipe qui conçoit le plan de migration vers IPv6 :

  • La sécurité, pour laquelle IPv6 peut poser quelques différences (comme pour le routage, je les trouve mineures) : les RFC 4942, RFC 6092 et RFC 6169 contiennent des analyses utiles sur la sécurité d'IPv6 (dommage, à mon avis, que le RFC 6104 ne soit pas cité).
  • L'administration des adresses IP (IPAM adaptés à IPv6) et la gestion du réseau,
  • Et bien sûr les techniques de transition adaptés à cette organisation particulière.

On peut espérer qu'en 2012, la plupart des grosses organisations sérieuses ont au moins franchi la phase 0. Mais pas mal de petites organisations ne l'ont même pas encore commencé.

Étape suivante, la phase 1. Il s'agit cette fois de donner un accès IPv6 à ses clients ou utilisateurs, via des tunnels pour l'instant, car le réseau n'est pas forcément prêt pour de l'IPv6 natif partout. Par exemple, il est courant que le réseau interne d'un opérateur, équipé de routeurs récents, permette IPv6 mais que l'accès aux clients passe par des équipements qu'on ne contrôle pas complètement (par exemple des DSLAM) et qui ne sont pas prêts pour IPv6. (Notez qu'il n'est pas obligatoire de passer par toutes les phases. Si on a un réseau où on peut utiliser du natif tout de suite, nul besoin d'un détour par des tunnels.) La phase 1 peut se faire avec une technologie comme 6rd (RFC 5569), si on contrôle le CPE.

Naturellement, à cette phase 1, il n'y aura pas de miracle : on utilisera des tunnels, donc on aura les problèmes associés aux tunnels comme la MTU diminuée.

Ensuite, place à la phase 2. Cette fois, on fournit de l'IPv6 natif. Tout fonctionne en IPv6 et, surtout, avec le même niveau de qualité qu'en IPv4. C'est un point très important car un certain nombre de fournisseurs qui se vantent de permettre IPv6 ne surveillent pas automatiquement la connectivité IPv6 (laissant les clients faire cette surveillance) et, même lorsqu'on leur signale un problème, le traitent uniquement dès qu'ils ont du temps libre (alors qu'un problème IPv4 est traité immédiatement). Un niveau de service équivalent à celui d'IPv4 est crucial si on veut convaincre les clients de migrer. Si vous faites l'audit du niveau de préparation IPv6 d'un fournisseur d'accès ou d'hébergement, ce sont les meilleurs tests : 1) le monitoring est-il également fait pour IPv6 ? 2) en cas de panne IPv6, y a-t-il le même niveau de mobilisation que pour IPv4 ? (Ou bien, est-ce que le NOC réagira en se disant « ah, IPv6, c'est Richard, on va attendre qu'il revienne de vacances », ce qui est le cas de la majorité des sociétés prétendant faire de l'IPv6 aujourd'hui.)

À ce stade, il faut encore fournir le service IPv4. Compte-tenu de l'épuisement des adresses, il faudra probablement déployer du CGN/NAT444, peut-être avec l'aide de technologies comme DS-Lite (RFC 6333). Au début du déploiement, le CGN peut encore être une grosse machine centrale puis, si son usage croît, être réparti petit à petit sur d'autres machines.

Normalement, l'usage d'IPv4 devrait ensuite suffisamment baisser pour qu'on puisse passer à la phase 3, un réseau purement IPv6. En novembre 2012, au moment où j'écris ces lignes, cela semble une perspective très lointaine, sauf peut-être sur des réseaux très spécifiques. Mais cela arrivera bien un jour.

Même dans ce cas, il est possible qu'il faille fournir une connectivité IPv4 à certains clients. DS-Lite, qui tunnele le trafic IPv4 sur le réseau IPv6, est là encore utile. Si, ce qui est plus vraisemblable, on a juste besoin de permettre l'accès des clients IPv6 à des sites Web qui sont restés en IPv4, NAT64 (RFC 6144 et RFC 6146) sera sans doute la bonne solution. Mais, bon, c'est un problème pour le futur... Le RFC a un ton plutôt pessimiste et, à mon avis, voit le verre IPv6 plutôt à moitié vide.


Téléchargez le RFC 6782


L'article seul

RFC 6781: DNSSEC Operational Practices, Version 2

Date de publication du RFC : Décembre 2012
Auteur(s) du RFC : O. Kolkman (NLnet Labs), W. Mekking (NLnet Labs), R. Gieben (SIDN Labs)
Pour information
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 22 décembre 2012


Comme avec toute technique fondée sur la cryptographie, le protocole DNSSEC impose, non seulement des bons algorithmes et une mise en œuvre correcte, mais surtout des procédures rigoureuses et soigneusement exécutées. C'est le but de ce RFC, qui remplace le RFC 4641 et qui explique tout ce à quoi doivent s'attendre les registres et autres administrateurs de zones DNS, grandes ou petites, qui déploieraient DNSSEC. (Le cas des serveurs DNS récursifs, par exemple les résolveurs d'un FAI, n'est pas étudié.)

Notre RFC rappelle donc des concepts de base du DNS (notamment le fait que la réjuvénation des modifications n'est pas instantanée) puis rappelle les différentes clés (cf. section 1.1 pour une définition précise de clé) utilisées par DNSSEC et leurs caractéristiques souhaitables (longueur, période maximale pendant laquelle on les utilise, lieu de stockages, etc). Tout n'est pas encore bien connu dans ce domaine. Certes, la racine est signée depuis juillet 2010, ainsi que plus de 80 TLD mais, au niveau en dessous du TLD, peu de zones sont signées (dans les 1 % de .fr, par exemple) et l'expérience opérationnelle peut donc encore être améliorée.

Il explique ensuite les considérations temporelles (DNSSEC utilise le temps et nécessite des horloges bien synchronisées, par exemple par NTP). Le DNS étant hiérarchique, il faut veiller, lors de toutes les manipulations, à bien rester synchronisé avec le gérant de la zone parente, dont les enregistrements de type DS (delegation signer) pointeront vers notre clé. Le but est, qu'à tout moment, une chaîne de confiance intacte aille de la clé de confiance jusqu'aux enregistrements du domaine. Si un lien de cette chaîne casse, le domaine sera marqué comme bogus (RFC 4033, section 5) et rejeté par les résolveurs validants.

Enfin, le RFC étudie le rollover, le remplacement d'une clé. Les clés ne pouvant pas raisonnablement être utilisées éternellement, il faut prévoir à l'avance les remplacements périodiques et aussi, hélas les remplacements en urgence en cas de compromission. Il faut apporter beaucoup de soin à ce remplacement, si on veut éviter que, pendant une certaine période, les données publiées dans le DNS soient invalides et donc rejetées par un résolveur DNS paranoïaque (il faut publier la nouvelle clé suffisamment à l'avance pour qu'elle soit présente partout ou bien signer tous les enregistrements avec les deux clés, l'ancienne et la nouvelle). Mon article à la conférence SATIN en 2011 avait montré que c'était loin d'être le cas : les erreurs sont fréquentes, même pour les grandes zones sérieuses.

Bref, pour un gérant de zone DNS, déployer DNSSEC, ce n'est pas uniquement signer la zone : c'est aussi mettre en place des procédures de sécurité, analogues à celle d'une autorité de certification.

Maintenant, avec la section 3, voyons les détails pratiques. D'abord, la génération et le stockage des clés cryptographiques. D'abord, un message d'espoir : en lisant ce RFC, on peut avoir l'impression d'un ensemble de tâches très compliquées, impossible à réaliser correctement. Heureusement, il existe déjà des logiciels qui, en automatisant la plupart de ces tâches, rendent les choses bien plus faciles. J'utilise pour cela OpenDNSSEC.

D'abord, avant de se lancer, il faut faire certains choix technico-politiques :

  • Est-ce qu'on n'utilise qu'un type de clé ou bien est-ce qu'on sépare KSK (Key Signing Key) et ZSK (Zone Signing Key) ? Contrairement à ce qu'on lit souvent, la dichotomie entre une KSK et une ZSK n'a rien d'obligatoire, et elle complique les choses.
  • Est-ce que les KSK vont être configurés par certains comme clés de confiance, à partir desquels on valide ? Cela permet d'être indépendant des autres acteurs comme la racine mais cela augmente les responsabilités.
  • Quels sont les délais pertinents, par exemple le champ Expire du SOA, le temps de réaction souhaité en cas de problème ? Il faut aussi se demander si NOTIFY (RFC 1996) marche bien (ou si on ne peut compter que sur le paramètre Refresh de l'enregistrement SOA) et si on utilise IXFR (RFC 1995) ou AXFR,
  • Quels sont les choix cryptographiques (par exemple, concernant la longueur des clés RSA) ?

Une fois ces choix faits, on pourra configurer le résultat (dans OpenDNSSEC, fichier /etc/opendnssec/kasp.xml). Mais que choisir ?

Pour le choix entre une séparation KSK/ZSK et une clé unique, le choix est purement un problème opérationnel du côté du gestionnaire de zone. Les résolveurs ne feront pas de différence.

Un problème à garder en tête pour le stockage des clés est le risque de compromission de la clé (vol du disque sur lequel se trouve la partie privée de la clé, par exemple). Si la clé privée est sur le disque d'une machine connectée à l'Internet, le risque est plus élevé que s'il est sur une machine déconnectée et enfermée dans un coffre-fort. Encore mieux, pour les plus riches, l'usage des HSM permet d'être raisonnablement sûr qu'il n'y aura pas de vol de la clé. D'un autre côté, pour signer des enregistrements, une clé sur une machine non-connectée est certainement moins pratique. Une des façons de résoudre le dilemne est de séparer KSK et ZSK : on met la KSK en sécurité dans un endroit bien protégé (elle ne sert qu'à signer la ZSK, qui ne change pas tous les jours) et on fait les signatures des enregistrements de la zone avec la ZSK. En cas de compromission de la ZSK, son remplacement est relativement simple, puisqu'il est entièrement interne à la zone, il ne nécessite pas d'interaction avec la zone parente. (C'est ainsi, par exemple, que fonctionne la racine.)

Comme toujours en sécurité,il y a un fort risque de blinder la porte en oubliant la fenêtre : il ne sert pas à grand'chose de protéger la KSK avec des précautions de niveau militaire si les données de la zone, celles qu'on va signer, peuvent être facilement modifiées par un attaquant (encore que le RFC oublie de dire que la possession de la clé privée permette de générer des enregistrements mensongers sans que le registre s'en aperçoive). De même, le HSM empêche certes le méchant de copier la clé privée, mais il ne l'empêche pas de signer : si le pirate prend le contrôle de la machine connectée au HSM, il peut faire signer à ce dernier ce qu'il veut. Bref, il n'y a pas de solution miracle en matière de sécurité.

Séparer KSK et ZSK permet donc plus de souplesse dans la gestion de la sécurité. Mais cela rend les choses plus complexes. Si les clés sont gérés automatiquement par un outil comme OpenDNSSEC, ce n'est pas trop un problème. Sinon, il vaut peut-être mieux n'avoir qu'une clé.

Une question qui agite les milieux DNSSEC depuis de nombreuses années est celle du remplacement (rollover) des clés. Il y a deux écoles :

  • Celle qui dit que les remplacements doivent être systématiques et fréquents, pour qu'ils deviennent de la routine ; elle se sépare en deux sous-écoles, une qui favorise les remplacements périodiques et une qui préfère les faire au hasard,
  • Et l'école qui dit que les remplacements ne doivent se faire que s'il y a une bonne raison, par exemple une forte suspicion que la clé privée a été copiée.

Notre RFC note qu'il n'y a pas consensus sur cette question. Il note qu'un facteur important est « est-ce que la clé est utilisée comme clé de confiance quelque part ? », c'est-à-dire est-ce que des gens l'ont configuré dans leur résolveur validant (directives trusted-keys ou managed-keys de BIND et trust-anchor ou trust-anchor-file de Unbound) ? Cela peut se faire, par exemple pour éviter de dépendre de la hiérarchie du DNS (on peut imaginer une clé DNSSEC de gouv.fr installée dans les résolveurs des ministères pour être sûr de ne pas être affectés par des problèmes à l'AFNIC ou à la racine). Notez que cela peut arriver sans le consentement du gérant de la zone. Si ce dernier publie un DPS (DNSSEC Practice Statement) disant en gros caractères « n'utilisez pas notre KSK comme clé de confiance, ne vous fiez qu'au DS de la zone parente », alors, on peut tenir pour acquis qu'il y aura peu de cas où la KSK sera installée en dur dans les résolveurs. Autrement, le remplacement devient bien plus compliqué car il faut prévenir tous les gens qui ont configuré cette clé de confiance. Certains ne seront pas joignables ou ne réagiront pas et il faudra donc prendre le risque de casser leur accès DNSSEC. Ainsi, pour la racine (qui ne peut pas compter sur l'enregistrement DS de la zone parente) qui est forcément clé de confiance, on peut penser qu'il n'y aura jamais de remplacement de la KSK originelle, la 19036, sauf en cas de compromission : cela nécessiterait de changer trop de résolveurs.

Notez qu'il existe un mécanisme pour mettre à jour les clés de confiance, décrit dans le RFC 5011. Comme il n'est jamais sûr que tous les « clients » le mettent en œuvre, il est difficile de savoir si on peut compter dessus (dans Unbound, trust-anchor-file: "/etc/unbound/root.key" installe une clé de confiance statique et auto-trust-anchor-file: "/var/lib/unbound/root.key" - notez le auto- devant - installe une clé qui pourra être mise à jour par les procédures du RFC 5011). Ces procédures n'ont jamais été testées pour la racine.

Si on sépare KSK et ZSK, c'est normalement le bit SEP (Secure Entry Point, cf. RFC 3757) qui les distingue (dans le cas le plus courant, la ZSK aura un champ Flags de 256 et la KSK de 257 à cause du bit SEP). Ce bit n'est pas utilisé par les validateurs mais certains outils s'en servent pour trouver la KSK (par exemple le dnssec-signzone de BIND). Si on n'a qu'une seule clé, elle sert de KSK et doit donc avoir le bit SEP (autrement, le dnssec-signzone de BIND vous dira dnssec-signzone: fatal: No self signed KSK's found). Notez que certains outils ne vous laisseront pas facilement n'utiliser qu'une clé. Par exemple, avec dnssec-signzone, vous aurez le message dnssec-signzone: fatal: No non-KSK DNSKEY found; supply a ZSK or use '-z'. et vous devrez utiliser l'option indiquée pour signer quand même.

Un peu de cryptographie, maintenant. La durée de vie raisonnable d'une clé dépend de sa longueur. Le RFC suggère de décider d'une durée de vie, en tenant compte des contraintes opérationnelles, et d'en déduire la longueur. Une KSK qui a des enregistrements DS dans sa zone parente peut durer vingt ans sans problème, sauf si on désire tester régulièrement les procédures de remplacement ou sauf si la clé privée est compromise. Si on veut la remplacer régulièrement, une durée raisonnable proposée par le RFC est d'un an.

Quel algorithme cryptographique choisir ? Les quatre standardisés à l'heure actuelle (le RFC en cite trois mais ECDSA est apparu depuis), RSA, DSA et GOST sont bien connus et spécifiés et considérés comme fiables. En partie pour des raisons de performance, le RFC suggère la combinaison RSA/SHA-256 comme l'algorithme préféré (RFC 5702) et RSA/SHA-1 sinon.

Les algorithmes fondés sur les courbes elliptiques (GOST - RFC 5933 - et ECDSA - RFC 6605) ont des avantages importants sur RSA, notamment les clés et signatures plus petites. Mais très peu de résolveurs validant les gèrent et signer une zone uniquement avec ces algorithmes serait donc peu utile. D'autre part, même si le RFC ne le dit qu'en passant, les problèmes de brevet sont bien plus nombreux que pour RSA.

Si on a choisi RSA, il faut se décider pour une longueur de clé, suffisante pour résister à la cryptanalyse pendant la durée de vie de la clé (le RFC 3766 contient des calculs intéressants sur la solidité des clés). Comme le note le RFC, en dépit d'un FUD important, personne n'a encore annoncé la cryptanalyse d'une clé RSA de 1024 bits (le record publié est aux alentours de 700 bits). Et, le jour où cela arrivera, ce ne sera pas la fin de RSA mais la fin d'une seule clé. Bien sûr, la cryptanalyse progresse (et, le RFC oublie ce point, les meilleurs résultats ne sont pas forcément publiés) mais le RFC estime que les clés de 1024 bit sont encore sûres pour dix ans.

Néanmoins, utiliser des clés plus grandes est raisonnable si on veut une très longue durée de vie ou bien si on estime que le remplacement de la clé sera difficile (ce qui est certainement le cas de la clé de la racine). Pour ces cas, une clé de 2048 bits est donc utile. Attention, ce n'est pas gratuit, notamment la vérification est quatre fois plus lente et la signature huit fois moins rapide.

Certains férus de cryptographie peuvent tiquer à la pensée de n'utiliser que 1024 bits. Mais l'argument massue du RFC est celui de l'équilibre : on ne fait pas du DNSSEC pour le plaisir de la cryptographie. On le fait pour protéger quelque chose, par exemple un site Web de banque en ligne. Et ce genre de sites est en général protégé par TLS avec des clés qui ne sont souvent pas plus longues. Si un attaquant peut casser une clé de 1024 bits, il peut s'attaquer à TLS aussi bien qu'à DNSSEC. Avec des clés de 2048 bits, on blinde fortement la porte... alors que la fenêtre du rez-de-chaussée ne l'est pas toujours. Bref, si un brusque progrès de la cryptanalyse permet de casser ces clés de 1024 bits plus tôt que les dix ans indiqués, cela fera du bruit et cassera bien d'autres choses que DNSSEC.

Notons que, contrairement à son prédécesseur RFC 4641, notre RFC ne fait plus dépendre la solidité d'une clé du fait qu'elle soit largement utilisée ou pas. La cryptographie a évolué depuis le RFC 4641.

Où stocker ensuite ces clés ? Idéalement, sur une machine sécurisée et non connectée au réseau. On apporte les données sur cette machine, on signe et on repart avec les données signées pour les apporter au serveur de noms. C'est très sûr mais cela ne peut pas marcher si on utilise les mises à jour dynamiques du DNS (RFC 3007). Dans ce cas, il faut bien avoir la clé privée sur le serveur de noms (on parle de online key). C'est donc moins sûr et le RFC suggère, dans ce cas, que le serveur maître ne soit pas directement accessible de l'Internet (technique du hidden master, où le vrai maître n'est pas dans les enregistrements NS de la zone). Notez qu'une des motivations pour la séparation KSK/ZSK vient de là : avoir une KSK peu utilisée et dont la clé privée est stockéee de manière très sûre et une ZSK en ligne, plus vulnérable mais plus facile à changer.

Comme toujours en matière de sécurité, ces bons avis doivent être mis en rapport avec les contraintes opérationnelles et économiques. Ainsi, on peut sans doute améliorer la sécurité des clés en les gardant dans un HSM. Mais ces engins sont chers et pas pratiques pour les opérations quotidiennes.

Et la génération des clés ? C'est un aspect souvent oublié de la sécurité cryptographique mais il est pourtant essentiel. La clé doit être vraiment imprévisible par un attaquant et pour cela elle doit être générée en suivant les recommandations du RFC 4086 et de NIST-SP-800-90A, « Recommendation for Random Number Generation Using Deterministic Random Bit Generators ». Par exemple, avec les outils de génération de clés de BIND (dnssec-keygen), il ne faut pas utiliser l'option -r /dev/urandom en production, car elle n'utilise qu'un générateur pseudo-aléatoire. (Les HSM disposent tous d'un générateur correct.)

À noter que la version précédente de ce document, le RFC 4641 faisait une différence entre les zones DNS selon leur place dans la hiérarchie (plus ou moins haute). Cette distinction a disparu ici et les mêmes règles de sécurité s'appliquent à toutes. L'une des raisons de ce choix est qu'on ne peut pas facilement déterminer quelles zones sont importantes pour un attaquant (grossebanque.com est peut-être plus importante que le TLD .td, même si ce dernier est placé plus haut dans la hiérarchie). Cela n'empêche évidemment pas chaque gérant de zone de devoir déterminer si sa zone est critique ou pas, avant d'adapter les mesures de sécurité en conséquence.

La section 4 de notre RFC est ensuite consacrée au gros morceau de la gestion opérationnelle de DNSSEC : les remplacements de clés (key rollovers). Qu'on choisisse de faire des remplacements réguliers, pour qu'ils deviennent une simple routine, ou qu'on choisisse de n'en faire que lors d'évenements exceptionnels (comme une copie illégale de la clé), les remplacements sont une réalité et il faut s'y préparer. Par exemple, même si on décide de ne pas en faire systématiquement, il faut s'entrainer (et tester ses procédures) avec une zone de test. L'opération est délicate en raison de l'existence des caches DNS, qui vont garder la vieille information un certain temps. Personnellement, je déconseille fortement de faire les remplacements à la main : le risque d'erreur est bien trop grand. Il faut plutôt automatiser le processus, et avec un logiciel soigneusement débogué. L'expérience (mon article à la conférence SATIN en 2011) montre que les erreurs sont, elles aussi, une réalité.

Si on a décidé d'avoir deux clés, ZSK et KSK, leurs remplacements sont indépendants. Les ZSK sont les plus simples car elles peuvent être remplacées sans interaction avec la zone parente (pas d'échange d'enregistrements DS). Le RFC explique ensuite (en grand détail : je n'en donne qu'un court résumé ici) les deux méthodes connues pour remplacer une ZSK :

  • la pré-publication de la future clé,
  • et la double signature.

Dans le premier cas, on génére la nouvelle ZSK, on la publie (sans qu'elle signe quoi que ce soit) puis, lorsque le nouvel ensemble DNSKEY est dans tous les caches, on utilise la nouvelle ZSK pour signer. Une fois que les signatures faites avec l'ancienne clé ont disparu des caches, on arrête de publier l'ancienne clé. Le remplacement est terminé. Cette description très sommaire de l'algorithme suffit déjà, je crois, à montrer qu'il vaut mieux ne pas le faire à la main.

Quant à la double signature (plus rare, en pratique), elle consiste à signer tout de suite avec la nouvelle clé, tout en continuant à signer avec l'ancienne, pour les caches ayant seulement l'ancienne clé.

La section 4.1.1.3 résume les avantages et inconvénients de chaque méthode. La pré-publication nécessite davantage d'étapes (ce qui est grave si on la fait à la main, et moins si on a tout automatisé). La double signature est plus coûteuse puisque la zone sera, pendant la période transitoire, bien plus grosse (les signatures forment l'essentiel de la taille d'une zone signée). Dans les deux cas, comme il n'y a pas besoin d'interagir avec la zone parente, le processus peut être entièrement automatisé et c'est bien ce que fait, par exemple, OpenDNSSEC.

Et pour remplacer une KSK ? La double signature devient alors plus intéressante, puisque la KSK ne signe pas toute la zone, seulement l'ensemble d'enregistrements DNSKEY. Les problèmes de taille ne se posent donc pas. Par rapport au remplacement d'une ZSK, la grosse différence est l'interaction avec la zone parente. Il n'existe pas d'API standard pour le faire. Les bureaux d'enregistrement (BE) utilisent en général EPPRFC 5910 - avec le registre mais le gestionnaire de la zone, avec son BE, a typiquement une interface Web, ou bien une API non-standard, par exemple à base de REST (cf. aussi la section 4.3.2). L'opération nécessite donc souvent une intervention manuelle comme décrit dans mon article sur un exemple avec OpenDNSSEC.

Et si on a une clé unique ? Le cas est proche de celui d'un remplacement de KSK et le RFC recommande la double-signature, car c'est la solution la plus simple (et, si on n'utilise qu'une clé, c'est qu'on aime la simplicité).

La section 4.2 couvre le cas des préparatifs pour un remplacement d'urgence. On arrive le lundi matin au bureau, le coffre-fort est grand ouvert et la clé USB qui stockait la clé privée a disparu (une variante moins gênante est celle où la clé privée est détruite, mais pas copiée, par exemple en raison d'un incendie). Il faut alors remplacer cette clé et c'est bien plus facile si on a planifié avant. Notez qu'il y a toujours un compromis ici : si on supprime immédiatement l'ancienne clé, désormais compromise, une partie des résolveurs (ceux qui ont les anciennes signatures, mais pas l'ancienne clé) dans leurs caches considéreront la zone comme invalide. Mais, si on continue à diffuser l'ancienne clé, on augmente la durée pendant laquelle le voleur pourra injecter des informations mensongères. Il existe une méthode intermédiaire, faire retirer l'enregistrement DS par la zone parente. Selon les TTL en jeu, cela peut permettre de diminuer la durée du problème. Comme on le voit, il vaut mieux faire les calculs, l'analyse et le choix de la meilleure méthode avant le fatal lundi matin...

Une solution possible est d'utiliser des Standby keys, qui seront publiées (et donc dans tous les caches) mais pas utilisées pour signer, et dont la partie privée sera gardée à un endroit différent.

Le problème est évidemment plus grave si la clé en question avait été configurée par certains comme clé de confiance dans leurs résolveurs. Il faut alors prévenir tout le monde de la compromission, par un message (authentifié) envoyé à plusieurs endroits, pour maximiser les chances de toucher tout le monde. Si la clé de la racine (ou d'un grand TLD comme .net) était compromise, on verrait sans doute l'annonce sur dns-operations, NANOG, Twitter, etc. Outre l'authentification de l'annonce, la nouvelle clé devra elle aussi être authentifiée, par un moyen non compromis : ne mettez pas la partie privée de la KSK dans le même coffre-fort que la partie privée de votre clé PGP !

Autre cas amusant pour les gérants d'une zone DNS, le changement d'opérateurs. Par exemple, le titulaire d'une zone décide de passer d'un hébergeur DNS à un autre (notez que l'hébergeur est souvent le BE mais ce n'est pas obligatoire). Si les deux hébergeurs (en pratique, c'est évidemment le perdant qui fait des histoires) coopèrent, le problème est relativement simple. Le RFC suppose que l'ancien hébergeur ne va pas transmettre la clé privée (si elle est dans un HSM, il ne peut tout simplement pas). Dans ce cas, l'ancien hébergeur doit mettre dans la zone la clé publique du nouveau, et les signatures calculées par le nouveau avec ses clés. Le nouvel opérateur publie la même zone et, une fois le changement terminé (une fois que les clés du nouvel hébergeur sont dans tous les caches), le nouvel hébergeur peut retirer les clés et les signatures de l'ancien. Ce n'est pas très pratique (il faut échanger clés publiques et signatures). Personnellement, je trouve cet algorithme tout à fait irréaliste. Dans le DNS d'aujourd'hui, des obligations bien plus modérées (en cas de changement d'hébergeur, continuer à servir la zone jusqu'à ce que les TTL sur les enregistrements NS expirent) ne sont jamais respectées par les hébergeurs perdants, même lorsqu'elles figurent dans les obligations contractuelles. Le RFC note à juste titre que c'est un problème économique et qu'il n'a pas de solution technique.

Il reste donc le cas qui sera sans doute le plus probable, celui où l'ancien hébergeur de la zone DNS ne coopérera pas. (Techniquement, il peut même saboter activement le transfert, en publiant un enregistrement DNSKEY avec un très long TTL, pour « empoisonner » les caches.) La seule solution est alors de passer par une phase où la zone ne sera pas sécurisée par DNSSEC : le parent retire l'enregistrement DS, on attend que l'ancien DS ait disparu des caches, puis on en remet un, pointant vers une clé du nouvel hébergeur.

Quelques mesures techniques dans les résolveurs validants peuvent aider :

  • Limiter les TTL qu'on accepte (RFC 2308) pour diminuer le risque d'obstruction,
  • Vérifier la délégation lorsque les enregistrements NS vont expirer, pour être sûr de ne pas rester bloqué sur de vieux serveurs de noms (c'est également une protection contre l'attaque des domaines fantômes),
  • Lorsque la validation échoue, réessayer après avoir viré les DNSKEY du cache.

Le gérant de la zone peut aussi aider en n'ayant pas des TTL trop longs.

Gérer proprement du DNSSEC impose une grande rigueur sur les questions temporelles. Avant DNSSEC, le temps dans le DNS était toujours relatif. Par exemple, le champ Expire de l'enregistrement SOA était relatif au moment de la dernière synchronisation avec le serveur maître. Même chose pour les TTL. Mais, avec DNSSEC, le temps devient absolu. Les dates de début et de fin de validité dans un enregistrement RRSIG, par exemple, sont absolues. Elles dépendent donc d'une horloge à l'heure.

Quelques conseils, donc, sur le temps :

  • La période de validité des signatures devrait être au moins égale au TTL (autrement, des signatures encore dans le cache pourraient être expirées),
  • Ne pas attendre le dernier moment pour re-signer. Cela laisse un délai pour corriger d'éventuels problèmes. Par exemple, si les signatures ont en permanence deux jours de validité devant elles, cela permet de survivre pendant un week-end, en cas d'incapacité à re-signer.
  • Ne pas mettre de TTL trop bas (du genre 5 minutes) à la fois à cause de la charge sur les serveurs et aussi parce que la validation DNSSEC nécessite de récupérer beaucoup d'enregistrements et qu'il ne faut pas que leur TTL expire avant que le processus ne soit terminé.
  • Pour une zone signée, avoir un Expire (dans le SOA) plus long que la durée de validité des signatures ne sert pas à grand'chose : un serveur esclave qui servirait des signatures qui ne sont plus valides serait pire qu'un serveur esclave qui ne servirait plus rien.

Bon, mais alors, quelle durée choisir pour la validité des signatures (les outils de signature de BIND mettent un mois, par défaut). C'est un compromis : une durée trop longue et on est vulnérable aux attaques par rejeu. Une durée trop courte et on risque de n'avoir pas assez de temps pour réagir en cas de problème. Une erreur dans la configuration du pare-feu, les serveurs esclaves qui ne peuvent plus se synchroniser, les signatures sur ces serveurs esclaves qui expirent et crac, la zone est invalide. Cela arrive vite. Mon opinion personnelle est qu'aujourd'hui, les procédures ne sont pas assez testées et l'expérience DNSSEC est insuffisante. Il faut donc jouer la sécurité et avoir des durées de validité longues (au moins deux semaines). Dans le futur, au fur et à mesure de la montée en compétence et de l'amélioration des logiciels, on pourra mettre des durées de validité des signatures plus courtes, fermant ainsi la porte aux attaques par rejeu.

Voilà, nous avons couvert le gros de ce RFC. La section 5, qui suit, se consacre à un problème rigolo, celui des enregistrements indiquant l'enregistrement suivant, les enregistrements next. L'un des choix importants de conception de DNSSEC était de permettre que les signatures se fassent entièrement hors-ligne. On ne pouvait donc pas prévoir toutes les questions posées au serveur et avoir une signature pour toutes les réponses « ce domaine n'existe pas ». Il y a donc des enregistrements qui disent « il n'y a pas de domaine ici », enregistrements qui sont signés pour qu'un résolveur validant puisse authentifier une réponse négative. Ces enregistrements next sont le NSEC et le NSEC3. Le premier est en clair (il indique le nom de l'enregistrement suivant celui qui n'existe pas), le second est brouillé (il indique le condensat suivant le condensat du nom qui n'existe pas). Pour l'administrateur, les NSEC sont plus pratiques, notamment au débogage. Mais ils permettent la récupération complète de la zone, en marchant de NSEC en NSEC.

Le choix entre NSEC et NSEC3 dépend du type de la zone. Si on a une petite zone au contenu prévisible (juste l'apex, un mail et un www, ce qui est le cas de très nombreuses zones), aucune raison d'utiliser NSEC3. Même chose si la zone est très structurée et donc très prévisible (ip6.arpa, ENUM...). Même chose si la zone est publique, ce qui est le cas par exemple de la racine (il existe une autre raison d'utiliser NSEC3, l'opt-out, qui intéresse surtout les grandes zones de délégation comme certains TLD). Autrement, si on n'est dans aucun de ces cas, si on est une assez grande zone au contenu imprévisible et qui n'est pas publique, il est cohérent d'utiliser NSEC3 (RFC 5155).

NSEC3 a certains paramètres à configurer (et qui sont publiés dans l'enregistrement NSEC3PARAM). Notamment, on peut définir le nombre d'itérations de hachage. Cette possibilité protège des attaques par dictionnaires pré-calculés mais elle est coûteuse et elle mène à l'exécution de code à chaque requête pour un nom inexistant. Le RFC suggère un nombre de 100 itérations, ce qui est colossal par rapport à ce que font la plupart des zones NSEC3 aujourd'hui (5 par défaut avec OpenDNSSEC, mais beaucoup l'abaissent, on trouve 1 pour .fr et .com, et même 0 pour .org...) NSEC3 ajoute un sel au début de l'itération et notre RFC suggère de changer ce sel en même temps que la ZSK.

Les changements depuis le RFC 4641 sont résumés dans l'annexe E. D'abord, les erreurs connues ont été corrigées. Ensuite, la fonction de hachage SHA-256 a été ajoutée aux recommandations. La partie sur le changement d'hébergeur DNS a été ajoutée. Le modèle avec séparation KSK/ZSK ne bénéficie plus d'un privilège particulier puisque le modèle avec une seule clé est également décrit.

(Les juristes noteront que VeriSign a un brevet sur certaines des techniques présentées dans ce RFC.)


Téléchargez le RFC 6781


L'article seul

RFC 6778: IETF Email List Archiving, Web-based Browsing and Search Tool Requirements

Date de publication du RFC : Octobre 2012
Auteur(s) du RFC : R. Sparks (Tekelec)
Pour information
Première rédaction de cet article le 31 octobre 2012
Dernière mise à jour le 31 janvier 2014


Ce RFC est le cahier des charges de l'outil d'accès aux archives des innombrables listes de diffusion de l'IETF. Le gros du travail de cette organisation repose sur ces listes de diffusion, dont la plupart sont publiques, archivées et accessibles via le Web. Cette masse d'information est un outil formidable pour comprendre les décisions de l'IETF et les choix techniques effectués. Mais son volume rend l'accès à l'information souvent difficile. L'IETF se vante de sa transparence (tout le travail est fait en public) mais avoir toutes les discussions accessibles ne suffit pas, si l'information est trop riche pour être analysée. D'où l'idée de développer une ensemble d'outils permettant d'accéder plus facilement à ce qu'on cherche. C'est désormais accessible en https://mailarchive.ietf.org/.

Avant, la recherche était particulièrement difficile si une discussion s'étendait sur une longue période et surtout si elle était répartie sur plusieurs listes. Imaginons un auteur d'un RFC, un président de groupe de travail, ou un simple participant, qui veut retrouver toutes les discussions qui ont concerné un Internet-draft donné. Il va trouver des messages dans la liste du groupe de travail mais aussi dans celles d'une ou plusieurs directions thématiques, et peut-être aussi dans la liste générale de l'IETF. Certains ont chez eux des copies de toutes ces listes (copies parfois incomplètes) pour utiliser des outils locaux. (Au fait, personnellement, je me sers surtout de grepmail et je cherche encore un outil qui indexerait les données.)

En l'absence de copie locale, notre participant IETF courageux va compter sur la force brute, ou bien va essayer un moteur de recherche généraliste (mais il est ennuyeux pour l'IETF de devoir compter sur un outil externe pour son propre travail).

Ce n'est pas qu'il n'existait aucun outil à l'IETF. Il y a des solutions proposées sur le site de l'IETF (l'option Email Archives Quick Search). Mais elles ne couvrent pas tous les besoins, loin de là.

Quels sont ces besoins ? La section 2 en donne la liste. D'abord, il faut une interface Web. Elle doit permettre de naviguer dans un fil de discussion donné, ou suivant la date. (Les outils d'archivage classique comme MHonArc permettent déjà tous cela.) Les fils doivent pouvoir être construits en suivant les en-têtes prévus à cet effet (References: et In-Reply-To:) mais aussi en se fiant au sujet pour le cas où les dits en-têtes auraient été massacrés en route, ce qui arrive.

Surtout, il faut une fonction de recherche. Elle doit fonctionner sur une liste, ou un ensemble de listes, ou toutes les listes. Elle doit permettre d'utiliser ces critères :

  • Nom ou adresse de l'expéditeur,
  • Intervalle de dates,
  • Chaîne de caractères dans le sujet ou dans le corps du message,
  • Chaîne de caractères dans un en-tête quelconque. Le plus important est bien sûr le Message-ID: lorsqu'on veut donner une référence stable d'un message (« ton idée a déjà été proposée dans <5082D93B.6000308@cnam.fr> »). Le but est de pouvoir faire circuler une référence comme http://datatracker.ietf.org/mlarchive/msg?id=5082D93B.6000308@cnam.fr.

Et de les combiner avec les opérateurs booléens classiques (AND, OR et NOT).

Il n'y a pas que la recherche dans la vie, on voudrait aussi évidemment avoir des URI stables pour chaque message (stables et beaux). Et cet URL devrait être mis dans le champ Archived-At: du message avant sa distribution (cf. RFC 5064).

À propos d'URI, comme indiqué dans l'exemple de recherche via un Message-ID: montré plus haut, notre RFC demande que les recherches soient représentables par un URI, qui puisse être partagé (et qui soit donc stable). Le RFC ne donne pas d'exemple mais cela aurait pu être quelque chose comme http://datatracker.ietf.org/mlarchive/search?subject=foobar&startdate=2002-05-01&enddate=2004-06-01&author=smith (dans la version publiée, c'est en fait quelque chose comme https://mailarchive.ietf.org/arch/search/?qdr=a&q=text%3A%28eszett%29&as=1&f_list=precis%2Cxmpp). Naturellement, « stabilité » fait référence à l'URI, pas au résultat, qui peut varier dans le temps (par exemple si des nouveaux messages arrivent).

La plupart des archives à l'IETF sont publiques et doivent être accessibles anonymement mais quelques unes nécessitent une autorisation. Dans ce cas, le cahier des charges demande que le système d'authentification utilisé soit celui de datatracker.ietf.org.

Difficulté supplémentaire, toutes les listes IETF ne sont pas gérées au même endroit et par le même logiciel. Les listes hébergées à l'IETF le sont avec mailman mais il existe aussi des listes hébergées ailleurs et notre cahier des charges demandent qu'elles puissent être intégrées dans ce système de recherche (par exemple en abonnant l'adresse du programme d'archivage à la liste).

Il y a aussi des cas où des archives de listes de diffusion deviennent accessibles alors qu'elles ne l'étaient pas avant et doivent être incorporées dans le corpus géré par le nouveau système. Le RFC demande qu'au moins le format d'entrée mbox (RFC 4155) soit accepté. Et qu'il serait souhaitable d'accepter aussi le maildir.

En sens inverse, le système doit permettre d'exporter les messages (un système ouvert ne l'est pas si on ne peut pas en sortir l'information pour la garder et l'étudier chez soi ; la fonction d'exportation n'a pas qu'un intérêt technique, elle est aussi un moyen de garantir la pérénnité de l'information publique). On doit pouvoir exporter une liste entière, une liste pour un intervalle de temps donné et, dans le meilleur des cas, le résultat d'une recherche (une vue, pour employer le langage des SGBD). Là encore, l'exportation en mbox est impérative et celle en maildir souhaitée.

Voilà, c'est tout, l'appel d'offres formel de l'IAOC était en ligne. Plus rigolo pour le programmeur de cet ambitieux projet : la section 3 lui rappelle qu'il devrait se préparer à l'arrivée du courrier électronique internationalisé... Le produit final a été livré le 29 janvier 2014 et est disponible en https://mailarchive.ietf.org/.


Téléchargez le RFC 6778


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 6771: Considerations for Having a Successful "Bar BOF" Side Meeting

Date de publication du RFC : Octobre 2012
Auteur(s) du RFC : L. Eggert (NetApp), G. Camarillo (Ericsson)
Pour information
Première rédaction de cet article le 18 octobre 2012


Autrefois, du temps des débuts de l'IETF, les seules réunions ayant un statut officiel étaient les réunions formelles des groupes de travail. Avec le temps, elles sont devenues tellement formelles (et n'ayant plus guère de rapport avec un « groupe de travail ») qu'un type de réunions plus légères est apparu petit à petit, les BOF (Birds Of a Feather). Les BOF étaient au début simples et faciles à organiser, comme l'étaient les groupes de travail des débuts. Mais elles se sont ossifiées petit à petit, devenant aussi formelles qu'un groupe de travail, et ayant même leur propre RFC, le RFC 5434. Continuant cette évolution logique, des participants à l'IETF ont créé un mécanisme léger alternatif aux BOF, les Bar BOF, qui étaient comme leur nom l'indique, des réunions faites au bistrot. Maintenant, on parle de fixer des règles pour les bar BOF...

Les bar BOF sont fréquentes pendant les réunions physiques de l'IETF. Elles se réunissent souvent dans un bar, d'où elles tirent leur nom, et permettent de discuter de manière complètement informelle, de nouvelles idées qui donneront peut-être naissance plus tard à un groupe de travail, voire à un ou plusieurs RFC. Elles ne sont pas mentionnées dans l'agenda officiel et n'ont aucun statut particulier. N'importe qui peut organiser une bar BOF comme il veut (alors que l'organisation d'une BOF est désormais toute une affaire, décrite dans le RFC 5434). Elles ont déjà été mentionnées dans un RFC, le fameux Tao (RFC 6722).

La malédiction se poursuivant, certaines bar BOF sont devenues tellement formalistes qu'on peut se demander si certains ne réclameront pas bientôt statuts et règles pour ces réunions. Ce RFC 6771 essaie de bloquer cette tendance, en plaidant pour que les bar BOF restent complètement an-archiques.

Car ce n'est pas le cas : on voit de plus en plus de bar BOF tenues dans les salles de réunion (et plus au café), avec les chaises organisées comme dans une salle de classe, des orateurs situés sur l'estrade, un tour de parole, des présentations faites avec PowerPoint et, surtout, plus de boissons du tout...

Ce RFC signale que cette évolution peut être due en partie au fait que le terme bar BOF est trop proche de BOF et que les débutants mélangent les BOF (dotées d'un statut, celui du RFC 5434) et les bar BOF. C'est au point que certains participants, voulant aboutir à la création d'un groupe de travail, se sentent obligés de faire une bar BOF uniquement parce qu'ils croient qu'une règle de l'IETF impose cette étape ! Les auteurs du RFC recommandent donc de parler plutôt de « réunion parallèle » (side meeting).

Et, pour que ces réunions parallèles se passent bien, notre RFC 6771 propose quelques conseils. D'abord (section 2), comment gérer les invitations. Une réunion parallèle doit être petite (« uniquement les gens nécessaires et pas plus »). Il ne s'agit pas, comme c'est souvent le cas pour les BOF, de sonner le clairon pour ramener le maximum de gens, espérant ainsi montrer que le sujet est considéré comme important par la communauté. On ne devrait donc pas faire d'annonce publique d'une réunion parallèle (par exemple, sur une liste de diffusion). Si on le fait, on risque de manquer de chaises dans le bar, et de ne pas pouvoir s'entendre d'un bout de la réunion à l'autre, menant à des réunions excessivement formelles, avec tour de parole. (Plusieurs bar BOF ont déjà souffert de ce syndrôme « apéro Facebook ».)

Bref, pas de touristes à une réunion parallèle, uniquement « a few good people », des gens qui vont activement participer au travail (l'IETF ne décide normalement pas sur la base du nombre de participants mais sur le nombre de gens qui vont effectivement bosser). L'implication plus large de la communauté viendra après. La réunion parallèle doit avant tout rester du remue-méninges, chose qui ne se fait pas dans des grands groupes. Par définition, les idées exprimées lors d'une réunion parallèle sont incomplètes et imparfaites et il faut pouvoir les discuter franchement.

De même, on n'est pas obligé d'inviter un membre de l'IESG ou de l'IAB en croyant que cela fera plus sérieux et plus crédible.

Après le Qui, la section 3 couvre la question du Où. Comme leur nom l'indique, les bar BOF se tiennent traditionnellement dans les bars. Mais la tendance récente est de la faire souvent dans les salles d'une réunion IETF, en partie parce que cela fait plus « sérieux ». Notre RFC, qui n'hésite pas à descendre dans les détails concrets, note que les bars sont souvent bruyants, ce qui pose un problème notamment pour les non-anglophones (le bruit gène beaucoup plus lorsque la conversation est dans une langue étrangère). Pour garder la convivialité, en supprimant le bruit, le RFC recommande de choisir un restaurant calme, voire de prendre une arrière-salle du bar. Les salles de la réunion IETF sont en général trop « salle de classe », un environnement qui ne convient pas au remue-méninges entre pairs. Cet environnement est bon pour les présentations, pas pour les discussion.

Toujours concret, le RFC note enfin que se réunir dans un bar ou un restaurant permet souvent de... manger. En effet, certaines réunions IETF se tiennent dans des endroits où le ravitaillement est difficile et la réunion d'Anaheim (IETF 77) a ainsi laissé un souvenir particulièrement cuisant. Sortir est donc souhaitable.

Après le Qui et le Où, le Comment. La section 4 s'insurge contre la tendance de plus en plus marquée à singer les réunions des groupes de travail. On voit ainsi des réunions parallèles ayant un agenda formel, des présentations avec supports, des organisateurs qui se présentent comme bar BOF chair. Les auteurs de notre RFC craignent que ce cirque provoque des réactions pavloviennes chez les participants, les faisant se comporter comme si la réunion parallèle était déjà devenue un vrai groupe de travail. Ces réunions qui caricaturent les réunions officielles ne sont pas très efficaces, et elles entraînent des confusions chez certains participants qui croient qu'il s'agit de réunions officielles, simplement parce qu'elles en ont l'apparence.

Enfin, le Quand, en section 5. La principale recommendation est que les réunions parallèles, comme elles visent à commencer le travail pour résoudre un problème précis, n'ont pas forcément vocation à être toujours parallèles à une réunion IETF, elles peuvent parfaitement se tenir en parallèle d'une réunion RIPE, NANOG ou équivalent.

Et une anecdote amusante : comme obligatoire, ce RFC a une section « Sécurité ». Elle contient l'avertissement qu'on a constaté un oubli fréquent des portables dans les bars, après une réunion parallèle trop arrosée...


Téléchargez le RFC 6771


L'article seul

RFC 6770: Use Cases for Content Delivery Network Interconnection

Date de publication du RFC : Novembre 2012
Auteur(s) du RFC : G. Bertrand (France Telecom - Orange), E. Stephan (France Telecom - Orange), T. Burbridge, P. Eardley (BT), K. Ma (Azuki Systems), G. Watson (Alcatel-Lucent - Velocix)
Pour information
Réalisé dans le cadre du groupe de travail IETF cdni
Première rédaction de cet article le 20 novembre 2012


Le groupe de travail CDNI de l'IETF travaille à normaliser les interfaces entre CDN pour permettre à deux de ces systèmes de distribution de contenu de coopérer pour servir un client. Ce second RFC du groupe (le premier, le RFC 6707, décrivait en détail le problème à résoudre et l'état de l'art) rassemble trois études de cas, illustrant ainsi par ces scénarios l'utilité du travail du groupe.

Un ancien effort de normalisation des CDN à l'IETF avait eu lieu, produisant des documents comme le RFC 3570, qui décrivait déjà des scénarios d'usage. Ce nouveau RFC remplace ce RFC 3570 ; la terminologie est notamment très différente et reprend celle du RFC 6707. Conjointement avec ce RFC 6707, il va servir de base au document « cahier des charges » du groupe de travail CDNI, qui sera publié en RFC 7337.

Interconnecter des CDN offre en théorie de nombreux avantages : améliorer le vécu de l'utilisateur (temps de réponse plus courts, voir le RFC 6390) et diminuer les coûts pour l'opérateur (on n'utilise que le réseau interne au lieu des lignes extérieures) notamment. Mais, actuellement, chaque CDN fonctionne de manière indépendante des autres, ce qui fait qu'il n'est pas toujours possible de récolter ces bénéfices. Voyons les trois études de cas.

D'abord (section 2), le cas d'un CDN qui a une couverture géographique insuffisante. Un opérateur de CDN est présent dans une région donnée (mettons l'Europe) mais ne peut pas fournir de service aux lecteurs en Asie ou en Amérique. Et imaginons un autre opérateur de CDN en Amérique qui n'a pas de présence en Europe. Les interconnecter permettrait au nouvel ensemble de servir les deux continents, sans que chaque opérateur n'ait eu à supporter d'énormes investissements.

Un autre cas proche est celui où un FAI a construit un CDN en interne pour distribuer du contenu dont il a les droits. Un autre fournisseur de contenu a déjà un contrat avec un autre opérateur de CDN. Dans ce cas, le FAI va recevoir un gros trafic de la part de ce CDN, qui va saturer ses liaisons externes, alors que ce contenu pourrait être distribué plus efficacement par le CDN du FAI. Pour le FAI en question, il serait utile que cet autre CDN puisse s'interconnecter avec le CDN du FAI (section 2.3), afin d'améliorer les performances et de décongestionner les liens d'interconnexion.

Deuxième étude de cas (section 3), celle où le CDN a une couverture géographique jugée suffisante mais des capacités trop petites pour la charge. Cela peut être à cause d'une énorme augmentation temporaire de la demande (effet Slashdot, dit aussi flash crowd) par exemple suite à un événement particulier. Cet événement peut être prévu - match de football à diffuser - ou imprévu. (Le RFC cite l'exemple de la vidéodiffusion du mariage d'une célébrité ; il est triste de penser que des technologies si sophistiquées servent à de telles conneries.) Le CDN menace alors de s'écrouler sous la charge. Appelons un autre CDN à son secours ! L'idée est que le gestionnaire du CDN trop petit va payer un autre CDN, s'interconnecter à lui, et que les deux CDN feront face ensemble à la charge. (Une autre solution serait d'agrandir le CDN, mais, avec l'interconnexion des CDN, on peut prendre des marges de dimensionnement moins importantes, sans pour autant perdre sa capacité de faire face à d'éventuels pics de trafic.)

Une variante de ce cas est la résilience en cas de problème, par exemple une attaque par déni de service ou une panne massive d'une partie d'un CDN (section 3.2). S'interconnecter à un autre CDN permet alors de continuer à fonctionner. Actuellement, chaque CDN doit se débrouiller seul en cas de panne.

Dernière étude de cas (section 4), celui où le CDN n'a, ni problème de couverture géographique, ni problème de capacité, mais un problème de fonctions : le client a des exigences techniques particulières que le CDN ne sait pas remplir. Par exemple, un CDN sert du contenu en HTTP mais un client réclame qu'une partie du contenu soit servie en HTTPS (qui, entre autres, nécessite des processeurs plus rapides, pour les calculs cryptographiques) qu'il ne sait pas faire. S'allier avec un CDN qui, lui, sait faire du HTTPS, permettrait de rendre le client heureux (en lui évitant de signer deux contrats). Autre exemple donné par le RFC (mais peu convaincant depuis l'échec ridicule de WAP), celui d'un client qui demanderait tout à coup un protocole de distribution qui soit spécifique aux engins mobiles, alors que le CDN habituel de ce client n'a pas mis en œuvre ce protocole.

Et, bien sûr, exemple évident, un CDN qui serait toujours, en 2012, uniquement en IPv4 et à qui des clients réclameraient qu'il utilise enfin un protocole de ce siècle, IPv6. Sous-traiter la distribution en IPv6, par le biais des protocoles d'interconnexion que concevra le groupe de travail CDNI, permettrait au CDN IPv4 d'attendre encore un peu.

Plus subtil, le cas où le CDN peut distribuer le contenu avec le protocole demandé, mais pas avec les exigences quantitatives du client (par exemple portant sur la latence). S'associer avec un autre CDN, meilleur de ce point de vue, peut être utile.

Dans ces trois cas, si on pouvait facilement interconnecter des CDN, tout irait bien et les oiseaux chanteraient plus mélodieusement. Mais, à l'heure actuelle, une telle interconnexion se heurte à l'absence totale de normes techniques (cf. RFC 6707). Chaque fois que deux CDN s'interconnectent, ils doivent développer du code spécifique à ce couple. C'est justement le travail du groupe CDNI que de spécifier ces normes techniques, en attendant leur futur développement et déploiement. Une fois que cela sera fait, l'interconnexion de deux CDN ne sera plus « que » une affaire de business... (Comme l'accord Orange/Akamai annoncé le même jour que le RFC...)

Ah, un petit point à ne pas oublier (section 5), l'application de politiques de distribution restrictives. C'est une demande courante des clients (distribuer une vidéo en Amérique du Nord seulement, par exemple, et donc barrer l'accès aux visiteurs d'autres régions, ou bien ne permettre l'accès gratuit que pendant 24 h). Cela ajoute une contrainte assez ennuyeuse à l'interconnexion de CDN : il faut aussi transmettre ces restrictions. L'annexe A.1 traite en détail ce problème.

Dernier problème lors de l'interconnexion, la marque (branding), vue en annexe A.3. Un CDN qui fait appel à un autre pour traiter une partie de son travail peut souhaiter que sa marque apparaisse quand même (par exemple, URL avec son nom de domaine). La solution d'interconnexion doit donc penser à fournir une solution à ce problème.

Merci à Gilles Bertrand pour sa relecture.


Téléchargez le RFC 6770


L'article seul

RFC 6769: Simple Virtual Aggregation (S-VA)

Date de publication du RFC : Octobre 2012
Auteur(s) du RFC : R. Raszuk (NTT MCL), J. Heitz (Ericsson), A. Lo (Arista), L. Zhang (UCLA), X. Xu (Huawei)
Pour information
Réalisé dans le cadre du groupe de travail IETF grow
Première rédaction de cet article le 25 octobre 2012


Un des gros problèmes des routeurs de la DFZ, dans l'Internet d'aujourd'hui, est l'augmentation du nombre de routes. Il y a, en octobre 2012, environ 450 000 routes dans cette DFZ et ce nombre croît sans cesse. Ces routes doivent être mises en mémoire et la mémoire d'un routeur du cœur de l'Internet est quelque chose de compliqué, qu'on ne veut pas gaspiller. Des tas d'approches ont été proposées pour traiter ce problème. Ce RFC propose un moyen astucieux de limiter les dégâts, en permettant au routeur d'agréger les routes pour les préfixes IP proches. Ce RFC est donc très court car l'idée est simple.

Attention au terme de « table de routage », trop vague. Un routeur met des routes dans au moins deux tables, la RIB (Routing Information Base, la base constituée par les protocoles de routage, BGP et ses copains OSPF et IS-IS) et la FIB (Forwarding Information Base, typiquement placée dans la CAM car elle doit être très rapide, elle est consultée à chaque paquet). Actuellement, le routeur typique met toutes les entrées de sa RIB dans sa FIB. C'est sous-optimal car la RIB a beaucoup plus d'entrées que le routeur n'a de voisins réseau (des centaines de milliers de routes contre parfois seulement dix ou vingt routeurs voisins). Comme la taille de la FIB est souvent un facteur limitant (ce n'est pas le seul, donc ce RFC ne résout pas tous les problèmes de taille), il serait intéressant d'agréger violemment, en découplant RIB et FIB. Par exemple, si la RIB contient une entrée pour 2001:db8:16::/48 et une autre pour 2001:db8:17::/48, et que les deux vont vers le même voisin (ont le même next hop), mettre les deux entrées dans la FIB est du gaspillage, une seule entrée, pour 2001:db8:16::/47, suffirait. (Et le calcul pour déterminer ce qu'on peut agréger est simple.)

Au passage, on peut agréger dans la FIB mais moins dans la RIB car cette dernière doit être transmise aux routeurs pairs avec qui on échange des routes. Si on agrège, c'est une « compression avec perte » et les pairs ne recevront donc pas toute l'information. Néanmoins, ce RFC permet également de ne pas installer de routes dans la RIB. Celle-ci est typiquement dans une mémoire moins coûteuse mais on souhaite diminuer, non seulement la consommation mémoire mais également le rythme de changement. Moins on aura de préfixes, moins on aura de changements à gérer.

L'avantage de l'approche naïve ci-dessus est qu'elle est déployable unilatéralement : chaque routeur peut le faire dès aujourd'hui sans rien demander à personne. Son principal inconvénient est que la RIB n'est pas statique : si BGP change le next hop (le routeur suivant pour acheminer le paquet) de 2001:db8:17::/48, il faut désagréger en vitesse et mettre deux entrées dans la FIB.

L'approche de ce RFC est donc un peu différente : certains routeurs de l'AS vont annoncer des préfixes virtuels (VA prefix pour Virtual Aggregation prefix). Ils seront transmis, à l'intérieur de l'AS uniquement, par les protocoles de routage habituels et tous les routeurs vont l'avoir dans leur RIB. Ces préfixes virtuels couvrent plusieurs préfixes « réels ». Les routeurs qui veulent économiser de la mémoire ne vont pas installer les préfixes réels couverts dans leur FIB. Notez bien que les préfixes virtuels ne sont pas annoncés en dehors de l'AS. Si cette solution n'est plus déployable par un routeur seul, elle l'est par un AS seul.

Un opérateur réseau va donc typiquement avoir quelques très gros routeurs qui auront dans leur FIB (et dans leur RIB) tous les préfixes. Ils annonceront en plus les préfixes virtuels. Les autres routeurs, moins gros et moins coûteux, garderont tous les préfixes uniquement dans leur RIB et ne mettront pas dans la FIB les préfixes qui sont couverts par un des préfixes virtuels. Le préfixe virtuel pourra même être la route par défaut, entraînant ainsi la non-installation dans la FIB de tous les préfixes ayant le même next hop que la route par défaut.

Un peu de vocabulaire, maintenant (section 1.1) : un FIR (FIB Installation Router) est un des gros routeurs de cœur, qui installe toutes les routes dans sa FIB, et annonce les préfixes virtuels. Un FSR (FIR Suppressing Router) est un routeur situé plus aux marges du réseau et qui n'installe pas dans sa FIB les routes couvertes par un préfixe virtuel, si elles ont le même next hop que le préfixe virtuel. (Le RFC dit « supprimer une route » pour « ne pas l'installer dans la FIB ».) Une troisième catégorie de routeurs est composé des machines actuelles, qui ne connaissent pas ce RFC, et ne peuvent donc ni émettre les préfixes virtuels, ni supprimer des routes couvertes par un tel préfixe.

La section 2 décrit en détail le fonctionnement de ce système. Un FIR doit annoncer les préfixes virtuels en mettant dans les attributs de l'annonce BGP un ORIGIN (RFC 4271, section 5.1.1) à INCOMPLETE (pour dire que la route n'a pas été apprise par un protocole de routage). Il doit mettre NEXT_HOP (RFC 4271, section 5.1.3) à l'adresse du routeur qui gérera toutes les routes du préfixe virtuel. Et il doit ajouter un attribut NO_EXPORT (RFC 1997) pour éviter que ce préfixe virtuel ne sorte de l'AS.

Le FSR, lui, lorsqu'il reçoit de telles routes, les installe dans RIB et FIB. Il peut alors décider de supprimer de sa FIB les routes plus spécifiques ayant le même next hop. Comme vous le voyez, c'est très simple.

La section 3 du RFC se penche sur les problèmes opérationnels pratiques. D'abord, attention au fait qu'une route BGP peut être utilisée pour résoudre un next hop qui n'est pas directement connecté. Il ne faudra donc pas supprimer de la RIB de telles routes.

On l'a vu, les routeurs FSR peuvent économiser de la place non seulement en FIB mais également en RIB, en supprimant de celles-ci les routes couvertes par un préfixe virtuel. Attention, cela peut interagir avec une politique de redistribution de routes aux pairs. Si une telle politique est en place (fondée, par exemple, sur la longueur du préfixe) on peut avoir des cas où la route couverte aurait été redistribuée mais où le préfixe virtuel ne l'est pas. Dans ce cas, il ne faut pas supprimer la route couverte de la RIB (on peut toujours la supprimer de la FIB).

À noter que le groupe de travail grow avait également travaillé sur des mécanismes d'agrégation plus complexes (avec des tunnels MPLS pour joindre les routeurs annonçant les préfixes virtuels) mais que cela n'a pas abouti. Les Internet-Drafts ont été abandonnés. Un bon article de fond sur cette idée d'« agrégation virtuelle » est celui de Paul Francis et Xiaohu Xu (un des auteurs du RFC), « Extending Router Lifetime with Virtual Aggregation ».

Globalement, cela me semble une bonne idée. Avec les préfixes virtuels, ce n'est plus une solution locale au routeur mais c'est local à l'AS et donc ça reste déployable unilatéralement.

Merci à Sarah Nataf pour avoir attiré mon attention sur ce document et à Bastien Pilat et Benjamin Abadie pour leurs corrections.


Téléchargez le RFC 6769


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

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 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 6749: The OAuth 2.0 Authorization Framework

Date de publication du RFC : Octobre 2012
Auteur(s) du RFC : D. Hardt (Microsoft)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF oauth
Première rédaction de cet article le 13 octobre 2012


Le protocole OAuth a désormais sa seconde version, OAuth 2.0, normalisée dans ce RFC. OAuth permet de à un programme de s'authentifier sur le Web, pour accéder à un jeu limité de services, qu'un utilisateur lui a autorisé.

OAuth est donc un protocole d'authentification d'un tiers, le client, qui veut accéder à une ressource, par exemple un fichier, située sur un serveur et dont le contrôle revient à un propriétaire, le resource owner. (OpenID vise à authentifier un utilisateur humain, OAuth à authentifier la requête d'un programme, agissant pour le compte d'un humain.) Prenons un exemple (vous en trouverez d'autres dans le RFC, comme l'exemple classique de l'impression de photos, mais celui que j'indique a l'avantage d'être un exemple réel) : le service de microblogging Twitter permet à des utilisateurs (les propriétaires, dans la terminologie OAuth) de faire connaître au monde entier leurs pensées profondes en moins de 140 caractères. Le succès de ce service et l'existence d'une bonne (car très simple) API a poussé à l'arrivée de nombreux services tiers qui ont tous en commun de devoir accéder au compte Twitter de l'utilisateur (par exemple, Twibbon ou TwitterCounter). Une façon possible, pour ces services, d'accéder au compte Twitter de l'utilisateur est de lui demander son nom et son mot de passe. On voit les conséquences que cela peut avoir pour la sécurité : le service doit stocker le mot de passe (le fera-t-il de façon sûre ?), le service peut abuser de son privilège, puisqu'il a tous les droits du propriétaire, le serveur doit gérer l'authentification par mot de passe (pas la meilleure), retirer un droit d'accès à un service veut dire changer le mot de passe, retirant ainsi le droit d'accès à tous les services tiers, etc.

OAuth fournit une meilleure solution : le serveur, en recevant la requête du client, demande au propriétaire l'autorisation : twitter-oauth.png Cette demande se fait typiquement via un formulaire HTML.

Le service tiers reçoit alors un token, une autorisation qui lui est spécifique, et ne lui donne que certains droits. Il présentera ce token au serveur pour obtenir l'accès.

Tout se fait par redirections HTTP (RFC 7231, section 6.4 et ce RFC 6749, section 3). Bien sûr, pour que cela soit sûr, il y a de nombreux détails à prendre en compte.

Si OAuth v1 (RFC 5849) était juste l'officialisaton à l'IETF d'un protocole qui avait été développé à l'extérieur, cette nouvelle version 2 marque des changements profonds, et incompatibles avec l'ancienne version. C'est d'abord une refonte de la norme, d'un seul document à un ensemble dont ce nouveau RFC 6749 n'est que le document de cadrage. Les documents décrivant effectivement le protocole ne sont pour la plupart pas encore parus (il y a par exemple un projet de RFC sur les scénarios d'usage, et un entièrement consacré à la sécurité, via une études des menaces portant sur OAuth). Seuls les RFC 6750, sur un type particulier de token, et RFC 6755 sur des URN pour OAuth, accompagnent ce nouveau OAuth. C'est aussi le passage d'un protocole relativement simple à un ensemble de protocoles, partageant un cadre commun mais n'étant plus forcément interopérables (section 1.8), puisque OAuth v2 permet bien des variantes. C'est complètement contraire aux principes posés dans le RFC 6709, sur les extensions aux protocoles. Donc, attention, un service OAuth v1 ne peut pas interagir avec un serveur OAuth v2 (quand ils existeront) ou le contraire. Les programmeurs OAuth sont encouragés à repartir de zéro, vue la différence des deux protocoles.

Une fois que Twitter a adopté ce protocole (notez que, à la date de publication de ce RFC, Twitter utilise OAuth v1 et n'a pas annoncé d'intention de passer à la v2) et documenté son usage, la plupart des services tiers l'ont intégré (par exemple Twibbon).

Lisons maintenant le RFC. Premièrement, les concepts (section 1) et le vocabulaire (section 1.1). Ce qui se jouait autrefois à deux (le client et le serveur) est désormais fréquemment une partie à trois (OAuth Love Triangle, dit Leah Culver), le client (client, Twibbon dans le cas plus haut), le serveur (server, Twitter dans le cas plus haut) et le propriétaire (resource owner, moi). Notez qu'OAuth v2 a transformé le triangle en carré, en passant à quatre rôles, le serveur ayant été séparé en deux, le serveur qui contrôle l'accès à la ressource convoitée, et celui qui donne les autorisations. En pratique, on ne sait pas encore si des serveurs suivront cette séparation.

Pour voir le cheminement complet d'une authentification OAuth, on peut regarder la jolie image de Yahoo (mais attention, elle utilise une ancienne terminologie) ou bien suivre l'exemple de la section 1.2 du RFC. Si le client, le service d'impression printer.example.com veut accéder aux photos stockées sur le serveur photos.example.net, et dont le propriétaire est Jane :

  • Le client et le serveur doivent déjà avoir un accord entre eux, préalable, avec un secret partagé pour s'authentifier. OAuth ne permet pas à un nouveau client inconnu d'en bénéficier.
  • Le client doit avoir lu la documentation du serveur, qui indique entre autre les URL à contacter.
  • Lorsque Jane visite le site du client, ici l'imprimeur, et demande l'impression de ses photos, le client contacte le serveur en HTTP pour demander un token, une suite de nombres aléatoires qui identifie de manière unique cette requête (on peut voir ce token dans la copie d'écran ci-dessus, c'est le paramètre oauth_token).
  • Le client doit alors utiliser les redirections HTTP pour envoyer Jane sur le site du serveur, afin qu'elle donne l'autorisation nécessaire. Les paramètres de la redirection indiquent évidemment le token.
  • Si Jane donne son accord (cela peut être un accord implicite, voir par exemple comment fait Twitter), le serveur signe la demande et renvoie le navigateur de celle-ci vers le client avec, dans les paramètres, une demande approuvée et signée (paramètre oauth_signature).
  • Le client peut alors demander au serveur des autorisations pour les photos, puis demander les photos elle-mêmes.

Un guide complet sur OAuth v1 est disponible en http://hueniverse.com/oauth/guide/. Une autre bonne introduction à OAuth v1 est « Gentle introduction to OAuth ». Parmi les applications amusantes d'OAuth, un curl OAuthisé en http://groups.google.com/group/twitter-api-announce/browse_thread/thread/788a1991c99b66df. Un exemple de programmation OAuth v1 pour accéder à Twitter en Python figure dans mon article. Mais OAuth v2 ne bénéficie pas encore de telles documentations.

OAuth v2 a suscité de nombreuses critiques, notamment sur sa complexité. Mon pronostic est qu'OAuth v2, victime du Second System Effect, ne sera guère déployé, la grande majorité des sites Web restant à la v1.

Une bonne critique qui synthétise la plupart des remarques qui ont été faites sur OAuth v2 est « OAuth 2.0 and the Road to Hell ». Eran Hammer, l'auteur, est marqué dans l'annexe C de ce RFC comme ayant participé à OAuth v2 jusqu'à la version 26 du brouillon (la version publiée est la 31). Il a ensuite cessé sa participation au projet et s'en explique dans cet article. Ses principaux arguments :

  • Le cadre est trop général, ne permettant pas de garantir l'interopérabilité de deux mises en œuvre d'OAuth v2 (ce point est admis dans la section 1.8 de ce RFC 6749). C'est au point qu'un très grand nombre de protocoles incompatibles entre eux pourraient légitimement se nommer « conformes à OAuth »..
  • OAuth v1 était simple et utilisable, issu d'un monde de startups Web qui voulaient une solution « bien assez bonne » et tout de suite. OAuth v2 a été chargé par des exigences de PHB comme de mentionner SAML et autres technologies des « gens de l'entreprise » (par opposition aux « gens du Web »). C'est une tendance analogue qui a tué les Web Services.
  • Étant plus complexe et plus adaptable à des besoins spécifiques, OAuth v2 sera moins sûr.

Téléchargez le RFC 6749


L'article seul

RFC 6744: IPv6 Nonce Destination Option for ILNPv6

Date de publication du RFC : Novembre 2012
Auteur(s) du RFC : RJ Atkinson (Consultant), SN Bhatti (U. St Andrews)
Expérimental
Réalisé dans le cadre du groupe de recherche IRTF RRG
Première rédaction de cet article le 10 novembre 2012


Une grande partie de la sécurité d'ILNP, architecture de séparation de l'identificateur et du localisateur, dépend d'un numnique, nombre imprévisible choisi par une machine et transmis à son correspondant au début d'une session. En renvoyant ce nombre, le pair prouve qu'il est bien le même correspondant. Ce RFC décrit les détails de l'option IPv6 Nonce (numnique), utilisée pour ILNP sur IPv6.

ILNP est décrit dans le RFC 6740, avec certains détails pratiques dans le RFC 6741. Comme tous les systèmes à séparation de l'identificateur et du localisateur, son talon d'Achille est le lien (binding) entre l'identificateur d'une machine et son localisateur. Si on reçoit un paquet disant « pour joindre la machine d'identificateur 3a59:f9ff:fe7d:b647, envoie désormais les paquets au localisateur 2001:db8:43a:c19 », faut-il le croire ? Évidemment, non, pas sur l'Internet public en tout cas. La solution adoptée par ILNP est d'avoir un numnique. C'est un nombre généré de manière imprévisible par un tiers (idéalement, ce devrait être un nombre aléatoire), que chaque machine envoie au début de la session ILNP. Lorsqu'un correspondant veut s'authentifier (par exemple lorsqu'il envoie le message de changement de localisateur cité plus haut, cf. RFC 6743), il inclura ce numnique.

Ce numnique sera transporté, aussi bien pour le début de la session que pour les mises à jour de localisateur, dans une option Destination IPv6 (ces options sont décrites dans le RFC 2460, section 4.6). Cette option sert donc à la sécurité d'ILNP. Mais elle a aussi une autre fonction, signaler, lors du débat d'une conversation, qu'on connait ILNP et que le correspondant peut l'utiliser (la coexistence pacifique d'ILNPv6 et d'IPv6 Classic en dépend). Elle ne doit donc apparaître que dans les paquets ILNP.

L'en-tête « options pour la Destination » peut contenir plusieurs options (en pratique, à l'heure actuelle, comme le note notre RFC, il n'est quasiment jamais utilisé), mais il ne doit y avoir qu'une seule option Nonce. Si d'autres options sont quand même présentes (comme celle du RFC 5570), le RFC recommande que Nonce soit la première dans l'en-tête.

La section 2 décrit la syntaxe de cette option. Elle comporte les champs obligatoires, Option Type (0x8b dans le registre IANA), Option length (en octets ; le numnique n'a pas de longueur fixe mais au moins les valeurs de 4 et 12 octets doivent être acceptées par les mises en œuvre de ce RFC) et Nonce (la valeur du numnique, de préférence générée selon les bons principes du RFC 4086).

En l'absence de l'option Nonce dans un paquet entrant, ILNP jettera le paquet si le localisateur source n'est pas dans la liste actuellement connue et stockée dans l'ILCC (Identifier-Locator Communication Cache, cf. RFC 6741). Lorsqu'une machine ILNP change sa liste de localisateurs (section 4), elle envoie un paquet avec la nouvelle liste et ce paquet doit inclure l'option Nonce (avec un numnique correct) pour être accepté. Le RFC recommande également d'inclure cette option dans les paquets suivants, pour une durée d'au moins trois RTT, afin de se prémunir contre un éventuel réordonnancement des paquets. (Notez que cela ne règle que le cas d'un retard du Locator Update, pas le cas de sa perte. Recevoir le paquet avec le numnique correct ne suffit pas à changer les localisateurs mémorisés, ne serait que parce que ce paquet ne contient qu'un seul localisateur et pas la liste actuelle.)

Si vous êtes en train de programmer une mise en œuvre d'ILNP, lisez aussi la section 5, qui donne d'utiles conseils, notamment sur l'ILCC (qui garde en mémoire le numnique actuel de la session, c'est une des informations les plus importantes qu'il stocke).

L'Internet à l'heure actuelle ne contient que des machines IP Classic. Comment cela va t-il se passer pour les premières machines ILNP ? La section 6 décrit la compatibilité. L'option Nonce sert à deux choses, indiquer le numnique, bien sûr, mais aussi signaler qu'ILNP est utilisé. Cette nouvelle option ne doit donc pas être présente dans des paquets IP Classic. Dans les paquets ILNP, elle doit être présente dans les premiers paquets (pour signaler qu'on connait ILNP) et dans tous les messages ICMP générés par les machines ILNP (comme le Locator Update du RFC 6743). Elle peut aussi être mise dans tous les paquets mais ce n'est pas indispensable. Le RFC recommande quand même de le faire si le taux de pertes de paquets de la session est particulièrement élevé (car les paquets portant l'option pourraient être perdus).

Donc, la machine recevant le premier paquet ILNP sait que son correspondent connait ILNP grâce à l'option Nonce. Et la machine qui émet le premier paquet ? Comment sait-elle que le pair connait ILNP ? La principale méthode est, comme toujours dans ILNP, via le DNS. Comme décrit en détail dans le RFC 6742, la présence d'enregistrements NID dans le DNS indique que la machine distante connait ILNP. Et si l'information dans le DNS est fausse ou dépassée ? Dans ce cas, vu le type de l'option Nonce (avec les deux bits de plus fort poids à 10, ce qui indique que le paquet doit être rejeté si cette option n'est pas comprise, RFC 2460, section 4.2). L'émetteur, en recevant le message ICMP de rejet (Parameter Problem), saura qu'il ne faut plus essayer en ILNP.

Dans un monde idéal, cela s'arrêterait là. Mais les options de destination comme celle décrite ici sont rares dans l'Internet actuel et il serait bien imprudent de promettre que celle d'ILNP passera sans problème. Comme l'a montré l'expérience d'IPv4, ce qui n'est pas utilisé finit par ne plus être géré correctement, notamment par les équipements intermédiaires. Le RFC ne mentionne pas ce problème mais évoque un problème proche, se contentant de dire que les routeurs IPv6 correctement programmés devraient ignorer tout l'en-tête Destination Options (dans un monde idéal, là encore).

La section 7 revient sur les exigences de sécurité. Le numnique ne doit pas être prévisible par un attaquant extérieur, il est donc recommandé qu'il soit généré selon les règles du RFC 4086. Notez bien que cela ne sert à rien si l'attaquant est situé sur le chemin des paquets et peut les sniffer. C'est également le cas en IP Classic et le seul mécanisme vraiment sûr dans ce cas est IPsec, si on veut protéger jusqu'à la couche 3.

Si vous aimez regarder les paquets qui passent sur le réseau avec wireshark ou tcpdump, désolé, mais ces logiciels ne gèrent pas encore les options spécifiques à ILNP et ne les analyseront pas.


Téléchargez le RFC 6744


L'article seul

RFC 6743: ICMP Locator Update message for ILNPv6

Date de publication du RFC : Novembre 2012
Auteur(s) du RFC : RJ Atkinson (Consultant), SN Bhatti (U. St Andrews)
Expérimental
Réalisé dans le cadre du groupe de recherche IRTF RRG
Première rédaction de cet article le 10 novembre 2012


Le protocole ILNP, décrit dans le RFC 6740, permet de séparer l'identificateur et le localisateur d'une machine. L'identificateur est stable, voire très stable, et identifie une machine, le localisateur est bien plus changeant et identifie un point d'attachement au réseau. Lors d'une communication entre deux machines, si le localisateur change, il faut pouvoir prévenir son correspondant. C'est le rôle des nouveaux messages ICMP Locator Update. Ce RFC 6743 décrit ces messages pour le cas d'IPv6.

Donc, comme déjà expliqué dans les RFC 6740 et RFC 6741, une machine ILNP peut avoir besoin de modifier dynamiquement la liste de ses localisateurs. Par exemple parce qu'elle s'est déplacée. Ou, tout simplement, parce qu'un nouvel attachement au réseau est disponible (nouveau FAI, par exemple).

Cela se fait avec des paquets ICMP envoyés au(x) correspondant(s). Ces paquets ont le type 156 et ne sont utilisés que pour ILNPv6 (ILNP sur IPv6 ; leur équivalent IPv4 est dans le RFC 6745). Le type 156 a été enregistré à l'IANA.

Leur syntaxe est décrite en section 2. Les champs les plus importants :

  • Operation, qui indique si on publie une liste de localisateurs ou bien si on accuse réception d'une liste,
  • Num of Locs, le nombre (> 0) de localisateurs dans le message,
  • Locator(s), qui est une liste de tuples {Locator, Preference, Lifetime}. Locator est un localisateur (64 bits en ILNPv6), Preference un entier qui représente la préférence associée à ce localisateur (plus elle est basse, plus il est préféré, voir aussi le RFC 6742) et Lifetime le nombre de secondes que ce localisateur va être valide (typiquement identique au TTL de l'enregistrement DNS L64, cf. RFC 6742).

Lorsqu'une liste de localisateurs change pour un nœud (ajout ou retrait d'un localisateur), le nœud envoie ce message à tous ses correspondants (tous les nœuds avec lesquels il est en train de communiquer). Ceux-ci enverront un accusé de réception (même contenu, seul le champ Operation changera). Le RFC ne spécifie pas quoi faire si on ne reçoit pas d'accusé de réception (les messages ICMP peuvent se perdre). C'est volontaire : le manque d'expérience pratique avec ILNP ne permet pas encore de recommander une stratégie de rattrapage particulière (réemettre, comme avec le DNS ?)

Notez que c'est une liste complète de tous les localisateurs qui est envoyée. Elle peut donc être grosse, programmeurs, attention aux débordements de tampon si Num of locs vaut sa valeur maximale, 256.

Le message Locator Update doit être authentifié (section 6) en incluant, pour chaque correspondant, l'option IPv6 Nonce (RFC 6744) avec la valeur en service pour ce correspondant. Les messages seront ignorés si le numnique (valeur choisie de manière à être imprévisible par l'attaquant) est incorrect. (Dans les environnements où on souhaite encore plus de sécurité, on peut ajouter IPsec.)

Et comment se passera la cohabitation avec les machines IPv6 classiques ? La section 5 traite ce cas. Comme le type ICMP 156 est inconnu des machines IPv6 classiques, elles ignoreront ces messages Locator Update (RFC 4443, section 2.4).


Téléchargez le RFC 6743


L'article seul

RFC 6742: DNS Resource Records for ILNP

Date de publication du RFC : Novembre 2012
Auteur(s) du RFC : RJ Atkinson (Consultant), SN Bhatti (U. St Andrews), Scott Rose (US NIST)
Expérimental
Réalisé dans le cadre du groupe de recherche IRTF RRG
Première rédaction de cet article le 10 novembre 2012


Le système ILNP, qui vise à fournir une nouvelle (et meilleure) architecture à l'Internet, dépend du DNS pour plusieurs fonctions critiques. Plusieurs nouveaux types d'enregistrement DNS sont nécessaires et ce RFC les décrit.

Avant de lire ce RFC, il faut connaître ILNP. Le mieux est de commencer par le RFC 6740, qui décrit tout le système. Le RFC 6741 fournit ensuite quelques détails pratiques. Il faut aussi naturellement connaître les bases du DNS (RFC 1034 et RFC 1035).

C'est fait ? Vous avez lu tout cela ? Alors, place à ce nouveau RFC, le RFC 6742. ILNP utilise le DNS essentiellement pour permettre un rendez-vous entre deux machines. Celle qui veut commencer connaît le nom de l'autre mais aucune information pratique sur comment la rencontrer. Quatre types d'enregistrements sont utilisés pour cela :

  • NID qui permet de trouver l'identificateur d'une machine à partir de son nom,
  • L64 et L32 qui permettent de trouver le localisateur d'une machine à partir de son nom,
  • Et LP, une optimisation facultative qui sera présentée plus loin.

Commençons par le NID. Un de ses rôles est d'indiquer à la machine qui veut en contacter une autre si sa future correspondante connait ILNP (ou bien si elle est uniquement en IP Classic). Sa présence dans le DNS est donc un signal : « tu peux y aller, elle parle ILNP ». Un enregistrement erroné (disant qu'une machine a un NID alors qu'en fait elle ne parle pas ILNP) n'est pas fatal mais ralentirait sérieusement l'établissement de la connexion.

Le NID a reçu le numéro 104 (cf. le registre IANA) et il comporte deux champs, une préférence et l'identificateur. Attention, ce sont les préférences les plus faibles qui sont celles à choisir en premier. Par exemple, voici trois NID pour host1.example.com :

host1.example.com. IN NID 10 0014:4fff:ff20:ee64
                   IN NID 20 0015:5fff:ff21:ee65
                   IN NID 50 0016:6fff:ff22:ee66

L'identificateur 0014:4fff:ff20:ee64 est le préféré. (La syntaxe des identificateurs et des localisateurs est décrite dans le RFC 6740.)

Si un serveur DNS « connaît ILNP », c'est-à-dire qu'il a été programmé avec du code spécifique pour ILNP, au lieu d'attribuer aux enregistrements ILNP le traitement par défaut, il peut optimiser, par exemple en envoyant des enregistrements non demandées mais qui seront probablement utiles. Cette optimisation, qui n'a rien d'obligatoire, est analogue à ce que font les serveurs actuels pour une requête MX : si la réponse est mail.example.com, ils incluent également les adresses IP de mail.example.com dans la réponse, conscients qu'elles seront probablement nécessaires bientôt (si on demande le MX de example.com, c'est en général pour lui envoyer du courrier juste après). Ici, un serveur « connaissant ILNP » à qui on demande le NID de host1.example.com peut aussi mettre dans le réponse des L64 et des L32, non demandés mais qui seront probablement utiles juste après.

Le type L64 stocke des localisateurs pour ILNPv6, c'est_à-dire ILNP tournant sur IPv6. La présence de L64 dans le DNS indique que la machine peut faire de l'ILNP au-dessus d'IPv6. Pour ce protocole, les localisateurs font 64 bits, d'où le nom de ce type. Son numéro est 106. Lui aussi a une préférence, suivie par le localisateur proprement dit.

Voici un exemple où la machine host1.example.com a deux localisateurs, avec une préférence pour 2001:0db8:1140:1000 :

host1.example.com. IN L64 10 2001:0db8:1140:1000
                   IN L64 20 2001:0db8:2140:2000

Rappelez-vous que les localisateurs d'ILNPv6 ont une syntaxe qui ressemble à celle des adresses IPv6 mais il s'agit bien d'un type différent.

Quant au type L32, il stocke des localisateurs pour ILNPv4, c'est-à-dire l'incarnation d'ILNP pour IPv4. Leur présence dans le DNS indique que la machine peut faire de l'ILNP au-dessus d'IPv4. Pour ce protocole, les localisateurs font 32 bits, d'où le nom de ce type. Son numéro est 105. Il comprend une préférence, puis le localisateur proprement dit.

Voici un exemple où la machine host1.example.com a trois localisateurs, 10.1.2.0 étant le préféré (la machine est sans doute multi-homée) :

host1.example.com. IN L32 10 10.1.2.0
                   IN L32 20 10.1.4.0
                   IN L32 30 10.1.8.0

Le dernier type d'enregistrement DNS, LP, est un peu différent. Il s'agit de fournir un niveau d'indirection. En effet, si une machine change de localisateurs (ce qui est normal, en ILNP), et veut pouvoir être jointe, la méthode est de mettre à jour le DNS. Or, la zone où est déclarée la machine peut ne pas être facilement accessible en écriture (RFC 2136 ou méthode équivalente). L'idée (voir RFC 6740) est donc de pointer, via un enregistrement LP, vers une zone prévue pour les mises à jour rapides, où se trouveront les localisateurs.

L'enregistrement LP a le numéro 107 et comprend une préférence et un FQDN. Ce FQDN aura à son tour des L32 ou des L64. Voici un exemple :

host1.example.com. IN LP 10 subnet1.dynamic.example.net.
                   IN LP 20 subnet3.backup.example.com.

; Puis, dans la zone dynamic.example.net :

subnet1.dynamic.example.net. IN L64 50 2001:0db8:1140:1000
                             IN L64 100 2001:0db8:2140:2000

Avec cet exemple, si host1.example.com change de localisateur, on ne touche pas à la zone example.com, on ne modifie que dynamic.example.net. Cette indirection via les LP n'est pas indispensable mais elle aidera dans bien des cas, lorsque la zone « principale » ne permettra pas les mises à jour rapides. Autre avantage, toutes les machines d'un même sous-réseau ayant le même localisateur, leurs noms pourront pointer vers le même LP et une seule mise à jour suffira pour tout le monde.

La section 3 synthétise ensuite l'usage de ces types d'enregistrement. Le minimum pour une machine ILNP est un NID + un L64 (ou L32 en ILNPv4) :

host1.example.com. IN NID 10 0014:4fff:ff20:ee64
                   IN L64 10 2001:0db8:1140:1000

Si la machine est multi-homée, on aura plusieurs L64 :

host1.example.com. IN NID 10 0014:4fff:ff20:ee64
                   IN L64 10 2001:0db8:1140:1000
                   IN L64 20 2001:0db8:2140:2000

Si la machine est mobile, elle aura souvent intérêt à utiliser les LP et cela donnera quelque chose du genre :

host1.example.com. IN NID 10 0014:4fff:ff20:ee64
                   IN LP  10 mobile-1.example.net.

; ...

mobile-1.example.net. IN L64 2001:0db8:8140:8000

Rappelons que ces enregistrements ne doivent apparaître que si la machine parle ILNP. Un de leurs rôles est de signaler qu'ILNP est disponible.

Un client ILNP qui veut récupérer ces informations ne doit pas compter qu'elles soient toutes envoyées d'un coup (même si c'est une optimisation recommandée). Au passage, rappelez-vous que la requête ANY, envoyée à un résolveur, n'a pas forcément la sémantique attendue (elle renvoie ce que le résolveur a dans son cache, pas forcément toutes les données disponibles sur les serveurs faisant autorité). D'autre part, même si la réponse du serveur faisant autorité incluait tous les enregistrements, certains résolveurs peuvent, pour des raisons de sécurité, en jeter certains. Enfin, même si les données sont gardées dans le cache, elles expirent au bout d'un moment et les TTL ne sont pas forcément les mêmes pour tous les types d'enregistrement. Le client ILNP doit donc se préparer à faire plusieurs requêtes, par exemple NID (s'il n'y a pas de résultat, la machine distante ne parle pas ILNP) puis LP (qui est facultatif), puis L64 puis enfin, s'il n'y a pas de L64, se résigner à L32.

À propos des TTL, notez qu'il est logique que les TTL soient assez longs pour les NID (une information normalement très stable, je dirais que plusieurs jours ne sont pas un problème). En revanche, les L32 et L64 peuvent avoir des TTL bien plus courts (le RFC ne donne pas de chiffre mais, disons, moins d'une minute), surtout si la machine ou le réseau est mobile. On peut alors s'inquiéter « est-ce que ces courts TTL, empêchant une mise en cache sérieuse, ne vont pas augmenter excessivement la charge sur le système DNS, et ralentir les requêtes ? ». Mais plusieurs articles (« Reducing DNS Caching », « DNS performance and the effectiveness of caching ») ont montré que les caches du DNS étaient surtout rentables pour l'information d'infrastructure (enregistrements NS et colle). Pour les enregistrements « terminaux » comme les adresses IP ou les localisateurs, les caches sont moins nécessaires.

Un petit mot sur la sécurité, maintenant. Comme les informations nécessaires sont vraiment critiques (un L64 erroné et tout le trafic va à une autre machine), la section 4 recommande d'utiliser DNSSEC (RFC 4033) pour protéger ses informations. (À l'été 2012, le déploiement de DNSSEC est très avancé, alors que celui d'ILNP est inexistant. Il est donc raisonnable de compter que DNSSEC sera disponible.) Lors des mises à jour dynamiques, il faut utiliser les sécurités décrites dans le RFC 3007. Par exemple, avec le serveur de noms Yadifa, on peut mettre à jour dynamiquement une zone signée. On copie la clé privée (par exemple, pour une clé générée avec dnssec-keygen pour la zone secure.example, le fichier de la clé privée peut être Ksecure.example.+005+05461.private) dans le répertoire indiqué par la directive keyspath de Yadifa et c'est tout. Les mises à jour dynamiques seront faites et automatiquement signées. Le journal de Yadifa dira :

2012-09-25 20:54:12.754705 | server   | I | update (831e) secure.example. SOA (127.0.0.1:44480)
2012-09-25 20:54:12.754749 | server   | D | database: update: checking DNSKEY availability
2012-09-25 20:54:12.754778 | server   | D | database: update: processing 0 prerequisites
2012-09-25 20:54:12.754791 | server   | D | database: update: dryrun of 2 updates
2012-09-25 20:54:12.754828 | server   | D | database: update: opening journal page
2012-09-25 20:54:12.755008 | server   | D | database: update: run of 2 updates
2012-09-25 20:54:13.000526 | server   | D | database: update: closed journal page

À la date de publication de ce RFC, il n'existe pas encore de logiciel DNS qui gère ILNP.

Pour finir, quelques articles sur l'idée d'utiliser le DNS pour localiser une machine mobile : « An End-To-End Approach To Host Mobility », « Reconsidering Internet Mobility » et « Mobile Host Location Tracking through DNS ».


Téléchargez le RFC 6742


L'article seul

RFC 6741: ILNP Engineering Considerations

Date de publication du RFC : Novembre 2012
Auteur(s) du RFC : RJ Atkinson (Consultant), SN Bhatti (U. St Andrews)
Expérimental
Réalisé dans le cadre du groupe de recherche IRTF RRG
Première rédaction de cet article le 10 novembre 2012


Le RFC 6740 décrivait l'architecture générale du mécanisme de séparation de l'identificateur et du localisateur ILNP. C'était le premier document à lire pour comprendre ILNP. Ce RFC 6741 est plus concret, exposant les questions d'ingéniérie autour d'ILNP. Il décrit surtout des points qui sont indépendants de la version d'IP utilisée, d'autres RFC couvrent les points spécifiques à IPv4 (RFC 6745 et RFC 6746) ou IPv6 (RFC 6743 et RFC 6744).

Donc, ILNP vise à fournir une meilleure architecture à l'Internet, en faisant évoluer IP vers une séparation de l'identificateur d'une machine (stable, indépendant de comment et par qui la machine est attachée au réseau) avec le localisateur (lié à l'attachement actuel au réseau, et pouvant donc changer). ILNP est décrit dans le RFC 6740 mais celui-ci ne donne qu'une vision de haut niveau, à laquelle manquent pas mal de détails. C'est le rôle de notre RFC que de combler ces manques. L'architecture ILNP peut avoir bien des incarnations concrètes, y compris par des approches « table rase » où on ne tient aucun compte de l'existant. Ce RFC 6741 présente une autre approche, plus progressive, où on essaie de déployer ILNP dans l'Internet actuel.

Vous avez bien lu le RFC 6740 d'architecture d'ILNP ou son résumé ? Alors, allons-y, plongeons nous dans les détails ILNP. D'abord, les identificateurs (section 2). Toute machine ILNP en a au moins un. Ils ne sont pas liés à une interface réseau et une machine avec N interfaces peut très bien n'avoir qu'un seul identificateur. (Notez toutefois qu'un identificateur peut être formé à partir d'une caractéristique d'une interface, comme l'adresse MAC. Mais ce n'est qu'un mécanisme de génération de l'identificateur, la carte réseau peut ensuite être changée sans affecter celui-ci.)

Les identificateurs sont des chaînes de 64 bits et la représentation la plus simple est donc un entier non signé de 64 bits (uint64_t dans un programme en C, par exemple). Comme les identificateurs d'interface d'IPv6 (section 2.5.1 du RFC 4291), ils utilisent la syntaxe EUI-64. Cette syntaxe décrit notamment deux bits, U et G, le premier indiquant si l'identificateur est globalement unique ou non, et le second indiquant s'il s'agit d'une adresse de groupe. Attention pour les programmeurs, rien n'empêche une machine de prendre l'identificateur qu'elle veut et, en pratique, des collisions peuvent se produire. À plusieurs reprises, notre RFC donne des conseils à ceux qui mettent en œuvre ILNP pour que ces collisions n'aient pas de conséquences graves.

Si le bit U est à 1, cela indique que l'identificateur dérive de l'adresse MAC, et est donc garanti unique via l'enregistrement à l'IEEE.

Si le bit U est à 0, cela veut dire que l'identificateur n'est pas dérivé d'un registre central et n'a donc qu'une signification locale. Cela permet à ILNP de se passer d'une dépendance vis-à-vis d'une autorité unique. Autre intérêt, on peut alors générer un identificateur qui soit une clé cryptographique, par exemple (RFC 3972). On peut aussi avoir des identificateurs temporaires, pour préserver la vie privée, comme on le fait en IPv6 avec les adresses temporaires du RFC 8981.

Normalement, ce RFC n'était censé couvrir que les points indépendants de la famille d'adresses utilisée. Néanmoins, on y trouve aussi l'encodage des localisateurs et identificateurs dans un paquet IP (section 3). En IPv6, dans les champs « adresse IP » (source et destination), le localisateur prend les 64 bits de plus fort poids, et l'identificateur le reste. Grâce à cet encodage, le routeur IPv6, qui ne tient compte que du préfixe, traitera le localisateur comme un préfixe IP normal et n'aura besoin d'aucune modification pour gérer de l'ILNP. Le format du paquet ILNPv6 est en effet exactement le même que celui du paquet IPv6 classique.

C'est plus complexe en IPv4, en raison de la petite taille des champs adresse. On met donc les localisateurs dans l'adresse (source et destination), afin que les routeurs IPv4 puissent travailler comme aujourd'hui, et l'identificateur (qui fait toujours 64 bits) doit être mis dans une option IP, comme décrit dans le RFC 6746.

Et au niveau 4 (transport), qu'est-ce qui doit changer ? La principale modification est que TCP ou UDP doivent lier l'état d'une session en cours uniquement à l'identificateur et non plus à une adresse. Ainsi, le tuple traditionnel de TCP {adresse IP locale, port local, adresse IP distante, port distant}, qui identifie une connexion en cours, doit être remplacé par {identificateur local, port local, identificateur distant, port distant}, afin de bénéficier d'ILNP (notamment de la possiblité de changer d'adresse sans casser la connexion).

Attention, TCP doit normalement remplir le champ « somme de contrôle » (Checksum dans l'en-tête TCP) en incluant les deux adresses IP, locale et distante. En ILNP, il ne doit plus utiliser que les identificateurs, les localisateurs étant remplacés, pour le calcul de la somme de contrôle, par une série de bits nuls.

Un aspect d'ingéniérie très important d'ILNP est l'ILCC, Identifier-Locator Communication Cache. Cette structure de données, décrite en section 5, garde trace des détails permettant de maintenir une communication avec les CN (Correspondent Node, les machines ILNP avec qui on parle). De tels caches existent déjà pour certains protocoles (par exemple pour ARP, sur une machine Unix, vous pouvez l'afficher avec la commande arp -a -n, pour NDP, sur Linux, avec ip -6 neighbour show). Et ceci sans parler des informations que doit garder TCP. Donc, le nouvel ILCC n'est pas forcément une grosse contrainte pour les machines.

Que stocke l'ILCC ?

  • Le ou les Identificateurs du nœud local, en indiquant les préférences, et s'ils sont actuellement en service (utilisables pour une nouvelle session),
  • Le ou les Localisateurs du nœud local, en indiquant les préférences, et s'ils sont actuellement en service,
  • Le ou les Identificateurs de chaque correspondant (CN), en indiquant les préférences, leur validité, et s'ils sont actuellement en service,
  • Le ou les Localisateurs de chaque correspondant, en indiquant les préférences, leur validité, et s'ils sont actuellement en service,
  • Les numniques à utiliser pour chaque correspondant, celui vers le CN et celui depuis le CN.

La validité peut être déterminée par divers moyens. Lorsque l'information a été apprise dans le DNS, c'est typiquement le TTL qui est utilisé. Toutefois, même lorsque le TTL expire, ce n'est pas une bonne idée de retirer les valeurs immédiatement (on risque de se couper d'un CN qui n'a pas mis à jour ses données assez vite). Il vaut donc mieux marquer un Localisateur comme « pas à jour mais peut-être encore utilisable si on n'a pas le choix ».

Et pour accéder à l'ILCC, quelle clé de recherche utilise-t-on ? L'identificateur, ce qui serait logique ? Raté. Pour les paquets qui contiennent un numnique, on utilise un tuple {Identificateur, Numnique} et pour les autres un tuple {Identificateur, Localisateur}. Le but de ce choix est de se prémunir contre les cas où deux machines utiliseraient le même identificateur (ce qui peut arriver, surtout avec le bit U à zéro).

On a vu qu'un des buts d'ILNP était de gérer proprement les cas où une machine change de connectivité (panne d'un lien, déplacement, etc). La section 6 explique les détails de ce cas. Lorsqu'une machine apprend qu'un de ses localisateurs ne marche plus, elle prévient ses CN (Correspondent Node) par un message ICMP Locator Update (RFC 6743 et RFC 6745). Ce message permet de retirer ou d'ajouter des localisateurs. Il est authentifié par le numnique, qui doit être identique à celui d'une session en cours (sinon, le paquet entrant ne correspond à aucune entrée dans l'ILCC, voir la section précédente).

Ça, c'est pour les sessions en cours. Pour les nouvelles, si une machine veut être contactée, elle doit mettre à jour la liste de ses localisateurs dans le DNS. ILNP dépend donc assez fortement des mises à jour dynamiques du DNS (RFC 2136 et RFC 3007), ou d'un mécanisme similaire.

Le lecteur attentif a pu remarquer plus tôt que le localisateur joue le rôle d'un préfixe IP, le routage est fondé sur lui. Mais un préfixe IP n'a pas forcément une longueur fixe. En IPv6, on peut parfaitement avoir un Tier 1 qui annonce un /32 en BGP, qui route ensuite dans son IGP des /48 et finalement un réseau local d'un client de l'opérateur qui route sur des /64. ILNP ne change rien à cela (section 7). Le localisateur comprend en fait deux parties, de longueur variable, un préfixe de localisateur et un sélecteur de réseau. Dans le cas de l'annonce BGP citée plus haut, les 64 bits du localisateur se partagent entre 32 bits de préfixe et 32 bits pour choisir un réseau.

On a vu qu'ILNP dépend énormément du DNS. Il est donc logique que ce RFC compte une une section 8 consacrée à ce service. D'abord, comme on l'a vu, pour des raisons de sécurité, ILNP recommande fortement de sécuriser les mises à jour du DNS (RFC 3007). Cette technique marche dans de nombreuses mises en œuvre du DNS (par exemple, BIND ou Active Directory l'ont depuis des années). Les clients capables d'utiliser TSIG ou une technique similaire pour mettre à jour un serveur DNS sont disponibles pour toutes les plate-formes (comme nsupdate sur Unix). Un exemple figure dans mon article sur le RFC 6742.

Pour accéder à l'information disponible, quatre nouveaux types d'enregistrement DNS sont créés par le RFC 6742 :

  • NID pour stocker l'identificateur,
  • L32 et L64 pour stocker des localisateurs de 32 (pour IPv4) et 64 bits,
  • LP, pour ajouter un niveau d'indirection vers le localisateur, apportant ainsi davantage de souplesse pour les changements (qui peuvent être fréquents) des localisateurs, qui peuvent être délégués à une autre zone.

Quels TTL utiliser pour ces enregistrements ? Le choix est particulièrement important pour les localisateurs, qui peuvent parfois changer vite. Dans certains cas, un TTL de quelques secondes seulement peut donc être une valeur raisonnable pour les L32 et L64. Si cela vous semble peu, rappelez-vous que des études comme celle de Alex C. Snoeren, Hari Balakrishnan, & M. Frans Kaashoek, « Reconsidering Internet Mobility » (dans Proceedings of 8th Workshop on Hot Topics in Operating Systems en 2002) ou celle de S. Bhatti & R. Atkinson, « Reducing DNS Caching » (dans Proc. GI2011 - 14th IEEE Global Internet Symposium en 2011) ont montré qur le cache dans le DNS est surtout utile pour les enregistrements d'infrastructure (type NS et colles, c'est-à-dire adresses IP des serveurs situés dans la zone qu'ils servent), pas pour les enregistrements « terminaux » comme AAAA ou MX.

Les enregistrements LP et NID sont bien plus stables et peuvent, eux, avoir des TTL de plusieurs jours. Dans le cas d'identificateurs temporaires et/ou cryptographiquement signés, un TTL plus court est toutefois à envisager.

À noter que le RFC recommande que les machines ILNP publient dans le DNS, non seulement les NID et L64 spécifiques d'ILNP mais aussi des plus traditionnels AAAA pour les machines non-ILNP. Un serveur DNS qui connait ILNP peut également envoyer d'autorité les NID et L64 dans la section additionnelle de la réponse DNS. Les machines non-ILNP ignoreront ces enregistrements inconnus mais les autres pourront en tirer profit.

L'expérience (douloureuse) d'IPv6 a montré que la possibilité d'un déploiement progressif, n'exigeant pas de tout le monde qu'il migre, était un élément nécessaire de tout nouveau protocole réseau. La section 10 de notre RFC regarde donc de près si ILNP est déployable progressivement. D'abord, les paquets ILNP, que ce soit ILNPv4 ou ILNPv6 sont indistinguables, pour les routeurs, les pare-feux et autres équipements, de paquets IPv4 et IPv6 classiques. Ils devraient donc passer sans problème sur ces équipements, sans qu'on change leurs configurations, leurs protocoles de routage, etc. ILNP, comme HIP, peut en effet être déployé uniquement sur les machines terminales, par une simple mise à jour logicielle. Pour la même raison, des machines ILNP peuvent coexister avec des machines IP Classic sur un même lien.

Je trouve que le RFC est trop optimiste : l'expérience montre que les options IP, nécessaires à ILNP, passent mal dans l'Internet IPv4 actuel et n'ont guère été testées en IPv6 (le RFC ne mentionne que le cas des pare-feux qui bloqueraient explicitement les options et pas celui de routeurs bogués). De toute façon, une exception est à prévoir, en ILNPv4 uniquement, les routeurs du réseau local devront être mis à jour pour gérer une extension d'ARP. Autre exception, certains routeurs NAT, selon la façon dont ils sont réglés, peuvent casser ILNP en réécrivant ce qu'ils croient être une adresse et qui serait un bout de l'identificateur.

Pour les applications, c'est plus compliqué. Si l'application est « bien élevée » (n'utilise que des noms de domaine, ne manipule pas explicitement d'adresses IP), elle devrait fonctionner en ILNP sans problème. Mais bien des applications ne sont pas bien élevées (FTP, SNMP...)

La section 14, consacrée aux applications et API revient en détail sur ces questions. D'abord, une bonne partie des applications existantes, notamment parmi celles écrites en C, utilise l'API dite BSD Sockets. Elle n'est pas forcément incompatible avec ILNP. Par exemple, les applications IPv6 peuvent mettre la concaténation du localisateur et de l'identificateur dans les champs de l'API prévus pour mettre une adresse IP et cela passera, puisque c'est justement l'encodage du couple {Identificateur, Localisateur} sur le câble. Néanmoins, cette API est de trop bas niveau, même sans tenir compte d'ILNP (par exemple, elle oblige à avoir un portage d'IPv4 en IPv6 alors que cette modification dans la couche 3 devrait être invisible des applications). Souhaitons donc (et pas seulement pour ILNP) que les programmeurs passent à des API plus abstraites.

Tout le monde ne programme pas en C. Pour les autres langages, il est courant d'utiliser des API de plus haut niveau que ces sockets. Ainsi, en Java, les clients Web vont plutôt faire appel à la classe java.net.URL. Ainsi, complètement isolés des couches basses, ils passeront à ILNP sans s'en rendre compte. Même chose pour des langages comme Ruby ou Python.

Le piège classique des API réseau est l'utilisation de références, lorsqu'Alice dit à Bob « va voir Charlie ». Ces références cassent pas mal de protocoles. Une solution pour ILNP serait de faire des références avec des FQDN.

Et pour communiquer entre machines ILNP et non-ILNP ? Le RFC recommande que les machines ILNP gardent également l'IP Classic, approche connue sous le nom de dual stack (être capable de parler les deux protocoles). Une longue coexistence d'ILNP avec des machines IP est prévue. Pour la machine qui initie la connexion, si elle trouve un NID dans le DNS, elle tente ILNP (en mettant l'option Nonce/numnique), sinon elle reste en IP Classic. Si la machine distante ne gère pas ILNP (malgré ce que raconte le DNS), elle rejettera l'option Nonce avec un message ICMP (l'option a un type qui indique que le paquet doit être rejeté par ceux qui ne comprennent pas l'option, cf. RFC 2460, sections 4.2 et 4.5), qui permettra à l'initiateur de voir qu'il s'est trompé et doit réessayer en IP traditionnel.

Pour la machine qui répond aux demandes de connexion, si le paquet initial contient une option Nonce, c'est que le demandeur gère ILNP. Sinon, on s'en tient à l'IP de nos grand-mères.

Question sécurité, la section 9 est consacrée à IPsec. Il n'est pas très différent avec ILNP de ce qu'il est avec IP Classic. Le principal changement est que les associations de sécurité se font avec l'identificateur, pas avec l'adresse (elles ne changent donc pas si une machine change de localisateur). Ainsi, AH ne valide que l'identificateur (le localisateur n'est pas protégé, ce qui permet à ILNP+AH de fonctionner même en présence de NAT).

Autres questions de sécurité en section 11 : les auteurs estiment qu'ILNP n'est pas moins sûr qu'IP. Il ne l'est pas non plus forcément davantage. Un exemple typique est qu'une machine peut mentir sur son identificateur, comme elle peut mentir sur son adresse IP (les solutions sont également les mêmes, IPsec + IKE ou bien les CGA du RFC 3972).

Le principal risque nouveau est celui de faux messages ICMP Locator Update. Ils pourraient provoquer bien des dégâts, par exemple en convaincant un CN d'envoyer tous les paquets d'une machine à un attaquant. C'est pour cela que l'option Nonce est absolument indispensable, même lorsque IPsec est utilisé. À noter que cette option ne protège pas contre un attaquant situé sur le chemin, puisque ce dernier peut alors écouter le réseau et lire le numnique (la situation est exactement la même en IP Classic, par exemple avec les numéros de séquence TCP, qui ne protègent que contre les attaquants hors du chemin). On est donc bien dans un cas « sécurité pas pire qu'avec IP Classic (mais pas meilleure non plus) ». Si on veut aller plus loin en sécurité, il faut IPsec ou un équivalent.

À noter aussi que les autres messages ICMP (Packet too big, Destination unreachable, etc), ne sont pas protégés par le numnique. Ces messages sont en général émis par des équipements intermédiaires, genre routeurs, qui ne connaissent normalement pas le numnique. Comme en IP Classic, ils peuvent donc parfaitement être usurpés (cf. RFC 5927).

La sécurité inclus aussi le respect de la vie privée (section 12). Notre RFC renvoie au RFC 6740 qui discutait cette question dans le cadre d'ILNP.

Enfin, la section 13 contient diverses notes sur des problèmes pratiques. Notamment :

  • Les délais de mise à jour lorsqu'une machine ILNP se déplace trop vite, par rapport à la réjuvénation du DNS. Mobile IP avait déjà ce problème. La mobilité d'un piéton, ça va, celle d'un avion va poser des problèmes.
  • L'absence de garantie qu'on peut réellement joindre une machine via le localisateur indiqué. En effet, ILNP ne teste pas cela. Par exemple, un enregistrement L64 dans le DNS peut être erroné et rien ne l'indique au client ILNP. Comme en IP Classic, on n'est jamais sûr qu'un paquet arrivera et les logiciels doivent en tenir compte.

Comme il n'y a pas encore eu de déploiement, même limité, même de test, d'ILNP, nul doute que la liste des problèmes et questions s'allongera lorsqu'on passera à l'expérience sur le terrain.


Téléchargez le RFC 6741


L'article seul

RFC 6740: ILNP Architectural Description

Date de publication du RFC : Novembre 2012
Auteur(s) du RFC : RJ Atkinson (Consultant), SN Bhatti (U. St Andrews)
Expérimental
Réalisé dans le cadre du groupe de recherche IRTF RRG
Première rédaction de cet article le 10 novembre 2012


Le protocole ILNP vient d'être spécifié dans une série de neuf RFC, dont ce RFC 6740 est le point de départ, décrivant l'architecture générale d'ILNP. ILNP appartient à la famille des protocoles à séparation de l'identificateur et du localisateur. Ces protocoles visent à résoudre une limite fondamentale de l'Internet : l'adresse IP est utilisée à la fois comme identificateur (nommer une machine, par exemple pendant la durée d'une session TCP) et comme localisateur (indiquer son point d'attachement au réseau). Cette confusion rend certaines configurations, notamment le multi-homing et la mobilité, très difficiles.

Ce n'est pas qu'ILNP soit le premier protocole à vouloir séparer ces deux fonctions. Avant de donner le feu vert à la publication de ces RFC, l'IESG a notamment examiné HIP et LISP, avant de conclure qu'ILNP avait des caractéristiques suffisamment originales pour qu'il soit intéressant qu'il soit décrit dans des RFC.

ILNP avait été choisi par les présidents du groupe de recherche Routage de l'IRTF comme étant la base des futurs travaux sur une meilleure architecture pour l'Internet (travaux décrits dans le RFC 6115). S'il faut le résumer en cinq points :

  • ILNP est défini comme une architecture abstraite, avec plusieurs concrétisations possibles. Celle décrite dans ces RFC est compatible avec l'Internet actuel (une autre, plus « table rase », serait possible).
  • ILNP fonctionne entièrement dans les machines terminales, les routeurs ne sont pas changés.
  • Chaque machine ILNP a au moins un Identificateur et au moins un Localisateur. En IPv6, ils sont indiqués dans chaque paquet (ILNP peut aussi tourner au-dessus d'IPv4 mais c'est plus complexe.)
  • Pour trouver le Localisateur d'une machine qu'on veut contacter, la méthode standard est d'utiliser le DNS (ILNP repose nettement plus sur le DNS que ses concurrents).
  • Les changements de localisateur en cours de session sont faits par un nouveau message ICMP, Locator Update. Ces derniers sont sécurisés par un numnique, nombre imprévisible envoyé au début de la session.

Bon, après cette introduction rapide, voyons tout en détail. D'abord, pourquoi veut-on à tout prix séparer identificateur et localisateur ? Le mieux est de relire le RFC 4984 pour avoir tous les détails. Disons que l'actuelle confusion de l'identificateur et du localisateur est pénible pour :

  • La croissance des tables de routage : pour avoir des adresss IP stables, certains réservent du PI et l'annoncent dans la table de routage globale.
  • Le multi-homing : sans adresses PI, pas de moyen facile de gérer les adresses de ses fournisseurs d'accès.
  • La mobilité : changer d'endroit ou de fournisseur casse les connexions TCP en cours.

Face à ces problèmes, des tas de propositions pour améliorer les mécanismes d'adressage et de nommage dans l'Internet ont été faites : RFC 814, RFC 1498, RFC 2101, RFC 2956 et bien d'autres. La conclusion était souvent la même : le mélange de fonctions d'identification d'une machine et de sa localisation dans le réseau est une mauvaise idée. Ces fonctions devraient être séparées.

Il y a un petit problème terminologique ici : les architectures où ces fonctions sont séparées sont parfois toutes appelées « séparation de l'identificateur et du localisateur ». Mais notre RFC adopte un vocabulaire plus strict. Il réserve ce terme de « séparation de l'identificateur et du localisateur » aux architectures (comme ILNP) où la séparation est faite dès le début (dans les machines terminales) et utilise le terme de « map and encapsulate » (qu'on trouve souvent abrégé en map-and-encap) aux architectures qui utilisent un tunnel pour transporter les paquets entre deux machines ne connaissant pas la séparation Identificateur/Localisateur. Selon cette terminologie, LISP, dont le nom veut dire Locator/Identifier Separation Protocol, n'est donc pas un « vrai » système « à séparation de l'identificateur et du localisateur ».

Ce RFC, le premier à lire lorsqu'on veut comprendre ILNP, est d'abord la description d'une architecture. On n'y trouvera pas de protocole, de format des paquets, etc. Les protocoles concrets viennent après, dans d'autres RFC. Deux protocoles qui mettent en œuvre l'architecture ILNP ont été définis, ILNPv4 pour IPv4 et ILNPv6 pour IPv6. Je parlerai surtout d'ILNPv6, qui est plus simple à exposer (le faible espace d'adressage d'IPv4 a nécessité quelques astuces qui rendent ILNPv4 plus difficile à comprendre).

Comme indiqué plus haut, d'autres incarnations de l'architecture ILNP peuvent être imaginées, notamment en choisissant une approche « table rase » qui ferait tourner cette architecture sur un nouveau protocole, sans relation avec IP. Mais, pour l'instant, ces hypothétiques incarnations n'ont pas été définies.

Les autres RFC à lire, une fois celui-ci achevé, sont :

  • RFC 6741, « ILNP Engineering and Implementation Considerations », qui décrit les questions concrètes communes à ILNPv4 et ILNPv6,
  • RFC 6742, « DNS Resource Records for ILNP », qui explique les enregistrements DNS nécessaires pour ILNP,
  • RFC 6743, « ICMPv6 Locator Update message », définit le nouveau message ICMP Locator Update,
  • RFC 6744, « IPv6 Nonce Destination Option for ILNPv6 », normalise la nouvelle option IPv6 permettant d'indiquer le numnique de la connexion,
  • RFC 6745, « ICMPv4 Locator Update message », définit le nouveau message ICMP Locator Update pour IPv4,
  • RFC 6746, « IPv4 Options for ILNP », normalise deux nouvelles options IPv4, une pour indiquer le numnique de la connexion, une pour indiquer l'identificateur (pour IPv6, il tient dans l'adresse et cette option n'est pas nécessaire),
  • RFC 6747, « ARP Extension for ILNPv4 », qui décrit comment adapter le vieux protocole ARP à ILNP,
  • RFC 6748, « Optional Advanced Deployment Scenarios for ILNP », explore des fonctions plus avancées d'ILNP et des perspectives plus lointaines.

Les section 2 et 3 détaillent cette architecture. Parmi les propriétés importantes de l'Identificateur, le fait qu'une machine puisse en avoir plusieurs, par exemple à des fins de protection de la vie privée : avoir le même Identificateur tout le temps permettrait la traque d'une machine à travers ses déplacements, un problème analogue à celui qui a mené au RFC 8981. Une machine peut donc utiliser plusieurs identificateurs (mais, évidemment, pas au sein d'une même session).

Si l'application ne se sert que de noms de domaine pour contacter son pair, elle est dite « bien élevée » et fonctionnera sans problèmes avec ILNP. Ce comportement est celui recommandé par le RFC 1958. Si, par contre, l'application utilise explicitement des adresses IP (le RFC cite les fichiers de configuration d'Apache), elle pourra avoir des ennuis avec ILNP, où ces adresses ont une sémantique différente.

Les connexions des protocoles de transport, comme TCP, utilisent uniquement l'identificateur, résistant ainsi aux changements de localisateurs. Une machine d'un site multi-homé peut ainsi basculer d'un FAI à l'autre sans casser ses connexions TCP (cf. section 3.4).

Notez bien que l'identificateur identifie une machine, pas une interface réseau. Sa sémantique est donc très différente de celle des adresses IPv4, IPv6, ou des Interface Identifier d'IPv6 (RFC 4219).

Cela ne signifie pas que l'identificateur puisse être utilisé directement par les applications clientes. Comme indiqué plus haut, il est plutôt recommandé de se servir du nom de domaine.

Dans cette architecture, qu'est-ce qui est le plus proche d'une adresse IP ? Probablement le couple {Identificateur, Localisateur}, I-LV (pour Identifier - Locator Vector, cf. section 3.3). Ce couple désigne une liaison, notée (I, L), entre un identificateur et un localisateur.

Bref, un paquet ILNP contiendra un I-LV source et un I-LV destination. Notez que la sémantique d'un I-LV est proche de celle d'une adresse IP mais pas identique (l'I-LV se sépare en deux, I et L, l'adresse IP est structurée différemment, avec plusieurs préfixes hiérarchiquement emboîtés, etc). Le RFC 6741 indique comment ces IL-V sont représentés dans un paquet IP.

Dans les fichiers ou entre discussions entre humains, les identificateurs ont le format d'un Interface Identifier IPv6 (section 3.1.2). Ce format, normalisé dans le RFC 4291 est fondé sur le format EUI-64 par exemple 3a59:f9ff:fe7d:b647. Si le bit « global » est mis à 1, l'identificateur est supposé être unique au niveau mondial.

Le localisateur a une syntaxe analogue (par exemple, 2001:db8:43a:c19). Une machine peut aussi avoir plusieurs localisateurs (par exemple parce qu'elle a plusieurs connexions réseau). Le routage sera fait sur la base des localisateurs, comme avec IP Classique aujourd'hui (ce n'est donc pas par hasard que le localisateur ressemble à un préfixe IPv6). Le localisateur peut être modifié en route (cas du NAT). Contrairement à l'identificateur, relativement stable (en tout cas pendant la durée d'une connexion), le localisateur peut changer souvent (par exemple en situation de mobilité). Lorsque cela se produit, la machine avertit ses correspondants (CN pour Correspondent Nodes) avec un message ICMP Locator Update. Si elle veut être contactée (si c'est un serveur), elle doit aussi mettre à jour le DNS. Ces deux mécanismes sont décrits en détail dans le RFC 6741.

Ces identificateurs et localisateurs sont publiés dans le DNS (cf. RFC 6742). Une application qui veut contacter www.example.com aujourd'hui utilise le DNS pour connaître l'adresse IP correspondante. Demain, elle utilisera ILNP pour connaître identificateur et localisateur. (Pour des raisons de sécurité, DNSSEC est recommandé.)

Il est aussi précisé que l'un des buts d'ILNP est de pouvoir l'incarner dans des protocoles qui sont compatibles avec l'existant (pour permettre à ILNP et IP Classique de coexister) et déployables de manière incrémentale (ne pas exiger que tout le monde passe à ILNP d'un coup).

La section 4 explique ensuite comment se fait le routage. Alice et Bob connaissent ILNP et veulent se parler, avec, entre eux, plusieurs routeurs traditionnels ne connaissant rien à ILNP. (En terminologie ILNP, Bob est le CN - Correspondent Node.) Dans le cas le plus courant, Bob a mis son (ou ses) Identificateurs et son (ou ses) Localisateurs dans le DNS (notez que les serveurs DNS utilisés n'ont pas besoin de connaître ILNP, mais cela optimise le temps de réponse DNS s'ils le gèrent). Cela a pu être fait manuellement ou, mieux, automatiquement via les mises à jour dynamiques (de préférence sécurisées, cf. RFC 3007). Alice va faire une requête DNS (cf. RFC 6742) et récupérer ainsi Identificateur et Localisateur de Bob (notez qu'ILNP n'a pas pour l'instant de mécanisme pour récupérer un Localisateur à partir d'un Identificateur).

Alice et Bob vont avoir besoin dans leurs systèmes d'une nouvelle structure de données, l'ILCC (I-L Communication Cache, section 4.2 et RFC 6741) qui permet de se souvenir des Localisateurs actuellement en service pour un CN donné. Au début, on y met les localisateurs récupérés via le DNS.

Ensuite, en IPv6, tout est simple. Alice fabrique un paquet IPv6, contenant l'option Nonce (numnique) du RFC 6744, et dont la source est la concaténation de son Localisateur et de son Identificateur (avec les valeurs données plus haut à titre d'exemple, ce sera 2001:db8:43a:c19:3a59:f9ff:fe7d:b647). La destination est formée en concaténant Localisateur et Identificateur de Bob. Les deux adresses ainsi fabriquées sont des adresses IPv6 tout à fait normales et les routeurs entre Alice et Bob suivent la méthode de routage, et de résolution d'adresses en local (NDP) traditionnelles.

En IPv4, cela sera toutefois plus complexe (on ne peut pas mettre Identificateur et Localisateur dans les 32 bits d'une adresse IPv4, et ARP ne permet pas de résoudre un Identificateur, trop gros pour lui). Voir les RFC 6746 et RFC 6747 pour les solutions adoptées.

Comment est-ce que cela résout le problème du multi-homing, déjà cité plusieurs fois ? Comme l'explique la section 5, ILNP traite le Muti-homing en fournissant un Identificateur par machine et au moins un Localisateur par FAI. Alice utilise un des localisateurs pour le paquet initial, puis prévient Bob par un message ICMP Locator Update pour annoncer les autres. En cas de panne ou de ralentissement d'un des FAI, Bob pourra envoyer ses paquets via les autres localisateurs (l'identificateur restant inchangé).

Pour les connexions entrantes (si Alice est un serveur Web), on publiera dans le DNS tous les localisateurs et le client les essaiera tous.

Multi-homing est en fait un terme très large. Il y a plusieurs cas :

  • Host multi-homing où une machine a plusieurs connexions à l'Internet. C'est relativement rare mais cela peut être, par exemple, un smartphone connecté en Wi-Fi et 3G en même temps. ILNP permet à cette machine d'utiliser les deux localisateurs, chacun issu des deux connexions possibles.
  • Site multi-homing où c'est un site entier qui est connecté à plusieurs opérateurs. Le RFC cite le cas où le site a des adresses PI et les annonce en BGP (ce qui charge la table de routage globale) mais il oublie le cas où les routeurs de sortie du site font simplement du NAT vers les adresses des FAI (ce qui ne permet ni la redondance des connexions entrantes, ni la continuité des connexions TCP). Dans le scénario typique de site multi-homing avec ILNP, les routeurs du site annoncent sur le réseau local avec RA (Router Advertisement) les N préfixes des N opérateurs utilisés, et les machines les utilisent comme localisateurs. Dans ce cas, les routeurs du site n'ont pas besoin de connaître ILNP, les machines terminales font tout le travail (enregistrer les localisateurs, les abandonner s'ils ne sont plus annoncés, etc).

Dans ILNP, la mobilité est traitée quasiment comme le multi-homing (section 6). Elle est donc très différente du Mobile IP du RFC 6275. Dans les deux cas, l'identificateur reste constant pendant que le localisateur actuellement utilisé peut changer. La principale différence est le délai : en cas de mobilité rapide, les mécanismes d'ILNP peuvent être trop lents pour assurer la transition (point que le RFC oublie de mentionner).

Comme pour le multi-homing, il peut y avoir mobilité d'une machine (le smartphone cité précédemment qui, maintenant, se déplace) ou d'un réseau entier (cas d'un bateau en déplacement, par exemple, où il faudra que les machines à bord connaissent ILNP). ILNP obtient le maintien de la connectivité grâce à des localisateurs qui changent dynamiquement (même en cours de session), une mise à jour de la liste que connait le CN, grâce aux messages ICMP Locator Update et enfin les mises à jour dynamiques du DNS (RFC 2136) pour continuer à recevoir de nouvelles sessions même après déplacement.

Avec IP Classic, si le téléphone se déplace et perd la Wi-Fi, les connexions TCP en cours sont coupées. Avec ILNP, le téléphone pourra simplement utiliser le(s) localisateur(s) restant(s) (ici, celui de la 3G) et garder ses connexions.

On a vu qu'ILNP était un truc assez ambitieux, promettant de résoudre plein de problèmes. Mais, comme l'ont montré les malheurs de plusieurs protocoles, être meilleur ne suffit pas. L'inertie de la base installée est forte. Il faut donc absolument, pour qu'un nouveau protocole ait la moindre chance de réussir, des mécanismes de compatibilité avec l'existant et de déploiement incrémental (on ne peut pas exiger que tout le monde migre au même moment). La section 8 discute en détail ces points. D'abord, un paquet ILNPv6 ne se distingue en rien d'un paquet IPv6 actuel (c'est un peu plus compliqué avec ILNPv4, pour lequel le traditionnel ARP ne suffit pas, cf. RFC 6747). Cela veut dire que les routeurs, de la petite box au gros routeur du cœur de l'Internet n'auront besoin d'aucun changement. Le routeur ne sait même pas que le paquet est de l'ILNPv6 (voir le RFC 6741 sur les détails concrets des paquets ILNP). On est donc dans un cas très différent de celui d'IPv6 où il fallait modifier tous les routeurs situés sur le trajet.

Côté DNS, il faudra des nouveaux types d'enregistrement (RFC 6742). Cela ne nécessite pas de modifications des résolveurs/caches. Sur les serveurs faisant autorité, il faudra légèrement modifier le code pour permettre le chargement de ces nouveaux types.

Il serait tout de même souhaitable que les serveurs DNS, lorsqu'ils reçoivent une requête pour des noms qui ont des enregistrements ILNP, envoient tous ces enregistrements dans la réponse. Ce n'est pas nécessaire (le client pourra toujours les demander après) mais cela diminuera le temps total de traitement. (Les requêtes de type ANY, « donne-moi tous les enregistrements que tu as », ne renvoient pas forcément le résultat attendu, un cache n'ayant pas forcément tous les enregistrements correspondant à un nom.)

Si Alice et Bob connaissent tous les deux ILNP et qu'Alice initie une session avec Bob, tout se passera bien. Alice demandera l'enregistrement DNS de type NID, le serveur lui renverra l'identificateur de Bob, les localisateurs seront ajoutés par le serveur DNS (s'il connait ILNP) ou demandés explicitement par Alice par la suite. Alice générera le numnique, et l'enverra à Bob avec sa demande de connexion (RFC 6744). Mais, dans une optique de déploiement incrémental, il faut prévoir le cas où Alice aura ILNP et pas Bob, ou bien l'inverse. Que se passera-t-il alors ?

Si Alice connait ILNP et pas Bob, il n'y aura pas d'enregistrement NID dans le DNS pour Bob. Alice devra alors reessayer avec de l'IP classique. Si un enregistrement NID était présent à tort, Alice tentera en ILNP et enverra le numnique. Bob, en recevant cette option inconnue, rejettera le paquet en envoyant un message ICMP indiquant à Alice ce qui s'est passé.

Si Alice ne connait pas ILNP alors que Bob le connait, Alice ne demandera pas le NID et ne tentera rien en ILNP. Si Bob accepte l'IP Classic, la connexion marchera, sans ILNP.

Vu du point de vue de Bob (qui ne connait pas les requêtes DNS qui ont été faites), la connexion est en ILNP si l'option Nonce était présente dans le paquet initial, et en IP Classic autrement.

Le RFC ne mentionne toutefois pas trois problèmes pratiques :

  • Si un enregistrement DNS annonce à tort que Bob connait ILNP, Alice essaie d'abord en ILNP puis passe en IP Classic, ce qui augmentera le temps d'établissement d'une connexion.
  • Plus grave, si le paquet ICMP indiquant que Bob ne connait pas ILNP est perdu ou filtré (un certain nombre de sites bloquent stupidement la totalité des messages ICMP), le délai avant qu'Alice n'essaie en IP Classic sera très long. C'est le problème connu sous le nom de « malheur des globes oculaires » (RFC 6555 et RFC 6556).
  • Les options IPv6 sont très rares dans l'Internet d'aujourd'hui. Les mauvaises expériences avec les options IPv4 font qu'on peut être inquiet de leur viabilité.

Et la sécurité ? La section 7 couvre le cas particulier des interactions entre ILNP et IPsec (RFC 4301). La principale différence avec IP Classic est que l'association de sécurité IPsec se fait avec les identificateurs et plus avec les adresses.

Pour la sécurité d'ILNP en général, c'est la section 9 qu'il faut lire. En gros, ILNP a le même genre de risques qu'IP (on peut mentir sur son localisateur aussi facilement qu'on peut mentir sur son adresse IP) et les mêmes mesures de protection (comme IPsec).

Les Locator Updates d'ILNP, qui n'ont pas d'équivalent dans IP, sont protégés essentiellement par le numnique (RFC 6744). Sans cela, un méchant pourrait faire un faux Locator Update et rediriger tout le trafic chez lui. Avec le numnique, les attaques en aveugle sont extrêmement difficiles. Par contre, si l'attaquant peut espionner le trafic (par exemple s'il est sur le chemin de celui-ci), le numnique ne protège plus (c'est analogue au problème du numéro de séquence initial de TCP, cf. RFC 6528). Il faut alors chiffrer toute la session avec IPsec (selon le type de menaces, on peut aussi envisager SSH ou TLS). Cette situation n'est pas très différente de celle d'IP Classic.

Notez qu'il existe deux numniques par session, un dans chaque sens. Les chemins sur l'Internet étant souvent asymétriques, cela complique la tâche de l'attaquant (s'il n'est que sur un seul chemin, il ne trouvera qu'un seul numnique).

Autre attaque courante sur l'Internet (même si le RFC dit, curieusement, qu'elle existe mais n'est pas répandue), l'usurpation d'adresses. Il est facile de mentir sur son adresse IP. Peut-on mentir sur son Identificateur ou bien son Localisateur ? Disons que mentir sur son Identificateur est en effet facile et qu'on ne peut guère l'empêcher. Contrairement à HIP, ILNP n'a pas forcément de protection cryptographique de l'identificateur (cf. RFC 7343). Il est possible d'utiliser les adresses cryptographiques du RFC 3972, il reste à voir si cela sera déployé. Autre solution dans le futur, utiliser IPsec avec des clés indexées par l'identificateur (mais cela reste bien théorique).

En revanche, un mensonge sur le Localisateur est plus difficile. Il peut être protégé par les techniques du RFC 2827 et RFC 3704. Certains protocoles au-dessus, comme TCP avec ses numéros de séquence initiaux imprévisibles, ajoutent une autre protection.

Autre aspect de la sécurité, la vie privée. Comme le rappele la section 10, avoir un identificateur stable peut faciliter le suivi d'une machine (et donc de son utilisateur) même lorsqu'elle se déplace. Ce problème est connu sous le nom d'identity privacy. Le problème avait déjà été mentionné avec IPv6 et la solution est la même : se servir des identificateurs temporaires du RFC 8981. (Une machine ILNP n'est pas forcée de n'avoir qu'un seul identificateur.)

Autre menace, celle sur la location privacy. Non spécifique à ILNP, c'est le fait qu'on puisse connaître la localisation actuelle d'une machine via son localisateur. Le problème est très difficile à résoudre, la qualité de la connectivité étant inversement proportionnelle à la dissimulation de l'adresse. Si on force le passage par une machine relais fixe (comme le permet Mobile IP), on a une bonne protection de la vie privée... et une bonne chute des performances et de la résilience.

Si le localisateur a été publié dans le DNS, un indiscret qui veut le connaître n'a même pas besoin d'une communication avec la machine qu'il veut pister, interroger le DNS (qui est public) suffit. Si une machine veut rester discrète sur sa localisation et qu'elle n'a pas besoin d'être contactée, le mieux est qu'elle ne mette pas son localisateur dans le DNS.

Il n'existe encore aucune mise en œuvre publique d'ILNP. Un projet existe mais rien n'est encore sorti.

Pour les curieux d'histoire, la section 1.2 présente la vision des auteurs sur les différentes étapes ayant mené à ILNP. Ils remontent jusqu'en 1977 où la note IEN1 notait déjà le problème qu'il y avait à faire dépendre les connexions d'une adresse qui pouvait changer. Cette note proposait déjà une séparation de l'identificateur et du localisateur, qui n'a pas eu lieu dans TCP/IP. Par exemple, TCP utilise dans la structure de données qui identifie une connexion les adresses IP de source et de destination. Tout changement d'une de ces adresses (par exemple parce que la machine a bougé) casse les connexions TCP en cours.

Après ce choix, et quelques années plus tard, l'idée d'une séparation de l'identificateur et du localisateur est revenue, compte-tenu de l'expérience avec TCP/IP. En 1994, une note de Bob Smart repropose cette idée. Même chose en 1995 avec Dave Clark. Enfin, en 1996, Mike O'Dell propose son fameux 8+8, qui n'atteindra jamais le statut de RFC mais reste la référence historique des propositions de séparation de l'identificateur et du localisateur. (Une grosse différence entre 8+8 et ILNP est que ce dernier n'impose pas de réécriture du localisateur en cours de route).

Depuis, plusieurs autres travaux ont été faits en ce sens, mais sans déboucher sur beaucoup de déploiements. Des « vrais » protocoles de séparation de l'identificateur et du localisateur (rappelons que les auteurs ne considèrent pas LISP comme faisant partie de cette catégorie), seul HIP a connu une description dans un RFC et plusieurs mises en œuvres. ILNP offre sans doute moins de sécurité que HIP (contrairement à HIP, pas besoin d'établir une connexion avant toute communication) mais autant qu'avec l'IP actuel. Et ILNP est moins disruptif que HIP, ce qui peut être vu comme un avantage ou un inconvénient.

Quelques lectures :


Téléchargez le RFC 6740


L'article seul

RFC 6733: Diameter Base Protocol

Date de publication du RFC : Octobre 2012
Auteur(s) du RFC : V. Fajardo (Telcordia Technologies), J. Arkko (Ericsson Research), J. Loughney (Nokia Research Center), G. Zorn (Network Zen)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dime
Première rédaction de cet article le 26 octobre 2012


Pendant longtemps, le seul protocole standard d'authentification entre un NAS et sa base d'utilisateurs était Radius. Diameter, normalisé dans notre RFC (qui fait suite au RFC 3588), visait à le remplacer, et est bien plus riche en fonctions.

Traditionnellement, lorsqu'un client PPP ou d'un protocole similaire se connecte à son FAI, sa session est terminée sur un NAS, équipement qui ne possède en général pas de base des utilisateurs autorisés. Il y a plusieurs raisons à cela, comme le fait que le NAS n'est en général pas un ordinateur généraliste, il a peu de moyens, notamment en place disque ou bien comme le fait qu'un FAI a typiquement plusieurs NAS (au moins un par POP), et qu'il souhaite centraliser l'authentification. (Dans le monde 802.11, le NAS est typiquement nommé AP - Access Point.)

Le mécanisme habituel est donc que le NAS soit client d'un protocole d'authentification et que le FAI gère un serveur de ce protocole, serveur qui connaitra les utilisateurs autorisés. Le même protocole assure en général également des fonctions de comptabilisation des accès, d'où le sigle AAA (Authentication, Authorization and Accounting). Le premier protocole standard en ce sens est Radius (RFC 2865), que Diameter vise à remplacer. (Un protocole privé, Tacacs, qui sera documenté dans le RFC 1492, avait également été utilisé.) Diameter avait été normalisé à l'origine dans le RFC 3588. Après une longue gestation (plusieurs années, alors qu'aucun changement de fond n'a été fait, et pas moins de trois « Last Calls » devant l'IETF), il est désormais remplacé par ce nouveau RFC 6733. Le protocole reste le même et les logiciels conformes à l'ancien et au nouveau RFC devraient interopérer.

Que reproche Diameter à Radius ? La section 1 de notre RFC détaille les faiblesses de Radius perçues par les auteurs de Diameter. Une analyse plus détaillée figure dans le RFC 3169 :

  • Utilisation d'UDP, protocole de transport n'assurant pas de fiabilité,
  • Pas de mécanisme de redondance standard,
  • Limites de taille pour certains paramètres (par exemple la longueur d'un attribut n'est codée que sur un octet, ce qui limite les attributs à 256 caractères).

Diameter est donc plus riche et plus complexe que Radius. Diameter reprend aussi plusieurs idées de Radius comme le codage en doublets Attribut / Valeur (AVP pour Attribute-Value Pairs) ou comme l'utilisation des NAI du RFC 7542 pour coder l'identité vérifiée.

Le RFC est bien plus long et compliqué que son équivalent Radius (154 pages !). La section 1 introduit le protocole, et ses usages, et le compare aux exigences listées dans le RFC 2989.

La section 2 précise le protocole, par exemple le mécanisme de transport fait l'objet de la sous-section 2.1, qui impose au minimum TCP et SCTP (les détails sont dans le RFC 3539). Diameter écoute par défaut sur le port 3868. La 2.4 introduit le nouveau concept d'Application Identifier, valeur enregistrées auprès de l'IANA qui identifie un usage particulier de Diameter (plus riche que Radius, Diameter permet davantage d'usages). Par exemple, l'usage en tant que service d'authentification pour un NAS (Application Identifier n° 1) n'est pas dans le cœur du protocole, il est délégué au RFC 4005. D'autres RFC décrivent des applications de Diameter comme le RFC 4740 qui parle de son usage pour SIP. 2.5 parle de la différence entre connexions et sessions, une connexion étant un concept de la couche 4 alors qu'une session Diameter peut impliquer plusieurs connexions. En 2.8, on trouve le bestiaire des agents Diameter, les clients et les serveurs bien sûr mais également les relais ou bien les traducteurs, pour parler à des agents d'autres protocoles, notamment Radius.

La section 3 décrit l'en-tête des paquets Diameter et les codes de commande qu'ils contiennent comme Capabilities-Exchange-Request. Seuls les codes communs à toutes les applications sont définis dans la section 3.1, des codes aussi importants que AA-Request (demande d'authentification, l'équivalent du Access-Request de Radius) sont délégués à d'autres RFC (comme le RFC 4005).

En section 4, nous arrivons aux AVP eux-même, les doublets attributs-valeur qui portent l'information. On notera en 4.1 un concept désormais fréquent dans les protocoles réseaux, l'option Mandatory qui indique pour un AVP, s'il doit absolument être connu de l'implémentation (le dialogue Diameter avorte autrement) ou bien s'il peut tranquillement être ignoré, par exemple par une vieille implémentation qui ne connait pas ce nouvel AVP. La sous-section 4.3 décrit, entre autre, les URI Diameter, de plan aaa:, comme aaa://host.example.com:666:transport=stcp;protocol=diameter.

Les sections 5 à 8 spécifient les nombreuses machines à état qui doivent être mises en œuvre par les agents Diameter. Au contraire de Radius qui, comme le DNS, est purement requête/réponse, Diameter nécessite un vrai automate dans chaque agent.

La sous-section 5.2 explique comment un agent Diameter peut en trouver un autre. Avec Radius, la configuration (par exemple du serveur d'authentification) devait être manuelle. Avec Diameter, on peut utiliser SLP (RFC 2165) ou NAPTR combiné avec SRV (RFC 2782).

La section 13, sur la sécurité, est très stricte. Un agent Diameter doit pouvoir faire du TLS (mais, contrairement au RFC 3588, IPsec n'est plus qu'une possibilité secondaire).

Une bonne introduction à Diameter a été publié en http://www.interlinknetworks.com/whitepapers/Introduction_to_Diameter.pdf. Il n'existe que trois implémentations de serveur Diameter en logiciel libre, Free Diameter, Open Diameter et OpenBlox Diameter, et, à part la première, elles semblent peu maintenues. (Et je ne suis pas sûr qu'OpenBlox soit vraiment libre.)

Le bilan opérationnel de Diameter est mince : beaucoup plus complexe que Radius, il ne l'a pas réellement remplacé dans son secteur, l'authentification via un NAS. Diameter semble bien être une nouvelle victime de l'effet « Deuxième système ».

Quels sont les changements par rapport au premier RFC Diameter, le RFC 3588 ? La section 1.1.3 en donne un résumé (la liste exacte est trop longue pour être incluse dans ce RFC déjà très long). Si les changements sont nombreux, ils ne sont pas suffisamment importants pour qu'on puisse parler d'un nouveau protocole. C'est le même Diameter et les nouveaux logiciels pourront parler avec les anciens. Les changements sont des clarifications, des abandons de certaines fonctions, et la correction des nombreuses erreurs du RFC précédent (à mon avis, il y a une leçon à en tirer : les spécifications compliquées sont plus difficiles à faire correctement). Certaines fonctions étaient mentionnées dans le RFC 3588 mais même pas décrites complètement. Les principaux changements :

  • Plus de mécanisme pour négocier en cours de session une sécurisation de la session par le chiffrement et introduction d'un nouveau port, le 5868, pour des connexions chiffrées avec TLS dès le début. (En fait, l'ancien mécanisme reste mais uniquement pour assurer la compatibilité.)
  • La demande irréaliste du RFC 3588 d'avoir toujours IPsec a été retirée.
  • Simplification de plusieurs fonctions comme la découverte du pair (pour laquelle il existait un zillion de méthodes dans le RFC 3588).
  • Et bien d'autres clarifications, corrections de bogue dans les machines à état, etc.

Téléchargez le RFC 6733


L'article seul

RFC 6731: Improved Recursive DNS Server Selection for Multi-Interfaced Nodes

Date de publication du RFC : Décembre 2012
Auteur(s) du RFC : T. Savolainen (Nokia), J. Kato (NTT), T. Lemon (Nominum)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF mif
Première rédaction de cet article le 19 décembre 2012


Lorsqu'une machine connectée à l'Internet a plusieurs interfaces réseaux, et apprend (par exemple en DHCP) l'existence d'un résolveur DNS différent sur chaque interface, lequel utiliser ? Le principe de base de cette nouvelle norme est qu'il faudrait garder en mémoire chaque résolveur et utiliser à chaque fois celui qui correspond à l'interface réseau qu'on va utiliser.

Autrefois, le problème ne semblait pas crucial : après tout, un résolveur DNS en vaut un autre, puisque tous donnent les mêmes réponses. Mais ce n'est plus le cas aujourd'hui. Par exemple, sur certaines interfaces, le résolveur DNS peut donner accès à des noms de domaine privés, strictement locaux, que les autres résolveurs ne connaissent pas. On ne peut donc pas se contenter de prendre l'un des résolveurs au hasard, ni même « le meilleur » résolveur car chacun peut avoir des caractéristiques uniques (par exemple, l'un des résolveurs connait le domaine privé foo.example et un autre un autre domaine privé bar.example). D'où cette règle de garder en mémoire tous les résolveurs connus. (Le RFC utilise le terme de RDNSSRecursive DNS Servers - pour les résolveurs.)

Ce n'est pas tout de mémoriser tous les résolveurs, encore faut-il savoir lequel utiliser. C'est le rôle de nouvelles options DHCP normalisées ici, qui permettent de distribuer les méta-informations dont le client a besoin pour savoir de quel résolveur se servir.

Si on veut mieux comprendre le problème de ces machines ayant plusieurs interfaces réseaux, il faut lire le premier RFC du groupe de travail MIF, le RFC 6418, qui définit le problème. Un exemple d'une telle machine est un smartphone qui a accès à la fois à un réseau WiFi privé et à la 3G. Mais il y a aussi le cas où il n'y a qu'une seule interface physique, mais plusieurs virtuelles, par exemple un accès à l'Internet par le FAI local et un VPN vers le réseau sécurisé de l'entreprise. La partie la plus évidente du problème des machines à plusieurs interfaces est celui des noms privés (section 2.1). Imaginons que la société Foobar ait le domaine foobar.example et qu'un sous-domaine internal.foobar.example contienne les informations privées, spécifiques à l'entreprise et non visibles dans le DNS public. Cela se fait en configurant spécialement les résolveurs utilisés par les employés de l'entreprise. Par exemple, avec Unbound, pour un domaine nommé 42 et servi par 91.191.147.246 et 91.191.147.243, cela serait :

stub-zone:
   name: "42"
   stub-addr: 91.191.147.246
   stub-addr: 91.191.147.243

Si un de ces employés est en voyage, connecté depuis l'hôtel, ayant activé le VPN, et que sa machine utilise le résolveur de l'hôtel, il ne pourra pas utiliser les noms en internal.foobar.example. (Vous pouvez vous dire « il faut utiliser le résolveur DNS de l'entreprise pour tout ». Mais il sera en général plus lent et il pourra avoir ses propres limites, par exemple ne pas pouvoir résoudre facebook.com car le résolveur de l'entreprise censure ce nom.)

Notez aussi que le fait que l'application de ce RFC permettre de gérer les noms de domaines privés (non rattachés à l'arbre principal du DNS) ne signifie pas que ces noms privés soient une bonne idée, approuvée par l'IETF. Ce point avait été une des grosses controverses dans le groupe de travail. La section 6 donne à ce sujet des conseils pour minimiser les risques associés à ces noms privés. (En gros, les choisir uniques, par exemple en les suffixant du nom de l'organisation, pour que tout le monde ne nomme pas ses machines dans .private ou .lan.)

En général, le « bon » résolveur à utiliser dépend de l'interface de sortie et les techniques de ce RFC sont donc à utiliser en combinaison avec celles du RFC 4191 et du RFC 3442. Même si un nom de domaine est visible partout, il peut se résoudre en des adresses IP différentes selon l'interface réseau utilisé (cas célèbre de smtp.orange.fr qui ne donne pas le même résultat aux abonnés d'Orange et aux autres.) On peut encore citer le cas des extensions au DNS utilisées dans certains cas de coexistence IPv4-IPv6 (RFC 6147).

Il peut y avoir des cas encore plus complexes et notre RFC ne prétend pas tout résoudre (section 2.3).

Avant de décrire la solution standardisée, le RFC présente trois études de cas permettant d'illustrer un problème soluble (section 3). Des études de cas plus détaillées, avec examen des pratiques actuelles, figurent dans le RFC 6419.

D'abord, le cas d'un foyer connecté à l'Internet via un FAI ainsi qu'à un réseau privé, les deux connexions passant par le même CPE. Ce réseau privé utilise uniquement des noms dans un domaine qui n'apparait pas sur l'Internet (mettons hidden.example). Pour que tout marche, du point de vue de l'utilisateur, il faut envoyer les requêtes de résolution de noms au résolveur du réseau privé, si le nom se termine en hidden.example et au résolveur du FAI autrement. Le plus simple est qu'un relais DNS tourne sur le CPE et aiguille automatiquement les requêtes DNS vers le bon résolveur.

Autre scénario d'usage, celui mentionné plus tôt d'un smartphone connecte à la fois au réseau 3G et à un accès WiFi local. Pour des raisons financières, on souhaite utiliser le WiFi dans le plus grand nombre de cas. Mais on peut avoir besoin d'établir certaines connexions via la 3G, soit parce que certains services ne sont que là, soit pour des raisons de sécurité (à mon avis, le RFC surestime nettement la sécurité de la 3G mais c'est une autre histoire).

Le smartphone doit donc utiliser le DNS de l'accès WiFi par défaut mais avoir des règles (par exemple une liste de destinations sensibles qu'on ne veut contacter qu'en 3G) qui imposeront l'utilisation du résolveur DNS du fournisseur de 3G.

Enfin, dernière étude de cas, celui du road warrior doté d'un accès à un (ou plusieurs) VPN de son entreprise. Aussi bien pour des raisons de sécurité que d'accès à des noms de domaines privés, on veut faire passer les accès au réseau interne de l'entreprise (requêtes DNS comprises) par le VPN. Par contre, pour consulter Facebook et YouTube, on va passer par l'accès par défaut.

La section 4 du RFC donne ensuite les règles exactes à suivre pour que tout se passe bien. Le principe essentiel est que la machine doit construire une liste de résolveurs (et pas uniquement garder le dernier annoncé) accessibles, en notant pour chacun les options envoyées par DHCP (nouvelles options décrites un peu plus loin), qui vont permettre de sélectionner le résolveur à utiliser pour une requête donnée. Par défaut, on considère que tous les résolveurs sont équivalents (donnent les mêmes résultats). Mais certains critères permettent de les distinguer :

  • La confiance qu'on leur accorde (voir section 9.2 du RFC). C'est assez subjectif mais on peut penser, par exemple, qu'un résolveur atteint par un VPN IPsec vers son entreprise est plus digne de confiance que le résolveur d'un hotspot dans un café. Certains disent même que la 3G avec son fournisseur mobile est plus sûre (c'est l'exemple de pseudo-code dans l'annexe C, avec IF_CELLULAR préféré à IF_WLAN.) Cette confiance est à configurer dans le client, il n'y a pas de protocole pour la déterminer.
  • La préférence indiquée en DHCP (voir les nouvelles options DHCP plus loin.).
  • Les domaines privés qu'ils gèrent... ou pas.
  • Le fait qu'ils valident avec DNSSEC ou pas. À noter que cela peut aussi dépendre des clés DNSSEC connues. Dans le cas le plus fréquent, le résolveur ne valide qu'avec la clé de la racine du DNS. Mais, s'il a d'autres clés configurées, il faut lire l'annexe B du RFC car c'est un peu plus compliqué.

Avec tous ces critères, on peut faire une sélection intelligente du résolveur. Ainsi, s'il faut résoudre un nom en private.mycompany.example et qu'un seul des résolveurs annonce ce domaine (les autres gérant l'arbre public du DNS), c'est clair qu'il faut utiliser ce serveur, les autres ne pourront pas répondre. Les règles de sélection exactes figurent dans la section 4.1. Si vous préférez lire le pseudo-code, l'annexe C contient une mise en œuvre de cet algorithme.

Les sections 4.2 et 4.3 décrivent les nouvelles options pour DHCPv4 (RFC 2131) et DHCPv6 (RFC 8415). Elles sont quasiment identiques en v4 et v6 donc je me limite à celle de v6 :

  • Son code est 74 (146 en v4),
  • Elle contient l'adresse IPv6 du résolveur et la préférence attribuée à ce serveur (High, Medium ou Low),
  • Elle contient une liste de domaines que le résolveur connait, par exemple private.company.example, (et . tout court s'il connait tous les domaines, ce qui est le cas d'un résolveur normal), ainsi qu'une liste de domaines correspondant à des préfixes IP pour les résolutions dans ip6.arpa (RFC 3596).

Un client DHCP qui connait notre RFC met une demande de cette option dans sa requête et reçoit en échange la liste ci-dessus. Attention, elle est limitée en taille par les contraintes de DHCP (section 4.4), il ne faut donc pas espérer y indiquer des centaines de domaines possibles.

Une fois qu'un résolveur a été sélectionné pour une requête DNS, il doit continuer à être utilisé si cette requête déclenche à son tour d'autres requêtes (section 4.7). Imaginons qu'on cherche l'adresse IPv6 de portal.company.example, on va faire une requête AAAA portal.company.example et si on obtient une réponse portal.company.example CNAME www.example.com, alors, la requête ultérieure AAAA www.example.com doit utiliser le même résolveur, pour être cohérente, au cas où www.example.com renvoie des adresses différentes selon le résolveur qui demande. Programmeurs, attention, cela implique de garder un état et de ne pas faire la sélection du résolveur de manière indépendante pour chaque requête.

De même qu'on garde une liste de résolveurs à utiliser, il faut aussi avoir autant de caches que d'interfaces, ou vider le cache entre deux requêtes, pour éviter qu'une information venant du cache n'« empoisonne » une résolution. Et il ne faut pas oublier, lorsqu'une interface réseau disparait, de vider le cache des données apprises via cette interface (section 4.8). Le logiciel local de la machine devient donc assez compliqué !

Voilà, vous savez tout. Si le problème vous intéresse et que vous voulez creuser la question, l'annexe A de ce RFC présente « ce qui aurait pu être », les autres mécanismes qui auraient pu être choisis (comme « envoyer la requête sur toutes les interfaces réseau et prendre la première réponse qui revient »).

Actuellement, il semble que certains systèmes de Nokia et de Microsoft (Name Resolution Policy Table) utilisent déjà ce mécanisme dans leurs téléphones.


Téléchargez le RFC 6731


L'article seul

RFC 6730: Requirements for IETF Nominations Committee tools

Date de publication du RFC : Septembre 2012
Auteur(s) du RFC : S. Krishnan, J. Halpern (Ericsson)
Pour information
Première rédaction de cet article le 27 septembre 2012


L'IETF dispose d'une institution curieuse, le NomCom (Nominations Committee) qui est chargée de sélectionner des candidats pour des postes à l'IESG, l'IAB ou l'IAOC. Sa tâche d'examen des noms et de sélection nécessite un certain nombre d'outils informatiques, qui n'existent pas forcément tous à l'heure actuelle. Ce RFC est le cahier des charges des outils, pour servir de base aux futurs développements.

Tous les détails sur le NomCom et son fonctionnement sont spécifiés dans le RFC 7437. On peut aussi consulter le site officiel. Le NomCom dispose déjà d'un outil (accessible via le Web pour sa partie publique, mais il a aussi une partie privée, réservée aux membres du NomCom) mais qui est insuffisant. Notre nouveau RFC liste les nouveautés nécessaires pour cet outil. La première exigence, étiquetée META-001 est que le nouvel outil devra reprendre toutes les fonctions de l'ancien.

Ensuite, comme le NomCom travaille avec des données personnelles, la plupart des exigences du cahier des charges concernent la sécurité. Le logiciel stockera des noms, des appréciations, des opinions sur des personnes, etc, toutes choses assez sensibles. Il faudra un système d'authentification (exigences AUTH-001 à AUTH-003), capable de distinguer trois rôles (membre ordinaire de l'IETF, membre du NomCom, président du NomCom). Les membres ordinaires n'ont accès qu'à la partie publique. Ils se servent pour cela de leur compte datatracker.ietf.org (cf. RFC 6175, tout le monde peut se créer un compte avec cet outil puisque tout le monde peut participer à l'IETF).

Toutes les communications seront évidemment chiffrées et l'exigence SEC-001 demande que les données stockées le soient de telle façon qu'on minimise même leur exposition accidentelle (même l'administrateur ne doit les voir que sur une action explicite de sa part). Les données seront stockées chiffrées avec la clé publique du NomCom (exigences SEC-002 à SEC-005) et seront détruites à la fin de la sélection (toutes les données ne sont pas concernées, voir plus loin).

Moins cruciales, les autres exigences portent sur le processus de désignation des candidats (exigences NOM-001 à NOM-011) et sur l'enregistrement de l'acceptation ou du rejet car un candidat peut ne pas accepter sa désignation, qui a pu être faite par un tiers (exigences AD-001 à AD-007).

Enfin, l'outil devra gérer les réponses des candidats aux questionnaires qui leur seront soumis (« que ferez-vous si vous êtes élu à l'IAB ? » (exigences QR-001 à QR-007) et surtout les retours des membres sur les candidatures (exigences FB-001 à FB-006). Ces retours, avis, et opinions forment une part essentielle du processus mais, malheureusement, les exigences d'ouverture et de sécurité ne sont pas faciles à concilier. Ainsi, les messages envoyés au NomCom par les membres sont archivés, contrairement aux autres données collectées par le NomCom (exigence FB-005).

On peut finir avec l'amusante annexe A de ce RFC, qui décrit les commandes OpenSSL nécessaires pour la gestion de la cryptographie dans l'outil du NomCom. La configuration (le fichier nomcom-config.cnf) ressemble à :

[ req ]
distinguished_name = req_distinguished_name
string_mask        = utf8only
x509_extensions    = ss_v3_ca

[ req_distinguished_name ]
commonName           = Common Name (e.g., NomcomYY)
commonName_default  = Nomcom12

[ ss_v3_ca ]

subjectKeyIdentifier = hash
keyUsage = critical, digitalSignature, keyEncipherment, dataEncipherment
basicConstraints = critical, CA:true
subjectAltName = email:nomcom12@ietf.org
extendedKeyUsage= emailProtection
# modify the email address to match the year.

Et on peut générer le certificat avec :

openssl req -config nomcom-config.cnf -x509 -new -newkey rsa:2048 \
   -sha256 -days 730 -nodes -keyout privateKey.pem \
   -out nomcom12.cert

Téléchargez le RFC 6730


L'article seul

RFC 6729: Indicating Email Handling States in Trace Fields

Date de publication du RFC : Septembre 2012
Auteur(s) du RFC : D. Crocker (Brandenburg InternetWorking), M. Kucherawy (Cloudmark)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF appsawg
Première rédaction de cet article le 7 septembre 2012


Lorsqu'on débogue un problème de courrier électronique en examinant un message reçu, le technicien regarde souvent en premier les champs Received: de l'en-tête. Ceux-ci indiquent les différents MTA qui ont pris en charge le message et sont notamment très utiles en cas de retard inattendu : ils permettent de voir quel MTA a traîné dans la remise du message au MTA suivant. Mais cela ne suffit pas toujours. Aujourd'hui, il est de plus en plus fréquent que les messages soient retardés en raison d'un traitement local à une machine, par exemple le passage par un programme de sécurité qui met très longtemps à vérifier quelque chose. Il n'y avait pas de moyen pratique avec les champs Received: pour indiquer ces traitements. C'est désormais fait avec un nouvel indicateur dans Received: : state qui permet de signaler le passage d'un traitement lent à un autre.

Voici un exemple d'une suite de champs Received:. Rappelez-vous qu'elle se lit de bas en haut :


Received: from slow3-v.mail.gandi.net (slow3-v.mail.gandi.net [217.70.178.89])
        by mail.bortzmeyer.org (Postfix) with ESMTP id 5EC103AD82
        for <stephane+blog@bortzmeyer.org>; Thu,  6 Sep 2012 18:26:36 +0000 (UTC)
Received: from relay4-d.mail.gandi.net (relay4-d.mail.gandi.net [217.70.183.196])
        by slow3-v.mail.gandi.net (Postfix) with ESMTP id 2268638B64
        for <stephane+blog@bortzmeyer.org>; Thu,  6 Sep 2012 20:21:20 +0200 (CEST)
Received: from mfilter1-d.gandi.net (mfilter1-d.gandi.net [217.70.178.130])
        by relay4-d.mail.gandi.net (Postfix) with ESMTP id 0844C172094
        for <stephane+blog@bortzmeyer.org>; Thu,  6 Sep 2012 20:21:10 +0200 (CEST)
Received: from relay4-d.mail.gandi.net ([217.70.183.196])
        by mfilter1-d.gandi.net (mfilter1-d.gandi.net [10.0.15.180]) (amavisd-new, port
        10024)
        with ESMTP id 9nO2SZ5sO3KB for <stephane+blog@bortzmeyer.org>;
        Thu,  6 Sep 2012 20:21:08 +0200 (CEST)

On note que la machine mfilter1-d.gandi.net a renvoyé le message à relay4-d.mail.gandi.net d'où il venait. Ce n'est pas une erreur, mfilter1-d.gandi.net est la machine de filtrage et utilise Amavis pour un certain nombre de tests sur le message (absence de virus, par exemple) avant de le réinjecter. Ici, cet examen a été rapide (deux secondes, si on peut se fier aux horloges des machines) mais, s'il est plus long (et Amavis peut être très long), il serait souhaitable de pouvoir le marquer plus clairement.

Il existe bien des tests/vérifications/etc qui peuvent ainsi ralentir un message : mise en quarantaine, modération, tests anti-spam ou anti-virus, etc. Pour les indiquer plus clairement, notre RFC reprend le champ Received: (défini à la section 4.4 du RFC 5321 et un des outils les plus importants du technicien qui fait fonctionner le courrier électronique). Ce champ comprend plusieurs clauses (dans les exemples ci-dessus, on voit les clauses from, by, with et for, définies dans la section 4.4 du RFC 5321). Notre RFC en ajoute une nouvelle, state (désormais enregistrée, section Additional-registered-clauses), qui ressemble à ça (exemple du RFC car je n'ai pas encore trouvé de clause state dans mes boîtes aux lettres, bien qu'il existe apparemment déjà une mise en œuvre en production) :


Received: from newyork.example.com
                  (newyork.example.com [192.0.2.250])
              by mail-router.example.net (8.11.6/8.11.6)
                  with ESMTP id i7PK0sH7021929
                  for <recipient@example.net>;
              Fri, Feb 15 2002 18:33:29 -0800
Received: from internal.example.com
                  (internal.example.com [192.168.0.1])
              by newyork.example.com (8.11.6/8.11.6)
                  with ESMTP id i9MKZCRd064134
                  for <secret-list@example.com>
                  state moderation (sender not subscribed);
              Fri, Feb 15 2002 17:19:08 -0800

Ici, le MTA de newyork.example.com a décidé de ne pas envoyer le message tout de suite mais de le soumettre à un modérateur (avant-dernière ligne du plus ancien Received:, clause state). Cela suffit à expliquer le délai d'une heure vingt entre les deux Received:, sans imaginer une coupure réseau ou une autre panne. On voit que la clause state indique l'entrée dans un nouvel état (ici, l'état « en attente d'approbation par le modérateur »), la sortie étant marquée par le champ Received: suivant (qui, ici, n'a pas d'état explicite). Rappelez-vous (promis, c'est la dernière fois que je le dis) que les champs Received: se lisent de bas en haut.

La clause state dans l'exemple ci-dessus utilisait le mot-clé moderation. Une liste limitative de tels mots-clés est enregistrée (section Registered-states) et elle comprend notamment :

  • auth : le message attend une authentification,
  • content : le contenu du message va être analysé, par exemple pour s'assurer qu'il ne contient pas de spam ou de malware,
  • moderation : passage par le modérateur,
  • timed : message délibérement gardé, en attendant l'heure de la remise (voir RFC 4865),
  • normal : ce mot-clé est enregistré mais, en fait, c'est celui par défaut, lorsqu'aucune clause state n'est présente,
  • other : il y a toujours des cas où on ne sait pas :-)

À noter que le mot-clé peut être suivi d'une barre oblique et d'une valeur (non enregistrée, on met ce qu'on veut), on peut donc avoir moderation/not-subscribed ou quarantine/spam. D'autres états pourront être enregistrés dans le futur, sous la politique « Premier arrivé, premier servi » (cf. RFC 5226). Ce point avait été le principal sujet de discussion avant la publication du RFC, certains auraient préféré la politique plus restrictive « Examen par un expert ».

Les programmeurs de MTA qui veulent ajouter cette clause aux champs Received: qu'ils écrivent ont tout intérêt à bien lire les sections 4 et 5, qui discutent de quand utiliser la clause state. Elle n'est pas prévue pour des opérations différentes à l'intérieur d'un même agent. Le RFC recommande bien qu'elle ne soit utilisée que lorsqu'on passe à un agent différent, par exemple de Postfix à Amavis. Autrement, on risque de se retrouver avec plein de Received: qui rendront l'analyse plus difficile (et risquent d'atteindre la limite des MTA, qui rejettent les messages ayant trop de Received:, pensant qu'ils bouclent). L'idée est de déboguer les performances et donc cette clause est là uniquement pour les problèmes temporels, pas pour n'importe quelle action ou changement d'état interne à l'agent.


Téléchargez le RFC 6729


L'article seul

RFC 6726: FLUTE - File Delivery over Unidirectional Transport

Date de publication du RFC : Novembre 2012
Auteur(s) du RFC : T. Paila (Nokia), R. Walsh (Tampere University of Technology), M. Luby (Qualcomm), V. Roca (INRIA), R. Lehtonen (TeliaSonera)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF rmt
Première rédaction de cet article le 7 novembre 2012


Peut-on envoyer un fichier d'un ordinateur à un autre lorsque la liaison est unidirectionnelle, c'est-à-dire que les paquets ne voyagent que dans un sens ? Pas question de se servir de FTP ou de HTTP, qui reposent sur le protocole de transport TCP, qui a besoin de bidirectionnalité (car il dépend du retour des accusés de réception). Le protocole FLUTE (File Delivery over Unidirectional Transport) normalisé dans ce RFC, fournit un ensemble de mécanismes pour effectuer ce transfert. La principale application concerne le multicast, où une machine unique diffuse un fichier à plusieurs autres, qu'elle ne connait pas forcément et qui ne peuvent pas lui écrire. Un exemple typique est la distribution des mises à jour d'un gros logiciel à des milliers, voire millions, de machines dans le monde. Parmi les usages possibles, distribuer de la vidéo, une nouvelle version d'un jeu très populaire, etc.

Pour cela, FLUTE s'appuie sur le système ALC (RFC 5775) + LCT (Layered Coding Transport, RFC 5651), qui fait l'essentiel du travail. ALC+LCT sert de protocole de transport d'objets binaires, FLUTE se charge de la sémantique. FLUTE dépend aussi d'autres protocoles de la famille multicast, comme FEC (RFC 5052), qui assure la fiabilité du transport, en permettant au récepteur de détecter les erreurs.

Transférer des gros fichiers sur un réseau ouvert comme l'Internet implique également un mécanisme de contrôle de la congestion, pour éviter que l'émetteur ne noie le réseau sous les paquets, sans se rendre compte que les tuyaux sont pleins. Comme on n'a pas TCP pour limiter la congestion en détectant les paquets perdus, il faut trouver un autre mécanisme. Dans le cas de FLUTE, les récepteurs souscrivent plusieurs abonnements multicast, éventuellement de débits différents, et jonglent avec ces divers abonnements. (Sur des réseaux fermés, le contrôle de congestion de FLUTE peut se faire par encore d'autres mécanismes comme le shaping.)

Les métadonnées (les propriétés du fichier) sont transmises dans un élément XML. On y trouve entre autres :

  • Un identifiant du fichier, un URI. C'est juste un identifiant, et rien ne garantit qu'on puisse récupérer le fichier à cet « endroit ».
  • Un type de contenu, par exemple text/plain.
  • La taille du fichier.
  • Un encodage utilisé pendant le transport, par exemple la compression avec zlib (RFC 1950).
  • D'éventuelles informations de sécurité comme une empreinte cryptographique ou une signature numérique.

L'élement XML <File> qui contient tout cela est mis ensuite dans un élément <FDT-Instance> (FDT = File Delivery Table) qui contient également les informations externes au fichier (comme la date limite pendant laquelle cette information sera valable). Voici l'exemple que donne le RFC, pour le fichier track1.mp3 :


<?xml version="1.0" encoding="UTF-8"?>
<FDT-Instance xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="urn:ietf:params:xml:ns:fdt
                         ietf-flute-fdt.xsd"
     Expires="2890842807">
     <File
       Content-Location="http://www.example.com/tracks/track1.mp3"
       Content-Length="6100"
       Content-Type="audio/mp3"
       Content-Encoding="gzip"
       Content-MD5="+VP5IrWploFkZWc11iLDdA=="
       Some-Private-Extension-Tag="abc123"/>
</FDT-Instance>

Cet élément XML est transmis avec le fichier. Les informations liées à l'émission du fichier (adresse IP source qui émettra le fichier, début de l'émission, etc) sont récupérées par le destinataire par un moyen non spécifié ici (cf. section 6). Cela a pu être une description SDP (RFC 4566), une ressource sur le Web ou bien d'autres méthodes, même une configuration manuelle. Le point important est que, une fois toutes ces informations en sa possession, le récepteur FLUTE peut se préparer à recevoir le fichier, et peut vérifier sa bonne délivrance (l'émetteur, lui, n'en saura rien, puisque la liaison est unidirectionnelle).

L'envoi unidirectionnel de fichiers soulève des problèmes de sécurité particuliers (section 7, très détaillée). Si le fichier transmis est confidentiel, il doit être chiffré avant, que ce soit par un chiffrement global du fichier (par exemple avec PGP) ou en route par IPsec.

Et si l'attaquant veut modifier le fichier ? On peut utiliser une signature numérique du fichier, avant son envoi ou bien, pendant le trajet authentifier les paquets ALC avec le RFC 6584 ou bien TESLA (Timed Efficient Stream Loss-Tolerant Authentication, RFC 4082 et RFC 5776) ou encore, là aussi, IPsec. À noter que certaines de ces techniques demandent une communication bidirectionnelle minimale, par exemple pour récupérer les clés publiques à utiliser.

Ce RFC est la version 2 de FLUTE, la version 1 était normalisée dans le RFC 3926, qui avait le statut expérimental. Avec ce nouveau document, FLUTE passe sur le chemin des normes IETF. La liste des changements importants figure en section 11. Notez tout de suite que FLUTE v2 est un protocole différent, incompatible avec FLUTE v1.

Je ne connais pas les implémentations de FLUTE mais il en existe plusieurs (pour la version 1) par exemple jFlute, l'ancien MCL v3 (plus maintenue en version libre mais Expway en a une version commerciale fermée) ou MAD-FLUTE fait à l'université de Tampere.

Merci à Vincent Roca pour sa relecture attentive.


Téléchargez le RFC 6726


L'article seul

RFC 6725: DNS Security (DNSSEC) DNSKEY Algorithm IANA Registry Updates

Date de publication du RFC : Août 2012
Auteur(s) du RFC : 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 30 août 2012


Lors de la conception d'un protocole cryptographique, il est essentiel de permettre l'agilité des algorithmes, c'est-à-dire de changer d'algorithme pour répondre aux progrès de la cryptanalyse. C'est ainsi que DNSSEC inclut dans les enregistrements DNS de clés et de signatures un numéro qui identifie l'algorithme utilisé. Les numéros possibles sont dûment notés dans un registre IANA et ce nouveau RFC « nettoie » le registre, mettant à jour des entrées inutilisées.

Au passage, les érudits noteront que cette absence d'agilité cryptographique (l'algorithme n'est pas indiqué donc un seul algorithme est possible) est un des inconvénients de DNScurve. Mais ne digressons pas. Quels changements a apportés notre nouveau RFC 6725 ? Les numéros 4, 9 et 11, correspondant à des algorithmes qui n'ont jamais été déployés sont désormais marqués comme « réservés ». C'est tout. On ne peut pas les réaffecter (au cas où il traine dans la nature des mises en œuvre expérimentales utilisant ces algorithmes).

4 était réservé pour un algorithme à courbes elliptiques (on n'a jamais su lequel), 9 et 11 n'étaient pas officiellement affectés mais l'ont apparemment été non-officiellement.


Téléchargez le RFC 6725


L'article seul

RFC 6724: Default Address Selection for Internet Protocol version 6 (IPv6)

Date de publication du RFC : Septembre 2012
Auteur(s) du RFC : D. Thaler (Microsoft), R. Draves (Microsoft Research), A. Matsumoto (NTT), T. Chown (University of Southampton)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF 6man
Première rédaction de cet article le 12 septembre 2012


Lorsqu'une machine IPv6 a plusieurs adresses et qu'elle va initier une communication avec une autre machine ayant elle-même plusieurs adresses, quelle adresse choisir pour la source ? Et pour la destination ? Ce RFC donne deux algorithmes (un pour la source et un pour la destination) à suivre pour que la sélection d'adresse par défaut soit prévisible. Naturellement, il sera toujours possible, pour l'ingénieur système ou pour le programmeur, de passer outre ce choix par défaut et de choisir délibérement une autre adresse. Ce RFC remplace le RFC 3484.

Alors, quel est le problème ? En IPv6, il est courant d'avoir plusieurs adresses IP pour une machine (RFC 4291). Par exemple, si un site est multi-homé, les machines peuvent avoir une adresse par FAI. Ou bien il peut y avoir des tunnels, qui viennent avec leurs adresses. Toutes ces adresses peuvent avoir des caractéristiques variables : portée, statut (préférée, abandonnée, cf. RFC 4862), temporaire (pour des raisons de vie privée, cf. RFC 8981) ou pas... Voici un exemple sur une machine Debian ayant six adresses IPv6 :


% ip -6 addr show 
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qlen 1000
    inet6 2605:4500:2:245b::f00/64 scope global 
       valid_lft forever preferred_lft forever
    inet6 2605:4500:2:245b::bad:dcaf/64 scope global 
       valid_lft forever preferred_lft forever
    inet6 2605:4500:2:245b::42/64 scope global 
       valid_lft forever preferred_lft forever
    inet6 fe80::5054:ff:fed9:83b3/64 scope link 
       valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qlen 1000
    inet6 fe80::5054:ff:fe9f:5bb1/64 scope link 
       valid_lft forever preferred_lft forever

Il faudra donc un mécanisme pour décider de l'adresse source à utiliser.

Quant à la machine de destination, elle peut aussi avoir plusieurs adresses, par exemple plusieurs enregistrements AAAA sont dans le DNS. Il faudra donc aussi choisir l'ordre dans lequel on essaiera les adresses de destination. À noter que ce choix peut inclure le choix entre IPv6 et IPv4. Si les deux machines (source et destination) sont en double pile, va t-on utiliser IPv4 ou IPv6 ? (Notre RFC donne la préférence à IPv6 mais voyez plus loin pour les règles exactes.)

Notez que les deux algorithmes ne rendent donc pas le même type de résultat. Pour la destination, l'algorithme produit une liste d'adresses ordonnées, pouvant mêler IPv4 et IPv6. Pour la source, il produit une adresse, la meilleure, et forcément en IPv6 (la sélection d'une adresse source IPv4 est un problème intéressant mais non couvert par ce RFC).

Soit une application en C qui appelle la routine standard getaddrinfo() (RFC 3493) pour trouver les adresses IP du correspondant. Dans le cas le plus fréquent, elle va essayer toutes les adresses IP renvoyées par getaddrinfo(), dans l'ordre où ce dernier les a renvoyées, et l'application ne spécifiera pas son adresse source (c'est le cas simple : les variantes sont discutées plus loin). Pour mettre en œuvre ce RFC, getaddrinfo() va utiliser l'algorithme de sélection de la destination, pour trier la liste obtenue du DNS, et le noyau du système va utiliser l'algorithme de sélection de la source pour décider de l'adresse IP source, au moment du connect().

À noter qu'essayer uniquement la première adresse IP renvoyée par getaddrinfo() serait une mauvaise stratégie : si elle est injoignable, aucune communication ne sera possible, alors que certaines des autres adresses marchaient peut-être. Essayer les adresses de manière strictement séquentielle n'est pas non plus optimum et le RFC 6555 conseille de le faire en partie de manière parallèle.

Si on veut résumer les deux algorithmes utilisés, on peut dire qu'ils préfèrent former des couples source/destination où les deux adresses ont la même portée, ont la portée la plus étroite possible, sont des adresses préservant la vie privée, et, en fin de compte, partagent le plus de bits de préfixe possibles.

Comme indiqué plus haut, cet algorithme pourra toujours être surmonté par un choix explicite du programmeur comme la directive outgoing-interface d'Unbound (mal nommée puisque prenant comme paramètre une adresse IP et pas une interface) ou comme, avec OpenSSH, l'option -b sur la ligne de commande (ou bien BindAddress dans le fichier de configuration). Ou bien un choix explicite de l'administrateur système qui peut éditer une table des politiques (celle qui dit par exemple que IPv6 est préféré à IPv4, ce qu'on peut changer), modifier la préférence par défaut en faveur des adresses de préservation de la vie privée, et permettre ou pas l'addition automatique de certaines adresses à la table des politiques.

Que contient cette « table des politiques » ? La section 2.1 la détaille. Elle stocke des préfixes d'adresses IP et, comme pour une table de routage, c'est le plus spécifique (le plus long) qui gagne. Sur un système Linux, c'est en général le fichier /etc/gai.conf qui contient la table, fichier que l'administrateur système peut éditer selon ses goûts (section 10.3 du RFC). La table par défaut contient :

Prefix        Precedence Label
::1/128               50     0
::/0                  40     1
::ffff:0:0/96         35     4
2002::/16             30     2
2001::/32              5     5
fc00::/7               3    13
::/96                  1     3
fec0::/10              1    11
3ffe::/16              1    12

La préférence est donnée aux préfixes ayant le champ Precedence le plus élevé. Ainsi, si on a le choix entre les adresses 2001:db8:1::cafe et fec0::90ff:fe92:bd00, la première a une précédence de 40 (en raison de la règle ::/0), la seconde de 1 (en raison de la règle fec0::/10) : rappelez-vous que c'est le préfixe le plus spécifique qui est choisi, pas celui qui est le premier dans la table). On va donc choisir l'adresse publique, 2001:db8:1::cafe (le préfixe fec0::/10 a été abandonné par le RFC 3879).

Autre conséquence de cette table, IPv6 est préféré à IPv4 (représenté par ::ffff:0:0/96, cf. RFC 4291, section 2.5.5.2). Si on veut changer cela, par exemple parce qu'on a une connectivité IPv6 vraiment trop mauvaise (voir le problème des globes oculaires et la section 10.3.1 de notre RFC), on édite gai.conf ou son équivalent et on met, par exemple (syntaxe de gai.conf) une précédence de 100 :

precedence ::ffff:0:0/96  100

D'autres trucs Linux sont documentés dans « IPv6 Source Address Selection on Linux ». Si on travaille sur FreeBSD, la configuration est dans /etc/ip6addrctl.conf et il faut donc regarder la documentation de ip6addrctl.

Notez que cette table peut être dynamique : une implémentation a le droit d'y ajouter des préfixes en cours de route, par exemple pour ses ULA (RFC 4193).

Autre définition importante, la notion de la longueur du préfixe commun. Cette longueur est définie en comparant uniquement les 64 premiers bits de l'adresse. Ainsi, la longueur du préfixe commun à 2001:db8:1::bad et 2001:db8:2::bad est 32 (2001:db8 est la seule partie commune). Mais la longueur du préfixe commun à 2001:db8:1::bad:dcaf et 2001:db8:1::bad:cafe n'est que de 64 et pas de 112 comme on pourrait le croire à première vue. C'est parce qu'on ignore l'Interface ID (les 64 derniers bits). C'est un des gros changements par rapport au précédent RFC, le RFC 3484, motivé par des problèmes comme une mauvaise interaction avec des systèmes de répartition de charge..

Et les propriétés des adresses (section 3) ? On a entre autres :

  • La portée : locale au lien, locale au site, ou globale. Ainsi, fe80::35cd:efc1:e399:3aa9 a une portée inférieure à 2001:4f8:3:2bc:1::64:21.
  • Le fait d'être l'adresse « de référence » (home address) ou l'adresse actuelle du mobile (care-of address) lorsqu'on utilise les fonctions de mobilité du RFC 6275. En pratique, elles sont très peu déployées donc on peut ne pas faire trop attention à cette propriété.

Maintenant, les algorithmes eux-mêmes. D'abord, pour le choix de l'adresse source (sections 4 et 5). Il faut d'abord établir une liste d'adresses candidates pour la destination choisie. La méthode conseillée est que cet ensemble de candidates soit la liste des adresses attachées à l'interface réseau par laquelle les paquets vont sortir. Sur une machine Linux, si on veut écrire à ::1, ce sera l'interface locale (lo) et si on veut écrire à 2001:4860:4860::8888, ce sera la plupart du temps eth0. Cela permet notamment de tenir compte des filtres éventuels des routeurs (un FAI ne laissera pas passer des paquets dont l'adresse source n'est pas chez lui, cf. RFC 2827).

Une fois cette liste établie, il faut choisir l'adresse IP source (notez le singulier), parmi cet ensemble de candidates. Conceptuellement, il s'agit de trier la liste des candidates et, pour cela, il faut une fonction permettant de comparer ces adresses deux à deux. La définition de cette fonction est le cœur de notre RFC. Soient deux adresses SA et SB pour une destination D, ces huit règles permettent de les départager :

  • Si SA = D, choisir SA (préférer une adresse source qui soit égale à la destination, pour les paquets locaux à la machine),
  • Si la portée de SA est différente de celle de SB, choisir l'adresse qui a la même portée que D. En gros, pour une destination locale au lien, on préférera des adresses sources locales au lien. Exemple : destination 2001:db8:1::1, candidates source 2001:db8:3::1 et fe80::1, on choisira 2001:db8:3::1,
  • Éviter les adresses marquées comme « dépassées » (RFC 4862, section 5.5.4), qu'on doit donc classer après celles qui ne sont pas dépassées,
  • Si la machine utilise Mobile IP (c'est très rare), préférer l'adresse de réference (home address) à l'adresse de connexion actuelle (care-of address),
  • Préférer l'adresse correspondant à l'interface de sortie vers D. Notez que cette règle ne servira à rien si on a suivi le conseil de ne mettre dans l'ensemble des candidates que les adresses de l'interface de sortie,
  • Utiliser l'étiquette (label) attribuée dans la table des politiques. On choisit de préférence l'adresse source qui a la même étiquette que l'adresse de destination,
  • Préférer les adresses temporaires du RFC 8981. Si la destination est 2001:db8:1::d5e3:0:0:1 et que les adresses candidates sont 2001:db8:1::2 (publique) et 2001:db8:1::d5e3:7953:13eb:22e8 (temporaire), on choisit 2001:db8:1::d5e3:7953:13eb:22e8. Cette règle est un changement par rapport au prédecesseur de notre RFC, le RFC 3484. Cette préférence doit être réglable (sur Linux, c'est apparemment avec la variable sysctl net.ipv6.conf.*.use_tempaddr qui, mise à 1, alloue des adresses temporaires et, mise à 2, fait qu'elles sont préférées),
  • Et enfin la dernière règle, mais qui sera souvent utilisée (plusieurs des règles précédentes ne s'appliquent qu'à des cas particuliers), la règle du préfixe le plus long. On choisit l'adresse source qui a le préfixe commun avec D le plus long. Si la destination est 2001:db8:1::1 et que les adresses source possibles sont 2001:db8:1::2 (48 bits communs) et 2001:db8:3::2 (32 bits communs), on sélectionne 2001:db8:1::2.
  • Si aucune des huit règles standards n'a suffi, si les deux adresses sont encore ex-aequo, le choix est spécifique à l'implémentation (par exemple, prendre la plus petite).

Une implémentation a le droit de tordre certaine de ces règles si elle dispose d'informations supplémentaires. Par exemple, si elle suit la RTT des connexions TCP, elle peut connaître les « meilleures » adresses et ne pas utiliser la huitième règle (préfixe le plus long).

Maintenant, il faut choisir l'adresse de destination (section 6). Cette fois, le résultat est une liste d'adresses qui seront essayées dans l'ordre. Et, contrairement au précédent, cet algorithme gère IPv6 et IPv4 ensemble (les règles de sélection de la source n'étaient valables que pour IPv6 ; par exemple la règle du plus long préfixe commun n'a guère de sens avec les courtes adresses v4). Le point de départ est la liste d'adresses récupérées en général dans le DNS. Et il y a ensuite dix règles de comparaison entre les destinations DA et DB, en tenant compte des adresses sources, S(DA) et S(DB). Beaucoup de ces règles sont proches de celles utilisées pour la sélection de la source donc je ne les réexplique pas ici :

  • Éviter les destinations injoignables (la machine ne le sait pas forcément mais elle a pu acquérir cette information, par exemple via le RFC 4861, section 7.3),
  • Préférer les portées identiques. Si DA et S(DA) ont une portée identique, et que ce n'est pas le cas pour DB et S(DB), choisir DA. Si les destinations connues sont 2001:db8:1::1 et 198.51.100.121, avec comme adresses source disponibles 2001:db8:1::2, fe80::1 et 169.254.13.78, alors le premier choix est 2001:db8:1::1 (source 2001:db8:1::2) puis 198.51.100.121 (source 169.254.13.78). Ce n'est pas une préférence pour IPv6 (elle intervient plus tard, dans la sixième règle) mais une conséquence du fait que l'adresse IPv4 169.254.13.78 est locale au lien (RFC 3927),
  • Éviter les adresses dépassées,
  • Choisir les adresses de référence en cas de mobilité,
  • Choisir de préférence la destination qui aura la même étiquette que l'une de ses sources possibles,
  • Préferer les destinations avec la plus haute précédence (dans la table des politiques vue plus haut). Avec la table par défaut, c'est cette règle qui mènera à faire les connexions en IPv6 plutôt qu'en IPv4 (section 10.3),
  • Préférer les destinations accessibles par de l'IPv6 natif plutôt que via un tunnel. Cela n'élimine pas tous les tunnels car celui-ci peut être situé plus loin, hors de la connaissance de la machine, comme avec le 6rdRFC 5969 - de Free),
  • Préférer les portées plus spécifiques, on tentera les adresses locales au lien avant les adresses publiques. Si on a le choix entre les destinations 2001:db8:1::1 ou fe80::1, et que les sources possibles sont 2001:db8:1::2 ou fe80::2, on préférera fe80::1 (avec la source fe80::2),
  • Utiliser le plus long préfixe commun entre la source et la destination. Si les destinations possibles sont 2001:db8:1::1 et 2001:db8:3ffe::1, avec comme sources possibles 2001:db8:1::2, 2001:db8:3f44::2 ou fe80::2, le premier choix est 2001:db8:1::1 (pour al source 2001:db8:1::2) puis 2001:db8:3ffe::1 (pour la source 2001:db8:3f44::2),
  • Si on arrive là, ne toucher à rien : contrairement à la sélection de la source, il n'est pas nécessaire de sélectionner une adresse, on peut tout à fait laisser l'ordre inchangé.

Le lecteur subtil a noté que l'interaction de ces règles avec le routage IP normal n'est pas évidente. Le principe de base est qu'une machine sélectionne la route de sortie avant de sélectionner l'adresse source mais la section 7 de notre RFC autorise explicitement une implémentation d'IPv6 à utiliser l'adresse source pour le choix de la route.

Voilà, les deux algorithmes sont là. Mais, si vous voulez les mettre en œuvre et pas seulement comprendre comment ils marchent, la section 8 est une lecture recommandée, car elle donne de bons conseils d'implémentation. Par exemple, comme l'algorithme de sélection de la destination a besoin de connaître les adresses sources possibles, le RFC suggère à getaddrinfo() de demander à la couche 3, pour obtenir la liste des adresses source possibles. Il sera alors capable de renvoyer une liste de destinations déjà triée. Il peut même garder en mémoire cette liste d'adresses, pour éviter de refaire un appel système supplémentaire à chaque fois. (Le RFC dit toutefois que cette mémorisation ne devrait pas durer plus d'une seconde, pour éviter d'utiliser une information dépassée.)

Et la sécurité (section 9) ? Il n'y a que des petits détails. Par exemple, en annonçant des tas d'adresses différentes pour lui-même, un méchant peut, en examinant les adresses source de ceux qui se connectent à lui, apprendre leur politique locale (pas une grosse affaire). Autre cas amusant, en sélectionnant soigneusement les adresses source ou destination, on peut influencer le chemin pris par les paquets, ce qui peut être utile par exemple pour sniffer. Mais c'est une possibilité très limitée.

Quels sont les changements de notre RFC 6724 par rapport à son prédécesseur, le RFC 3484 ? Ils sont détaillés dans l'annexe B. Les principaux (dans l'ordre à peu près décroissant d'importance) :

  • Préférence désormais donnée aux adresses temporaires sur les autres, afin de mieux préserver la vie privée, désormais considérée comme plus importante (c'était déjà le cas dans plusieurs implémentations d'IPv6),
  • Changement de la définition de « longueur du préfixe commun » pour se limiter aux 64 premiers bits (c'est-à-dire, excluant l'Interface ID),
  • Certains changements pour mieux gérer le cas où le réseau de sortie filtre selon l'adresse source (RFC 2827 et RFC 5220),
  • Ajout de la possibilité, pour une mise en œuvre d'IPv6, d'ajouter automatiquement des entrées à la table des politiques,
  • Ajout d'une ligne dans la table des politiques pour les ULA du RFC 4193 (fc00::/7),
  • Ajout d'une ligne dans la table des politiques pour les adresses du défunt 6bone (RFC 3701), avec une faible préférence pour qu'elles ne soient pas sélectionnées.

À noter que les premières versions de ce RFC étaient rédigées simplement sous forme d'une liste des différences avec le RFC 3484. C'était illisible.

Enfin, une anecdote, le prédécesseur, le RFC 3484, avait été accusé d'un problème sérieux. Mais c'est contestable, les responsabilités sont partagées : l'algorithme du RFC 3484 (qui ne concerne qu'IPv6) est certes discutable, l'implémentation de Vista n'est pas géniale (extension du RFC 3484 à IPv4, où les préfixes sont bien plus courts), la configuration de l'auteur de l'article est mauvaise (il dépend de l'ordre des enregistrements, qui n'est pas garanti par le DNS, c'est la même erreur qu'un programmeur C qui dépendrait de la taille d'un int) et, pour couronner le tout, le NAT qui fait qu'une machine ne connait pas son adresse publique.

Une intéressante discussion de certaines objections à ce RFC a eu lieu sur SeenThis.


Téléchargez le RFC 6724


L'article seul

RFC 6722: Publishing the "Tao of the IETF" as a Web Page

Date de publication du RFC : Août 2012
Auteur(s) du RFC : P. Hoffman (VPN Consortium)
Pour information
Première rédaction de cet article le 30 août 2012


Le fonctionnement et les particularités de l'IETF étaient traditionnellement décrits dans un RFC nommé Tao, à l'usage des débutants qui débarquaient dans ce monde merveilleux. Le dernier de ces RFC a été le RFC 4677 : désormais, pour évoluer plus facilement, le Tao est une page web ordinaire, régulièrement tenue à jour. Depuis, en juin 2024, le Tao a cessé d'être maintenu (cf. RFC 9592.

Le Tao est le document à lire absolument quand on débute à l'IETF. Il explique son fonctionnement, ses codes, ses rites, son jargon. L'IETF est à ma connaissance la seule SDO à le faire, ce qui est un gage d'ouverture. Le Tao a été d'abord publié comme RFC 1391, puis a connu de nombreuses évolutions jusqu'au RFC 4677. Mais les RFC, statiques et longs à faire publier, ne sont pas le canal idéal pour ce genre de documents, qui doit évoluer en permanence.

Désormais, le Tao est donc une page Web, et contrôlée par l'IESG, qui sera donc l'autorité responsable pour son contenu. Actuellement, cette page est encore très proche du RFC 4677 mais elle va petit à petit s'en éloigner.

Si vous voulez participer à la maintenance du Tao, cela se fait sur la liste de diffusion tao-discuss@ietf.org. Un éditeur (actuellement Paul Hoffman) décide ensuite des changements qui seront transmis à l'IESG (cette proposition est visible en ligne). L'IESG accepte ou refuse les changements et le secrétariat n'a plus qu'à éditer la page.

Le Tao est versionné (la version d'aujourd'hui est 20120829) et on peut accéder aux versions précédentes (dès qu'il y en aura plusieurs). On a donc des identificateurs stables pour les précédentes versions (toutes les organisations qui publient des documents devraient en faire autant).

Il existe des traductions du Tao qu'on trouve ici ou là mais le RFC note qu'elles sont toutes non-officielles (et souvent pas à jour). Par exemple, en français, on trouve une traduction du RFC 3160 ou bien la traduction de l'ISOC-Togo.

La section 3 du RFC couvre les propositions alternatives : certains auraient préféré un wiki pour des modifications plus rapides ou plus souples, mais le choix a finalement été de privilégier la sécurité.


Téléchargez le RFC 6722


L'article seul

RFC 6721: The Atom "deleted-entry" Element

Date de publication du RFC : Septembre 2012
Auteur(s) du RFC : J. Snell
Chemin des normes
Première rédaction de cet article le 26 septembre 2012


Le format Atom, normalisé dans le RFC 4287, est surtout utilisé pour la syndication de contenus Web. Dans ce cas, si une entrée d'un flux Atom n'est plus publiée (remords de l'auteur ou autre raison), le client Atom n'avait pas de moyen de le savoir. Désormais, avec l'extension de ce RFC, surnommée « pierre tombale », on peut indiquer que l'absence d'une entrée est délibérée.

Rappelez-vous qu'un flux de syndication comporte un certain nombre d'entrées mais rarement la totalité des articles d'un site Web (dans le flux de ce blog, par défaut, les articles des quatre derniers mois). On ne peut donc pas dire, lorsqu'un article n'a pas d'entrée dans le flux Atom, si l'article a été supprimé ou simplement s'il n'a pas été inclus dans le flux. Si, par exemple, l'entrée a été gardée dans la mémoire locale du client de syndication, elle risque d'y rester même si l'article original a disparu du site.

Pour éviter cela, ce RFC ajoute un nouvel élément XML à Atom. Il est défini avec la syntaxe Relax NG (l'espace de noms XML abrégé en at est http://purl.org/atompub/tombstones/1.0) :


deletedEntry =
  element at:deleted-entry {
    atomCommonAttributes,
    attribute ref { atomUri },
    attribute when { atomDateConstruct },
    ( element at:by { atomPersonConstruct }?
    & element at:comment { atomTextConstruct }?
    & element atom:link { atomLink }*
    & element atom:source { atomSource }?
    & anyElement* )
 }

On note donc que la référence de l'article détruit (ref) est obligatoire. Elle correspond à l'attribut id d'un flux Atom, qui a la forme d'un URI. Ainsi, cet article que vous êtes en train de lire a l'id tag:bortzmeyer.org,2006-02:Blog/6721 et une pierre tombale, si je supprimais cet article, comporterait <at:deleted-entry ref="tag:bortzmeyer.org,2006-02:Blog/6721" ....

Comme l'attribut ref, l'attribut when est obligatoire et contient la date et l'heure de destruction (au format du RFC 3339). Il est particulièrement utile si une entrée est détruite puis recréée : en examinant les dates, un client Atom peut savoir quel est l'évènement le plus récent (la suppression ou la création) et ignorer les autres.

Les autres attributs de l'élement at:deleted-entry sont facultatifs. C'est le cas par exemple de comment qui permet d'ajouter une explication en texte libre. Voici, tiré du RFC, un exemple minimal :


<at:deleted-entry
          ref="tag:example.org,2005:/entries/1"
          when="2005-11-29T12:11:12Z"/>

et un exemple plus complet :


<at:deleted-entry
          ref="tag:example.org,2005:/entries/2"
          when="2005-11-29T12:11:12Z">
          <at:by>
            <name>John Doe</name>
            <email>jdoe@example.org</email>
          </at:by>
          <at:comment xml:lang="la">Lorem ipsum dolor</at:comment>
</at:deleted-entry>

Notez bien que l'élement at:deleted-entry n'est qu'indicatif : on ne peut évidemment pas garantir qu'un client Atom facétieux ne va pas conserver localement (et même redistribuer) des entrées qu'il avait gardé dans son cache et qui ont été détruites dans le flux original.

Autre piège de sécurité : un client Atom ne doit pas croire aveuglément tous les at:deleted-entry qu'il rencontrerait sur le Web ! Car un méchant peut toujours publier des pierres tombales pour un autre site que le sien. Il faut donc vérifier l'origine (la pierre tombale doit être dans le même flux que l'article original, ce qui peut poser des problèmes avec les agrégateurs et autres redistributeurs) et/ou vérifier les signatures cryptographiques attachées (avec XML Signature).

Cette extension est mise en œuvre au moins dans AtomBeat (voir leurs intéressants exemples d'usage).


Téléchargez le RFC 6721


L'article seul

RFC 6716: Definition of the Opus Audio Codec

Date de publication du RFC : Septembre 2012
Auteur(s) du RFC : JM. Valin (Mozilla Corporation), K. Vos (Skype Technologies), T. Terriberry (Mozilla Corporation)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF codec
Première rédaction de cet article le 11 septembre 2012


Il y a désormais plus de deux ans que le groupe de travail codec de l'IETF avait commencé un effort inédit de spécification d'un codec audio libre. Ce nouveau RFC est le couronnement de cet effort : Opus, le codec standard et libre est désormais officiel.

Opus n'est pas un format de fichiers, comme MP3. Il est conçu pour l'audio en temps réel (RFC 6366 pour son cahier des charges). Il est prévu pour un grand nombre d'utilisations audio distinctes : téléphonie sur IP, mais aussi, par exemple, distribution de musique en temps réel. Il est prévu pour être utilisable lorsque la capacité du réseau est minimale (dans les 6 kb/s) aussi bien que lorsqu'elle permet de faire de la haute fidélité (mettons 510 kb/s, cf. section 2.1.1). Ses deux principaux algorithmes sont la prédiction linéaire (plus efficace pour la parole) et la transformation en cosinus discrète (plus efficace pour la musique).

Le projet codec avait déjà produit deux RFC : le RFC 6366 était le cahier des charges du nouveau codec, et le RFC 6569 posait les principes de développement et d'évaluation dudit codec. Je renvoie à ces documents pour l'arrière-plan de la norme Opus. Celle-ci a été acceptée sans problèmes par le groupe de travail (c'est plutôt le mécanisme de tests qui a suscité des controverses.)

Opus présente une particularité rare à l'IETF : la norme est le code. Habituellement, à l'IETF, la norme est le texte du ou des RFC, rédigés en langue naturelle. Il existe souvent une implémentation de référence mais, en cas de désaccord entre cette implémentation et le RFC, c'est ce dernier qui gagne et le programme doit être modifié. Pour Opus, c'est tout le contraire. La moitié du RFC 6716 (180 pages sur 330, en annexe A, soit 30 000 lignes de code pas toujours bien commentées et avec plein de nombres magiques) est constituée par l'implémentation de référence (en C, langage que le RFC qualifie de « lisible par un humain », ce qui est parfois optimiste) et c'est elle qui fait autorité en cas de différence avec l'autre moitié, les explications (voir sections 1 et 6 du RFC). Ce point a suscité beaucoup de débats à l'IETF et on trouve trace des critiques, entre autres, dans l'évaluation détaillée qui avait été faite pour GenArt. L'idée de ce choix « le code est la norme » était que l'alternative (faire une spécification en langue naturelle, complète et sans ambiguité), serait bien plus de travail et, dans le cas particulier d'un codec audio, serait peut-être même irréaliste. (À noter que seul le décodeur est normatif. On peut améliorer la sortie de l'encodeur, tant que le décodeur arrive à lire ce qu'il produit.)

Le langage C étant ce qu'il est, il n'est pas étonnant que des bogues aient été découvertes depuis, corrigées dans le RFC 8251.

L'autre moitié du RFC est composé d'explications, avec beaucoup de maths.

Un codec libre est difficile à obtenir, surtout vu le nombre de brevets, la plupart futiles, qui encombrent ce domaine. Plusieurs déclarations de brevet ont été faites contre Opus : #1520, #1524, #1526, #1602, #1670, #1712 et #1741. Une liste mise à jour est disponible à l'IETF.

Comme ces codecs sont très loin de mes domaines de compétence, je ne vais pas me lancer dans des explications détaillées du fonctionnement d'Opus : lisez le code source :-) Notez que le code fait beaucoup d'arithmétique en virgule fixe (et aussi avec des entiers, bien sûr) donc attention si vous le reprogrammez dans un autre langage, les calculs doivent être exacts (voir section 1.1).

Si vous n'avez pas l'ambition de reprogrammer Opus, si vous voulez simplement une idée générale de son fonctionnement, la section 2 est faite pour vous. Opus, comme indiqué plus haut, a deux « couches », LP (prédiction linéaire) et MDCT (transformée en cosinus discrète). L'une ou l'autre (ou même les deux en même temps) est active pour encoder le signal audio, donnant ainsi à Opus la souplesse nécessaire. La couche LP est dérivée du codec Silk. Elle permet le débit variable mais aussi le constant (section 2.1.8). La couche MDCT, elle, est basée sur CELT.

Le codec Opus peut favoriser la qualité de l'encodage ou bien la consommation de ressources (processeur, capacité réseau). Cela permet d'ajuster la qualité du résultat aux ressources disponibles (section 2.1.5). Idem pour la sensibilité aux pertes de paquets : Opus peut être ajusté pour mettre plus ou moins de redondance dans les paquets. Avec le moins de redondance, on augmente la capacité mais on rend le décodage plus sensible : un paquet perdu entraîne une coupure du son.

Le format des paquets est décrit en section 3. À noter qu'Opus ne met pas de délimiteur dans ses paquets (pour gagner de la place). Il compte qu'une couche réseau plus basse (UDP, RTP, etc) le fera pour lui. Une possibilité (optionnelle dans les implémentations) de formatage avec délimiteur figure dans l'annexe B.

Chaque paquet compte au moins un octet, le TOC (Table Of Contents). Celui-ci contient notamment 5 bits qui indiquent les configurations (couches utilisées, capacité réseau utilisée et taille des trames).

Le fonctionnement du décodeur est en section 4 et celui de l'encodeur en section 5. Mais le programmeur doit aussi lire la section 6, qui traite d'un problème délicat, la conformité à la spécification. Je l'ai dit, la référence d'Opus est un programme, celui contenu dans ce RFC. Cela n'interdit pas de faire d'autres mises en œuvre, par exemple à des fins d'optimisation, à condition qu'elles soient compatibles avec le décodeur (c'est-à-dire que le décodeur de référence, celui publié dans l'annexe A du RFC, doit pouvoir lire le flux audio produit par cette mise en œuvre alternative). Pour aider aux tests, des exemples (testvectorNN.bit) et un outil de comparaison, opus_compare, sont fournis avec l'implémentation de référence (les tests sont en https://opus-codec.org/testvectors/). Un outil de comparaison est nécessaire car il ne suffit pas de comparer bit à bit la sortie de l'encodeur de référence et d'un nouvel encodeur : elles peuvent différer, mais dans des marges qui sont testées par opus_compare. Si vous avez écrit votre propre encodeur, ou modifié celui de référence, les instructions pour tester figurent en section 6.1.

Autre avertissement pour les programmeurs impétueux que les 150 pages d'explication et les 180 pages de code n'ont pas découragés : la sécurité. Opus est utilisé sur l'Internet où on trouve de tout, pas uniquement des gens gentils. La section 7 met donc en garde le programmeur trop optimiste et lui dit de faire attention :

  • Si on veut chiffrer un flux Opus, il ne faut pas utiliser d'algorithme vulnérable aux attaques à texte clair connu. En effet, bien des parties du flux (comme les trames de silence ou comme les octets TOC) sont très prévisibles.
  • Le décodeur doit être très robuste face à des erreurs (volontaires, ou bien provoquées par des bogues) dans le flux qu'il décode. Une programmation naïve peut mener à des accidents comme le dépassement de tampon ou, moins grave, à une consommation exponentielle de ressources (RFC 4732). L'implémentation de référence est censée être propre de ce point de vue, et résister à presque tout. Elle a été testée avec des flux audio aléatoirement modifiés, ainsi qu'avec des encodeurs faisant du fuzzing. Elle a également été testée avec Valgrind.

Le compte-rendu des tests divers se trouve dans l'Internet-Draft draft-ietf-codec-results.

L'annexe A contient le code source de l'implémentation de référence encodée en Base64 (qu'on trouve également en ligne sur le site Web officiel et qui est distribuée par git en git://git.xiph.org/opus.git). Par défaut, elle dépend de calculs en virgule flottante mais on peut la compiler avec la macro FIXED_POINT pour ne faire que de la virgule fixe (voir le fichier README). Voici un exemple d'utilisation avec la version de développement (il n'y en avait d'autre prête à ce moment)

% export VERSION=1.0.1-rc2
% wget http://downloads.xiph.org/releases/opus/opus-$VERSION.tar.gz
...
% tar xzvf opus-$VERSION.tar.gz 
...
% cd opus-$VERSION
% ./configure
...
% make
...
% make check
...
All 11 tests passed
...

Il n'existe pas à l'heure actuelle d'autre mises en œuvre d'Opus.

Combien de logiciels intègrent actuellement le code Opus pour lire et produire des flux audios ? Difficile à dire. L'excellent client SIP Csipsimple a Opus depuis plusieurs mois. Autre exemple, le logiciel de voix sur IP Mumble l'a promis pour bientôt.

Un bon article en français sur Opus, notamment ses performances : « Un codec pour les dominer tous ». Et un article de synthèse de Numérama sur ce RFC. Pour une comparaison des performances d'Opus avec les autres, voir https://www.opus-codec.org/comparison/. Pour les nouveautés de la version 1.1 (publiée après le RFC), voir la liste officielle.

Merci à Régis Montoya pour sa relecture.


Téléchargez le RFC 6716


L'article seul

RFC 6713: The application/zlib and application/gzip media types

Date de publication du RFC : Août 2012
Auteur(s) du RFC : J.R. Levine (Taughannock Networks)
Pour information
Première rédaction de cet article le 25 août 2012


Encore un RFC qui comble un manque ancien. Les types MIME application/gzip et application/zlib n'avaient jamais été formellement enregistrés. Voici qui est fait.

Ces deux types apparaissent désormais dans le registre IANA avec ce RFC 6713 comme référence. Rien de nouveau, ils étaient déjà utilisés dans de nombreuses applications. (Parfois, des types non officiels étaient utilisés comme application/x-gzip ou encore des trucs comme application/gzipped.)

Pour ceux qui veulent apprendre ces deux techniques de compression, Zlib est spécifié dans le RFC 1950 (et a un site « officiel ») et Gzip est dans le RFC 1952 et a aussi son site. Les deux techniques sont très proches (utilisant l'algorithme Deflate du RFC 1951), la principale différence étant que Gzip inclut un en-tête et une terminaison. Il est donc plus adapté pour les fichiers (et Zlib pour le streaming).

Ah, au fait, soyez prudent : comme le dit l'inévitable section Security Considerations, les données comprimées récupérées sur l'Internet (qui est, comme le dit le sage Beigbeder, « l'empire de la méchanceté, de la bêtise ») peuvent être trompeuses. Elles peuvent prétendre être en Zlib ou en Gzip et comporter des erreurs, des pointeurs ne pointant pas au bon endroit, des champs Longueur qui n'indiquent pas la longueur, et autres choses qui peuvent mener à des accidents comme le dépassement de tampon. Programmeurs, attention.


Téléchargez le RFC 6713


L'article seul

RFC 6710: Simple Mail Transfer Protocol Extension for Message Transfer Priorities

Date de publication du RFC : Août 2012
Auteur(s) du RFC : A. Melnikov (Isode), K. Carlberg (G11)
Chemin des normes
Première rédaction de cet article le 26 août 2012


Des tas d'utilisateurs du courrier électronique souhaiteraient un mécanisme de priorité, permettant de dire que tel message est plus important que tel autre et devrait être traité en premier. Après tout, les ressources (par exemple la capacité disponible dans le réseau) sont souvent insuffisantes et il serait souhaitable que les messages vraiment urgents en profitent avant les informations envoyées par Twitter (« vous avez un nouvel abonné »). Il n'existait pas jusqu'à présent, pour un serveur de messagerie, de moyen standard en SMTP de dire à un de ses pairs quelle était la priorité d'un message. C'est désormais fait grâce à la nouvelle extension SMTP MT-PRIORITY.

Dans les en-têtes du message (le format des messages est normalisé dans le RFC 5322), il existait un en-tête standard, Priority:, décrit dans le RFC 2156. Ce dernier avait à l'origine été écrit pour assurer l'interfaçage avec X.400. Ce système avait été un échec complet mais l'en-tête Priority: garde son utilité (on trouve aussi souvent un en-tête non officiel et n'ayant pas exactement la même sémantique, notamment par le nombre de niveaux et leur représentation, X-Priority:.) Par contre, l'inconvénient de noter la priorité dans le message est que cela oblige les MTA à analyser les en-têtes, ce qui n'est pas normalement leur rôle. De manière cohérente avec l'évolution du courrier électronique depuis quinze ans (meilleure séparation entre le format du RFC 5322 et le transport normalisé dans le RFC 5321), la priorité est désormais exprimable lors de la session SMTP. (Un autre RFC en cours d'écriture, draft-melnikov-smtp-priority-tunneling, utilisera un nouvel en-tête, MT-Priority:, pour le cas où on doive tunneler des messages prioritaires au dessus de MTAs qui ne gèrent pas les priorités.) Par exemple, un MTA dont les files d'attente d'envoi de messages sont grandes, pourra mettre au début de la file les messages de plus forte priorité.

Notez bien que c'est une priorité, donc relative (« ce message est très urgent, celui-ci l'est moins ») pas d'une garantie de délai. Le courrier électronique demeure « au mieux », sans délais certains. Les annexes de ce RFC contiennent des discussions plus en détails sur certaines utilisations de ces priorités. Si on ne se satisfait pas de la délivrance « au mieux », il faut utiliser une autre extension SMTP (DELIVERBY dans le RFC 2852 et section 5.2 de notre RFC 6710) ou regarder du côté de techniques réseaux comme DiffServ (RFC 2474).

Notez aussi que l'une des raisons du peu de déploiement effectif de l'en-tête Priority: est un problème de confiance (comme souvent quand on prétend faire de la qualité de service : tout le monde va demander la qualité maximale). Rien ne garantit que celui qui met dans ses messages Priority: urgent le fait à bon escient, peut-être ajoute-t-il systématiquement cette indication pour que ses messages aillent plus vite. Notre RFC 6710 précise donc bien que le MTA récepteur n'est pas obligé d'honorer les priorités de n'importe qui. Il peut ne le faire que lorsqu'il connait l'expéditeur et lui fait confiance (voir les mécanismes utilisés en sections 4.1 et 5.1).

Maintenant, les détails techniques (section 3) : la nouvelle extension SMTP se nomme Priority Message Handling et est annoncée par le mot-clé MT-PRIORITY lors de la connexion SMTP. Par exemple (S indique le serveur et C le client) :

S: 220 example.com SMTP server here
C: EHLO mua.example.net
S: 250-example.com
S: 250-AUTH STARTTLS
S: 250-AUTH SCRAM-SHA-1 DIGEST-MD5
S: 250-SIZE 20000000
S: 250-DSN
S: 250-ENHANCEDSTATUSCODES
S: 250 MT-PRIORITY MIXER

(Le paramètre MIXER est le nom d'une politique de priorités et est expliqué plus loin, section 9.2.) La priorité du message est annoncée par un paramètre de la commande MAIL FROM également nommé MT-PRIORITY. Elle va de -9 (plus faible priorité) à 9 (priorité la plus élevée). Par exemple :


C: MAIL FROM:<eljefe@example.net> MT-PRIORITY=6
S: 250 2.1.0 <eljefe@example.net> sender ok
C: RCPT TO:<topbanana@example.com>
S: 250 2.1.5 <topbanana@example.com> recipient ok

En pratique, tous les serveurs ne géreront pas forcément 19 niveaux distincts (il n'y en avait que 3 dans le RFC 2156). L'annexe E explique pourquoi ce choix de 19.

Cette extension est utilisable aussi bien pendant la soumission (RFC 6409) que pendant la transmission (RFC 5321), ainsi qu'en LMTP (RFC 2033).

Lorsque le MTA « serveur » gérant cette extension reçoit un message ayant une priorité explicite, il va le traiter en fonction de cette priorité. Par défaut, la priorité est de zéro (d'où le choix d'avoir des priorités négatives, on voit tout de suite si la priorité est plus ou moins importante que celle par défaut, voir annexe E pour les raisons de ce choix). En prime, le MTA va noter cette priorité dans l'en-tête Received: qu'il va ajouter au message. Avant cela, le MTA aura du toutefois vérifier l'émetteur : le RFC précise qu'on peut accepter des priorités négatives de n'importe qui mais qu'on ne devrait accepter des positives (élevant le niveau de priorité) que des émetteurs qu'on a authentifiés d'une manière ou d'une autre, et à qui on fait confiance. Autrement, il serait facile de réclamer systématiquement la plus haute priorité (9), épuisant ainsi les ressources du serveur. Un exemple d'une politique d'autorisation pourrait être « n'accepter de priorités positives que depuis les utilisateurs authentifiés avec la commande AUTHRFC 4954 - ainsi que depuis les MTA dont l'adresse IP a été mise dans une liste blanche, suite à un accord bilatéral avec leur gérant ». (Voir aussi les sections 5.1 et 11.)

Naturellemnt, un MTA peut avoir des politiques plus complexes comme de modifier automatiquement la priorité demandée en fonction de l'émetteur (« maximum 3 pour 2001:db8:666::1:25 »). Il doit dans ce cas prévenir l'émetteur en réponse au MAIL FROM :

C: MAIL FROM:<eljefe@example.net> MT-PRIORITY=6
...
S: 250 X.3.6 3 is the new priority assigned to the message

Lorsqu'un serveur transmet un message à un autre serveur SMTP, il inclut la priorité, sauf évidemment si l'autre serveur n'a pas annoncé qu'il gérait les priorités (extension MT-PRIORITY).

Les considérations pratiques liées au déploiement de cette extension MT-PRIORITY figurent dans la section 9. Ainsi, si on a plusieurs serveurs de courrier pour un même domaine (via plisieurs enregistrements MX), le RFC recommande de veiller à ce que tous ou aucun acceptent l'extension de gestion de la priorité. Autrement, des problèmes difficiles à déboguer vont survenir. (De toute façon, avoir plusieurs enregistrements MX est complexe et déconseillé pour les petits domaines, exactement pour ce genre de raisons.)

J'ai parlé un peu plus haut du paramètre « Nom de la politique de priorité » qu'un serveur peut ajouter lorsqu'il indique qu'il gère les priorités. La section 9.2 décrit plus en détail ce que cela signifie. L'idée est que différentes organisations vont avoir des politiques de priorité différentes : nombre de niveaux, notamment. L'idée est de donner un nom à ces politiques afin de permettre à un serveur d'indiquer quelle politiques il suit. Par exemple, si le serveur a une politique qui ne gère que trois niveaux, -1, 0 et 1, un message indiquant qu'il a réduit la priorité demandée de 3 à 1 n'est pas inquiétant. Il est recommandé d'enregistrer les politiques à l'IANA (la section « SMTP PRIORITY extension Priority Assignment Policy »). Ce nouveau registre est rempli selon la règle « Norme nécessaire » du RFC 5226. Il comprend actuellement trois politiques, issues de normes existantes. Par défaut, la politique appliquée est MIXER qui est celle du RFC 2156 et reprise dans l'annexe B de notre RFC 6710 : trois niveaux de priorité seulement (-4, 0 et 4), pas de valeurs numériques définies par défaut pour les tailles maximales des messages ou pour les délais de retransmission.

Deux autres annexes décrivent des utilisations des priorités, avec la politique associée. L'annexe A concerne l'usage militaire (politique STANAG4406, six niveaux, les deux plus urgents étant étiquetés Flash et Override). Et l'annexe C concerne les services d'urgence (RFC 4190 et RFC 4412). Un avis personnel : il n'est sans doute pas sérieux d'utiliser le courrier électronique sur l'Internet public pour des appels aux pompiers ou des messages militaires alors que l'ennemi attaque.

Puisqu'on a parlé de l'IANA, outre ce nouveau registre, les enregistrements suivants ont été faits (section 10) :

  • MT-PRIORITY a été ajouté aux extensions SMTP (la section « SMTP Service Extensions »).
  • Quelques codes de réponse améliorés (RFC 5248) ont été enregistrés, comme X.3.6 pour indiquer que la priorité demandée a été changée ou comme X.7.16 qui signale que le message est d'une taille trop importante pour sa priorité.

Et questions mises en œuvre ? Aujourd'hui, un Postfix typique, par exemple, ne gère pas encore ces priorités (et répond 555 5.5.4 Unsupported option: MT-PRIORITY=3 si on essaie.) Il existe apparemment déjà trois MTA qui ont en interne ce concept de priorité et qui, en l'absence de norme, la déterminaient de manière non-standard. Ils n'ont pas encore été adaptés à ce RFC. Pour cela, l'annexe D donne d'intéressants avis sur les stratégies d'implémentation possibles.


Téléchargez le RFC 6710


L'article seul

RFC 6709: Design Considerations for Protocol Extensions

Date de publication du RFC : Septembre 2012
Auteur(s) du RFC : B. Carpenter, B. Aboba, S. Cheshire
Pour information
Première rédaction de cet article le 15 septembre 2012


Concevoir des protocoles de communication monolithiques qui n'évoluent jamais est une chose. Concevoir des protocoles qui soient extensibles, qui puissent, après leur conception initiale, évoluer par le biais d'extensions, est un exercice plus difficile. Cet excellent RFC de l'IAB décrit comment faire un protocole extensible et comment assurer ainsi une évolution heureuse. C'est un document avant tout destiné aux auteurs de protocoles, mais qui intéressera aussi les étudiants en réseaux informatiques et tous les techniciens curieux, qui veulent savoir comment ça marche.

Parmi les innombrables exemples de protocoles IETF qui ont été étendus, on peut citer les extensions d'internationalisation de SMTP dans le RFC 6531, la recherche floue dans IMAP avec le RFC 6203, ou les capacités BGP du RFC 5492.

Le RFC 5218 (section 2.2.1), qui décrivait les raisons du succès pour un protocole réseau, notait parmi celles-ci l'extensibilité. Beaucoup de protocoles IETF ont des mécanismes pour cette extensibilité, qui est largement reconnue comme un bon principe. Mais, si elle est mal faite, des ennuis peuvent survenir, et cela peut menacer l'interopérabilité, voire la sécurité. Le RFC sur SMTP, le RFC 5321, note ainsi (section 2.2.1) que les protocoles avec peu d'options sont partout et que ceux avec beaucoup d'options sont nulle part. Un RFC comme le RFC 1263 (consacré aux extensions de TCP) critiquait également l'abus des extensions, et ce dès 1991. Malgré cela, d'innombrables RFC normalisent des extensions à tel ou tel protocole, mais il n'existait pas encore de document d'architecture sur le principe des extensions, rôle que ce RFC ambitionne de jouer.

D'abord, une distinction importante (section 2) entre extension « majeure » et « de routine ». Les secondes sont celles qui ne modifient pas le protocole de manière substantielle (et peuvent donc être introduites avec un minimum d'examen), les premières changent le protocole sérieusement et doivent donc être étudiées de près. Le problème est particulièrement aigu si l'extension est faite par d'autres personnes que le protocole originel : les « extensionneurs » risquent de ne pas connaître certaines règles non écrites que les auteurs originaux avaient en tête. Pour éviter cela, la spécification originale d'un protocole devrait toujours expliciter les règles, et décrire comment étendre le protocole proprement.

Comment distinguer une extension majeure d'une extension de routine ? Les extensions majeures sont celles qui peuvent empêcher l'interopérabilité (la capacité de deux pairs à communiquer), perturber le fonctionnement de l'Internet, ou mettre en péril la sécurité. Cela se produit notamment :

  • Si l'extension nécessite que les mises en œuvre existantes soient modifiées. Par exemple, si un protocole a un champ de taille fixe Foobar sur un octet et que, les 256 valeurs étant occupés, on passe à un champ de deux octets, les nouvelles mises en œuvre ne pourront pas parler aux anciennes, tout l'en-tête étant décalé à partir de ce champ (uniquement pour un octet ajouté). Il existe des méthodes pour éviter ces problèmes (par exemple utiliser des TLV au lieu des champs de taille fixe) mais elles ont aussi des inconvénients (de performance, par exemple) et, de toute façon, nécessitent d'avoir été mises dès le début dans le protocole. Un autre exemple est celui d'un protocole où les messages ont un type et où tout type inconnu fait couper la communication. Dans ce cas, ajouter un type de message, même optionnel, représente une extension majeure (là aussi, il existe des solutions, comme de spécifier dès le début que les messages de type inconnu doivent être silencieusement ignorés, cf. section 4.7).
  • Si l'extension change fondamentalement le modèle sous-jacent. C'est d'autant plus difficile à détecter que ce modèle n'est pas toujours explicite. Bien des RFC décrivent au bit près le format des messages mais sont très courts sur la vision de haut niveau du protocole. Le RFC donne l'exemple d'une extension qui ajouterait un état à un protocole qui était précédemment sans état.
  • Des nouveaux usages du protocole peuvent aussi représenter une extension majeure. Par exemple, si des changements purement quantitatifs se produisent (trafic accru, paquets plus gros comme dans le cas d'EDNS ou encore algorithmes qui ne supportent pas le passage à l'échelle d'une utilisation plus intense).
  • Si on change la syntaxe du protocole (par exemple si on inverse deux champs).
  • Si on change le modèle de sécurité.
  • Et, bien sûr, si on crée une extension qui ne « rentre pas » dans le modèle d'extension originellement envisagé.

Et les extensions de routine, alors, elles ressemblent à quoi ?

  • Elle n'ont aucune des caractéristiques citées plus haut, qui identifient les extensions majeures.
  • Elle sont opaques au protocole (les messages avec la nouvelle extension sont traités par le protocole comme ceux d'avant).

Une extension de routine ne nécessitera aucun changement sur les vieux programmes. Seuls ceux qui voudront utiliser la nouvelle extension auront à être modifiés.

Quelques exemples d'extensions de routine : les options spécifiques à un fournisseur de DHCP (RFC 2132), les options spécifiques à un fournisseur de Radius (RFC 2865), les types MIME de l'arbre vnd (vendor), etc. Ce n'est que lorsqu'on est sûr que l'ajout d'une extension ne sera que de la routine qu'on peut avoir des politiques du genre « premier arrivé, premier servi » (RFC 5226), c'est-à-dire peu ou pas d'examen préalable. Et encore, l'expérience a montré que même les extensions de routine pouvaient poser des problèmes inattendus et qu'un examen de toutes les extensions par un expert est souvent une bonne chose.

Une fois posée cette importante distinction entre extensions de routines et extensions majeures, la section 3 de notre RFC s'attache des bons principes architecturaux pour assurer une extensibilité heureuse :

  • Limiter l'extensibilité à ce qui est « raisonnable »,
  • Penser avant tout à l'interopérabilité,
  • Garder les extensions compatibles avec le protocole de base,
  • Ne pas permettre des extensions qui créent un nouveau protocole, incompatible avec le précédent,
  • Permettre de tester les extensions,
  • Bien coordonner les allocations de paramètres (noms, numéros, etc),
  • Faire davantage attention aux extensions aux composants critiques de l'Internet comme le DNS ou BGP.

Premier principe, limiter l'extensibilité. Il faut essayer de ne traiter que les cas les plus courants et ne pas chercher l'extensibilité à tout prix. C'est évidemment plus facile à dire qu'à faire. Comme le note le RFC 5218, un protocole qui rencontre un « succès fou » est utilisé dans des contextes que ses concepteurs n'imaginaient pas. Alors, essayer de déterminer à l'avance les extensions qui vont être vraiment utiles... On peut donc être amené à réviser le mécanisme d'extension en cours de route.

Deuxième principe, l'interopérabilité, c'est-à-dire la capacité de deux mises en œuvre complètement différentes du même protocole à communiquer. Le RFC 4775 (section 3.1) insiste sur ce concept, qui est au cœur de la mission de l'IETF. Une extension qui empêcherait les nouveaux programmes de communiquer avec les anciens casserait cette interopérabilité et serait donc inacceptable.

D'autres familles de protocole que la famille TCP/IP avaient une approche différente : le protocole était tellement bourré d'options très larges que deux mises en œuvre toutes les deux conformes à la norme pouvaient néanmoins ne pas pouvoir communiquer car elles n'implémentaient pas les mêmes options. C'est ce qui est arrivé aux protocoles OSI et la solution adoptée avait été de créer des profils (un ensemble d'options cohérent), créant ainsi autant de protocoles que de profils (les profils différents n'interopéraient pas même si, sur le papier, c'était le même protocole). Notre RFC dit clairement que ces profils ne sont pas une solution acceptable. Le but est d'avoir des protocoles qui fonctionnent sur tout l'Internet (alors qu'OSI avait une vision beaucoup plus corporate où il n'était pas prévu de communications entre groupes d'utilisateurs différents).

En pratique, pour assurer cette interopérabilité, il faut que le mécanisme d'extension soit bien conçu, avec notamment une sémantique claire (par exemple, précisant ce que doit faire un programme qui rencontre un message d'un type inconnu, ou bien un message d'un type qui ne correspond pas à ce qu'il devrait recevoir dans son état actuel).

Le RFC note aussi qu'écrire les plus belles normes ne suffira pas si elles sont mal mises en œuvre. On constate que les problèmes liés aux extensions sont souvent dus à des implémentations qui ne le gèrent pas correctement. Un exemple est celui des options d'IP qui, bien que clairement spécifiées dès le début (RFC 791), ne sont toujours pas partout acceptées en pratique.

Et puisqu'on parle d'interopérabilité, une idée qui semble bonne mais qui a créé beaucoup de problèmes : les extensions privées. Pas mal de programmeurs se sont dit « de toute façon, ce système ne sera utilisé que dans des réseaux fermés, tant pis pour l'interopérabilité sur le grand Internet, je peux, sur mon réseau, ajouter les extensions que je veux ». Mais les prédictions ne sont que rarement 100 % vraies. Les ordinateurs portables, les smartphones et autres engins se déplacent, et les implémentations ayant des extensions privées se retrouvent tôt ou tard à parler aux autres et... paf. Même chose lorsque deux extensions privées rentrent en collision, par exemple à la suite de la fusion de deux entreprises. Imaginons que chacune d'elles ait choisi de mettre du contenu local dans un attribut DHCP de numéro 62, en pensant que, DHCP n'étant utilisé que sur le réseau local, cela ne gênerait jamais. Des années après, une des deux entreprises rachète l'autre, les réseaux fusionnent et... repaf.

Pour résoudre ce problème, on a parfois fait appel à des espaces réservés comme le fameux préfixe « X- » devant le nom d'un paramètre (RFC 822). Le RFC 6648 a mis fin à cette pratique (qui était déjà retirée de plusieurs RFC), notamment parce que les paramètres « privés », tôt ou tard, deviennent publics, et qu'alors les ennuis commencent.

Un problème proche existe pour les paramètres considérés comme « expérimentaux ». Ils ont leur utilité, notamment pour que les programmeurs puissent tester leurs créations. C'est ainsi que le RFC 4727 propose des valeurs pour les expérimentations avec de nouveaux protocoles de transport, des nouveaux ports, etc. Le RFC 3692 décrit plus en détail les bonnes pratiques pour l'utilisation de valeurs expérimentales. Elles doivent être strictement limitées au système en cours de test, et jamais distribuées sur l'Internet. Si l'expérience est multi-site, c'est une bonne raison pour ne pas utiliser de valeurs expérimentales. C'est ainsi que des expériences comme HIP et LISP ont obtenu des paramètres enregistrés, non expérimentaux, pour pouvoir être testés en multi-sites.

À noter que ces valeurs expérimentales ne sont nécessaires que lorsque l'espace disponible est limité. Le champ Next header d'IPv6 ne fait qu'un octet et il est donc logique de bloquer deux valeurs réutilisables, 253 et 254, pour expérimenter avec des valeurs non officiellement enregistrés. Mais ce n'est pas le cas, par exemple, des champs de l'en-tête HTTP, composés d'un grand nombre de caractères et permettant donc des combinaisons quasi-infinies. Si on expérimente avec HTTP, il y a donc peu de raisons de réserver des champs expérimentaux.

Troisième principe architectural, la compatibilité avec le protocole de base. Elle implique un double effort : les auteurs du protocole original doivent avoir bien spécifié le mécanisme d'extensions. Et les auteurs d'extensions doivent bien suivre ce mécanisme. Quelques exemples de protocole où le mécanisme d'extensions est documenté en détail : EPP (RFC 3735), les MIB (RFC 4181), SIP (RFC 4485), le DNS (RFC 2671 et RFC 3597), LDAP (RFC 4521) et Radius (RFC 6158).

Quatrième principe d'architecture, faire en sorte que les extensions ne mènent pas à une scission, avec apparition d'un nouveau protocole, incompatible avec l'original. Des changements qui semblent très modérés peuvent empêcher l'interopérabilité, ce qui serait de facto un nouveau protocole. Un protocole trop extensible peut donc ne pas être une si bonne idée que cela, si cette extensibilité va jusqu'à la scission.

Comme le note le RFC 5704, écrit dans le contexte d'une grosse dispute entre l'IETF et l'UIT, la scission (fork) peut venir de l'action non coordonnée de deux SDO différentes. Mais il n'y a pas toujours besoin d'être deux pour faire des bêtises : le RFC 5421 réutilisait un code EAP, rendant ainsi le protocole incompatible avec la précédente version. L'IESG avait noté le problème (documenté dans la section IESG Note du RFC 5421) mais avait laissé faire.

Cette notion de scission est l'occasion de revenir sur un concept vu plus haut, celui de profil. Il y a deux façons de profiler un protocole :

  • Retirer des obligations (ce qui peut créer de gros problèmes d'interopérabilité),
  • Ajouter des obligations (rendre obligatoire un paramètre qui était facultatif).

Contrairement à la première, la seconde approche peut être une bonne idée. En réduisant le nombre de choix, elle peut améliorer l'interopérabilité. Par contre, retirer des obligations est presque toujours une mauvaise idée. Ces obligations, dans un RFC (les fameux MUST, SHOULD et MAY), sont décrites avec les conventions du RFC 2119 et ce RFC insiste bien sur le fait qu'elles doivent être soigneusement choisies. Par exemple, un MUST ne doit être utilisé que si la violation de cette obligation est effectivement dangereuse, par exemple pour l'interopérabilité. Si ce conseil a été suivi, changer un MUST en SHOULD dans un profil va donc être négatif à coup presque sûr. Et, le RFC rappelle aussi qu'un MAY veut dire « vous n'êtes pas obligés de l'implémenter » mais certainement pas « vous avez le droit de planter si l'autre machine l'utilise ».

Place au cinquième principe, les tests. On a vu que ce n'est pas tout de bien normaliser, il faut aussi bien programmer. Pour s'assurer que tout a été bien programmé, il faut tester. Cela implique d'avoir développé des jeux de tests, essayant les différents cas vicieux (par exemple, essayer toutes les possibilités du mécanisme d'extension, pour vérifier qu'aucune ne plante les programmes ne les mettant pas en œuvre). Sinon, le test sera fait dans la nature, comme cela avait été le cas du fameux attribut 99 de BGP. La norme spécifiait très clairement ce qu'un pair BGP devait faire d'un attribut inconnu, mais IOS n'en tenait pas compte et, lorsque quelqu'un a essayé d'utiliser réellement cette possibilité de la norme, il a planté une bonne partie de l'Internet européen... TLS, étudié plus en détail plus loin, fournit un autre exemple d'implémentations déplorables, bloquant le déploiement de nombreuses extensions.

Sixième grande question d'architecture, l'enregistrement des paramètres. Beaucoup de protocoles ont besoin de registres pour noter les valeurs que peuvent prendre tel ou tel champ (par exemple, il y a un registre des numéros de protocole de transport et un registre des options DHCP). Ces registres et leur bonne utilisation sont une question souvent sous-estimée de l'interopérabilté. Si un champ du paquet identifie une extension et que deux extensions incompatibles utilisent le même numéro, l'accident est inévitable. Cette collision peut être due à l'absence de registre mais on rencontre régulièrement des développeurs qui ne vérifient pas le registre et qui s'attribuent tout simplement un numéro qui leur semble libre. (Le RFC note, de manière politiquement correcte, qu'il ne peut pas « publier les noms sans embarrasser des gens ». Mais cela semble particulièrement fréquent pour les numéros de port et pour les plans d'URI.)

Les concepteurs de protocole devraient vérifier, d'abord si un des registres existants ne suffit pas et, sinon en créer un. Dans ce cas, il faut soigneusement choisir la politique d'allocation des valeurs dans ce registre. Le RFC 5226 décrit les différentes politiques possibles, de la plus laxiste à la plus stricte. Attention : choisir une politique très stricte peut avoir des effets de bord désagréables, par exemple encourager les gens à « s'auto-enregistrer », c'est-à-dire à prendre un numéro au hasard (et tant pis pour l'interopérabilité) parce que la complexité et la lenteur des procédures les ont découragés. Il peut être préférable d'avoir une approche plus ouverte du registre, qui devrait documenter ce qui existe plutôt que d'essayer de contrôler tous les enregistrements.

Enfin, septième et dernier principe architectural à garder en tête pour faire des protocoles extensibles, l'importance particulière des services critiques. Si on arrête BGP, l'Internet ne fonctionne plus. Si on arrête le DNS, il n'y a quasiment plus aucune activité possible (même si vous ne voyez pas de noms de domaine, ils sont présents dans la communication). Même chose pour certains algorithmes comme le contrôle de congestion : si on modifie cet algorithme et qu'on se trompe, on peut mettre l'Internet à genoux. Il faut donc faire dix fois plus attention lorsqu'on étend ces protocoles critiques.

Le RFC cite un exemple BGP. Il existait depuis longtemps dans les IGP comme OSPF la notion de LSA opaque (LSA = Link State Attribute, la structure de données qui contient les informations que s'échangent les routeurs). « Opaque » signifie que les routeurs n'ont pas forcément besoin de comprendre son contenu. Ils peuvent le propager sans l'analyser et cela permet des extensions intéressantes du protocole, en introduisant de nouveaux types de LSA opaques. L'expérience montre que cela marche bien.

Mais l'introduction de nouveaux attributs dans BGP ne s'est pas aussi bien passé puisque des routeurs ont réinitialisé les sessions locales si un attribut, transmis par un routeur lointain, était inconnu ou mal formé. (Cas du fameux attribut 99.)

Une fois ces sept principes en tête, la section 4 se penche sur le protocole de base. Une bonne extensibilité implique un bon protocole de base, conçu pour l'extensibilité. Cela implique :

  • Une spécification bien écrite,
  • Prenant en compte l'interaction avec des versions plus récentes ou plus anciennes du protocole. Cela inclut la détermination des capacités du pair, la négociation des paramètres, le traitement des extensions inconnues (nécessaire pour que les nouvelles implémentations ne plantent pas les anciennes), etc.
  • Décrivant bien les principes architecturaux du protocole, ainsi que sa sécurité (pour éviter qu'une extension ne casse un modèle de sécurité bien fait mais pas assez explicite).
  • Précisant clairement le modèle d'extensions et notamment quelles extensions sont majeures et lesquelles sont de routine.
  • Interagissant le moins possible avec les composants critiques de l'Internet. Par exemple, si un nouveau protocole nécessite des modifications sérieuses au DNS, cela va faire hésiter.

Écrire un protocole bien extensible nécessite aussi de prêter attention à ce qui peut sembler des petits détails. Ainsi (section 4.1), le problème des numéros de versions. Il est courant que le protocole porte un tel numéro, permettant au pair de savoir tout de suite s'il a affaire à une implémentation équivalente (même numéro de version) ou pas (numéro de version plus récent ou plus ancien). Par exemple, voici une session TLS avec l'outil gnutls-cli de GnuTLS :

% gnutls-cli  --verbose  --port 443 svn.example.net
...
- Version: TLS1.2

où on voit que le serveur accepte TLS version 1.2. Un tel versionnement n'est utile que si le protocole de base précise bien ce qu'il faut faire lorsqu'on rencontre une version différente. Par exemple, si un logiciel en version 1.1 rencontre un 2.0 ? Il y a plusieurs sémantiques possibles, par exemple le protocole de base peut préciser que toute version doit être un sur-ensemble de la version antérieure (le logiciel en 2.0 doit accepter toutes les commandes du 1.1). Une autre sémantique pourrait être qu'il n'y a compatibilité qu'au sein d'une même version majeure (entre 1.0, 1.1, 1.2, etc) et que donc les deux logiciels de l'exemple (1.1 et 2.0) doivent renoncer à se parler. Dans les deux cas, cela doit être clairement spécifié.

Un contre-exemple est fourni par la norme MIME. Le RFC 1341 décrivait un en-tête MIME-Version: mais sans dire ce que devait faire une implémentation correcte de MIME si elle rencontrait une version inférieure ou supérieure. En fait, ce RFC 1341 ne précisait même pas le format de la version ! Le RFC 1521 a un peu précisé les choses mais pas au point qu'on puisse prédire le comportement d'une mise en œuvre de MIME face à des versions nouvelles. Notre RFC 6709 estime donc que le MIME-Version: n'a guère d'utilité pratique.

Pour un exemple plus positif, on peut regarder ROHC. Le RFC 3095 décrivait un certain nombre de jeux de paramètres pour la compression. À l'usage, on leur a découvert des limitations, d'où le développement de ROHCv2 (RFC 5225). Ce dernier n'est pas compatible mais ne plante pas les ROHC précédents, ils ont simplement des jeux de paramètres différents et la négociation initiale (qui n'a pas changé en v2) permet à un ROHC ayant les jeux v1 de se comprendre facilement avec un plus récent.

Quelles sont les stratégies utilisées par les protocoles pour la gestion des versions ? Il y en a plein, toutes n'étant pas bonnes. On trouve :

  • Pas de gestion de versions. Le cas le plus célèbre est EAP (RFC 3748) mais c'est aussi le cas de Radius (RFC 2865). Cela les a protégé contre l'apparition de multiples versions à gérer mais, comme la demande d'extensibilité est toujours là, elle s'est manifestée de manière non officielle (voir l'étude de cas de Radius en annexe A.2).
  • HMSV (Highest mutually supported version) : les deux pairs échangent les numéros de version du protocole qu'ils savent gérer et on choisit la plus élevée qui soit commune aux deux. Cela implique que la version plus élevée est toujours « meilleure » (alors que, parfois, une version supérieure retire des fonctions). Cela implique aussi que gérer une version implique aussi de gérer toutes les versions inférieures (si un pair annonce 3.5 et un autre 1.8, HMSV va choisir 1.8 alors que le pair en 3.5 ne sait pas forcément gérer cette vieille version).
  • Min/Max : une variante de HMSV où on annonce non pas un numéro de version (la plus élevée qu'on gère) mais deux (la version la plus élevée qu'on gère, et la moins élevée). Ainsi, il n'y a pas besoin de gérer éternellement les vieilles versions. Dans certains cas, cela peut mener à l'échec de la négociation. Si Alice annonce 2.0->3.5 et que Bob répond avec 1.0->1.8, ils n'auront aucune version compatible (Bob est trop vieux). Au moins, cela permettra d'envoyer un message d'erreur clair.
  • Considérer que les vieilles versions sont compatibles avec les récentes. L'idée est que l'implémentation récente peut envoyer ce qu'elle veut, l'ancienne devant réagir proprement (typiquement en ignorant les nouveaux messages et types). Cela a pour conséquence qu'une nouvelle version du protocole ne peut pas rendre obligatoire un message qui n'existait pas avant (puisque les vieilles implémentations ne le connaissent pas). Avec cette stratégie, qui est par exemple utilisée dans 802.1X, un logiciel n'est jamais dépassé, il peut toujours travailler avec ses successeurs.
  • Majeur/mineur : pour les numéros de versions à deux champs (comme 3.5 et 1.8 plus tôt), on considère qu'il y a compatibilité tant que le champ majeur ne change pas. 3.5 peut communiquer sans problème avec 3.0 mais aussi avec 3.9. Mais 3.5 ne peut pas parler avec 2.4 ou 5.2. Les contraintes de la stratégie précédente (ignorer les types inconnus, ne pas rendre un nouveau type obligatoire) ne s'appliquent donc qu'au sein d'un même numéro majeur.

Et c'est à peu près tout. Le RFC considère qu'il ne faut pas chercher d'autres stratégies de versionnement, qui ont de fortes chances d'être trop complexes pour être mises en œuvre sans erreur.

Autre chose importante à considérer lorsqu'on normalise le protocole de base (la première version) : les champs réservés. On trouve souvent dans les RFC des phrases comme (celle-ci est extraite du RFC 1035) « Reserved for future use. Must be zero in all queries and responses. ». (Dans le cas du DNS, ils ont été utilisés par la suite pour DNSSEC, bits AD et CD. Le bit 9, selon le RFC 6195, section 2.1, avait été utilisé de manière non standard autrefois et semble donc inutilisable désormais.) Certains champs dans l'en-tête sont donc gardés pour un usage futur et, presque toujours, le RFC demande à l'envoyeur de les mettre tous à zéro et au récepteur de les ignorer, ce qui est très important : autrement, on ne pourra jamais déployer d'implémentation d'une nouvelle version du protocole, qui utiliserait ces champs qui avaient été réservés. Dans les diagrammes montrant les paquets, ces champs sont en général marqués Z (pour Zero) ou MBZ (Must Be Zero, voir par exemple le RFC 4656). Notons que bien des pare-feux, fidéles jusqu'à l'excès au principe « tout ce qui est inconnu est interdit », au lieu d'ignorer ces champs, comme l'impose le RFC, jettent les paquets où ce champ ne vaut pas zéro. Ces engins sont une des plus grosses sources de problème lorsqu'on déploie un nouveau protocole. Donc, attention, programmeurs, votre travail n'est pas de vérifier ces champs mais de les ignorer, afin de permettre les futures extensions.

Autre problème douloureux, la taille à réserver aux champs (section 4.4). Certains protocoles utilisent des champs de taille illimitée (paramètres de type texte) ou suffisamment grands pour qu'on ne rencontre jamais la limite, même après plusieurs extensions du protocole. Mais ce n'est pas toujours le cas. Tout le monde se souvient évidemment de l'espace d'adressage trop petit d'IPv4 et de la difficulté qu'il y a eu à passer aux adresses plus grandes d'IPv6 (le champ Adresse étant de taille fixe, les deux versions ne pouvaient pas être compatibles). Dans la réalité, on rencontre :

  • Des champs Version trop petits, par exemple de seulement deux bits (après la version de développement et la version de production, on n'a plus que deux versions possibles).
  • Des champs stockant un paramètre pour lesquels la taille était trop petite pour la politique d'allocation (cf. RFC 5226) qui avait été adoptée. Par exemple, la politique FCFS (First-come, First-served, ou « Premier arrivé, premier servi »), la plus libérale, peut vite épuiser un champ de seulement huit bits (le problème s'est posé pour le champ Method Type d'EAP dans le RFC 2284).

Si un tel problème se pose, si on voit les valeurs possibles pour un champ arriver à un tel rythme que l'épuisement est une possibilité réelle, il y a plusieurs solutions :

  • Changer la politique d'allocation en la durcissant. Mais attention, une politique trop dure peut mener à des comportements comme l'auto-allocation (« je prends la valeur qui me plait et tant pis pour le registre »). C'est ce qui avait été fait pour EAP (RFC 3748, section 6.2) en passant de « Premier arrivé, premier servi » à « Norme nécessaire ». Pour éviter l'auto-allocation, diverses solutions alternatives avaient également été normalisées par ce RFC, comme la suivante :
  • Permettre des valeurs spécifiques à un fournisseur (vendor). Ainsi, chaque fournisseur qui crée une extension privée, spécifique à son logiciel, peut créer ses propres types/messages.
  • Agrandir le champ. La plupart des protocoles IETF ont des champs de taille fixe, pour des raisons de performance (il faut se rappeler qu'il peut y avoir beaucoup de paquets à traiter par seconde, ce n'est donc pas une optimisation de détail). Agrandir le champ veut donc en général dire passer à une nouvelle version, incompatible, du protocole.
  • Récupérer des valeurs inutilisées. C'est très tentant sur le principe (il est rageant d'épuiser un espace de numérotation alors qu'on sait que certaines valeurs ont été réservées mais jamais utilisées) mais cela marche mal en pratique car il est en général très difficile de dire si une valeur est vraiment inutilisée (peut-être qu'une obscure implémentation utilisée uniquement dans un lointain pays s'en sert ?)

Un usage particulier de l'extensibilité concerne la cryptographie (section 4.5). Celle-ci demande une agilité, la capacité à changer les algorithmes de cryptographie utilisés, pour faire face aux progrès constants de la cryptanalyse (c'est bien expliqué dans la section 3 du RFC 4962). Presque tous les protocoles de cryptographie sérieux fournissent cette agilité (le RFC ne donne pas d'exemple mais je peux citer deux contre-exemples, un à l'IETF, le TCP-MD5 du RFC 2385 depuis remplacé par le meilleur RFC 5925 qui est encore très peu déployé et, en dehors de l'IETF, le protocole DNScurve). Le problème est lorsqu'un algorithme noté comme obligatoire (avant d'assurer l'interopérabilité, un ou plusieurs algorithmes sont obligatoires à implémenter, pour être sûr que deux pairs trouvent toujours un algorithme commun) est compromis au point qu'il n'est plus raisonnable de s'en servir.

Soit un algorithme non compromis est déjà très répandu dans les mises en œuvre existantes du protocole et on peut alors le déclarer obligatoire, et noter le vieil algorithme comme dangereux à utiliser. Soit il n'existe pas encore un tel algorithme répandu et on a peu de solutions : déployer du code dans la nature prend beaucoup de temps. Bref, le RFC recommande que, lorsque les signes de faiblesse d'un algorithme face à la cryptanalyse apparaissent (le RFC ne cite pas de noms mais, en 2012, on peut dire que c'est le cas de SHA-1 et RSA), on normalise, puis on pousse le déploiement de solutions de rechange (par exemple SHA-2 et ECDSA dans ces deux cas, algorithmes qui sont aujourd'hui utilisables dans la plupart des protocoles IETF). Il faut bien se rappeler que le déploiement effectif d'un algorithme normalisé peut prendre des années, pendant lesquelles la cryptanalyse continuera à progresser.

Un aspect peu connu des protocoles applicatifs de la famille IP est qu'ils peuvent parfois tourner sur plusieurs transports, par exemple TCP et SCTP (section 4.6). Cela a parfois été fait dès le début, pour avoir le maximum de possibilités mais, parfois, le protocole de couche 7 n'était prévu que pour un seul protocole de couche 4, puis a été étendu pour un autre protocole. Par exemple, utilisant TCP, il ne passait pas à l'échelle, alors on l'a rendu utilisable sur UDP. (Dans ce cas, les concepteurs du protocole devraient lire le RFC 8085 car il y a plein de pièges.)

Cela peut évidemment casser l'interopérabilité. Si le protocole Foobar est normalisé pour tourner sur TCP ou SCTP, deux mises en œuvre de Foobar, une qui ne gère que TCP et une qui ne gère que SCTP (pensez aux systèmes embarqués, avec peu de ressources, ce qui impose de limiter les choix), ne pourront pas se parler. Notre RFC conseille donc de bien réflechir à ce problème. Davantage de choix n'est pas forcément une bonne chose. D'un autre côté, si le premier protocole de transport choisi a de sérieuses limites, on pourra en ajouter un autre comme option mais il sera quasi-impossible de supprimer le premier sans casser l'interopérabilité.

Enfin, dernier casse-tête pour le concepteur de protocoles, le cas des extensions inconnues (section 4.7). Je suis programmeur, je crée un programme pour la version 1.0 du protocole, ce programme sait traiter un certain nombre de messages. Le temps passe, une version 1.1 du protocole est créé, des programmeurs la mettent en œuvre et, soudain, les copies de mon programme reçoivent des messages d'un type inconnu, car introduit dans la 1.1. Que faire ? Première approche, une règle comme quoi les extensions inconnues doivent être ignorées (silently discarded). Je reçois un tel message, je le jette. Un champ qui était à zéro acquiert une signification ? J'ignore ce champ. L'avantage de cette approche est qu'elle permet le maximum d'interopérabilité. On est sûr que les vieilles versions pourront parler avec les nouvelles, même si seules les nouvelles pourront tirer profit des extensions récentes. L'inconvénient de cette approche est qu'on ne sait même pas si les nouveaux messages sont traités ou pas. Dans le cas de la sécurité, on voudrait bien pouvoir savoir si une extension qu'on considère comme indispensable a bien été acceptée par le pair (voir par exemple la section 2.5 du RFC 5080).

Autre approche, mettre un bit Mandatory (aussi appelé Must Understand) dans les messages. Si ce bit est à zéro, une vieille implémentation peut ignorer le message. Sinon, elle doit prévenir qu'elle ne sait pas le gérer (par exemple via un message ICMP). C'est ce que font L2TP (RFC 2661, section 4.1) ou SIP (RFC 3261, section 8.1.1.9). Cette méthode permet d'éviter qu'une extension cruciale soit ignorée par le pair. Mais elle diminue l'interopérabilité : si un programme récent l'utilise, il ne pourra pas parler avec les vieux qui ne savent pas du tout gérer cette extension.

On peut aussi négocier les extensions gérées au début de la session. Cela ralentit son établissement mais cela permet aux deux pairs qui dialoguent de savoir ce que fait l'autre. Typiquement, l'initiateur de la connexion indique ce qu'il sait gérer et le répondeur choisit parmi ces extensions acceptées. IKE (RFC 5996) fait cela, HTTP et SIP aussi, via leurs en-têtes Accept*: et Supported:.

Enfin, le concepteur d'un protocole de base, ou d'une extension à ce protocole doit lire la section 5 sur la sécurité. Elle rappelle qu'une extension à l'apparence inoffensive peut facilement introduire un nouveau risque de sécurité, ou parfois désactiver une mesure de sécurité qui était dans le protocole de base (l'ajout d'une poignée de mains dans un protocole qui était avant sans état peut créer une nouvelle occasion de DoS). L'analyse de sécurité de la nouvelle extension ne peut donc pas se contenter de reprendre celle du protocole de base, il faut s'assurer qu'il n'y ait pas de régression.

L'annexe A de notre RFC est très instructive car elle comprend trois études de cas de protocoles qui ont réussi, ou raté, leur extensibilité. La première concerne Radius (RFC 2865) grand succès mais qui, pour cette raison, a connu de fortes pressions pour son extension, pressions qui ont sérieusement secoué un protocole qui n'était pas vraiment conçu pour cela. L'idée dans le protocole de base était que les extensions se feraient en ajoutant des attributs (le protocole venait avec un certain nombre d'attributs standards dans les messages) dont la valeur pouvait avoir un nombre limité de types.

En pratique, on a constaté que, non seulement beaucoup de fournisseurs ne pouvaient pas s'empêcher de s'auto-allouer des noms d'attributs, mais aussi que bien des attributs ajoutés sortaient du modèle original (comme l'idée d'un dictionnaire, sur lesquels les correspondants se mettent d'accord et qui permet le déploiement de nouveaux attributs sans changer le code : idée astucieuse mais qui n'est pas dans le RFC 2865). La section 1 du RFC 2882, tirant un premier bilan, note qu'une des raisons de la tension est que le monde des NAS, pour lequel Radius avait été conçu, s'était beaucoup diversifié et complexifié, au delà du modèle initialement prévu. Le RFC 2882 notait aussi que certaines mises en œuvre ressemblaient à Radius (même format des messages) mais ne l'étaient pas vraiment (sémantique différente).

Un des cas compliqué est celui des types de données pour les attributs. Il était prévu d'ajouter de nouveaux attributs mais pas de nouveaux types. Il n'existe pas de registre des types définis, ni de moyen pour un client ou serveur Radius que savoir quels types gèrent son correspondant. L'utilisation d'attributs définis avec un type nouveau est donc problématique. Le RFC 6158 (section 2.1) a tenté de mettre de l'ordre dans ce zoo des types mais, publié plus de quatorze ans après la première norme Radius, il n'a pas eu un grand succès.

Radius dispose d'un mécanisme d'extensions spécifiques à un fournisseur (RFC 2865, section 6.2). Ce mécanisme a été utilisé à tort et à travers, notamment par des SDO différentes de l'IETF qui voulaient leurs propres extensions (alors que ces extensions n'avaient jamais été prévues pour être compatibles d'un fournisseur à l'autre). Autre problème, le cas des extensions « fournisseur » inconnues n'avait pas été traité. Or, certaines ont des conséquences pour la sécurité (définition d'une ACL par exemple) et il serait dommage qu'elles soient ignorées silencieusement. Le RFC 5080, section 2.5, estime que la seule solution est que les programmes mettant en œuvre Radius n'utilisent les extensions que lorsqu'ils savent (par exemple par configuration explicite) que l'autre programme les gère.

Autre protocole qui a connu bien des malheurs avec les extensions, TLS (annexe A.3). Son histoire remonte au protocole SSL, v2, puis v3, celle-ci remplacée par TLS. SSL, et TLS 1.0, n'avaient aucun mécanisme d'extension défini. Il a fallu attendre le RFC 4366 pour avoir un mécanisme normalisé permettant de nouveaux types d'enregistrements, de nouveaux algorithmes de chiffrement, de nouveaux messages lors de la poignée de mains initiale, etc. Il définit aussi ce que les mises en œuvre de TLS doivent faire des extensions inconnues (ignorer les nouveaux types, rejeter les nouveaux messages lors de la connexion). Mais, à ce moment, TLS était déjà très largement déployé et ces nouveaux mécanismes se heurtaient à la mauvaise volonté des vieilles implémentations. En pratique, les problèmes ont été nombreux, notamment pendant la négociation initiale. Ce n'est qu'en 2006 que les clients TLS ont pu considérer que SSLv2 était mort, et arrêter d'essayer d'interopérer avec lui. Encore aujourd'hui, de nombreux clients TLS restent délibérement à une version de TLS plus faible que ce qu'ils pourraient faire, pour éviter de planter lors de la connexion avec un vieux serveur (ces serveurs étant la majorité, y compris pour des sites Web très demandés). C'est ainsi que, lors de l'annonce de l'attaque BEAST en 2011, on s'est aperçu que TLS 1.1 résolvait ce problème de sécurité depuis des années... mais n'était toujours pas utilisé, de peur de casser l'interopérabilité.

Dans le futur, cela pourra même poser des problèmes de sécurité sérieux : il n'existe aucun moyen pratique de retirer MD5 de la liste des algorithmes de hachage, par exemple. TLS 1.2 (RFC 5246) permet d'utiliser SHA-256 mais tenter d'ouvrir une connexion en TLS 1.2 avec un serveur a peu de chances de marcher, le mécanisme de repli des versions n'existant que sur le papier.

Morale de l'histoire, dit notre RFC : ce n'est pas tout de faire de bonnes spécifications, il faut aussi qu'elles soient programmées correctement.

Dernier cas intéressant étudié, L2TP (RFC 2661). Fournissant dès le début des types spécifiques à un fournisseur, disposant d'un bit Mandatory pour indiquer si les types doivent être compris par le récepteur, L2TP n'a guère eu de problèmes. On pourrait imaginer des ennuis (RFC 2661, section 4.2) si un programmeur mettait un type spécifique et le bit Mandatory (empêchant ainsi toute interaction avec un autre fournisseur qui, par définition, ne connaîtra pas ce type) mais cela ne s'est guère produit en pratique.


Téléchargez le RFC 6709


L'article seul

RFC 6708: Application-Layer Traffic Optimization (ALTO) Requirements

Date de publication du RFC : Septembre 2012
Auteur(s) du RFC : S. Kiesel (University of Stuttgart), S. Previdi (Cisco Systems), M. Stiemerling (NEC Europe), R. Woundy (Comcast Corporation), Y R. Yang (Yale University)
Pour information
Réalisé dans le cadre du groupe de travail IETF alto
Première rédaction de cet article le 30 septembre 2012


Le système Alto (Application-Layer Traffic Optimization), permettant aux machines d'un réseau pair-à-pair de trouver le meilleur pair, par exemple pour obtenir un fichier plus rapidement, avance, lentement, mais sûrement. Ce nouveau RFC spécifie le cahier des charges d'Alto.

Alto peut servir à autre chose qu'au pair-à-pair. Mais le scénario d'utilisation principal est le suivant : une machine veut accéder à un fichier. Celui-ci est offert par plusieurs pairs. Lequel choisir ? En prendre un au hasard risque de ne pas être optimum, ni pour la machine (temps de transfert du fichier plus long qu'il ne pourrait l'être), ni pour son FAI (utilisation de liens externes plus coûteux que son réseau interne). Alto vise donc à permettre à des serveurs Alto de donner à leurs clients (les machines qui veulent accéder aux fichiers) des informations sur lesquelles décider intelligemment, ou même simplement d'indiquer directement le pair à utiliser. Le groupe de travail Alto a été créé en novembre 2008, le RFC 5693, qui définit le problème à résoudre, a été publié en octobre 2009, et voici désormais le deuxième RFC du groupe, le cahier des charges du protocole. (Pour ceux qui ne connaissent pas l'IETF, et qui craignent que le travail sur le protocole ne commence qu'une fois le cahier des charges terminé, je vous rassure, ce n'est pas ainsi que fonctionne l'IETF. Le protocole est déjà bien avancé à l'époque, et a été publié dans le RFC 7285.)

Pair-à-pair ou pas, le but d'Alto est donc d'améliorer simultanément la qualité de la vie pour l'utilisateur (télécharger les chefs d'œuvre de la culture plus vite) et pour le réseau (ne pas gaspiller des ressources chères comme les lignes transocéaniques). Cela ne peut pas se faire par des mesures uniquement faites par les machines terminales. Par exemple, celles-ci peuvent faire des ping mais elles ne peuvent pas déterminer si un lien est de peering (« gratuit ») ou de transit (facturé au 95ème centile de l'usage).

Les serveurs Alto ne feront pas bouger les octets : leur seul rôle est de dire aux pairs « tu devrais plutôt causer avec lui, ça devrait aller vite ». Les pairs sont ensuite responsables de leurs décisions.

L'habituelle section de terminologie, nécessaire pour comprendre le reste du RFC, est la section 2. Attention, le RFC 5693 définissait déjà certains termes (comme client Alto et serveur Alto) qui ne sont pas répétés ici. Les termes les plus importants :

  • Descripteur de groupe (Host Group Descriptor) : c'est l'information qui définit un groupe de machines. Cela peut être un préfixe IP (« toutes les machines en 2001:db8:1337::/32 ») ou un numéro d'AS (« toutes les machines joignables par l'AS 42 »).
  • Attribut d'une machine (Host Characteristics Attribute) : c'est une propriété attachée à une machine comme « accès Internet au forfait ».
  • Critère de classement. On a dit plus haut que le but d'Alto était de sélectionner le « meilleur » pair. Mais quelle est la définition de « meilleur » ? Par exemple, cela peut être « le moins cher » ou « celui avec la plus forte capacité réseau ». Alto est un protocole pour distribuer des choix, pas un mécanisme pour décider quel est le meilleur.
  • Recherche dépendante de la cible (Target-aware Query Mode) se dit d'une requête Alto où le client Alto connait une liste de pairs potentiels, envoie cette liste au serveur Alto (ainsi qu'un critère de classement) et reçoit en retour la liste triée selon le critère. (Plus exactement, le client envoie une liste de descripteurs de groupes, pas d'adresses IP des pairs potentiels.) On notera que ce mode permet au serveur de connaître les pairs potentiels de ses clients. En revanche, c'est ce mode qui permet au client de faire le moins de calculs, ce qui est utile pour les machines aux ressources réduites.
  • Recherche indépendante de la cible (Target-independant Query Mode) désigne une requête Alto où le client télécharge tout ou partie des descripteurs de groupe que connait le serveur, avec leurs attributs, et fait le calcul du meilleur pair lui-même. Préservant la vie privée du client, elle lui impose davantage de calculs.

Les exigences sur le futur protocole figurent en section 3 et sont numérotées AR-n (AR pour Alto Requirment). Elles vont des plus évidentes (exigence AR-1 : les clients et serveurs Alto doivent parler le protocole Alto...) aux plus pointues. Voici les plus importantes, selon moi.

Le protocole devra gérer les descripteurs de groupe : types multiples (AR-3), au moins les types « préfixe IPv4 » et « préfixe IPv6 » (AR-5) et extensible (possitibilité d'ajouter de nouveaux types de descripteurs de groupe dans le futur, AR-6). Les types « préfixes IP » sont, à ce stade, les types recommandés. Donc, en deux mots, les pairs possibles seront identifiés par leur adresse (« j'hésite entre un pair en 2001:db8:1:2::af et un pair en 192.0.2.43, tu me recommandes lequel ? »). Voir aussi AR-7 et AR-8.

Le protocole devra permettre d'indiquer un critère de classement (AR-11) permettant de comparer les machines entre elles. Alto ne détermine pas comment on fait les calculs : il utilise le résultat (on peut tout imaginer, y compris des tables gérées à la main, par exemple en fonction du fait que les liens sont de transit ou de peering). Alto devra, là aussi, être extensible et permettre d'ajouter d'autres critères dans le futur.

Ces critères doivent être relativement stables (ne pas oublier qu'une fois un transfert de fichiers commencé, il peut durer de nombreuses heures) donc ne pas dépendre, par exemple, de l'état de congestion du réseau (AR-13). À propos de la congestion, les applications qui utiliseront Alto ne doivent pas s'en servir comme remède contre la congestion, elles doivent utiliser un protocole qui dispose de mécanismes d'évitement de la congestion, comme TCP (AR-14, et aussi AR-29).

Le critère de classement doit pouvoir être indiqué au serveur (en mode « recherche dépendante de la cible », car, dans l'autre mode, c'est le client Alto qui classe) afin qu'il l'utilise pour classer (AR-16).

Où va être situé le client Alto ? Le protocole ne l'impose pas et il y aura au moins deux positionnements possibles : directement dans l'application (le client BitTorrent, par exemple) ou bien chez un tiers qui fera une partie du travail pour le compte du client (le tracker BitTorrent, par exemple). Alto devra fonctionner dans les deux cas (AR-18 et AR-19).

Et qui va fournir ses informations au serveur Alto ? Une possibilité évidente est que ce soit le FAI, et qu'Alto devienne un service de base de l'accès Internet, comme le résolveur DNS et le serveur NTP. Mais les exigences AR-20 et AR-21 demandent que le protocole n'impose pas ce choix : il faut que des acteurs tiers puisse jouer le rôle de serveur Alto.

Le protocole doit aussi permettre la redistribution de l'information obtenue (AR-25), en indiquant des conditions de redistribution.

Comment va-t-on trouver son serveur Alto ? Il faudra décrire un mécanisme et AR-37 demande que ce mécanisme soit intégré aux protocoles existants comme PPP ou DHCP (comme c'est le cas pour découvrir un résolveur DNS).

La sécurité étant un enjeu important pour Alto (voir aussi la section 5), il faudra aussi un mécanisme d'authentification des serveurs (AR-40), des clients (AR-41), la possibilité de chiffrer (AR-42), et d'ajuster la taille des requêtes et réponses selon le niveau de confiance du client envers le serveur, ou réciproquement (AR-44). Un client devra donc pouvoir rester intentionnellement vague dans sa demande, au risque évidemment que les informations du serveur soient moins pertinentes.

Et la sécurité ? Outre le RFC 5693 qui couvrait déjà la sécurité d'Alto, la section 5 de notre RFC met l'accent sur le point le plus important, le risque de distribution d'informations sensibles.

Ce risque existe dans les deux sens, du client vers le serveur et du serveur vers le client. Le client ne souhaite pas forcément communiquer au serveur tout ce qu'il sait. Par exemple, lorsque la HADOPI espionne, un client Alto ne va pas dire à un serveur qu'il ne connait pas « je cherche une copie HD du dernier Disney ». Et, en sens inverse, un serveur Alto géré par un FAI n'est pas forcément enthousiaste à l'idée de donner des informations qui permettent de se faire une bonne idée de la configuration de son réseau, de l'identité des opérateurs avec qui il peere et autres informations confidentielles.

Même si le client ne donne pas d'informations aussi évidentes que dans l'exemple ci-dessus, un serveur malin peut déduire plein de choses des demandes que le client lui adresse (la liste des pairs potentiels, par exemple, est une information utile pour repérer les plus grosses sources de contenu en pair-à-pair).

Pour l'opérateur du serveur, le principal risque est en recherche indépendante de la cible, lorsque le client télécharge de grandes quantités d'information. Un serveur prudent ne dira donc pas tout. En outre, même si le serveur accepte de donner ces informations au client, il peut quand même s'inquiéter de ce qu'elles deviendront. Un tiers qui écoute le réseau ne va t-il pas mettre la main sur l'information confidentielle ? Et, même si l'information donnée à chaque client est limitée (par exemple, uniquement une partie des descripteurs de groupes que le serveur connait), ne risque t-on pas de voir des clients coopérer pour récupérer chacun un bout, avant de le mettre en commun ?

Le futur protocole Alto devra donc contenir des mesures pour faire face à ces problèmes : par exemple, permettre au serveur d'être délibérement incomplet ou imprécis (annoncer un préfixe IP plus général que le vrai, par exemple), authentifier clients et serveurs, chiffrer les communications contre l'écoute par TMG, etc. En revanche, le RFC écarte l'idée de DRM dans les données Alto, complexes et facilement contournables. Les acteurs Alto sont donc prévenus que les données échangées ne peuvent pas être 100 % confidentielles. Un client ou un serveur méchant pourra toujours en faire mauvais usage.

À noter que les intérêts du client et du serveur peuvent être contradictoires. Ainsi, les requêtes en mode indépendante de la cible préservent la vie privée du client (il ne dit rien sur ce qu'il va faire des données) mais oblige le servur à diffuser de l'information. Et, pour les requêtes en mode dépendant de la cible, c'est le contraire :le client se dévoile, le serveur ne prend pas de risque.


Téléchargez le RFC 6708


L'article seul

RFC 6707: Content Distribution Network Interconnection (CDNI) Problem Statement

Date de publication du RFC : Septembre 2012
Auteur(s) du RFC : B. Niven-Jenkins (Velocix (Alcatel-Lucent)), F. Le Faucheur (Cisco), N. Bitar (Verizon)
Pour information
Réalisé dans le cadre du groupe de travail IETF cdni
Première rédaction de cet article le 26 septembre 2012


Aujourd'hui, les CDN sont partout. Ces serveurs munis de nombreux disques et disposés dans les réseaux des FAI, au plus près de l'abonné, afin de servir du contenu numérique le plus rapidement possible, sont derrière un grand nombre de sites Web (non, ce blog n'utilise pas de CDN) et derrière bien des fournisseurs de streaming. La plus connue des entreprises de CDN est Akamai mais il en existe bien d'autres. Et c'est là que le problème commence : il n'existe aucun mécanisme d'interconnexion des CDN. Chacun utilise ses protocoles spécifiques et pas question de les faire travailler ensemble. L'IETF a donc créé un groupe de travail, CDNI, chargé de réfléchir à l'interconnexion des CDN. Ce RFC est le premier du groupe, et il essaie de définir le problème (les solutions viendront plus tard, le cahier des charges formel a été publié dans le RFC 7337).

L'extension massive des CDN est bien sûr liée à l'augmentation considérable du contenu numérique : présentations PowerPoint ennuyeuses, vidéos de chats mignons, communiqués de presse en PDF qui prennent plusieurs mégaoctets pour ne pas dire grand'chose, publicités débiles, webinars en haute définition et au contenu vide, etc. Sans le CDN, un site Web qui veut distribuer un fichier de N mégaoctets à M clients va voir N*M mégaoctets passer sur sa liaison Internet. Avec le CDN, le fournisseur de contenu (CSP dans le RFC pour Content Service Provider) n'aura à faire passer le contenu qu'une fois, vers le CDN. Le contenu sera ensuite distribué par les serveurs du CDN, situés typiquement chez les FAI (notez aussi que certains FAI ont leur propre CDN). Meilleure latence, meilleure résilience (attaques dDoS et flash crowds), meilleur débit, bref, tous les avantages.

Aujourd'hui, les CDN ne coopèrent pas. Si un fournisseur de CDN est très présent en Europe et en Amérique, mais pas en Asie, un CSP client de ce CDN verra ses clients asiatiques mécontents. Pour les satisfaire, il devra signer un contrat avec un autre CDN, très présent en Asie. Il serait pourtant plus simple que le premier fournisseur de CDN puisse s'appuyer sur l'infrastructure du second et lui transmettre données et instructions. Mais, en l'absence de normes techniques pour l'interconnexion des CDN, cela n'est possible aujourd'hui que par des arrangements privés. C'est l'une des principales motivations pour la création du groupe de travail CDNI. L'idée est que, dans le futur, le premier fournisseur de CDN cité (celui qui est trés présent en Europe et en Amérique) aura juste à signer un contrat avec le second fournisseur et, techniquement, tout se passera tout seul, il utilisera le réseau du second sans que le fournisseur de contenu n'y voit rien.

Avant d'attaquer la question de l'interconnexion, notre RFC 6707 précise qu'il vaut mieux connaître les CDN pour suivre. Si ce n'est pas le cas, il recommande la lecture des RFC 3040 qui décrit les composants d'un CDN, RFC 3466 et RFC 3570, les deux derniers étant le résultat du travail du précédent groupe de travail IETF sur les CDN. Le RFC recommande également la lecture de « A Taxonomy and Survey of Content Delivery Networks ».

La section 2 de notre RFC précise les cas où il est intéressant d'interconnecter les CDN. À la raison donnée plus haut (permettre à des CDN de s'allier pour avoir une meilleure couverture géographique), s'ajoute le désir de permettre l'interconnexion des CDN que gèrent certains FAI : en se regroupant, ils pourraient former un CDN alternatif aux CDN indépendants des FAI comme Akamai. Il y a aussi des cas où un FAI a déployé plusieurs CDN spécialisés et souhaite après les regrouper. Enfin, un dernier scénario envisagé est celui où un CDN doit faire appel temporairement à un autre (suite à une grosse panne, par exemple) et doit le faire vite, sans programmer des scripts spécifiques.

Mais qu'est-ce que veut dire « Interconnecter des CDN » ? Des essais ont déjà été tentés, montrant qu'il y avait des choses qui marchaient et d'autres qui étaient vraiment pénibles en l'absence de normes. La section 3 identifie quatre interfaces par lesquelles on voudrait connecter des CDN, et pour lesquelles il n'existe pas de normes :

  • Interface de contrôle du CDN, par laquelle on démarre et arrête le service, on indique les politiques suivies (« aucun contenu ne doit pas être distribué en dehors des États-Unis », par exemple), on déclenche la copie de contenu, on vire le contenu qui ne doit plus être servi, etc.
  • Interface de routage des requêtes du CDN, qui n'est pas le routage de la couche 3. Il s'agit ici de s'assurer que les requêtes des utilisateur seront routées vers un CDN et un seul (qu'il n'y ait pas de boucles « c'est lui, non c'est lui »).
  • Interface de distribution des métadonnées au CDN. Ces métadonnées sont les données au sujet du contenu : ses caractéristiques techniques (HD ou pas, par exemple, pour permettre la sélection du bon fichier), informations de zonage (tel document ne doit être servi que dans telle région du Monde), etc.
  • Interface de journalisation (logging) du CDN. Elle permet de faire remonter les données de trafic, à des fins de statistiques, de facturation, etc. Sans elle, un CDN hésiterait à s'associer à un autre si cela signifiait qu'il n'aurait plus accès aux données de trafic.

Vous avez noté quelque chose qui manque ? Prenez le temps de réfléchir avant de regarder le paragraphe suivant.

Une interface importante est exclue du projet CDNI : l'interface d'acquisition des données elle-mêmes. Ce n'est pas tout de s'entendre avec un autre CDN pour qu'il contribue à distribuer le contenu de vos clients, encore faut-il mettre la main sur le dit contenu ! Mais notre RFC considère le problème comme déjà largement résolu. Il existe en effet plusieurs protocoles standards, ayant toutes les caractéristiques voulues, et effectivement utilisés par les CDN (HTTP et rsync sont deux exemples typiques). En écartant ce problème des données, le groupe CDNI se focalise sur le contrôle des CDN.

Et pour les quatre interfaces citées plus haut, ne pourrait-on pas trouver des protocoles existants qui résolvent le problème, sans avoir besoin de développer quelque chose de nouveau ? La section 4 reconnait que ce serait très souhaitable, cite des protocoles intéressants (comme XMPP ou APP) et étudie cette question.

  • L'interface de contrôle, dit le RFC, est un problème très ouvert et, bien qu'il soit souhaitable de réutiliser des protocoles existants, le RFC ne s'avance pas à en suggérer certains.
  • Pour l'interface de routage, en revanche, notre RFC considère qu'une simple fonction requête/réponse (par exemple « tu peux gérer ça ? / oui ») suffit et que cette interface peut donc être réalisée avec des protocoles de type Web Services comme XML-RPC ou REST. Le groupe de travail n'aurait alors à normaliser que le format exact de ces services. Il y a toutefois d'autres fonctions, liées à la sélection du CDN le plus efficace pour une requête, pour lequel le RFC suggère d'étudier des techniques comme ALTO (RFC 5693).
  • Même chose pour l'interface d'accès aux métadonnées, où il n'y aura pas non plus de nécessité de développer un protocole entièrement nouveau.
  • L'interface de journalisation pourrait aussi utiliser des protocoles existants comme évidemment SNMP ou syslog. Attention, ils ne sont pas forcément parfaits. Par exemple, dans SNMP, la remise des notifications asynchrones - traps - n'est pas garantie - cf. annexe A.3 - ce qui est un problème pour la facturation.

Des détails sur cette réutilisation de protocoles existants figurent dans l'annexe A. Elle est particulièrement riche pour le cas de l'interface de routage, qui doit permettre des scénarios de redirection complexes (plus complexes que, par exemple, les simples 301 et 302 de HTTP). Pour la journalisation, si le protocole de transport peut être un protocole existant, il restera à spécifier le format des données transportées (les champs, leur syntaxe, leur sémantique, etc).

La traditionnelle section de sécurité (section 6) est longue car une telle interconnexion des CDN soulève plein de problèmes difficiles. C'est d'autant plus vrai que le contenu numérique servi est souvent commercial et que le fournisseur de contenu souhaite en contrôler la distribution. Dans un CDN homogène, c'est relativement facile. Mais comment faire lorsqu'on interconnecte des CDN hétérogènes ? Il va falloir faire confiance aux autres...

En outre, l'interconnexion des CDN différents va introduire des problèmes légaux, puisque les CDN en question seront peut-être gérés par des entreprises différentes, donc soumises à des lois différentes. Ainsi, une loi locale peut obliger à anonymiser plus ou moins les données envoyées sur l'interface de journalisation.

  • Pour l'interface de contrôle, le principal problème de sécurité est le risque qu'un attaquant ne puisse contrôler le CDN par ce biais. Elle devra donc imposer une authentification sérieuse.
  • Pour l'interface de routage, les problèmes sont très proches : imaginez un méchant renvoyant toutes les requêtes vers un CDN qui n'est pas au courant et qui se retrouverait ainsi inondé.
  • L'interface des métadonnées est moins sensible mais, quand même, les informations peuvent ne pas être publiques.
  • L'interface de journalisation reçoit des données confidentielles et qui doivent donc être protégées, par exemple par du chiffrement. Mais elle peut aussi être utilisée pour de la facturation (« j'ai traité ce mois-ci N requêtes de tes clients, voici la note ») et elle doit donc être protégée contre la falsification.

L'annexe B intéressera les concepteurs de protocoles et les étudiants car elle définit les non-buts, ce que le groupe CDNI n'essaiera pas de faire. Par exemple :

  • L'interface entre le fournisseur de contenu et le CDN (on ne s'occupera que de l'interface entre CDN), et les éventuelles transformations de ce contenu (réencodage des vidéos entrantes, par exemple).
  • L'interface entre le CDN et le consommateur (avec éventuellement authentification). Même chose pour les menottes numériques.
  • Comme indiqué plus haut, la synchronisation des données entre les CDN est aussi hors-sujet.
  • Les algorithmes utilisés en interne par le système de routage du CDN pour décider à quel CDN partenaire il envoie des requêtes sont considérés comme une question interne et donc non traitée par le groupe CDNI. Seule l'interface de routage est dans le domaine d'activité de ce groupe.
  • Et, naturellement, tous les aspects commerciaux et juridiques sont également exclus du travail de l'IETF.

Autre partie intéressante de l'annexe B, celle consacrée aux autres groupes de travail IETF qui avaient une importance pour ce sujet :

  • ALTO, bien sûr (RFC 5693), par exemple pour router les requêtes vers le « meilleur » CDN. Comme indiqué plus haut, cela n'a pas d'influence directe sur le travail de CDNI puisque l'utilisation d'ALTO (ou pas) est une décision interne à chaque CDN.
  • DECADE (RFC 6646). Ce groupe travaille à réduire l'usage du « dernier kilomètre » (celui qui connecte Mme Michu à son FAI) en permettant le téléversement de contenu par Mme Michu, sur un serveur mieux placé. Le RFC estime toutefois que le rapport avec les CDN est trop lointain pour que le travail de DECADE soit directement utilisable.
  • PPSP, qui n'a pas encore de RFC, mais qui travaille sur le streaming en pair-à-pair. Son sujet est plutôt l'acquisition de contenu, un point qui a été explicitement exclu de CDNI.

Enfin, pour ceux et celles qui veulent vraiment beaucoup approfondir, les Internet-Drafts qui avaient précédé le RFC contenaient également une annexe (non gardée dans le RFC final) intéressante sur les autres efforts de normalisation des CDN. On y trouve de nombreux projets, parfois toujours actifs, y compris un ancien groupe de travail IETF, CDI, qui avait produit plusieurs RFC intéressants (RFC 3466, RFC 3568 et RFC 3570). Trop ambitieux, ce groupe n'avait pas vraiment réussi à faire avancer l'interconnexion.


Téléchargez le RFC 6707


L'article seul

RFC 6703: Reporting IP Network Performance Metrics: Different Points of View

Date de publication du RFC : Août 2012
Auteur(s) du RFC : A. Morton (AT&T Labs), G. Ramachandran (AT&T Labs), G. Maguluri (AT&T Labs)
Pour information
Réalisé dans le cadre du groupe de travail IETF ippm
Première rédaction de cet article le 24 août 2012


Le groupe de travail IPPM de l'IETF a défini de nombreuses métriques, des définitions rigoureuses de grandeurs qu'on peut mesurer sur un réseau. Ce nouveau RFC porte sur un problème un peu différent : une fois qu'on a ces métriques, comment publier les résultats ? Quels sont les pièges de la publication ? Parmi les paramètres de la mesure, que mettre en évidence ? Ce RFC est loin de traiter en détail toutes ces questions, il décrit surtout les conséquences de deux points de vue différents : celui de l'ingénieur réseaux, intéressé surtout par les performances de son réseau, et celui du programmeur, intéressé par les performances de son application.

Il y a bien sûr un lien entre les deux : si le réseau perd beaucoup de paquets, par exemple (RFC 7680 et RFC 6673), les applications auront de moins bonnes performances. Mais, dans certains cas, les deux points de vue ne s'intéressent pas exactement à la même chose. Voyons en quoi. (À noter aussi que ce RFC 6703 ne regarde que les analyses sur le relativement long terme, au moins plusieurs heures. Et il ne se penche pas sur le problème, bien plus difficile, de la publication vers M. Toutlemonde, par exemple pour lui communiquer la QoE.)

Toute présentation de mesures nécessite évidemment de connaître l'audience. On ne va pas communiquer de la même façon vers le management et vers les techniciens, par exemple. Et, même parmi les techniciens, il existe plusieurs catégories. Ce RFC s'intéresse à la différence entre « les gens du réseau » (qui pensent planification des investissements, dépannage, SLA, etc) et « les gens des applications » qui se demandent quel va être l'effet du réseau sur les applications. Les premiers mesurent des métriques comme le taux de pertes de paquets (RFC 7680) ou comme le délai d'acheminement (RFC 7679), avec l'idée de modifier le réseau (par des investissements ou bien des changements de la configuration), si les chiffres sont défavorables. Les seconds vont ajuster les applications pour s'adapter à ces résultats, qu'ils ne peuvent pas changer.

Les recommandations de notre RFC occupent la section 3. Lorsqu'on publie des mesures, on doit notamment :

  • Inclure au minimum le taux de pertes de paquets (RFC 7680) et le délai d'acheminement (RFC 7679). On notera que c'est ce que fait la commande ping, même si elle ne suit pas exactement les métriques IPPM. Notons aussi que la norme UIT Y.1540 donne une définition assez proche de celle de l'IETF.
  • Indiquer la moyenne et la médiane (ce que ping ne fait hélas pas). Les deux statistiques sont utiles (et les deux ont des limites, par exemple aucune des deux ne gère proprement les distributions bimodales).

C'est le minimum. Mais on peut l'enrichir, avec d'autres métriques comme la variation du délai d'acheminement (RFC 3393), le réordonnancement des paquets (RFC 4737), la capacité (RFC 3148 et RFC 5136, le premier RFC décrivant la capacité utile et le second celle mesurée au niveau IP). Et on peut ajouter d'autres statistiques, pour ne pas être bloqués par les limites de la moyenne et de la médiane. Par exemple, minimum, maximum, « 95 percentile ».

Bon, et les deux points de vue différents dont je parlais au début, que deviennent-ils ? La section 4 du RFC examine les différentes métriques selon ces deux points de vue. Par exemple, le taux de pertes du RFC 7680 a un paramètre important : le délai d'attente avant qu'on renonce à attendre un paquet. Le RFC 7680 ne donne pas de valeur quantitative. Intuitivement, on pourrait penser que des durées de l'ordre de la demi-seconde suffisent. Après tout, on n'a jamais vu ping signaler un délai plus long, non ? Mais ce n'est pas idéal. En cas de boucle de routage, par exemple, avant que l'IGP ne converge enfin, un délai de plusieurs secondes est possible (cf. « A Fine-Grained View of High Performance Networking » à NANOG 22 ou « Standardized Active Measurements on a Tier 1 IP Backbone » dans IEEE Communications Mag. de juin 2003). Un délai long est donc recommandé. En modélisant le pire cas dans le réseau, notre RFC arrive à une recommandation de 50 secondes, qui devrait couvrir tous les cas. Revenons maintenant aux deux point de vue. L'homme (ou la femme) du réseau veut déterminer le vrai taux de perte, en étant sûr que les paquets sont vraiment perdus et pas simplement très en retard. Mais la femme (ou l'homme) des applications n'a pas besoin de tels délais d'attente : l'application ne patientera jamais autant. Pour la plupart des applications, si ça n'arrive pas en quelques secondes, c'est comme si c'était perdu.

Faut-il alors faire deux mesures pour nos deux points de vue ? C'est une possibilité. Le RFC en suggère une autre : ne faire qu'une mesure, avec le délai long, mais noter le moment où le paquet arrive et calculer le taux de pertes avec deux délais différents, pour faire deux rapports.

Et le cas des paquets erronés (par exemple car ils ont une somme de contrôle invalide) ? Pour le RFC 7680, ils sont à compter comme perdus (si le paquet est erroné, on ne peut même pas être sûr qu'il était bien pour nous). C'est le point de vue des gens du réseau. Mais les gens des applications ne sont pas toujours d'accord. Certaines applications, notamment dans le domaine de l'audio et de la vidéo temps-réel préfèrent que l'application reçoive les paquets erronés, dont on peut parfois tirer quelque chose. Notre RFC suggère donc de publier deux résultats, un en comptant les paquets erronés comme perdus, l'autre en les acceptant.

Et la métrique « délai d'acheminement des paquets », en quoi les deux points de vue l'affectent (section 5) ? Notre RFC s'oppose surtout à l'idée de présenter les paquets qui, lors de la mesure, n'arrivent pas, avec une valeur artificielle comme un nombre très grand ou comme l'infini. Quel que soit le point de vue, l'infini n'est pas une valeur utile et il vaut donc mieux considérer que le délai, pour un paquet qui n'arrive pas, est « indéfini ».

Maintenant, la capacité (sections 6 et 7). Notre RFC 6703 introduit un nouveau vocabulaire, « capacité brute » (raw capacity) pour celle du RFC 5136 (qui n'intègre pas les effets de la retransmission des paquets perdus ou erronés) et « capacité restreinte » (restricted capacity) pour celle du RFC 3148, qui intègre les actions du protocole de transport (retransmettre les données manquantes, par exemple). La capacité restreinte est donc inférieure ou égale à la capacité brute, et elle est plus proche de ce qui intéresse les utilisateurs.

D'abord, un rappel, la capacité n'est définie que pour un Type-P donné, c'est-à-dire (RFC 2330) un type de paquets (protocole, port, etc). Ensuite, le RFC 5136 définit trois métriques pour la capacité brute : capacité IP maximum (ce que le système peut faire passer), utilisation (ce qui passe effectivement, et qu'on pourrait appeler « débit » mais le RFC évite ce terme, trop galvaudé), et enfin capacité disponible (certaines applications, par exemple, voudraient simplement savoir si la capacité disponible est suffisante - supérieure à une certaine valeur). Les trois métriques sont liées : en en connaissant deux, on peut calculer la troisième. L'utilisation (et donc la capacité disponible) peut varier rapidement sur un réseau réel. Notre RFC 6703 recommande donc de moyenner sur une longue période, par exemple une minute (en notant que cinq minutes est plus fréquent, en pratique, mais peut-être trop long). D'autre part, il suggère de publier plusieurs chiffres : miminum, maximum et un intervalle (par exemple, le pourcentage de temps pendant lequel la métrique vaut entre telle et telle valeur, comme « la capacité est de X Mb/s pendant au moins 95 % du temps »). Maximum et minimum peuvent aussi être publiés sous forme d'un seul chiffre, leur ratio : (max/min = 1) => grande stabilité, (max/min = 10) => forte variabilité, etc.

Pour la capacité restreinte, un autre problème se pose : elle est dépendante des algorithmes de contrôle de congestion. Par exemple, avec certaines mises en œuvre de TCP anciennes, la capacité restreinte (celle réellement accessible aux applications) pouvait être très inférieure à la capacité brute, par exemple parce que TCP réagissait mal en cas de perte de paquets et ralentissait trop son débit. Notre RFC introduit donc un nouveau concept, le « Type-C » qui est l'ensemble des algorithmes du protocole de transport et leurs paramètres (RFC 6349). Il est nécessaire de publier le Type-C utilisé, avec les résultats. (Un exemple, sur Linux, est la valeur du paramètre sysctl net.ipv4.tcp_congestion_control.)

Autre piège, le temps d'établissement de la connexion TCP. Si on mesure la capacité restreinte avec quelque chose comme (sur Unix) time wget $GROSFICHIER, le délai pour la triple poignée de mains qui commence toute connexion TCP peut sérieusement affecter le résultat. Même chose avec le « démarrage en douceur » que fait TCP avant d'atteindre l'équilibre. Il peut diminuer la capacité mesurée (d'un autre côté, l'ignorer serait irréaliste puisque les « vraies » connexions l'utilisent). Bref, toutes ces informations doivent être publiées avec le résultat de la mesure.

Enfin (section 8), deux détails qui peuvent avoir leur importance : la distribution des paquets lors d'une mesure active (Poisson ? Périodique, ce que fait ping ?). Et la taille de l'échantillon (par exemple le nombre de paquets envoyés.) Ces détails doivent également être publiés.


Téléchargez le RFC 6703


L'article seul

RFC 6702: Promoting Compliance with Intellectual Property Rights (IPR) Disclosure Rules

Date de publication du RFC : Août 2012
Auteur(s) du RFC : T. Polk (National Institute of Standards and Technology), P. Saint-Andre (Cisco)
Pour information
Première rédaction de cet article le 21 août 2012


Les règles de l'IETF concernant la publication des brevets sur les techniques en cours de normalisation ont déjà été violées plusieurs fois, par exemple par RIM. Deux RFC viennent donc d'être publiés pour traiter ce problème : un répressif, le RFC 6701, qui dresse la liste des sanctions possibles contre les tricheurs. Et un préventif, ce RFC 6702, qui expose tous les mécanismes à mettre en œuvre pour encourager tout le monde à respecter les règles. Pour le résumer : la principale (voire unique) méthode envisagée est de rappeler les règles au bon moment, de façon à augmenter les chances qu'elles soient lues.

Que disent ces règles, au juste ? Formulées dans le RFC 8179 et répétées en ligne, elles imposent, en substance, qu'un participant à l'IETF qui connait des revendications de propriété intellectuelle (typiquement des brevets) sur une technique en cours de normalisation doit en informer l'IETF (cela se fait en ligne), qui publiera alors ces revendications. C'est tout. L'IETF n'impose que cette transparence, qui permet ensuite aux groupes de travail de prendre des décisions en toute connaissance de cause (RFC 2026, section 10.4). Le but est d'éviter les brevets sous-marins, où une entreprise fait normaliser une technologie sur laquelle elle a des brevets, qu'elle ne révèle qu'après la publication de la norme, lorsqu'il est trop tard pour chercher une alternative. Pas étonnant que cette obligation de divulgation déplaise aux maneuvriers de l'appropriation intellectuelle. Au moins deux tricheries ont été détectées, une de RIM et l'autre de Huawei (dans le RFC 6468). La seconde a été la goutte d'eau qui a fait déborder le buffer et mené à ces deux RFC qui essaient de redresser la barre. Ils ne définissent pas de nouvelles règles : les anciennes s'appliquent comme avant, ces deux nouveaux RFC disent juste comment le faire.

À noter que, comme l'ont montré l'analyse de ces deux cas, il s'agissait de tricheries délibérées. Mais il y a aussi eu des cas où la négligence ou l'ignorance ont fait que les brevets n'étaient pas annoncés à l'IETF, ou bien l'étaient en retard. Ces deux RFC vont aussi servir pour le cas où la violation des règles s'est faite de bonne foi. Car, même commis de bonne foi, ce manque de divulgation d'un brevet peut avoir des conséquences fâcheuses : un groupe de travail qui ne connaissait pas un brevet risque de négliger une piste alternative, non plombée par des brevets.

En pratique, les méthodes suggérées dans ce RFC concernent surtout les personnes ayant un rôle dirigeant à l'IETF (RFC 2418 et RFC 3669) : président de groupe de travail, directeur de zone (ceux qui forment l'IESG), etc. Ce sont ces personnes qui ont la responsabilité de faire avancer proprement le processus.

La section 3 du RFC décrit les stratégies disponibles. Il s'agit essentiellement de mieux informer les participants à l'IETF pour éviter toute inattention... ou toute fausse excuse. S'appuyant sur les conseils du RFC 3669, les responsables peuvent :

  • Rappeler les règles lorsqu'un Internet-Draft va être présenté à une réunion (le président d'un groupe de travail peut refuser la discussion si le présentateur ne confirme pas que les divulgations nécessaires n'ont pas été faites),
  • Rappeler les règles au moment où un Internet-Draft va être adopté par un groupe de travail,
  • Rappeler les règles avant de lancer des demandes solennelles comme le Working Group Last Call (le dernier tour de table avant qu'un Internet-Draft ne soit transmis par le groupe de travail à l'IESG) ou l'IETF Last Call (les outils qui génèrent le message envoyé à la liste ietf-announce@ietf.org incluent automatiquement un URL vers les divulgations de brevet pertinentes pour ce document),
  • Au moment où le document est transmis à un Directeur de Zone, pour examen, le texte standard inclus une question sur les divulgations de brevet.

L'idée est qu'on a plus de chance de capter l'attention des distraits si on envoie le rappel au moment où les auteurs travaillent activement sur le document, pour lui faire franchir une étape. Quant aux gens de mauvaise foi, ils auront moins de possibilités de faire croire à une erreur (« je n'avais pas vu le rappel »). Voici un exemple d'un appel à un IETF Last Call (pour le document « TCP Extensions for Multipath Operation with Multiple Addresses ») :

Date: Wed, 01 Aug 2012 09:43:18 -0700
From: The IESG <iesg-secretary@ietf.org>
To: IETF-Announce <ietf-announce@ietf.org>
Subject: Last Call: ...
...
The IESG plans to make a decision in the next few weeks, and solicits
final comments on this action.
...
The following IPR Declarations may be related to this I-D:

   http://datatracker.ietf.org/ipr/1842/
   http://datatracker.ietf.org/ipr/1843/

La même chose s'applique aux soumissions individuelles (section 4).

Un petit piège : les règles de divulgation précisent que la divulgation doit être tenue à jour. Par exemple, si un brevet qui avait simplement été déposé est accepté, le texte de la divulgation doit être modifié (section 6). Ne pas mettre à jour une divulgation est aussi sérieux que de ne pas en faire.

Si jamais vous accédez à des responsabilités à l'IETF et que vous avez à procéder vous-même à ces rappels, vous pourrez être aidé par l'annexe A de ce RFC, qui contient des messages-types qu'il n'y a qu'à copier-coller.


Téléchargez le RFC 6702


L'article seul

RFC 6701: Sanctions Available for Application to Violators of IETF IPR Policy

Date de publication du RFC : Août 2012
Auteur(s) du RFC : A. Farrel (Juniper Networks), P. Resnick (Qualcomm)
Pour information
Première rédaction de cet article le 21 août 2012


Comme toutes les organisations de normalisation, l'IETF a élaboré une série de règles pour gérer le difficile problème de l'appropriation intellectuelle et surtout des brevets. Ces règles existent depuis des années mais ce n'est que récemment, suite à deux affaires spectaculaires, que l'IETF a pris conscience du fait que la question des sanctions, en cas de violation de ces règles, n'avait jamais été sérieusement discutée. Ce RFC corrige ce manque et fait la liste des réactions possibles de l'IETF en cas de violation des règles. Disons-le tout de suite, il n'y en a pas de très dissuasives : l'IETF n'a pas le pouvoir de couper des têtes ou de condamner au bûcher. Un autre RFC, le RFC 6702, discute de l'aspect positif, comment encourager le respect des règles.

Que disent ces règles actuellement ? Documentées dans le RFC 8179, résumées sur le site Web et par l'IESG, et fréquemment rappelées pendant les réunions physiques et sur les listes de diffusion, par les fameux « Note Well », ces règles reposent sur deux piliers :

  • L'IETF peut normaliser des techniques brevetées,
  • Mais encore faut-il le savoir : pour cela, tout participant à l'IETF qui a connaissance, dans le cadre de son activité professionnelle, d'un brevet sur une technique en cours de normalisation doit en avertir l'IETF.

Le but est d'éviter les brevets sous-marins, par lesquels une entreprise pousse à la normalisation d'une technique, pour laquelle elle dispose de brevets, en dissimulant ces brevets pour qu'ils n'effrayent pas les normalisateurs.

La section 2 décrit plus en détail cette politique de l'IETF. D'abord, elle ne s'applique qu'aux contributeurs à l'IETF. Quelqu'un qui n'écrirait aucun document, ne prendrait jamais la parole aux réunions et ne s'exprimerait pas sur les listes de diffusion n'aurait pas à la respecter. C'est d'ailleurs la seule solution pour un employé que sa compagnie n'autorise pas à divulguer l'existence d'un brevet : se retirer du processus IETF (« Aime-la ou quitte-la »).

Cette politique est ensuite souvent rappelée aux participants, par exemple lorsqu'on s'inscrit à une liste de diffusion IETF, on est redirigé vers la page Web d'avertissement (Note Well).

Pour signaler un brevet portant sur une technologie en cours d'examen à l'IETF, cela se fait via un formulaire Web. Les déclarations sont elles-mêmes publiées sur le Web.

Que fait ensuite le groupe de travail IETF de ces déclarations ? L'IETF n'impose pas une politique unique à ses groupes de travail à ce sujet. Le groupe peut décider d'ignorer le brevet (n'oubliez pas que la grande majorité des brevets logiciels sont futiles : technologies évidentes, communes longtemps avant le brevet, etc). Il peut aussi décider de changer la technique en cours de normalisation pour contourner le brevet (et c'est la crainte de ce résultat qui motive certaines entreprises à garder leurs brevets secrets).

Naturellement, il y a des tricheurs. C'est ainsi que RIM ou Huawei (dans le RFC 6468) avaient caché leurs brevets. C'est à cause de ces tricheurs qu'il faut prévoir la possibilité de sanctions, dont la gravité doit être adapté à chaque cas.

Qui va décider de l'action à entreprendre contre les tricheurs (section 3) ? Les chefs du groupe de travail concernés, puisque ce sont eux qui connaissent le mieux tous les détails et, s'ils ne le peuvent pas, le directeur de zone (Area Director) responsable du groupe de travail.

La section 4 liste les sanctions elles-mêmes. Aucune n'est très effrayante, l'IETF n'ayant pas de pouvoirs particuliers. À noter que la liste présentée ici n'est pas exhaustive, d'autres sanctions pourront être imaginées dans le futur. Donc, en gros, par ordre de sévérité croissante, quelques-uns de ces sanctions :

  • Discussion en privé avec le participant,
  • Avertissement en privé,
  • Avertissement public avec les noms (politique nommée en anglais name and shame),
  • Refus d'accepter le tricheur comme auteur d'un document du groupe de travail (ce sont en effet les présidents du groupe de travail qui décident des auteurs), ou exclusion des documents qu'ils éditent actuellement (le droit d'auteur oblige à les mentionner dans la section Acknowledgments, même dans ce cas, il n'est pas possible de reproduire la condamnation d'Érostrate),
  • Rejet complet du document et donc de la technique qu'il normalise,
  • Ajout temporaire ou définitif du tricheur sur la liste noire des gens non autorisés à écrire sur la liste de diffusion du groupe de travail (RFC 3683, ce que le jargon IETF nomme une PR Action pour Posting Rights Action), la section 4.1 décrivant en détail pourquoi cette sanction est acceptable dans ce cas.

Comme toute les décisions à l'IETF, elles sont susceptibles d'appel devant l'IESG (section 5 et la section 6.5 du RFC 2026).

À noter que l'annexe A contient des indications pour ceux qui auront à choisir et appliquer les sanctions. Rien ne sera automatique et les décideurs devront faire preuve de jugement. Parmi les points qu'ils devront examiner avant de décider figurent l'ancienneté de la personne en cause dans l'IETF, le moment exact où le brevet a été révélé, la place de l'individu dans le travail en question (contributeur occasionnel ou principal ?), qualité des excuses présentées, etc.


Téléchargez le RFC 6701


L'article seul

RFC 6698: The DNS-Based Authentication of Named Entities (DANE) Transport Layer Security (TLS) Protocol: TLSA

Date de publication du RFC : Août 2012
Auteur(s) du RFC : P. Hoffman (VPN Consortium), J. Schlyter (Kirei AB)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dane
Première rédaction de cet article le 19 août 2012


À chaque seconde, d'innombrables transactions sur l'Internet sont protégées contre l'écoute et la modification malveillante par le protocole TLS. Ce dernier est capable de chiffrer la session (pour la protéger contre l'écoute par un tiers) et d'authentifier le pair avec qui on parle (pour s'assurer qu'on n'est pas en train de communiquer avec un usurpateur). Comment TLS authentifie t-il ? La méthode la plus courante aujourd'hui est de se servir de certificats X.509 vérifiés (en théorie) par une Autorité de Certification. Ce mécanisme repose sur une confiance aveugle dans de très nombreuses organisations, et a de nombreuses faiblesses, comme on l'a vu en 2011 où le piratage de plusieurs AC a permis à des attaquants d'obtenir de « vrais-faux » certificats, y compris pour des organisations qui n'étaient pas clientes des AC piratées. La démonstration étant ainsi faite que X.509 n'était pas digne de la confiance que certains lui accordent, il restait à concevoir une meilleure solution. Rendue possible par le déploiement de DNSSEC, voici DANE (DNS-based Authentication of Named Entities) et ses enregistrements DNS TLSA. DANE permet à chacun de publier de manière sécurisés ses certificats, bouchant ainsi les vulnérabilités de X.509, ou permettant même de s'en passer complètement.

Avant de décrire DANE, il faut comprendre le fonctionnement de X.509, afin de voir pourquoi il ne garantit pas grand'chose en matière de sécurité. (La section 1 du RFC contient une description plus détaillée.) Un client qui se connecte à un serveur et qui craint, souvent à juste titre, que la session soit écoutée, voire modifiée par un attaquant situé sur le chemin, va utiliser le protocole TLS, normalisé dans le RFC 5246 pour chiffrer la session. (TLS est utilisé dans de nombreuses applications, la plus connue étant le HTTPS du RFC 2818, celui du petit cadenas dans le navigateur Web.) Ce chiffrement le protège contre l'écoute passive. Mais d'autres risques se cachent derrière. Si le client croit parler à une machine alors qu'en fait, par le biais de piratages portant sur DNS, BGP ou un autre protocole, il parle à la machine de l'attaquant, le chiffrement seul ne le protégera pas. Pour cette raison, TLS ajoute l'idée d'authentification. Le client peut vérifier que le serveur est bien ce qu'il prétend être (l'inverse, l'authentification du client par le serveur, existe aussi mais est plus rare).

Aujourd'hui, cette authentification se fait essentiellement via X.509 (il existe d'autres voies, très marginales, comme celle du RFC 6091). Le principe de X.509 est le suivant. La clé publique du serveur TLS est contenue dans un certificat, contenant le nom du serveur, et signé par une autorité reconnue. En vérifiant la signature, le client TLS peut s'assurer qu'il parle bien à la machine souhaitée (on dit que TLS associe un nom à une clé). Si un navigateur Web se connecte à https://www.dns-oarc.net/, il doit recevoir un certificat signé et comportant le nom www.dns-oarc.net (la question du nom à indiquer est très compliquée dans X.509, voir le RFC 6125). Notez qu'en fait, TLS utilise un sous-ensemble de X.509, spécifié dans le RFC 5280 mais ce n'est pas essentiel pour cette analyse.

Mais quelles sont les « autorités reconnues » ? La plupart du temps, elles ont été choisies et configurées par l'éditeur du logiciel utilisé. Si vous être adepte de Firefox, c'est la fondation Mozilla qui a décidé que les centaines d'autorités de certification (AC) que connait ce logiciel sont dignes de confiance.

Tout repose donc sur l'AC. Si une AC est malhonnête, ou bien a été piratée, elle peut émettre des vrais-faux certificats, qui tromperont l'utilisateur. Cette dépendance vis-à-vis d'un tiers est traditionnellement une des faiblesses les plus critiquées de X.509, d'autant plus que les dites AC, pressées par des considérations économiques, ne font pas toujours de gros efforts pour vérifier les titulaires de certificats.

Mais il y a pire. Rappelez-vous qu'il suffit à un certificat de comporter la signature d'une AC pour être accepté. Il n'y a pas de limites aux noms pour lesquelles les AC peuvent s'engager. Si l'AC DigiNotar est reconnue comme AC de confiance par un client TLS, elle peut signer des certificats pour n'importe quel nom, même si le nom est géré par une organisation qui a choisi une autre AC. C'est le problème le plus fondamental de X.509. Ce système, conçu par l'UIT, supposait que le monde se divisait en deux, une masse de clients payants et une oligarchie d'AC toutes parfaites. Ce modèle a éclaté devant la réalité des choses : les AC ne sont pas toutes parfaites. L'année 2011 a montré que cette vulnérabilité, connue depuis longtemps, n'était pas purement théorique. Le détournement de l'AC Comodo, puis le piratage de DigiNotar, au cours de l'opération Tulipe Noire, ont montré que les AC, non seulement étaient vulnérables mais que, en outre, les vrais-faux certificats marchaient bien. C'est ainsi que le gouvernement iranien a pu, suite à Tulipe Noire, obtenir de vrais-faux certificats pour Gmail (alors que Google n'était pas client de DigiNotar), lui permettant d'observer le trafic de ses citoyens.

Bon, tout cela est bien triste, mais comment DANE empêche t-il cela ? Le principe est, plutôt que d'introduire un nouvel acteur, de réutiliser une infrastructure existante, le DNS avec des identificateurs existants, les noms de domaine. Le certificat est publié dans le DNS et signé avec DNSSEC (je schématise : lisez plus loin pour une description complète) et le client TLS peut alors le vérifier. Bien sûr, le piratage d'un registre DNS (ou d'autres acteurs) permettra de court-circuiter cette protection mais l'énorme avantage de cette technique est qu'on n'a pas besoin de faire confiance à toute la planète, seulement aux fournisseurs qu'on a choisi (et desquels on dépendait déjà). Ainsi, si on décide de fonder son identité en ligne sur un .com, on dépend de la sécurité de VeriSign mais seulement de celle-ci. En cas de piratage ou de malhonnêteté de VeriSign, seuls les .com seront affectés, les gens qui ont un .fr (par exemple) ne seront pas touchés.

Cette idée avait été documentée dans le RFC 6394, premier RFC du groupe de travail DANE, créé à la fois en raison des faiblesses manifestes de X.509, et parce que le déploiement de DNSSEC rendait réaliste une solution alternative. Le protocole DANE réalise le cahier des charges du RFC 6394 et crée pour cela un nouveau type d'enregistrement DNS, TLSA (ne cherchez pas une signification à ce sigle, il n'en a officiellement pas). Tel qu'actuellement normalisé, DANE couvre les besoins de HTTPS mais, pour des protocoles avec une indirection dans le DNS (comme les MX du RFC 5321 ou les SRV du RFC 6120), c'est plus compliqué et il faudra attendre de futurs RFC pour adapter les TLSA à ces cas.

Notez que d'autres protocoles peuvent aussi mettre leurs clés dans le DNS comme SSH avec le RFC 4255 et IPsec avec le RFC 4025.

À noter que notre RFC demande que les enregistrements DANE/TLSA soient protégés par DNSSEC mais ne précise pas comment le client le vérifie. Il existe plusieurs façons de déployer DNSSEC et notre RFC préfère ne pas trancher prématurément.

Bien, maintenant, place à DANE lui-même. Le cœur de ce protocole est le nouveau type d'enregistrement DNS TLSA, présenté en section 2. Il a le type 52 dans le registre IANA (cf. section 7).

Un enregistrement TLSA comprend :

  • un champ « Utilisation du certificat » (Certificate usage),
  • un champ « Sélecteur » (Selector),
  • un champ « Méthode de correspondance » (Matching type),
  • un champ « Données » (Data).

Le premier, « Utilisation du certificat », voit ses valeurs possibles enregistrées dans un nouveau registre IANA (voir aussi la section 7). On pourra ainsi ajouter de nouvelles utilisations sans modifier ce RFC. Pour l'instant, sont définies les valeurs numériques :

  • 0 : l'enregistrement TLSA est alors utilisé comme « contrainte sur l'AC ». Il spécifie un certificat qui doit être présent dans la chaîne des certificats utilisés pour la validation X.509. Il vient donc en complément de X.509. Son rôle est de lutter contre des attaques par une AC qui n'est pas celle choisie. Si on est client de GeoTrust, on peut mettre le certificat de l'AC GeoTrust dans l'enregistrement TLSA et, ainsi, un vrai/faux certificat émis par Comodo ou DigiNotar sera refusé. L'utilisation 0 est la plus traditionnelle, sans remplacer X.509 et bouchant simplement sa principale vulnérabilité. Attention si vous changez d'AC, il faudra quand même penser à mettre à jour vos enregistrements TLSA.
  • 1 : l'enregistrement TLSA indique le certificat du serveur TLS (qui devra toujours, comme dans l'utilisation 0, être validé selon les règles du RFC 5280). Il s'agit d'une « contrainte sur le certificat » et plus seulement sur l'AC. Il permet donc de se protéger contre une attaque par sa propre AC. Si elle décide d'émettre un nouveau certificat sans vous prévenir, il ne sera pas accepté. Attention en pratique, on change de certificats plus souvent que d'AC et il ne faut pas oublier de mettre à jour le TLSA.
  • 2 : cette fois, on quitte les rivages de X.509. Un certificat ainsi publié n'a plus besoin de passer la validation X.509 ou, plus exactement, la validation ne se fait que via l'AC qui détient ce certificat. Il s'agit donc de déclarer dans le DNS une nouvelle AC, en ignorant les AC pré-définies du client TLS. Un exemple typique est le cas d'une organisation qui est sa propre AC et émet ses propres certificats. Elle peut ainsi les voir acceptés automatiquement, sans payer une AC extérieure dont la fiabilité est douteuse.
  • 3 : comme l'utilisation 2, on se passe de l'infrastructure des AC traditionnelles, et on déclare dans le DNS, non pas une AC à soi comme dans l'utilisation 2, mais un certificat. C'est l'équivalent des certificats auto-signés mais avec cette fois une preuve de validité, offerte par DNSSEC.

Depuis le RFC 7218, il y a également des mnémoniques standards pour ces valeurs, ainsi que celles des deux champs suivants.

Le sélecteur, quant à lui, fait également l'objet d'un registre IANA. Actuellement, il compte deux valeurs numériques. D'autres pourront être ajoutées, sous la seule obligation d'une spécification écrite et stable :

  • 0 : l'enregistrement TLSA contient (dans son champ « Données ») le certificat complet.
  • 1 : l'enregistrement TLSA ne contient que la clé publique, omettant le reste du certificat.

Et la méthode de correspondance ? Voici un nouveau registre IANA, et ses valeurs :

  • 0 : la valeur dans le champ « Données » de l'enregistrement TLSA est la valeur exacte, à comparer bit à bit avec celle récupérée dans la session TLS.
  • 1 : la valeur dans le champ « Données » de l'enregistrement TLSA est le condensat SHA-256 de celle récupérée dans la session TLS.
  • 2 : idem, avec SHA-512.

Enfin, le champ de données contient, selon la valeur des autres champs, le certificat ou la clé publique, éventuellement condensées.

Voici des exemples d'enregistrement TLSA au format de présentation standard :


; Utilisation 0 (contrainte sur l'AC)
; Les données sont le condensat du certificat
_443._tcp.www.example.com. IN TLSA (
      0 0 1 d2abde240d7cd3ee6b4b28c54df034b9
            7983a1d16e8a410e4561cb106618e971 )

; Utilisation 1 (contrainte sur le certificat)
; Les données sont le condensat de la clé publique
_443._tcp.www.example.com. IN TLSA (
      1 1 2 92003ba34942dc74152e2f2c408d29ec
            a5a520e7f2e06bb944f4dca346baf63c
            1b177615d466f6c4b71c216a50292bd5
            8c9ebdd2f74e38fe51ffd48c43326cbc )

; Utilisation 3 (déclaration d'un certificat local)
; Le certificat entier (abrégé ici) est dans les données
_443._tcp.www.example.com. IN TLSA (
      3 0 0 30820307308201efa003020102020... )

Mais quel est ce nom bizarre dans les enregistrements, _443._tcp.www.example.com ? Décrit en section 3, le nom de domaine des enregistrements TLSA est la concaténation du numéro de port d'écoute du serveur TLS, du protocole (TCP, SCTP, etc) et du nom du serveur TLS. Ici, les enregistrements TLSA concernaient un serveur TLS www.example.com écoutant en TCP sur le port 443, donc, sans doute du HTTPS. Avec du SMTP sur TLS, ce serait sans doute _25._tcp.mail.example.com.

À noter que cette convention de nommage est générique (pour tous les protocoles) mais qu'il est prévu que, dans le futur, d'autres conventions soient adoptées, par exemple pour des protocoles où la relation entre service et serveur est plus complexe que dans le cas d'HTTP.

Une fois ces enregistrements publiés, comment le client TLS les utilise-t-il ? La section 4 décrit les règles à suivre. D'abord, le client TLS doit demander les enregistrements TLSA et vérifier s'ils sont utilisables :

  • s'ils sont signés avec DNSSEC et valides, c'est bon,
  • même signés correctement, si les enregistrements TLSA contiennent une utilisation, un sélecteur ou une méthode de correspondances inconnues, ils doivent être ignorés,
  • s'ils ne sont pas signés, ils doivent être ignorés (on ne peut pas leur faire confiance), on se rabat sur du TLS classique. Même chose si aucun des enregistrements TLSA n'est utilisable,
  • s'ils sont signés et invalides, cela signifie qu'un gros problème est en cours, peut-être une tentative d'empoisonnement DNS. Le client TLS doit alors avorter sa connexion.

Le but de ces règles est de s'assurer qu'un attaquant ne peut pas effectuer une attaque par repli, où il convaincrait le client qu'il n'y a pas d'enregistrements TLSA (RFC 6394, section 4). DNSSEC empêchera ce repli et DANE coupera alors la connexion TLS.

Pour les gens qui préfèrent le pseudo-code, les mêmes règles sont disponibles sous cette forme dans l'annexe B. Attention, c'est le texte de la section 4 qui est normatif, le pseudo-code n'étant là qu'à titre d'illustration. Par exemple, comme tous les pseudo-codes procéduraux, il « sur-spécifie » en indiquant un ordre d'évaluation qui n'est pas obligatoire.

Si le client TLS fait la validation DNSSEC lui-même (comme le permettent des bibliothèques comme libunbound), rien de spécial à dire. Mais s'il confie la validation à un résolveur externe (et se contente de tester que le bit adAuthentic Data - est bien mis à un dans la réponse), il doit s'assurer que le chemin avec ce résolveur est sûr : résolveur sur localhost, ou bien communication avec le résolveur sécurisée par TSIG (RFC 8945) ou IPsec (RFC 6071). C'est le problème dit de « la sécurité du dernier kilomètre ».

Comme vous voyez, le principe est très simple. Mais, comme souvent en sécurité, il y a plein de détails pièges derrière. La section 8 se consacre à l'examen de ces pièges. D'abord, DANE dépend de DNSSEC (RFC 4033). Si on n'a pas de DNSSEC, ou s'il est mal géré, tout s'écroule. Pas question d'envisager de déployer DANE avant d'avoir une configuration DNSSEC solide. (Au début du groupe de travail DANE à l'IETF, il était prévu que DNSSEC soit facultatif pour des utilisations comme 0 et 1, où DANE ne vient qu'en addition de X.509. Techniquement, ça se tenait mais cela compliquait l'analyse de sécurité, et les messages à faire passer. Donc, désormais, DNSSEC est obligatoire et on ne discute pas !)

DANE dépendant du DNS, cela veut dire qu'un administrateur DNS qui devient fou ou méchant peut changer les A, AAAA et TLSA d'un serveur et sans que cela soit détecté. Beaucoup d'AC émettant des certificats juste après avoir vérifié un échange de courrier, cela ne change donc pas grand'chose par rapport à X.509.

Par contre, si jamais le mécanisme de sécurité pour changer les TLSA était plus faible que celui pour changer les A et AAAA, alors, là, il y aurait un problème. La solution est simple : tous les enregistrements DNS doivent avoir le même niveau de sécurité.

Les enregistrements TLSA d'utilisation 0 et 1 viennent en supplément de X.509. Leur analyse de sécurité est donc relativement simple, ils ne peuvent pas affaiblir la sécurité qui existe. En revanche, ceux d'utilisation 2 et 3 sont nouveaux : ils peuvent permettre des choses qui n'existaient pas en X.509. Il faut donc bien réfléchir à l'AC qu'on indique par un certificat d'utilisation 2. En mettant son certificat dans un enregistrement TLSA, on lui donne tous les droits.

Comment fait-on une révocation avec DANE ? Les TTL normaux du DNS s'appliquent mais, si un méchant fait de l'empoisonnement DNS, il pourra réinjecter de vieux enregistrements. La seule protection est donc la durée de validité des signatures DNSSEC : trop courte, elle peut entraîner des risques pour la résilience de la zone (signatures expirées alors qu'on n'a pas eu le temps de les refaire), trop longue, elle permet à un méchant de continuer à utiliser un certificat normalement révoqué (attaque par rejeu, voir l'article de Florian Maury).

Au fait, petit piège avec les TTL : si tous les serveurs résolveurs gèrent les TTL proprement, il est courant que le résultat d'une requête DNS soit gardé dans l'application sans tenir compte de ces TTL, ce qui peut être gênant pour des applications qui restent ouvertes longtemps (comme un navigateur Web). Un client DANE doit donc veiller à toujours obtenir ses données d'un résolveur (ou à gérer les TTL lui-même) pour ne pas risquer de se servir de vieilles données (section 8.2).

La section 8.1 compare DANE aux AC classiques. Un registre de noms de domaines qui fait du DNSSEC a des responsabilités qui ressemblent assez à celles d'une AC : distribuer la clé publique (qui doit être toujours disponible) de manière authentifiée, garder la clé privée vraiment secrète (par exemple dans des HSM), avoir des plans prêts d'avance pour le cas d'une compromission de la clé, etc. D'abord, une évidence : les acteurs de l'industrie des noms de domaine (registres, registrars, hébergeurs DNS) ne sont pas meilleurs (ou pires) que les AC X.509. Comme elles, ils peuvent être incompétents ou malhonnêtes ou se faire pirater. On peut même penser que certains de ces acteurs ont une culture sécurité faible ou inexistante, très inférieure à celle de la pire AC. Mais la force de DANE ne vient pas de ce que les acteurs du DNS seraient magiquement meilleurs que ceux de X.509. Elle vient du fait qu'on choisit ses fournisseurs. Avec X.509, c'est la sécurité de la plus mauvaise AC qui compte puisque n'importe quelle AC peut émettre des certificats pour n'importe qui (la faille énorme de X.509). Avec DANE+DNSSEC, on revient à un modèle plus sérieux en matière de sécurité : il faut faire confiance à ses fournisseurs, certes, mais au moins on les choisit. Un déploiement correct de DANE implique donc une évaluation des acteurs qu'on a choisi. Si on a un .com, on dépend de la sécurité et de l'honnêteté de VeriSign. En revanche, un piratage du registre de .lu n'aura pas de conséquence. Si on choisit à la place un .lu, on dépend de la sécurité et de l'honnêteté de Restena mais plus de celle de VeriSign. Et ainsi de suite. (Tout ceci est également vrai pour les autres techniques de pubication de clés dans le DNS comme celles du RFC 4255.)

Le DNS étant hiérarchique, il faut ajouter à ses fournisseurs directement choisis, les registres situés « au dessus ». Ainsi, une compromission de la clé privée de la racine affecterait tous les domaines (avec X.509, c'est la compromission de n'importe laquelle des centaines d'AC qui aurait ce résultat), ce qui justifie les mesures coûteuses adoptées pour gérer la clé de la racine (meilleures que celles de la plupart des AC X.509).

Comme indiqué plus haut à propos de la sécurité du dernier kilomètre, un problème classique avec DNSSEC est le lien entre l'application cliente et le résolveur validant. Le RFC recommande (section 8.3), pour une sécurité correcte, que le résolveur soit sur la même machine (c'est très facile avec des logiciels comme dnssec-trigger). Aujourd'hui où le moindre téléphone sait jouer des films en haute résolution, le temps de calcul lié à la validation cryptographique n'est plus forcément un obstacle. La section A.3 revient en détail sur ce problème du dernier kilomètre.

Les gens qui aiment les problèmes opérationnels liront avec plaisir l'annexe A, qui rassemble plein de bons conseils sur le déploiement de DANE.

Maintenant, voyons les mises en œuvre existantes de DANE/TLSA. Il faut bien voir que ce mécanisme est encore récent. On ne trouve que peu d'enregistrements TLSA dans la nature, et aucun navigateur Web connu ne gère encore le TLSA standard (DANE ne nécessite par contre aucune modification du serveur Web, uniquement du client Web, et des serveurs DNS). Néanmoins, il existe plusieurs outils.

D'abord, côté DNS. BIND et NSD peuvent tous les deux être serveur maître pour une zone qui contient des enregistrements TLSA (nsd connait DANE/TLSA à partir de la version 3.2.11). Pour un serveur esclave, pas de problème, TLSA est juste un type d'enregistrement inconnu, que le serveur peut servir sans le comprendre. Pour valider ses zones DNS, l'excellent outil validns lit et vérifie le TLSA depuis juillet 2012.

D'accord, mais un être humain normal ne va pas fabriquer les enregistrements TLSA à la main. Et, même s'il le faisait, il serait souhaitable de vérifier leur cohérence avec le certificat présenté par le serveur HTTP. C'est le rôle de l'outil Swede. Il permet, par exemple, de créer l'enregistrement TLSA à partir du certificat actuellement distribué par le serveur HTTPS :

% ./swede create www.afnic.fr  
No certificate specified on the commandline, attempting to retrieve it from the server www.afnic.fr.
Attempting to get certificate from 192.134.4.20
Got a certificate with Subject: /1.3.6.1.4.1.311.60.2.1.3=FR/1.3.6.1.4.1.311.60.2.1.2=Ile de France/1.3.6.1.4.1.311.60.2.1.1=MONTIGNY LE BRETONNEUX/businessCategory=Non-Commercial Entity/serialNumber=0002 414757567/C=FR/ST=Ile de France/postalCode=78180/L=Montigny Le Bretonneux/OU=AFNIC/O=AFNIC/CN=www.afnic.fr
_443._tcp.www.afnic.fr. IN TYPE52 \# 35 010001ed8a70a9c8783777e463232ef343aa32f2bbd6aa0182e6a0fc929b64c8e06518
Attempting to get certificate from 2001:67c:2218:2::4:20
Got a certificate with Subject: /1.3.6.1.4.1.311.60.2.1.3=FR/1.3.6.1.4.1.311.60.2.1.2=Ile de France/1.3.6.1.4.1.311.60.2.1.1=MONTIGNY LE BRETONNEUX/businessCategory=Non-Commercial Entity/serialNumber=0002 414757567/C=FR/ST=Ile de France/postalCode=78180/L=Montigny Le Bretonneux/OU=AFNIC/O=AFNIC/CN=www.afnic.fr
_443._tcp.www.afnic.fr. IN TYPE52 \# 35 010001ed8a70a9c8783777e463232ef343aa32f2bbd6aa0182e6a0fc929b64c8e06518

[Le certificat est le même, qu'on accède au serveur en IPv4 ou en IPv6 mais Swede ne le sait pas à l'avance, d'où les deux connexions.] Notez aussi que Swede formatte l'enregistrement DNS comme un type inconnu, ce qui permet de le charger dans n'importe quel serveur. Il ne reste donc qu'à mettre le _443._tcp.www.afnic.fr. IN TYPE52 \# 35 010001ed8a70a9c8783777e463232ef343aa32f2bbd6aa0182e6a0fc929b64c8e06518 dans son fichier de zone.

Swede permet également de vérifier un enregistrement TLSA existant.

Maintenant, côté « divers », la bibliothèque NSS a un patch pour faire du TLSA mais il semble ancien en non maintenu : https://mattmccutchen.net/cryptid/#nss-dane.

L'outil sshfp, en dépit de son nom, fait aussi du TLSA. Il devrait être remplacé par hash-slinger.

Quelques petits trucs utiles, maintenant. Pour créer une clé à partir d'un certificat (afin d'utiliser le sélecteur 1), en Python, avec M2Crypto :

from M2Crypto import X509
cert = X509.load_cert('/path/to/cert')
print cert.get_pubkey().as_der()
print cert.get_pubkey().as_text()

Avec OpenSSL, pour un sélecteur 1 (uniquement la clé) openssl x509 -pubkey -in ... | openssl rsa -pubin | head -n -1 | tail -n +2 | base64 -d doit marcher (ajouter sha512sum - à la fin du tube pour condenser, méthode de correspondance 2). Pour l'extraire d'un serveur TLS existant :

% openssl s_client -showcerts -connect mattmccutchen.net:443 < /dev/null 2> /dev/null | \
        openssl x509 -pubkey | openssl rsa -pubin | \                          
        head -n -1 | tail -n +2 | base64 -d | sha256sum -
writing RSA key
62d5414cd1cc657e3d30ea5e6d0136e92306e725413c616a51cab4b852c70a1c  -

On trouve aujourd'hui des enregistrements TLSA dans de nombreux domaines. Voici quelques exemples avec le dig de BIND 9.9.1-P2 (sorti en juillet 2012). Notez le bit ad mais rappelez-vous qu'on ne peut s'y fier que si le résolveur est honnête et que la liaison avec le résolveur est protégée (même machine, ou bien TSIG, IPsec, tunnel TLS ou méthode équivalente) :

% dig TLSA _443._tcp.dane.rd.nic.fr
...
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 3, ADDITIONAL: 5
...
;; ANSWER SECTION:
_443._tcp.dane.rd.nic.fr. 1     IN      TLSA    3 0 1 63C43B664AB2EC24E5F65BF6671EE1BE48E6F12660FEEF9D7BB1EDA7 7499EDC0
_443._tcp.dane.rd.nic.fr. 1     IN      RRSIG   TLSA 5 6 1 20120810085609 20120711085609 24765 dane.rd.nic.fr. FXClnltKo1ZBKSHjmflwcIUIT5bo8AibfZnJJCLqhufBs4UW8HFGcdXU Hys0znMOmsoJVbeoj2GTRaNr1CoMoy/RJRMczo7CP32o6Z0m4BQeOgDf FSiGEG2YUMbwbiVyAgAQhunv1QdqFxvU+uoKCXs0LMLe/SM/vz8oHSJP 2zc=

...

% dig  TLSA  _5269._tcp.proxima.lp0.eu    
...
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 4, AUTHORITY: 5, ADDITIONAL: 5
...
;; ANSWER SECTION:
_5269._tcp.proxima.lp0.eu. 10800 IN     CNAME   _tlsa.proxima.lp0.eu.
_5269._tcp.proxima.lp0.eu. 10800 IN     RRSIG   CNAME 10 5 10800 20120920174820 20120718212409 42615 lp0.eu. GjhRHziHqL9OGkOVvuukyCt7wkD1VzUs5USbBgy3lHBUpfzcxydXFEMR VUiWRwmKDslIrM33tltjKax3jYA8anet8+TTqehoQJ72M37iN2nvx7zg 5JktVDBbYXkJtwzznFADVOT+6/2K243gGh5gjibogwLo9mzUer64jvIh VGWqFOG7HIP3/l2Ajg+x7q/Pe6PPB0n75Qtuu7e8zc13DA==
_tlsa.proxima.lp0.eu.   3600    IN      TLSA    3 1 2 490D884C778E9031D8F1BDFB4B6E7673418BAD66CB8115E36CED911E A612B688AE7CC1909BF23391574E41865E41A51E03ECBC18FA6125A5 A14C7D2BA5E0CFF3
_tlsa.proxima.lp0.eu.   3600    IN      RRSIG   TLSA 10 4 3600 20120920183558 20120719092413 42615 lp0.eu. t9xaSN+Owj41DrtKEeqJhwqcAGjLAfYF+PGjOuT32+hG8MI6XgSrXBmL +HaPXF6rgAdk1BoAkwLij4kpuPu50hIZ3tefTFduO2QU1S8YVEcMys4C FDFz70tGuhcBtyODLxMIWw1zgQGLD/i8dyQnNsllgtNkuJZVJVguAOAp Y35EjlFOXR9sYbvNJnCGcpxqNEZ3FjVmKVVnoOsW+irJwQ==

À noter la section A.2.1.1 pour l'utilisation des alias avec DANE, comme dans ce dernier cas.

% dig  TLSA  _443._tcp.ulthar.us       
...
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 5, ADDITIONAL: 5
...
;; ANSWER SECTION:
_443._tcp.ulthar.us.    3600    IN      TLSA    3 1 1 7EB3A92457701C1A99742E902337BAE786B656ABAF1B13DFE3616D09 90C4F4D8
_443._tcp.ulthar.us.    3600    IN      RRSIG   TLSA 8 4 3600 20120812104422 20120713104422 8550 ulthar.us. nqZ16HERJMQsAklddkhlU2r9TgHL0VUNxgtxmB5lKobI/1J+i66psClv 2hUWEN2EVudYVtViRF/b2b8JOl1ZmSoTVqxk0sF3LEr4UaUJMbO99SOB PiQjXKFI9XXoKyMz71zQiPSgFMos5dAxoKEhFTpAFJI2r3Jrl8QMvFmv +xo=

...

% dig  TLSA  _443._tcp.nohats.ca   
...
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 5, ADDITIONAL: 7
...
;; ANSWER SECTION:
_443._tcp.nohats.ca.    3600    IN      TLSA    1 0 1 6BCFF9A283336DD1ED99A9C40427741B5658863BD54F0A876A2BC4BF 8D822112
_443._tcp.nohats.ca.    3600    IN      RRSIG   TLSA 8 4 3600 20120730210435 20120716182008 28758 nohats.ca. VrY1bsk9IEijZ7yu9jiWUhgY0nsWuJGm1nDWBRI0X1iULJrJE1ZaXCFM PaoY3txlkhqPNbUq3AymKdtKXq9dtUVHF5UQCWnEm29X1YoU5I/Z5in5 VplLx3yp9pib3f7TifgC4Jw0dmYwWCr6jH2tQ1ELFaV2eDN1Li5Wizuk 0M0=

On peut vérifier le TLSA avec OpenSSL. Ici, sur mattmccutchen.net :

% dig +short TLSA _443._tcp.mattmccutchen.net
3 0 1 F9A682126F2E90E080A3A621134523C6DE4475C632A00CF773E6C812 A321BB25

Utilisation 3 (donc le serveur TLS doit envoyer le certificat correspondant) avec sélection 0 (tout le certificat) condensation en SHA-256. Testons :

% openssl s_client -showcerts  -connect mattmccutchen.net:443 < /dev/null 2> /dev/null | \
      openssl x509 -outform der | sha256sum -                               
f9a682126f2e90e080a3a621134523c6de4475c632a00cf773e6c812a321bb25  -

Je n'ai pas encore trouvé de vrai enregistrement TLSA pour d'autres protocoles que HTTP. C'est logique, puisque ceux-ci impliquent en général une indirection et sont donc plus complexes.

Enfin, si vous voulez un serveur HTTPS où DANE ne va pas marcher, rogue.nohats.ca a un enregistrement TLSA délibérement incorrect.

Autres articles sur DANE/TLSA :


Téléchargez le RFC 6698


L'article seul

RFC 6694: The "about" URI Scheme

Date de publication du RFC : Août 2012
Auteur(s) du RFC : S. Moonesamy
Pour information
Réalisé dans le cadre du groupe de travail IETF appsawg
Première rédaction de cet article le 24 août 2012


Les URI commencent par un plan (scheme en anglais), indiquant leur type. Un plan très répandu en pratique n'avait jamais été normalisé  : « about: ». Il permet de décrire des URI internes au navigateur. Le plus célèbre est le about:blank qui permet d'afficher une page blanche. Ce plan, et ce premier URI utilisant ce plan sont désormais officiellement spécifiés dans ce RFC.

Le plan est souvent appelé par erreur « protocole ». Mais il ne correspond pas toujours à un protocole, comme c'est le cas de notre about:. Celui-ci sert à tout, pages spéciales qui n'ont pas été récupérées sur le Web, accès à la configuration du navigateur et même amusants œufs de Pâques. Il figure désormais dans le registre des plans.

La section 2 indique la syntaxe formelle et la sémantique des URI about:. Un point important est que, contrairement aux URI http:, il n'y a pas de structure. Tout le texte après about: indique la ressource cherchée, sans qu'on puisse détailler des composants dans ce texte. Certains de ces textes sont eux-mêmes normalisés (comme le blank cité plus haut) mais pas tous. Et, comme about: décrit des ressources internes au navigateur, il est courant et normal que ces URI about: soient spécifiques d'un navigateur particulier. Attention donc aux URL about: dans cet article, certains ne marcheront pas dans votre navigateur.

Les noms « bien connus » sont désormais enregistrés (section 5.2). Pour l'instant, le registre IANA ne compte que blank (décrit sommairement en section 3) et invalid (qui vient d'une autre norme, au W3C) mais d'autres pourront s'y ajouter après la publication de ce RFC. Cet enregistrement est recommandé dès qu'au moins deux navigateurs connaissent ce nom. La procédure à suivre (cf. RFC 5226) est « premier arrivé, premier servi ». Ce principe n'a pas fait l'objet d'un consensus immédiat à l'IETF, certains auraient préféré une procédure plus formelle, « Spécification nécessaire ».

Il y a même des questions de sécurité liées aux URI about: (section 4) car ils donnent parfois accès à des informations sensibles comme des mots de passe.

Voici maintenant quelques URI about: à tester dans votre navigateur. N'hésitez pas à me raconter lesquels marchent et à m'en envoyer d'autres. De manière surprenante, il n'est pas toujours facile d'avoir de la documentation stable et fiable sur les about:. Pour Firefox, on peut consulter « Firefox about: pages » et pour Chrome « Google Chrome's about: Pages » ou bien « Behind the Scenes of Google Chrome: Optimizing and Troubleshooting », un bon article sur les réglages de Chrome pour maximiser les performances, qui fait beaucoup appel aux about:. Voici les exemples. Vous noterez que je n'en ai pas fait des liens hypertextes car des navigateurs comme Firefox n'acceptent pas tous les liens about: dans une page Web (sans doute pour des raisons de sécurité). Il faudra donc copier/coller :


Téléchargez le RFC 6694


L'article seul

RFC 6693: Probabilistic Routing Protocol for Intermittently Connected Networks

Date de publication du RFC : Août 2012
Auteur(s) du RFC : A. Lindgren (SICS), A. Doria (Consultant), E. Davies (Folly Consulting), S. Grasic (Lulea University of Technology)
Expérimental
Première rédaction de cet article le 1 septembre 2012


Les protocoles traditionnels de routage (comme, mettons, OSPF) sont conçus dans l'idée que les machines sont connectées et joignables en permanence, sauf rares pannes. Mais il existe des réseaux où cette hypothèse ne se vérifie pas. Par exemple, dans l'espace, domaine traditionnel du groupe de recherche DTN, il est fréquent que la communication soit l'exception plutôt que la règle. Comment router dans ces conditions ? Ce nouveau RFC propose un mécanisme de routage adapté à des connexions intermittente, Prophet.

On n'est plus dans le monde tranquille de l'Internet, avec ses connexions stables et ses problèmes connus. Ici, on est à l'IRTF, l'équivalent de l'IETF pour les recherches avancées. À l'IRTF, on étudie des problèmes comme les connexions entre vaisseaux perdus dans l'espace, ou groupes d'éleveurs samis se déplaçant en Laponie, ou encore entre objets communiquants se déplaçant sans cesse et ne venant que rarement à portée de radio des autres objets. C'est là que Prophet devient utile. (Voir le RFC 4838 pour avoir une meilleure idée des sujets sur lesquels travaille le groupe DTN.). Les protocoles de routage traditionnels (cf. section 1.3), conçus pour trouver le chemin optimum dans le graphe et pour éviter les boucles, n'ont pas réellement de sens ici (par exemple, l'émetteur et le destinataire peuvent ne jamais être allumés en même temps).

Le principe de base de Prophet est d'utiliser l'histoire des rencontres entre deux machines. Si deux engins viennent en contact radio de temps en temps, puis se re-séparent, la mise en œuvre de Prophet se souviendra de ses contacts et pourra se dire « ah, j'ai un bundle (cf. RFC 5050 et RFC 6255) à passer à Untel et, justement, je l'ai vu trois fois dans la dernière semaine, donc je garde le bundle, je devrais le revoir bientôt. » Au moment du contact, les machines Prophet échangent aussi des informations sur les machines qu'elles ont rencontré donc la décision peut aussi être « ah, j'ai un bundle à passer à Untel, je ne l'ai jamais croisé mais Machin l'a souvent fait et, justement, j'ai vu trois fois Machin dans la dernière semaine, donc je garde le bundle, je devrais revoir Machin bientôt, et je lui refilerai le bundle et la responsabilité. »

Une manière courante de résoudre ce problème est d'envoyer le message (dans l'architecture DTN, les messages sont découpés en unités de transmission appelées bundles) à tous ceux qu'on croise, qui le transmettent à leur tour à tous ceux qu'ils croisent et ainsi de suite jusqu'à ce que tout le monde l'ait eu. C'est ce qu'on appelle l'inondation et la mise en œuvre la plus connue de ce principe est dans Usenet (RFC 5537). Mais, dans Usenet, on supposait que tous les nœuds étaient intéressés par le message. Ici, un seul destinataire le veut et, pour ce cas, l'inondation fonctionne mais gaspille pas mal de ressources. Elle marche bien lorsque les ressources ne sont pas un problème mais Prophet se veut utilisable pour des réseaux d'objets communiquants, objets ayant peu de mémoire, de capacité réseau, et de processeur. Prophet adopte donc plutôt une démarche probabiliste : il ne garde que les routes les plus prometteuses, risquant ainsi de ne pas trouver de chemin vers la destination, mais limitant la consommation de ressources. Cet élagage des routes est la principale innovation de Prophet.

Pour échanger les routes (pas forcément les bundles), deux nœuds Prophet, lorsqu'ils se rencontrent, établissent un lien TCP entre eux. La mise en œuvre de Prophet doit donc pouvoir parler TCP et interagir avec le programme de gestion des bundles, pour pouvoir informer les besoins des bundles qu'on souhaite transmettre.

On notera que, comme toujours dans l'architecture DTN (Delay-Tolerant Networking, cf. RFC 4838), la transmission n'est pas synchrone : le message, découpé en bundles, va être bufferisé et pourra mettre « un certain temps » à atteindre sa destination. En outre, il est parfaitement possible que la source et la destination du message ne soient jamais allumés et joignables en même temps : on fait donc du réseautage transitif (le message d'Alice est transmis à René, qui le passe à Rose, qui l'envoit finalement au destinataire, Bob). L'annexe A contient un exemple plus détaillé.

À noter que Prophet est utilisé pour des connexions intermittentes, ce qui ne veut pas dire aléatoires. Elles peuvent au contraire être très prévisibles (cas d'engins spatiaux sur leur orbite, ou cas de déplacement d'objets sur un rythme circadien). D'autre part, Prophet n'est pas seulement utile pour le cas où les nœuds se déplacent mais aussi pour celui où ils sont fixes mais souvent en hibernation, par exemple pour économiser du courant (capteur industriel fixé dans un ouvrage d'art, par exemple). Dans les deux cas, la connectivité est intermittente et ce sont les mêmes solutions qu'on utilise. (Voir « Epidemic Routing for Partially Connected Ad Hoc Networks »).

Les détails pratiques, maintenant. Le RFC est long et il y a beaucoup de détails à prendre en compte. Ce qui suit est donc un simple résumé. La section 2 présente l'architecture de Prophet. À son cœur, la notion de « probabilité de remise [d'un message] » (delivery predictability). Notée P_, définie pour tout couple de machines (A, B), comprise entre 0 et 1, c'est la principale métrique de Prophet. Si P_(A, B) > P_(C, B), alors Prophet enverra les bundles destinés à B via C plutôt que via A. Attention, cette probabilité est asymétrique, P_(A, B) n'a aucune raison d'être égal à P_(B, A). Lorsque deux machines Prophet se rencontrent, elles échangent toutes les probabilités de remise qu'elles connaissent.

Au début, lorsqu'un nœud ne connait rien, la probabilité de remise est indéfinie. À la première rencontre, elle passe typiquement de 0,5 (paramètre P_encounter_first), reflétant l'ignorance encore grande. Au fur et à mesure des rencontres, la probabiité augmente (lentement, pour ne pas se heurter au plafond de 1 trop vite, paramètre delta). Cette augmentation est amortie par un intervalle minimum entre deux rencontres (paramètre P_encounter, pour éviter qu'un lien WiFi très instable ne se traduise par plein de rencontres, qui seraient en fait uniquement des rétablissements du lien). C'est un résumé, la définition complète de ce calcul figure en section 2.1.

Vous allez peut-être vous dire « mais les rencontres du passé ne signifient pas qu'elles vont se reproduire dans le futur ». En effet, si les rencontres sont complètement dues au hasard, le passé n'est pas un bon indicateur. Mais rappelez-vous que, dans les réseaux réels, les rencontres ne sont pas complètement aléatoires.

Ces différents paramètres ne sont pas forcément les mêmes pour tous les nœuds Prophet du réseau mais il est recommandé qu'ils soient proches. La section 3.3 détaille ces paramètres.

Ah, au fait, j'ai dit « quand deux nœuds Prophet se rencontrent ». Mais comment le savent-ils, qu'ils sont en vue l'un de l'autre ? Prophet nécessite que la couche 2 transmette cette information (« new neighbor in sight »). Comme détaillé en section 2.4, si Prophet peut tourner sur des protocoles de niveau 2 différents, il faut néanmoins que tous soient capables de signaler l'arrivée ou le départ d'un voisin, ainsi que l'adresse de niveau 2 pour le joindre.

La section 3 décrit le protocole utilisé entre les nœuds Prophet. Il permet d'échanger avec le pair :

  • La liste des nœuds connus (identifiés par l'EID défini dans le RFC 4838),
  • Les probabilités de remise à ces nœuds,
  • Les bundles à envoyer, et la réponse à ceux reçus depuis le pair.

La section 4 présente le format des messages Prophet. Ce format utilise largement des TLV. Chacun a un type (enregistré à l'IANA, cf. section 7) et, par exemple, le TLV Hello, qui sert en début de connexion, a le type 1. Les structure de données plus complexes, comme la table de routage, sont encodés en SDNV (RFC 6256).

La section 5 fournit ensuite les machines à états du protocole.

Et la sécurité ? Ce sujet obligatoire est traité en section 6. Ce sera vite fait : Prophet n'a à peu près aucune sécurité. Il est très vulnérable car les exigences du cahier des charges (machines avec peu de ressources, connectées seulement de manière très intermittente) rendent difficile toute conception d'un protocole de sécurité.

Prophet ne fonctionne donc que si tous les nœuds participant sont gentils et œuvrent dans le but commun. Un mécanisme de sécurité simple serait donc que tous les nœuds utilisent une authentification et que seuls les membres d'une même tribu soient autorisés à faire du Prophet ensemble.

Que pourrait-il se passer, autrement ? Un nœud peut prétendre de manière mensongère qu'il a des routes, en mettant toutes les probabilités de remise à 1 (attaque du trou noir : les autres nœuds lui confieront des bundles qu'il ne pourra pas transmettre). Il peut annoncer un identificateur qui n'est pas le sien, piquant le trafic destiné à un autre. Il peut aussi générer des tas de bundles et les transmettre à ses malheureux pairs (une attaque par déni de service). Et tout ceci serait encore pire si un réseau Prophet était connecté à l'Internet via une passerelle. Les méchants pourraient alors attaquer l'Internet, cachés derrière les faiblesses de Prophet. Bref, un nœud sadique peut faire beaucoup de dégâts, difficiles à empêcher. D'où l'importance de l'authentification, pour ne jouer qu'avec des copains de confiance.

Les sections 8 et 9 de notre RFC décrivent l'expérience existante avec les mises en œuvre de Prophet. C'est un vieux protocole, bien que le RFC ne sorte que maintenant, et il a déjà été implémenté plusieurs fois. Le première fois, écrite en Java, était pour un environnement original, Lego Mindstorms. Elle est documentée dans la thèse de Luka Birsa. Une autre mise en œuvre, en C++, a tourné sur le simulateur OmNet. Encore une autre, pour Android, est décrite dans l'article « Bytewalla 3: Network architecture and PRoPHET implementation ».

Le tout a déjà été testé dans un environnement réel, dans des montagnes du nord de la Suède, en 2006, et raconté dans « Providing connectivity to the Saami nomadic community » (avec une jolie photo de renne dans l'article).


Téléchargez le RFC 6693


L'article seul

RFC 6691: TCP Options and MSS

Date de publication du RFC : Juillet 2012
Auteur(s) du RFC : D. Borman (Quantum Corporation)
Pour information
Réalisé dans le cadre du groupe de travail IETF tcpm
Première rédaction de cet article le 26 juillet 2012


Le protocole TCP a une option nommée MSS (Maximum Segment Size, RFC 793, section 3.1) qui indique la taille maximale des segments (les paquets, au niveau TCP) qu'on peut recevoir. Quelle valeur y indiquer ? Faut-il tenir compte des options IP et TCP, dont la taille est variable ? Ce RFC a depuis été intégré dans la norme TCP, le RFC 9293.

Le RFC 879 semblait répondre clairement : on ne compte que le segment lui-même, pas les en-têtes IP ou TCP. Mais le reste du RFC 879 détaillait des exemples qui ne correspondaient pas à cette règle. Donc le RFC 1122 (section 4.2.2.6 et l'annexe A de notre RFC, pour l'historique) revenait là-dessus. En effet, les options IP et TCP sont de taille variable et peuvent changer pendant une connexion TCP. La MSS ne sera alors pas optimum. La MSS ne pouvant pas facilement changer en cours de connexion (elle est normalement envoyée avec le paquet SYN), il était nécessaire d'avoir une meilleure règle pour sa détermination. Cela n'a pas empêché des RFC ultérieurs comme le RFC 2385 de se prendre les pieds dans le tapis et de formuler les règles incorrectes pour la prise en compte des options variables (option d'authentification, dans le cas du RFC 2385).

Notre RFC 6691 réécrit donc la règle. La nouvelle (section 2) est « La MSS devrait être la MTU moins les en-têtes fixes d'IP et de TCP, sans les options de taille variable ». Notez le « fixes ». Si l'envoyeur des données met des options IP ou TCP, il doit donc diminuer la taille des données TCP, afin de respecter la MSS. Le but est d'éviter la fragmentation IP. Autrement, en-têtes fixes + options variables + MSS pouvaient dépasser la MTU, menant à la fragmentation.

L'en-tête fixe fait 20 octets en IPv4 et 40 en IPv6. L'en-tête TCP fixe est de 20 octets. Si la MTU est de 1500 octets (celle d'Ethernet), cela donnera une MSS de 1460 octets en IPv4 et 1440 en IPv6. Comme indiqué plus haut, si on rajoute des options IP (augmentant ainsi la taille de l'en-tête), on ne pourra pas envoyer 1460 (ou 1440) octets en TCP, il faudra se serrer (diminuer le nombre d'octets envoyés). C'est le comportement actuel de toutes les mises en œuvre de TCP, désormais officiellement documenté.

La règle est simple et bien exprimée. Le reste du RFC est consacrée à la justifier.

Pour résumer (section 4), il y a quatre choix possibles lorsque des options variables sont ajoutées à un paquet (comme l'option d'authentification du RFC 2385) :

  • L'expéditeur des paquets a réduit le nombre d'octets pour faire de la place et la MSS transmise par son pair tenait déjà compte des options : le paquet sera trop court et n'utilisera donc pas le réseau de manière optimum.
  • L'expéditeur des paquets a réduit le nombre d'octets pour faire de la place et la MSS transmise par son pair ne tenait pas compte des options (la règle recommandée par notre RFC) : le paquet est de la bonne taille.
  • L'expéditeur des paquets n'a pas réduit le nombre d'octets pour faire de la place mais la MSS transmise par son pair tenait déjà compte des options : le paquet sera de la bonne taille.
  • L'expéditeur des paquets n'a pas réduit le nombre d'octets pour faire de la place alors que la MSS transmise par son pair ne tenait pas compte des options : le cas le plus ennuyeux car le paquet sera trop long et devra être fragmenté.

Comme celui qui envoie des données ne sait pas si son pair a tenu compte des options ou pas, dans la MSS qu'il a indiquée, la seule solution sûre est donc, si on utilise les options, de décroître la quantité de données envoyées. (Rappelez-vous que seul l'envoyeur des données connait avec certitude les options utilisées. Le récepteur, qui avait indiqué dans l'option MSS la taille qu'il acceptait, ne sait pas s'il y aura des options variables.) Mais, si tout le monde fait cela, ajuster la MSS pour les options ne sert plus à rien. D'où la décision de notre RFC de ne pas tenir compte des options variables dans le calcul de la MSS.

La section 5 décrit d'ailleurs d'autres raisons derrière cette décision comme le fait qu'avec la nouvelle règle, la MSS peut être diminuée par la PMTUD. Par contre, elle ne peut pas être augmentée. Il vaut donc mieux ne pas la mettre trop bas, comme cela arriverait si on essayait de tenir compte des options variables. Elle traite aussi les cas de la compression ROHC (RFC 5795) et des « jumbogrammes » du RFC 2675.


Téléchargez le RFC 6691


L'article seul

RFC 6690: CoRE Link Format

Date de publication du RFC : Août 2012
Auteur(s) du RFC : Z. Shelby (Sensinode)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF core
Première rédaction de cet article le 16 août 2012


Le contexte de ce nouveau RFC est celui des machines ayant peu de ressources, les environnements « contraints ». Les serveurs HTTP tournant sur ces machines ont besoin d'un moyen de faire connaître la liste des services qu'ils proposent. Ce RFC propose de le faire en distribuant en REST des fichiers d'un format spécifique (normalisé ici) listant ces services. Le format s'appuie sur les liens du RFC 8288.

Le groupe de travail IETF CoRE travaille pour ces pauvres machines contraintes, n'ayant parfois qu'un processeur 8-bits et peu de mémoire, connectées par des LowPAN (RFC 4919). Il se focalise sur les applications de machine à machine, où un programme parle à un autre (et pas à un humain, comme la plupart des serveurs Web).

Le problème spécifique traité par ce RFC est celui de la découverte des services (typiquement représentés par un URI) offerts par une machine. Il n'y a pas d'humain dans la boucle, pour lire un mode d'emploi ou une documentation. Et des interfaces statiques sont trop rigides. L'idée de ce RFC est donc de mettre ces URI sous un format standard, dans une ressource à l'URI bien connu, /.well-known/core (les URI .well-known sont normalisés dans le RFC 8615). La ressource en question (cela peut être un fichier statique ou bien elle peut être construite à la demande) est récupérée en HTTP (GET /.well-known/core) ou bien avec le protocole COAP (RFC 7252). Et le format est une concrétisation du concept de lien décrit dans le RFC 8288.

Ainsi, un client CoRE pourra récupérer la liste des variables mesurées par un capteur, par exemple. C'est évidemment très limité par rapport à un moteur de recherche, mais c'est implémentable dans des machines même très limitées.

Le RFC 8288 décrivait un concept abstrait de lien, pour lequel il peut y avoir plusieurs sérialisations (liens <a> de HTML, en-têtes HTTP, liens Atom, etc). La sérialisation normalisée ici est conçue pour être compacte et triviale à analyser (rappelez-vous : machines contraintes), mais les mêmes données peuvent également être servies par des protocoles et des formats plus classiques, si on a aussi des clients plus puissants. Le format compact de ce RFC est identifié par le type application/link-format.

Chaque URI indique un service hébergé (section 2 du RFC). On les écrit entre chevrons. On peut les voir comme un lien « héberge » entre le serveur et le service (« ce serveur héberge - hosts - ce service »).

Voici un exemple de liens suivant ce format, adapté de la section 5 du RFC. Le serveur permet de contrôler des capteurs de température et de lumière. Il y a donc deux services :


</sensors/temp>;if="sensor",</sensors/light>;if="sensor"

Désolé de ne pas pouvoir vous montrer d'exemple réel mais une recherche Google inurl:".well-known/core" ne donne pas le résultat attendu. Trop malin, Google décide d'ignorer ce qu'il prend pour de la ponctuation.

Les URI indiqués sont relatifs. Ils sont relatifs à un contexte qui est en général l'endroit où on a obtenu la ressource /.well-known/core.

Ces liens, comme vous avez vu dans les exemples plus haut, peuvent contenir des attributs (section 3 du RFC). Les attributs spécifiques à ce format sont :

  • rt (Resource type), qui identifie le service (c'est un identificateur formel, pas un texte lisible pour les humains). Pour prendre l'exemple d'un service de mesure de la température, rt peut être une simple chaîne de caractères comme outdoor-temperature ou bien un URI pointant vers une ontologie comme http://sweet.jpl.nasa.gov/2.0/phys.owl#Temperature.
  • if (Interface), qui indique l'URI par lequel on va interagir avec le service. Plusieurs services peuvent avoir la même interface (comme dans le premier exemple donné plus haut avec le capteur de température et celui de lumière). La valeur de if peut être un URI pointant vers une description en WADL.
  • sz (Size), qui indique la taille maximale de la ressource qu'on va récupérer, une information essentielle pour les machines contraintes ! Cette information peut être omise si elle est inférieure à la MTU. Un exemple serait </firmware/v2.1>;rt="firmware";sz=262144.

Les attributs standards des liens peuvent aussi être utilisés, comme title (RFC 8288, section 5.4).

Voici pour la syntaxe du fichier (de la ressource) récupérée. Et pour le récupérer, ce fichier (cette ressource) ? La section 4 revient en détail sur le concept d'URI bien connu (normalisé dans le RFC 5785) et sur celui utilisé par CoRE, /.well-known/core. Un point intéressant est la possibilité de filtrer les requêtes (section 4.1). La syntaxe est définie par un gabarit RFC 6570 : /.well-known/core{?search*}. ce qui permet des requêtes comme :

  • ?href=/foo*, pour se limiter aux liens commençant par /foo,
  • ?foo=bar pour se limiter aux liens ayant un attribut foo dont la valeur est bar,
  • ?foo=* pour ne garder que les liens ayant un attribut foo (valeur quelconque).

Le serveur étant une machine contrainte, il a parfaitement le droit de ne pas mettre en œuvre les filtres (dans la libcoap, présentée plus loin, il y a une option de compilation --without-query-filter pour supprimer les filtres et réduire ainsi la taille du code). Le client doit donc être prêt à récupérer plus que ce qu'il a demandé.

Si on prend cette ressource Core :


</sensors/temp>;rt="temperature-c";if="sensor",</sensors/light>;rt="light-lux";if="sensor"

Alors une requête HTTP GET /.well-known/core?rt=light-lux renverra (si le serveur gère les filtres) uniquement :


</sensors/light>;rt="light-lux";if="sensor"

Des questions de sécurité à garder en tête ? Non, pas trop, dit la section 6, qui rappelle qu'un serveur est autorisé à donner des informations différentes selon le client, et rappelle aussi que ne pas mettre un URI dans /.well-known/core n'apporte pas grand'chose, question sécurité (un attaquant peut le deviner).

Enfin, en section 7, les nombreux enregistrements à l'IANA nécessaires :

Les implémentations de ce RFC semblent surtout se trouver dans les bibliothèques COAP comme libcoap, bien que COAP soit un protocole, pas un format. Voir le fichier net.c de cette bibliothèque. Une liste se trouve en bas de l'article Wikipédia.

TinyOS semble avoir un client capable de tester un /.well-known/core, voir http://docs.tinyos.net/tinywiki/index.php/CoAP. Par contre, je n'ai pas trouvé de validateur en ligne.


Téléchargez le RFC 6690


L'article seul

RFC 6686: Resolution of The SPF and Sender ID Experiments

Date de publication du RFC : Juillet 2012
Auteur(s) du RFC : M. Kucherawy (Cloudmark)
Pour information
Réalisé dans le cadre du groupe de travail IETF spfbis
Première rédaction de cet article le 21 juillet 2012


L'IETF avait créé en 2004 un groupe de travail nommé MARID, qui avait pour tâche de normaliser un mécanisme d'authentification faible du courrier électronique par le biais de la publication dans le DNS des serveurs autorisés à envoyer du courrier pour un domaine. Deux propositions étaient sur la table, SPF et Sender ID. Microsoft avait pratiqué une intense obstruction contre SPF, pour promouvoir sa propre solution, Sender ID. En 2006, l'IETF avait cédé devant cette obstruction, en renonçant à normaliser SPF, déjà très répandu, et en publiant les deux protocoles avec le statut Expérimental : RFC 4408 pour SPF et RFC 4406 pour Sender ID. Cette solution peu courageuse avait été contestée, notamment pour le risque que la coexistence de deux protocoles incompatibles faisait peser sur la bonne délivrance du courrier. Officiellement, la retraite de l'IETF devait être provisoire : une période de deux ans d'observation était prévue, suite à laquelle des conclusions pourraient être tirées sur l'expérience. En fait, c'est seulement six ans après qu'est publié notre RFC 6686 qui conclut enfin officiellement que Sender ID est un échec total et que seul SPF est déployé et utilisé.

Le groupe de travail spfbis avait été constitué en février 2012 pour documenter les preuves du déploiement de SPF et pour réviser la spécification. Ce document est son premier RFC, et il n'a pas été facile à produire, tant les controverses étaient vives. D'une certaine façon, c'est la création de ce groupe qui avait marqué le choix définitif en faveur de SPF. Mais, en 2006, le consensus n'était pas évident, notamment face à l'opposition acharnée de Microsoft, qui tenait à pousser sa solution. Il était pourtant déjà clair à l'époque que SPF était largement déployé et que Sender ID n'était pas utilisé, même par les services appartenant à Microsoft comme Hotmail. Mais la politique politicienne l'avait emporté et l'IETF avait donc fait semblant de traiter les deux protocoles sur un pied d'égalité.

Avantage de ce délai : il a permis de récolter beaucoup plus d'informations pratiques. C'est l'une des forces de ce RFC 6686 que de présenter de nombreuses données issues de plusieurs campagnes de mesure.

Notez aussi que ce RFC ne fait pas de comparaison technique des deux protocoles. Il considère que le choix a déjà été fait par la communauté et il se contente donc d'observer ce qui tourne réellement dans la nature.

Avant les chiffres, qui constituent l'essentiel de ce document, un petit rappel : le RFC 4408 introduisait un nouveau type de données DNS, le type SPF (code 99). Historiquement, SPF utilisait le type générique TXT (code 16) et le nouveau type SPF avait été ajouté alors que le déploiement était déjà largement commencé. Une question secondaire à laquelle notre RFC répond est donc « pour ceux qui utilisent SPF, avec quel type DNS ? ».

La section 3, le cœur de notre RFC, présente donc les résultats de différentes mesures. D'abord, trois séries de mesures actives (faites en interrogeant le DNS sur son contenu, comme peut le faire un logiciel comme DNSdelve) ont mesuré le pourcentage de domaines qui publiaient des enregistrements SPF (commençant par v=spf1) ou Sender ID (commençant par spf2.0/, oui, Microsoft était allé jusqu'à détourner le terme « SPF » pour brouiller davantage la discussion ; il était prévu de critiquer ce point dans le RFC mais le texte a dû être retiré pour ne fâcher personne).

La première étude avait été faite par Cisco à partir du million de domaines les plus populaires sur le Web selon Alexa. 39,8 % ont un enregistrement TXT d'authentification du courrier électronique. Seuls 1,3 % de ces enregistrements sont pour Sender ID.

La deuxième étude a été faite par le Trusted Domain Project, en utilisant comme liste de domaines des extraits des journaux de leurs serveurs de messagerie. Elle trouve 56,4 % de TXT d'authentification du courrier (dont 4,6 % pour Sender ID). Cette étude a également observé que certains serveurs DNS cassés répondent pour une demande de type TXT mais pas pour une demande de type SPF (ce point est couvert plus en détail par la suite, dans l'annexe A).

La troisième étude a été faite par Hotmail, à partir des domaines qui leur envoient du courrier. 46,2 % de TXT avec authentification. Hotmail, filiale de Microsoft, n'a pas publié le pourcentage de Sender ID parmi eux.

En étudiant le contenu de la zone .fr (non mentionnée dans le RFC, étude faite à l'AFNIC avec le logiciel DNSdelve), on trouve 20 % de domaines ayant un enregistrement SPF. Et aucun avec Sender ID... (la mesure a été faite en échantillonant la zone donc une poignée de domaines ayant Sender ID a pu échapper à la mesure). 70 % de ces domaines SPF sont dus à un seul hébergeur de courrier. À noter que cette étude n'a pas fait de différence entre les enregistrements DNS TXT et SPF.

Ces trois études portaient sur les enregistrements dans le DNS. Et pour les requêtes DNS, que voit-on ? Des mesures passives ont été faites (mais le RFC ne contient guère de détails), montrant très peu de requêtes de type SPF (99) et depuis un très petit nombre d'acteurs. À noter qu'on ne peut en général pas savoir, en envoyant ou en recevant du courrier, si le pair SMTP utilise SPF et/ou Sender ID.

Le serveur de noms de .fr d.nic.fr voit, sur ses différentes instances anycast, 0,7 % de requêtes TXT, et 0,1 % de requêtes SPF (données analysées par DNSmezzo). SPF est quand même loin devant un type comme NAPTR mais il est nettement dominé par TXT (toutes les requêtes TXT ne sont pas forcément pour SPF). L'abandon du type DNS SPF a ensuite été repris dans la nouvelle norme SPF, le RFC 7208.

Reste la question des programmes qui mettent en œuvre SPF et/ou Sender ID (section 3.2). L'offre logicielle pour Sender ID est recensée en http://www.microsoft.com/mscorp/safety/technologies/senderid/support.mspx. Aucun logiciel libre n'y est cité. Parmi les treize opérateurs mentionnés, au moins un n'utilise plus Sender ID (la dernière mise à jour date de 2007).

Celle de SPF est en http://www.openspf.net. Six bibliothèques sont citées, vingt-deux MTA (à la fois en logiciel libre et en privateur), ainsi que des patches pour les autres.

Il y a quand même un moyen de tester la présence de Sender ID dans un MTA, via l'extension SMTP SUBMITTER (RFC 4405). Elle est utilisée pour optimiser l'algorithme PRA du RFC 4407 en annonçant au récepteur l'identité de l'expéditeur. Deux logiciels la mettent en œuvre, Santronics WinServer et McAfee MxLogic. Les journaux des fournisseurs montrent qu'environ 11 % des sessions SMTP utilisent cette extension, mais sans qu'on sache s'il s'agit d'un logiciel très répandu ou de plusieurs logiciels moins populaires.

Le Trusted Domain Project a donc fait des mesures actives, se connectant à de nombreux MTA pour leur demander les extensions qu'ils géraient. 4,7 % annonçaient l'extension SUBMITTER et presque tous étaient du MxLogic.

Restait une question délicate à étudier : le refus de l'IETF de trancher entre les deux propositions SPF et Sender ID laissait ouverte la possibilité que ces deux protocoles donnent des résultats différents pour un même message. Par exemple que l'un l'accepte et que l'autre le refuse. Cela serait certainement gênant, l'acceptation ou le rejet d'un message dépendant du choix technique fait par le récepteur. D'abord, deux études par Hotmail et par Trusted Domain Project ont montré que, dans environ 50 % des cas, le PRA (l'identité utilisée par Sender ID, cf. RFC 4407) et le MAIL FROM SMTP (l'identité utilisée par SPF) sont les mêmes.

Ensuite, le Trusted Domain Project a analysé 150 000 messages reçus et abouti à la conclusion que, dans 95 % des cas, SPF et Sender ID auraient formé le même diagnostic (acceptation ou rejet). Une analyse analogue faite par Hotmail sur un échantillon plus large (des millions de messages) trouvait moins : 80 %.

Bon, en pratique, on a rarement vu de rapports comme quoi des ingénieurs système avaient été perturbés par les différences restantes.

La section 5 analyse tous ces résultats et synthétise :

  • Les enregistrements DNS de type SPF (99) n'ont pas été adoptés et des problèmes techniques à l'utilisation d'enregistrements d'un type « nouveau » demeurent.
  • Les enregistrements TXT publiés ne le sont que rarement pour Sender ID.
  • Il n'y a pas de données indiquant qu'en pratique, un des deux protocoles donnerait des résultats bien meilleurs qu'un autre.
  • Les mises en œuvre de SPF sont plus nombreuses et bien mieux mantenues. L'extension SMTP SUBMITTER est rare.

En conclusion, la section 6 estime que :

  • On a assez de données issues de l'expérience pour arriver à une conclusion.
  • Le type d'enregistrement DNS numéro 99, SPF, ne sert à rien.
  • Presque personne n'a déployé Sender ID,
  • Au contraire de SPF, très répandu. Malgré son statut officiel « Expérimental », il est bien plus déployé que certains protocoles normalisés.

Le problème des types de données DNS, déjà mentionné plusieurs fois ci-dessus, est traité en détail dans l'annexe A. SPF avait été créé en dehors de l'IETF et ses concepteurs n'avaient pas suivi la voie recommandée, qui consistait à utiliser un type d'enregistrement DNS spécifique. Au lieu de cela, ils s'étaient servis d'un type existant, et perçu comme généraliste, TXT (code 16). Il faut dire qu'à l'époque (le RFC ne le dit pas franchement), obtenir un nouveau type d'enregistrement DNS à l'IANA était très difficile.

Lorsque SPF est arrivé à l'IETF, il y avait déjà une forte base installée, et donc une grande difficulté à migrer vers un nouveau type d'enregistrement. Ce nouveau type, SPF (code 99), était accompagné lors de sa création d'un plan de migration, qui a été un échec.

Plusieurs raisons à cet échec sont identifiées par notre RFC 6686 :

  • Comme déjà signalé dans la section 3, des pare-feux configurés avec les pieds par un stagiaire refusent parfois les types DNS inconnus (donc le SPF), en violation du RFC 3597,
  • Le DNS n'est pas composé que de serveurs de noms, il y a aussi tout un ensemble de logiciels autour (par exemple les interfaces Web de gestion du contenu des zones, ou bien les bases de données qui stockaient les zones) qui auraient dû être modifiés pour adopter le nouveau type,
  • La base installée utilisait TXT et ne voyait pas de raison impérative de migrer (« faire plus propre » n'est pas une raison impérative),
  • Le plan était lui-même erroné : permettant au serveur de ne publier qu'un seul des deux types, et au client de n'en demander qu'un seul, il faisait que deux logiciels parfaitement conformes au RFC pouvaient être dans l'impossibilité de communiquer.

Depuis, des choses ont changé. L'allocation de nouveaux types, très pénible, a été considérablement libéralisée par le RFC 6195, suivant les recommandations du RFC 5507. Mais le déploiement effectif des nouveaux types reste un problème difficile dans l'Internet d'aujourd'hui.


Téléchargez le RFC 6686


L'article seul

RFC 6673: Round-trip Packet Loss Metrics

Date de publication du RFC : Août 2012
Auteur(s) du RFC : A. Morton (AT&T Labs)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF ippm
Première rédaction de cet article le 16 août 2012


Tiens, le groupe de travail ippm n'avait pas encore normalisé toutes les métriques possibles ? Il restait encore des indicateurs de performance et de qualité de service qui n'avaient pas de RFC. En voici une nouvelle, le taux de pertes de paquets sur un trajet aller-retour.

La plupart des applications ont besoin d'envoyer et de recevoir des paquets. Un exemple typique est la connexion TCP, qui requiert que le paquet SYN du demandeur soit transmis dans un sens et le SYN+ACK du demandé dans l'autre sens. Sans liaison bidirectionnelle, pas de TCP. Le taux de pertes sur le trajet aller-retour est donc certainement utile. Il est même déjà mis en œuvre dans le protocole TWAMP (Two-way Active Measurement Protocol, RFC 5357) mais sans que la métrique correspondante n'ait été définie proprement, selon les règles du RFC 2330. Notre RFC 6673 comble ce manque (le RFC 7680 définissait la métrique pour le taux de pertes en aller-simple). Attention toutefois en interprétant le résultat : si le taux de pertes aller-retour est plus significatif pour l'utilisateur (plus proche de son problème), il est moins adapté pour le diagnostic car il ne dit pas dans quel sens a eu lieu la perte.

Donc, maintenant, les détails. Suivant le principe du RFC 2330, la métrique est définie pour un certain type de paquets (on n'aura pas forcément le même taux de pertes en UDP et en TCP, par exemple, surtout si l'opérateur viole la neutralité du réseau), le « Type-P ». La section 3.2 donne la liste complète des paramètres de la mesure. À noter le Tmax qui indique le temps maximum pendant lequel on attend la réponse (un paquet peut donc être marqué comme perdu alors qu'il est simplement très en retard). À noter également que la métrique est définie en termes booléens : 0, le paquet arrive, 1, il n'arrive pas.

Première définition (section 4), Type-P-Round-trip-Loss. La source envoie un paquet, la destination répond et la source reçoit la réponse. Si cette réponse arrive avant Tmax, le résultat est 0 (succès) sinon 1 (échec). Naturellement, les problèmes habituels de mesure se posent ici, dont les RFC 7680 et RFC 2681 ont déjà discuté. À noter que la destination doit répondre « le plus vite possible » (une des grosses faiblesses de cette métrique, qui ne dépend pas que du réseau mais également du « réflecteur »). La section 4.4 discute plus en détail ce problème et suggère que la destination réponde en moins d'une seconde, ce qui ne devrait pas être trop difficile (cela suppose que Tmax soit très supérieur à une seconde). Notez aussi que, en l'absence de réponse, on ne peut pas savoir si le paquet a été perdu entre source et destination, ou bien entre destination et source (ou, pourquoi pas, si la destination était défaillante et n'a pas renvoyé le paquet).

Ça, c'était pour un seul paquet. Pour un ensemble de paquets, la section 5 définit Type-P-Round-trip-Loss-<Sample>-Stream. <Sample> doit être remplacé par le type de la distribution des paquets (RFC 3432). Deux exemples typiques : une distribution de Poisson ou une distribution périodique (où les paquets sont simplement envoyés à intervalles réguliers, comme le fait la commande ping, dont l'option -i permet de choisir cet intervalle). Cette grandeur sera un tableau de valeurs logiques, 0 pour le succès et 1 pour l'échec.

On pourra ensuite dériver de ce tableau des statistiques comme Type-P-Round-trip-Loss-<Sample>-Ratio (section 6), qui est la moyenne du tableau (« X % des paquets ont été perdus »). Notez que, sur des vrais réseaux de bonne qualité (qui perdent peu de paquets), il faudra envoyer des dizaines de milliers de paquets pour mesurer le taux de pertes de manière significative.

Comment mesure-t-on en pratique ces grandeurs ? La section 8 donne quelques indications. Par exemple, il aura fallu configurer les deux machines pour envoyer et recevoir (pour la source) et réfléchir (pour la destination) les paquets du Type-P choisi (qui peut être ICMP, auquel toutes les machines TCP/IP doivent répondre, mais pas forcément). Le protocole TWAMP du RFC 5357 peut être utilisé pour cela. La machine de destination ne doit pas, autant que possible, être elle-même une cause de perte de paquets et doit donc avoir notamment des tampons suffisamment larges.

Il faut aussi se préoccuper de sécurité (section 9) : comme il s'agit de mesures actives, il faut faire attention à ne pas écrouler le réseau sous la charge (option -f de ping...) Et, lorsqu'on mesure sur un vrai réseau, il faut se rappeler que des décisions de l'opérateur (par exemple de prioritiser certains flux) peuvent fausser la mesure (c'est une des raisons pour lesquelles il est essentiel de publier le Type-P utilisé par exemple « Ces tests ont été faits avec des paquets TCP SYN, port de destination 80 »).

Et les implémentations ? Le célèbre logiciel ping mesure et affiche un taux de pertes aller-retour, sans toutefois suivre rigoureusement la définition de notre RFC. Voici un exemple (la Freebox étant tombée en panne pendant la mesure, ce qui explique le taux élevé de 34 % de pertes) :

% ping -i 0.2 ns2.nic.fr
...
--- ns2.nic.fr ping statistics ---
9085 packets transmitted, 5981 received, +128 errors, 34% packet loss, time 1843752ms
rtt min/avg/max/mdev = 25.068/27.514/156.796/3.477 ms, pipe 3

ping est toutefois très limité : il n'utilise qu'un seul protocole, ICMP, qui peut être filtré ou limité en débit. Autrement, toutes les implémentations de TWAMP mesurent le taux de pertes aller-retour d'une manière compatible avec ce RFC. Même chose pour Cisco IP-SLA. L'auteur du RFC note que son employeur, AT&T, a mille points de mesure TWAMP, mille points IP-SLA et mesure ce taux de pertes cent mille fois par jour (chaque point mesure toutes les quinze minutes).


Téléchargez le RFC 6673


L'article seul

RFC 6672: DNAME Redirection in the DNS

Date de publication du RFC : Juin 2012
Auteur(s) du RFC : S. Rose (NIST), W. Wijngaards (NLnet Labs)
Chemin des normes
Première rédaction de cet article le 18 juin 2012


Depuis sa normalisation dans le RFC 1034, le DNS a suscité le développement d'innombrables extensions, plus ou moins réalistes, plus ou moins utilisées. L'enregistrement DNAME, sujet de ce RFC, semble encore très peu utilisé : il permet de donner un synonyme à une zone entière, pas à un seul nom, comme le fait l'enregistrement CNAME. DNAME avait à l'origine été normalisé dans le RFC 2672, que notre RFC met à jour.

Les enregistrements DNAME permettent d'écrire des équivalences comme :

vivendi-environnement.fr. DNAME veolia.fr.

et un nom comme www.vivendi-environnement.fr sera transformé en www.veolia.fr. Le but étant ici de changer le nom de l'entreprise en Veolia sans avoir à s'inquiéter de toutes les occcurrences de l'ancien nom qui trainent dans des signets privés, dans la presse écrite, sur del.icio.us, etc. DNAME a aussi été envisagé (mais peu utilisé) pour les délégations des sous-arbres de traduction d'adresses IP en noms (in-addr.arpa et ip6.arpa), afin de permettre une rénumérotation d'un réseau relativement légère (section 6.3, qui fournit un exemple et note honnêtement que cela ne résout qu'une petite partie du problème de la renumérotation). Il a aussi été prévu de l'utiliser pour les variantes de domaines IDN (par exemple pour faire une équivalence entre le domaine en chinois traditionnel et le domaine en chinois simplifié). Enfin, il est utilisé dans l'ONS fédéré.

En fait, les enregistrements DNAME ne sont pas aussi simples que cela. Le DNAME ne s'applique pas réellement à la zone mais à tous les sous-domaines de l'apex. Il faut donc dupliquer tous les enregistrements de l'apex (typiquement, les MX et les NS). Le vrai fichier de zone pour videndi-environnement.fr ressemblerait plutôt à :

@	IN	SOA	... Dupliquer le SOA de veolia.fr
        IN   NS  ... Idem pour NS et MX
        IN   MX   ...

        IN   DNAME veolia.fr.

; Et ça suffit, les noms comme www.vivendi-environnement.fr seront
; gérés par le DNAME.

DNAME est donc complémentaire du CNAME : celui-ci « aliase » un nom, le DNAME aliase un sous-arbre. Si on veut aliaser les deux, il faut faire comme dans le fichier de zone ci-dessus. Sinon, il faudrait DNAME et CNAME (mais on ne peut pas se servir des deux en même temps) ou bien créer un nouveau type de données (un BNAME, qui aurait les propriétés des deux, a été discuté à l'IETF).

Le tableau 1 du RFC donne des exemples de cas simples et de cas plus tordus. Il prend trois entrées, le nom demandé (QNAME pour Query Name), le nom du DNAME (owner name) et la cible de ce dernier. Par exemple, avec le DNAME ci-dessus (owner name videndi-environnement.fr, cible veolia.fr), un QNAME de videndi-environnement.fr ne donnera rien (le DNAME ne concerne que les domaines en dessous de l'apex), un QNAME de www.videndi-environnement.fr donnera www.veolia.fr, un QNAME de www.research.videndi-environnement.fr donnera www.research.veolia.fr. Attention, les chaînes (un DNAME pointant vers un DNAME) sont légales. Du point de vue sécurité, une chaîne est aussi forte que son maillon le plus faible et notre RFC, comme le RFC 6604 spécifie que DNSSEC ne doit valider une chaîne que si tous les alias sont valides (section 5.3.3).

Pour que la redirection vers la cible soit déterministe, le RFC impose (section 2.4) qu'un seul DNAME, au maximum, existe pour un nom. BIND refuserait de charger une telle zone et nous dirait (version 9.9.1) :

23-May-2012 22:39:35.847 dns_master_load: foobar.example:20: sub.foobar.example: multiple RRs of singleton type
23-May-2012 22:39:35.847 zone foobar.example/IN: loading from master file foobar.example failed: multiple RRs of singleton type
23-May-2012 22:39:35.847 zone foobar.example/IN: not loaded due to errors.

Si on préfère tester avec l'excellent validateur de zones validns, il faut se rappeler que ce test est considéré comme de politique locale et n'est pas activé par défaut. Il faut donc penser à l'option -p :

% validns -z foobar.example -p all ./foobar.example 
./foobar.example:19: multiple DNAMEs

Notre RFC prévoit le cas où le client DNS pourrait ignorer les DNAME. Le serveur synthétise des enregistrements CNAME équivalents (section 3.1) et les met dans la réponse. Le TTL de ses enregistrements doit être celui du DNAME (c'est un des gros changements par rapport au RFC 2672, où le TTL du CNAME généré était de zéro).

Notez qu'un DNAME peut être créé par mise à jour dynamique du contenu de la zone (section 5.2, une nouveauté par rapport au RFC 2672), masquant ainsi tous les noms qui pouvaient exister avant, sous son nom. Avec un serveur BIND 9.9.1, avant la mise à jour, on voit un nom ayant une adresse :

% dig @127.0.0.1 -p 9053 AAAA www.sub.foobar.example
...
;; ANSWER SECTION:
www.sub.foobar.example. 600     IN      AAAA    2001:db8::2

et, après une mise à jour dynamique où ce programme ajoute un DNAME pour sub.foobar.example et pointant vers example.org, on obtient :

% dig @127.0.0.1 -p 9053 AAAA www.sub.foobar.example
...
;; ANSWER SECTION:
sub.foobar.example.     300     IN      DNAME   example.org.
www.sub.foobar.example. 300     IN      CNAME   www.example.org.

(Si le serveur était récursif, on obtiendrait également l'adresse IPv6 de www.example.org.)

Les DNAME sont mis en œuvre dans BIND et nsd mais semblent peu déployés. Si vous voulez regarder ce que cela donne, testez testonly.sources.org qui est un DNAME de example.org donc, par exemple, www.testonly.sources.org existe :

% dig AAAA www.testonly.sources.org 
...
;; ANSWER SECTION:
testonly.sources.org.   86400   IN      DNAME   example.org.
www.testonly.sources.org. 0     IN      CNAME   www.example.org.
www.example.org.        171590  IN      AAAA    2001:500:88:200::10

(Notez que le serveur utilisé n'a pas suivi la nouvelle règle de notre RFC 6672 et a mis un TTL de zéro.)

Selon moi, une des raisons pour le peu de déploiement de DNAME est que le problème peut se résoudre tout aussi simplement, sans changement dans le DNS, par l'utilisation d'une préprocesseur ou bien en créant un lien symbolique entre les deux fichiers de zone (si le fichier ne contient que des noms relatifs, ça marche très bien, que ce soit avec BIND ou avec nsd).

Les changements par rapport au RFC 2672 sont limités. C'est le même type d'enregistrement (numéro 39) et le même format sur le réseau. Parmi les principaux changements, le TTL du CNAME synthétisé (déjà décrit plus haut) et la disparition complète de l'utilisation d'EDNS pour signaler qu'un client connait les DNAME (cette option était normalisée dans le RFC 2672, section 4.1). L'annexe A donne la liste complète des changements.


Téléchargez le RFC 6672


L'article seul

RFC 6666: A Discard Prefix for IPv6

Date de publication du RFC : Août 2012
Auteur(s) du RFC : N. Hilliard (INEX), D. Freedman (Claranet)
Pour information
Réalisé dans le cadre du groupe de travail IETF v6ops
Première rédaction de cet article le 21 août 2012


Une technique couramment utilisée en cas d'attaque par déni de service est le RTBH : Remote Triggered Black Hole où la victime demande à son FAI, via un protocole, de jeter des paquets sur tel ou tel critère. On utilise pour cela les protocoles de routage standards comme BGP ou OSPF. Même chose lorsqu'un opérateur réseaux veut propager en interne, entre ses routeurs, la décision de jeter ou de rediriger tel ou tel type de paquets. Pour cela, il est bien pratique de disposer d'un préfixe IP spécial, qui désigne le trou noir (ou l'IDS, si on redirige le trafic vers un équipement d'analyse spécial). Il n'existait pas de tel préfixe pour IPv6, c'est désormais fait avec ce RFC, qui enregistre 0100::/64.

Les RFC 5635 et RFC 3882 décrivent plus en détail cette idée de RTBH dans le cas d'une DoS. On sélectionne les paquets en fonction de leur adresse IP source ou destination et on les jette (trou noir) ou bien on les envoie (par exemple via un tunnel) vers un dispositif d'analyse. Pour configurer cela, il faut des adresses IP (plusieurs, car on peut avoir plusieurs traitements différents selon les attaques, donc une seule adresse IP ne suffit pas). Certains utilisent des adresses privées ou bien les adresses IP réservées pour la documentation (RFC 3849). Ce n'est pas très satisfaisant (et cela peut interférer avec les politiques de filtrage en interne, cf. section 2 du RFC) d'où le nouveau préfixe. Si on voit 0100::/64 dans la configuration d'un routeur, on sait désormais exactement ce que cela implique.

Ce préfixe peut être propagé, à l'intérieur du réseau de l'opérateur, ou bien entre l'opérateur et ses clients, par les protocoles de routage dynamiques habituels comme OSPF. Il ne doit pas être transmis à l'extérieur et il est recommandé de le filtrer en entrée, sur les liens de peering ou de transit. Comme il sert pour gérer des attaques qui peuvent être de taille impressionnante, une fuite de ce préfixe vers un autre opérateur pourrait potentiellement entraîner un reroutage de l'attaque vers cet autre opérateur (sections 3 et 5 du RFC). Prudence, donc !

Ce préfixe 0100::/64 est désormais dans le registre des adresses IPv6 spéciales.


Téléchargez le RFC 6666


L'article seul

RFC 6657: Update to MIME regarding Charset Parameter Handling in Textual Media Types

Date de publication du RFC : Juillet 2012
Auteur(s) du RFC : A. Melnikov (Isode), J. Reschke (greenbytes)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF appsawg
Première rédaction de cet article le 10 juillet 2012


Lorsqu'un programme envoie des données en les étiquetant avec le type MIME text/quelquechose, quels sont le jeu de caractères et l'encodage utilisés par défaut ? ASCII ? UTF-8 ? Un autre ? Si vous l'ignorez, vous n'êtes pas le seul. Très peu de gens connaissaient les règles appliquées par défaut et ce RFC choisit donc de les simplifier en les supprimant. Pour le résumer : il n'y aura plus de charset par défaut pour les nouveaux types MIME text/*.

Le RFC 2046, qui normalisait ces étiquettes MIME, disait pourtant (section 4.1.2) que le charset par défaut était US-ASCII (un point de vocabulaire au passage : le terme de charset est fréquent dans les normes IETF mais étymologiquement incorrect, puisqu'il désigne en fait à la fois un jeu de caractères et un encodage). Mais d'autres RFC avaient fait d'autre choix et l'exemple le plus connu était HTTP qui spécifiait que, lorsqu'un serveur envoie des données sans indiquer charset, c'est qu'elles sont en ISO 8859-1 (RFC 2616, section 3.7.1, le RFC 7231 a depuis changé cela), comme les en-têtes de la réponse HTTP. En pratique, le serveur HTTP prudent indiquera le charset (par exemple Content-Type: text/html; charset=UTF-8) plutôt que de compter sur cette règle mal connue.

Pire, certains types ont un mécanisme inclus dans les données pour trouver le charset, notamment text/html et text/xml. Bref, il est difficile à un programme de compter sur la valeur par défaut. Ce RFC formalise en fait un usage déjà très répandu : être explicite.

La nouvelle règle est donc « pas de valeur par défaut générique pour tous les text/*, chaque sous-type de text/* peut définir sa propre valeur par défaut, y compris imposer qu'une valeur explicite soit indiquée. » Pour des raisons de compatibilité avec l'existant, les sous-types existants ne sont pas modifiés, la nouvelle règle s'appliquera aux nouveaux sous-types. Notre RFC recommande en outre de choisir de ne pas avoir de valeur par défaut et, soit d'indiquer le charset dans le contenu (comme le fait XML avec son <?xml version="1.0" encoding="iso-8859-1"?>), soit de rendre obligatoire le paramètre charset= (indication explicite du charset).

Les nouveaux enregistrements de sous-types MIME de text/* ne devraient donc plus indiquer de valeur par défaut pour le charset. Si c'est absolument nécessaire, le RFC recommande que cette valeur soit UTF-8 (on est en 2012 et ASCII ne devrait plus être considéré comme le jeu de caractères par défaut).

On l'a dit, ce RFC ne change pas les sous-types existants et, par exemple, le charset par défaut du sous-type text/plain reste donc, lui, en ASCII.

Une alternative à l'étiquetage des données a toujours été d'essayer de deviner le charset par diverses heuristiques. Le RFC rappelle que cette méthode est dangereuse et déconseillée. Autre piège, le conflit entre l'information extérieure au contenu et celle incluse dans le contenu. Que faut-il faire avec un document XML servi en HTTP comme text/html; charset=iso-8859-1 et commençant par <?xml version="1.0" encoding="utf-8"?> ? Le RFC recommande de se fier à l'information la plus interne (ici, la déclaration XML, qui dit que le document est en UTF-8), probablement la plus correcte.

Ce RFC 6657 est désormais celui cité à l'IANA pour les nouveaux enregistrements dans le registre des sous-types de text/.


Téléchargez le RFC 6657


L'article seul

RFC 6652: SPF Authentication Failure Reporting using the Abuse Report Format

Date de publication du RFC : Juin 2012
Auteur(s) du RFC : S. Kitterman (Agari)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF marf
Première rédaction de cet article le 26 juin 2012


Le but principal de ce RFC est d'améliorer l'utilisation du format ARF (RFC 5965) pour rendre compte d'un problème d'authentification SPF. Ce protocole d'authentification du courrier électronique, normalisé dans le RFC 7208, n'avait pas de registre des modificateurs disponibles dans un enregistrement SPF. Ce RFC comble ce manque.

ARF est un format standard, structuré, permettant l'envoi de rapports d'incidents ou de problèmes (par exemple un spam) entre opérateurs. L'idée d'un format normalisé est de faciliter la production et la lecture automatique de ces rapports. Des extensions à ARF (RFC 6591 et RFC 6650) permettent de l'utiliser pour signaler des erreurs d'authentification.

SPF est un mécanisme d'authentification du courrier électronique qui fonctionne en listant les serveurs de courrier autorisés à émettre du courrier pour un domaine donné. Une fois l'émetteur connu, un récepteur peut alors appliquer ses politiques de sélection (accepter tous les messages en provenance de tel domaine, par exemple).

Les erreurs SPF peuvent être détectées par un récepteur de courrier, s'il fait des tests SPF, ou bien par un serveur de noms d'un domaine couvert par SPF : si on publie un enregistrement SPF spécialement fait pour cela (en utilisant les macros SPF qui permettent de récupérer plein d'informations sur la session SMTP en cours), le serveur DNS du domaine va voir passer les requêtes de vérification et pourra, par exemple, détecter une tentative d'usurpation pendant qu'elle se déroule.

Mais à qui signaler le problème ? Avant notre RFC 6652, il n'y avait pas d'autre moyen, en cas de problème SPF pour example.net, que d'écrire à postmaster@example.net. Désormais, la section 3 de notre RFC normalise des nouveaux modificateurs SPF, qu'on peut inclure dans ses enregistrements, et qui permettent d'indiquer des adresses de contact et les conditions sous lesquelles envoyer un beau rapport ARF conforme au RFC 6591 :

  • ra= (Reporting Address) est le nom à utiliser à la place de postmaster. Si l'enregistrement SPF de example.net contient ra=jimmy, on enverra l'éventuel rapport à jimmy@example.net (il n'existe aucun mécanisme pour spécifier un autre nom de domaine comme victim@somewhere.example, afin d'éviter que le gérant de example.net puisse faire spammer d'autres domaines).
  • rp= (Requested report Percentage) est la proportion de problèmes SPF qui peut déclencher l'envoi d'un rapport. Si l'enregistrement SPF de example.net contient rp=0, il ne veut jamais être embêté par des rapports. Si l'enregistrement contient rp=100, il veut un rapport à chaque fois. Et s'il contient rp=25, il veut qu'un problème sur quatre, choisi au hasard, fasse l'objet d'un rapport. Cela permet de limiter le trafic répétitif. Notez qu'un champ du rapport ARF, Incidents: (section 3.2 du RFC 5965), permet d'indiquer que d'autres incidents sont connus mais ne font pas l'objet d'un rapport. Comme le note la section 6.2, à propos de la sécurité, le volume de rapports envoyés peut être conséquent (et pas connu à l'avance).
  • rr= (Requested Reports) permet d'indiquer par quelle sorte de rapport on est intéressés (all = tous, f = erreurs fatales, etc, voir section 4.1).

Ces modificateurs SPF sont enregistrés dans le tout nouveau registre IANA, créé par ce RFC 6652 (section 5). Il inclut les modificateurs de la liste ci-dessus ainsi que exp= et redirect= qui avaient déjà été normalisés par le RFC 4408. Désormais, ce registre est ouvert à de futures additions, selon les règles « Norme nécessaire » du RFC 5226.

Tirés de l'annexe B, voici des exemples d'enregistrements SPF du domaine example.org utilisant les nouveautés de notre RFC. D'abord un cas simple, avec juste une demande que les rapports soient envoyés à postmaster :

v=spf1 ra=postmaster -all

Un cas un peu plus compliqué, toujours avec un seul modificateur :

v=spf1 mx:example.org ra=postmaster -all

Et un cas qui utilise tous les modificateurs de ce RFC. On demande que 10 % des rapports d'erreur (pas d'échec d'authentification, non, des erreurs lorsque l'enregistrement SPF ne peut être analysé, cf. RFC 7208, sections 2.6.6 et 2.6.7) soient envoyés à postmaster :

v=spf1 mx:example.org -all ra=postmaster rp=10 rr=e

Il reste à voir quel sera le déploiement de ce système. Apparemment, plusieurs fournisseurs de logiciels y travaillent.


Téléchargez le RFC 6652


L'article seul

RFC 6650: Creation and Use of Email Feedback Reports: An Applicability Statement for the Abuse Reporting Format (ARF)

Date de publication du RFC : Juin 2012
Auteur(s) du RFC : J. Falk (Return Path), M. Kucherawy (Cloudmark)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF marf
Première rédaction de cet article le 26 juin 2012


Le format ARF, normalisé dans le RFC 5965 permet à des acteurs de l'Internet (typiquemet des FAI et des gros hébergeurs de courrier comme Gmail) de s'envoyer des rapports structurés, produits et analysés automatiquement, au sujet des abus commis avec le courrier électronique, notamment du spam. Ce nouveau RFC du groupe de travail qui a conçu ARF expose comment et dans quelles circonstances utiliser ARF.

L'idée de base d'ARF était qu'un message serait détecté comme abusif (par exemple par l'utilisateur cliquant un bouton « C'est du spam ! ») et que cette détection déclencherait l'envoi d'un rapport ARF au responsable (qui pourra le faire suivre, si nécessaire). En comparaison avec un rapport non structuré, l'avantage d'ARF est que les messages ARF seront analysables par des programmes, pour rendre leur traitement plus efficace.

(Il existe des extensions à ARF pour des usages qui ne sont pas forcément des abus ou des erreurs d'authentification, comme l'extension du RFC 6430 mais elles sont encore peu déployées et pas étudiées ici.)

Ce RFC 6650 est largement inspiré d'un document externe à l'IETF, le RFC 6449. En quelque sorte, il en est la version officielle.

Les autres documents existants, comme la norme ARF (RFC 5965), sont purement techniques (définition d'un format) et ne répondent pas à des questions comme « à qui envoyer les rapports ? » ou « que faut-il mieux mettre dans un rapport ?  », qui font l'objet de ce RFC.

D'abord, faut-il un accord explicite du destinataire avant d'envoyer les rapports ARF ? La section 3 considère qu'il y a deux cas, celui de deux acteurs décidant entre eux de se transmettre des rapports ARF, relatifs à leurs clients. C'est le cas le plus fréquent aujourd'hui. Et le second cas est celui où des rapports non sollicités sont envoyés à quelqu'un dont l'expéditeur pense qu'il est concerné. En l'absence d'un accord préalable, ces rapports ne feront pas forcément l'objet de la même attention.

La section 4 détaille le premier cas, les rapports attendus. En vrac, elle demande, entre autres :

  • Que l'accord entre les deux acteurs soit respecté, notamment dans le choix de l'adresse de destination (arf-feedback@example.net, par exemple).
  • Que le rapport soit à la syntaxe ARF (évidemment) et que les éléments optionnels dans ARF soient inclus, s'ils sont disponibles (pas de rétention délibérée). Cela concerne Original-Mail-From, Arrival-Date, Source-IP, Original-Rcpt-To.
  • Pour relativiser la demande précédente, il peut y avoir occultation délibérée, pour préserver la vie privée, comme détaillé dans le RFC 6590.
  • Enfin, la section 4 demande (vœu pieux ?) que le récepteur agisse lorsqu'il reçoit des rapports qui le concernent (section 4.3 du RFC 6449).

La section 5 s'attaque aux rapports inattendus, envoyés sans concertation préalable. Elle est bien plus longue puisqu'il s'agit d'embêter des gens qui n'ont rien demandé (dans le précédent cas, les deux parties ont pu se mettre d'accord sur tous ces points, qui doivent être explicités ici.) Les auteurs du RFC demandent, entre autres :

  • Que le destinataire ait un moyen de ralentir le rythme d'envoi des rapports, pour que son infrastructure ne s'écroule pas sous la charge (il n'existe pas de mécanisme standard pour cela, cela doit être fait « à la main »).
  • Que l'expéditeur s'assure que ses messages soient crédibles, pour diminuer le risque qu'ils soient jetés sans autre forme de procès. Cela implique notamment une authentification SPF et/ou DKIM correcte.
  • Que l'expéditeur soit bien conscient qu'un traitement effectif des rapports reçus a un coût pour le destinataire et qu'il fasse donc attention à produire des rapports techniquement corrects et factuellement sérieux.
  • Que l'expéditeur n'envoie pas automatiquement des rapports sur la base d'une analyse automatique. Les logiciels de classification peuvent se tromper et prendre pour du spam ce qui n'en est pas. Il serait anormal de générer un spam (le rapport ARF) en échange d'un message qui n'en est pas un. (Je vois au boulot pas mal de rapports violant cette règle, réalisés en format ARF ou pas, qui sont manifestement automatiquement émis par un logiciel, et un logiciel particulièrement débile en plus.) La section 5 de notre RFC recommande d'utiliser plutôt les messages identifiés comme spam par un humain, ou bien ceux reçus par un pot de miel.
  • Que le MUA, s'il fabrique des rapports ARF, les envoie au fournisseur de service de l'utilisateur, pas au supposé responsable du message abusif. Actuellement, il existe plusieurs logiciels qui automatisent partiellement l'envoi de messages de plainte et qui, pour trouver le destinataire, font des requêtes whois au petit bonheur la chance (par exemple pour tous les AS sur le chemin suivi), avant d'envoyer la plainte à dix ou quinze adresses dont la plupart ne sont en rien responsables du message abusif. La bonne pratique est donc d'envoyer à son fournisseur, charge à lui de faire suivre intelligemment. Pour cela, il devra compter sur diverses heuristiques mais, au moins, il sait les utiliser.
  • Que le rapport soit correctement rempli, indication du bon Feedback-TYpe: (RFC 5965, section 3.1), indication de toutes les informations pertinentes, etc. Par contre, pas besoin d'hésiter avant de choisir le format ARF : les rapports qui suivent ce format sont lisibles manuellement, même si le destinataire n'a pas de logiciel adapté.
  • Que le destinataire agisse, sur la base des rapports corrects. Il existe des tas de rapports incorrects (envoyés au mauvais destinataire, par exemple) et le format ARF permet d'automatiser une partie du triage. Par exemple, le FAI peut regarder l'en-tête Source-IP: du rapport et jeter sans autre forme de procès les rapports où ladite adresse IP source ne fait pas partie de ses préfixes IP. Malgré cela, il y a quand même des rapports corrects ce qui ne signifie pas qu'ils seront lus. Le RFC discute également de la délicate question de la réponse : faut-il signaler à l'envoyeur du rapport que son message a été lu et qu'on a agi ? (Actuellement, même si les rapports d'abus sont traités, l'utilisateur ne reçoit jamais de retour.) La conclusion est que ce serait souvent une bonne idée que de signaler à l'émetteur du rapport qu'il n'a pas travaillé pour rien.

Les recommandations précédentes concernaient surtout les rapports envoyés en réponse à un message abusif, du spam par exemple. La section 6 couvre les rapports signalant un problème d'authentification, avec SPF ou DKIM. Ces rapports utiliseront le Feedback-Type: auth-failure (RFC 6591) et sont normalisés dans des documents comme le RFC 6652 et le RFC 6651. Les demandes pour cette section sont :

  • Qu'on n'envoie de tels rapports qu'à ceux qui les demandent, et aux adresses de courrier qu'ils ont indiqué,
  • Qu'on n'envoie pas de rapport ARF pour un problème d'authentification d'un rapport ARF (pour éviter les boucles). C'est aussi pour éviter ces boucles que le rapport doit être envoyé avec un MAIL FROM vide (plus exactement ayant la valeur <>),
  • Qu'on fasse attention aux attaques avec amplification. Il ne faut pas qu'un méchant fabrique un faux, juste pour que l'échec de l'authentification de ce faux déclenche l'émission d'un gros rapport ARF à destination d'un pauvre FAI qui n'y est pour rien.

Quelques pièges de sécurité peuvent attendre les utilisateurs du format ARF. La section 8 en fait le tour. D'abord et avant tout, les rapports ARF peuvent être des faux, fabriqués de A à Z (afin, par exemple, de faire accuser un innocent). La confiance qu'on leur accorde doit dépendre de l'authentification de l'émetteur et de la confiance qu'on accorde à cet émetteur. (C'est un problème ancien, voir par exemple la section 4.1 du RFC 3464.)

Le modèle originalement envisagé pour ARF était celui du rapport déclenché manuellement ; un utilisateur se plaint, il clique sur le bouton « Ceci est un spam », le message est transmis au fournisseur de messagerie qui fabrique un rapport ARF et l'envoie. Le rythme d'envoi des rapports restait donc limité. Au contraire, les évolutions récentes d'ARF, notamment pour le signalement de problèmes d'authentification, vont vers des rapports déclenchés automatiquement. Un message arrive, le test SPF échoue, paf, un rapport ARF est généré et envoyé. Cela peut mener à des rythmes d'envoi bien plus grands, qui peuvent dépasser les capacités de réception et de traitement du destinataire. C'est d'autant plus ennuyeux qu'un attaquant vicieux pourrait générer exprès des problèmes d'authentification, pour déclencher ces envois massifs. Il peut donc être raisonnable de limiter le débit d'envoi de tels rapports.

Autre façon de traiter ce problème : ne pas envoyer un rapport par incident. Le format ARF prévoit (RFC 5965, section 3.2) d'indiquer dans le rapport combien d'incidents similaires il couvre (champ Incidents:). On peut donc choisir, par exemple, de n'envoyer qu'un rapport pour N incidents ou, mieux de faire une décroissance exponentielle (un rapport par incident pour les 10 premiers, un rapport par série de 10 incidents pour les 100 suivants, etc).


Téléchargez le RFC 6650


L'article seul

RFC 6648: Deprecating the X- Prefix and Similar Constructs in Application Protocols

Date de publication du RFC : Juin 2012
Auteur(s) du RFC : P. Saint-Andre (Cisco), D. Crocker (Brandenburg InternetWorking), M. Nottingham (Rackspace)
Réalisé dans le cadre du groupe de travail IETF appsawg
Première rédaction de cet article le 25 juin 2012


Ce RFC met officiellement fin à une amusante tradition, qui était un des charmes des protocoles TCP/IP mais qui, en pratique, a causé quelques ennuis, justifiant son abandon. Cette tradition concernait le nommage des paramètres dans les protocoles. Normalement, ces noms étaient enregistrés à l'IANA pour éviter des collisions (par exemple, il ne doit y avoir qu'un seul champ nommé User-Agent: dans une requête HTTP). Comme cet enregistrement nécessitait une procédure, parfois lente et lourde, cela contrariait les gens qui voulaient expérimenter avec une nouvelle idée, qui impliquait un nouveau paramètre. L'habitude, avec l'appui de quelques RFC, s'était donc répandue de donner à ces paramètres expérimentaux, non officiels, un nom commençant par la lettre X suivie d'un tiret. Cette pratique a rencontré plusieurs problèmes et est donc désormais fortement déconseillée.

Le prefixe « X- » permettait de marquer clairement le nom de paramètre comme expérimental. Sans lui, certains développeurs auraient peut-être été tentés de s'auto-attribuer des noms, quitte à provoquer des collisions avec d'autres développeurs. Mais le problème de l'Internet est que les expériences durent : on invente un nouveau champ dans les requêtes HTTP, mettons X-recipe: pour indiquer sa recette favorite, on se dit que c'est juste un essai, qu'on ne va pas s'embêter à demander un nom officiel pour si peu, on l'utilise dans un patch de Firefox, dans un module Apache, des gens commencent à s'en servir, on se dit qu'il serait bon d'enregistrer un vrai nom et on s'aperçoit que la base installée d'utilisateurs est déjà trop grande pour abandonner le nom expérimental. C'est essentiellement pour éviter ce genre de blocage que l'IETF vient de décider de mettre fin à cette convention du « X- ».

Il y a d'autres protocoles que HTTP (d'où sont extraits les exemples précédents) qui utilisent de tels paramètres. Par exemple le format standard du courrier électronique (RFC 5322) ou bien les vCard (RFC 6350). Tous à un moment ou à un autre ont vu passer des paramètres dont les noms commençaient par « X- », X comme eXpérimental ou comme eXtension (SIP faisait un peu différemment avec des en-têtes dont le nom commençait par « P- », cf. RFC 5727). Une méta-information sur le paramètre, son statut expérimental, se trouvait ainsi stockée dans le nom. L'idée semblait tellement bonne qu'elle a même été codifiée par plusieurs RFC comme le RFC 822 (qui différenciait les Extension fields et les User-defined fields, section 4.1) ou comme le RFC 5545 (section 3.1). Par la suite, ces codifications ont souvent été retirées (pour le courrier, le RFC 2822 a annulé les dispositions du RFC 822).

Donc, ce nouveau RFC :

  • Supprime la convention « X- », même pour les cas où elle était non-officielle et non documentée (cas de HTTP),
  • Recommande à la place de nouvelles pratiques et de nouvelles conventions,
  • N'interdit pas les noms de paramètres locaux ou expérimentaux : c'est la convention « X- » qui est en cause, pas l'idée de paramètres non enregistrés,
  • Ne spécifie rien sur les paramètres « X- » existants, une question délicate qu'il faudra traiter au cas par cas.

Les programmeurs reçoivent (en section 2) la consigne de ne pas traiter un paramètre différemment juste sur la base de son nom. Qu'il commence par « X- » ou pas, le résultat doit être le même. (Faire autrement pourrait avoir des conséquences négatives sur la sécurité, par exemple si un programme considérait que les noms sans « X- » sont plus « sûrs » que les autres, comme expliqué en section 5.)

Quant aux créateurs de nouveaux paramètres (« Eh, je trouve qu'il faudrait pouvoir indiquer la boisson favorite de l'utilisateur, y a-t-il un en-tête Favorite-Drink: ?  »), la section 3 leur dit que :

  • Il faut s'attendre à ce que tout paramètre créé devienne un jour commun, largement déployé, non modifiable (c'est le grand problème avec la convention « X- » : les paramètres censés être expérimentaux deviennent permanents et non-modifiables),
  • Il faut utiliser des noms parlants et non déjà utilisés,
  • Et ne commençant pas par « X- ».

Pour limiter les risques de collision, si le paramètre n'est pas enregistré, cette section recommande de le préfixer avec le nom de l'organisation, à la Java, par exemple si l'organisation se nomme Example International et a le domaine example.com, utiliser Example-International-Favorite-Drink: ou Com-Example-Favorite-Drink: pour l'en-tête experimental.

Quant aux concepteurs des futurs protocoles, la section 4 leur dit :

  • N'oubliez pas de créer un registre des valeurs possibles pour les paramètres textuels, registre qui permettra d'éviter les collisions entre noms de paramètres. C'est le cas des noms de champs, utilisés entre autres par HTTP, par exemple.
  • Idéalement, les procédures d'enregistrement dans ledit registre devraient être suffisamment simples et claires pour que les créateurs de paramètres (section précédente) ne soient pas tentés de choisir des noms de manière unilatérale,
  • Ne faites pas de règles spécifiques pour les noms commençant par « X- ». Par exemple, ne spécifiez pas que ces noms sont interdits, ou qu'ils indiquent un type particulier de paramètre.

Reléguée en annexe A, mais essentielle, se trouve l'analyse historique de la convention « X- ». Il semble qu'elle ait été mentionnée la première fois par Brian Harvey en 1975, pour les paramètres FTP du RFC 691 (« an initial letter X be used for really local idiosyncracies »). Les RFC 737, RFC 743, RFC 775, RFC 822 ont ensuite repris l'idée, à laquelle les RFC 1123 et RFC 1154 ont donné une forme de reconnaissance officielle, en notant toutefois déjà le problème que posent des paramètres qui sont expérimentaux au début et qui deviennent normalisés sans le « X- » plus tard. On ne peut pas citer les nombreux RFC qui ont ensuite mentionné l'idée, sans forcément l'encourager. Mais même LDAP s'y était mis (RFC 4512). Par contre, cette convention n'a jamais reçu de validation au niveau de tout l'IETF : ni le RFC 2026, ni le RFC 5226 n'en parlent. Cette convention est donc (théoriquement) restée cantonnée à certains protocoles.

Les problèmes que pose cette convention « X- » ont quand même été notés assez tôt et, dès le RFC 2822, le courrier électronique arrêtait officiellement de l'utiliser. Idem pour SIP avec le RFC 5727.

Si vous voulez tout savoir des inconvénients de la convention « X- », la partie du RFC à lire est l'annexe B, qui énumère les problèmes. Le principal est que les paramètres ainsi nommés, normalement locaux et/ou temporaires, tendent à fuir vers l'extérieur et que, s'ils sont des succès, ils deviennent rapidement des « standards de fait » (et les programmes doivent le traiter comme tel). Il faut alors se décider entre une migration depuis le nom en « X- » et le nom officiel sans « X- », ou bien une officialisation du nom avec « X- ». Dans les deux cas, la convention « X- » n'aura pas aidé. Elle ne servirait que si les paramètres ainsi nommés étaient tous des échecs qui ne restaient pas longtemps. Mais ce n'est pas le cas. Un exemple typique est donné par les en-têtes HTTP x-gzip et x-compress, qui sont devenus des standards de fait, au point que le RFC 2068 (section 3.5) conseillait de les accepter, comme synonymes aux en-têtes standard ! (Son successeur, le RFC 2616, a gardé cette recommandation.)

Dans le contexte du courrier électronique, on voit un phénomène équivalent avec le conseil du RFC 5064 d'accepter X-Archived-At: comme équivalent à Archived-At: (section 2.5). Excellent exemple d'une expérimentation qui a tellement bien réussi qu'elle devient ensuite une gêne. Quant au conseil de considérer les deux noms comme équivalents, il est dangereux : les deux noms ont été définis séparement et peuvent avoir des propriétés subtilement différentes (le nom officiellement enregistré a souvent des règles de sécurité plus strictes sur son usage, par exemple).

Bien sûr, il y a des gens qui défendent la convention « X- ». D'abord, il peut y avoir des cas où elle est légitime :

  • Si on est absolument sûr que le paramètre ne sera jamais standardisé (l'expérience invite à la prudence...) Auquel cas l'annexe B recommande, pour éviter toute collision avec un nom officiel, de préfixer le nom du paramètre par celui de l'organisation.
  • Quant un paramètre existe déjà et qu'il a le nom qu'on voudrait. Le RFC estime que c'est une mauvaise idée. Si on a un paramètre priority et qu'on est tenté de créer x-priority, il vaut mieux utiliser un synonyme (comme urgency) ou bien être créatif (get-it-there-fast).
  • Quant les noms doivent être très courts (c'est le cas des étiquettes de langue du RFC 5646 où on peut utiliser x). Mais, là, il vaut encore mieux utiliser des numéros.

Les critiques de ce RFC mettaient en avant d'autres arguments, plus philosophiques :

  • Le « X- » était un signal clair du statut du paramètre (mais, on l'a vu, des paramètres « X- » sont devenus standardisés de fait).
  • Les collisions entre noms sont plus facilement évitées s'il existe une ségrégation, avec un préfixe dédié pour les noms locaux et expérimentaux. Mais la plupart des espaces de nommage sont de grande taille : rien n'empêche de nommer un en-tête Very-Long-Parameter-With-Useless-Information-Just-Because-I-Can: pour être sûr qu'on ne le confonde pas avec un autre. (Les étiquettes de langue citées plus haut sont un contre-exemple, où l'espace de nommage n'est pas énorme.)
  • En parlant d'économie, il existe un RFC, le RFC 3692 qui recommande d'utiliser des valeurs spéciales pour les expériences ou les cas locaux. Mais cela concerne surtout les paramètres numériques, où l'espace manque souvent. Si vous avez un seul octet pour stocker une valeur, enregistrer des paramètres expérimentaux risque d'épuiser rapidement cet octet. Un exemple est celui de l'algorithme de cryptographie utilisé par DNSSEC. Il n'y a que huit bits pour l'indiquer et il faut donc allouer des valeurs prudemment. C'est pour cela que les valeurs 253 et 254 sont réservées pour les expérimentations et l'usage privé. Les paramètres alphabétiques n'ont en général pas ce problème : on n'est pas près de tomber à court de noms pour les en-têtes HTTP !

Si les gens utilisaient la convention « X- », au lieu d'enregistrer le nom de leur paramètre, ce n'est pas uniquement pour semer des chausse-trappes sous les pieds des futurs programmeurs. C'est aussi parce que l'enregistrement d'un nom a souvent été considéré (souvent à juste titre) comme excessivement compliquée et bureaucratique. Si on veut mettre effectivement fin à la convention « X- », la bonne méthode est donc aussi de libéraliser l'enregistrement, ce qu'avaient fait les RFC 3864 ou RFC 4288. Plusieurs participants à l'IETF avaient fait remarquer lors des discussions sur ce RFC que le vrai enjeu était de normaliser plus rapidement, pour éviter que les concepteurs de nouveaux paramètres ne soient tentés de s'allouer des noms de manière sauvage.

Ce RFC ne s'applique qu'aux protocoles utilisant des paramètres textuels. Lorsque le paramètre est, au contraire, identifié par sa position ou par un nombre, il n'est évidemment pas concerné.


Téléchargez le RFC 6648


L'article seul

RFC 6647: Email Greylisting: An Applicability Statement for SMTP

Date de publication du RFC : Juin 2012
Auteur(s) du RFC : M. Kucherawy (Cloudmark), D. Crocker (Brandenburg InternetWorking)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF appsawg
Première rédaction de cet article le 18 juin 2012


La lutte contre le spam est un domaine où les certitudes (souvent assénées avec conviction) sont plus fortes que les faits. Prenez n'importe quel forum, en ligne ou ailleurs, où on discute des mesures qui pourraient limiter les conséquences du spam, vous y lirez et entendrez des affirmations radicales, par exemple sur l'efficacité du greylisting, sans que les affirmateurs ne se soucient d'appuyer leurs déclarations sur des mesures concrètes, faites dans la réalité. Comme le note notre RFC 6647, le greylisting est largement déployé, depuis de nombreuses années, marche bien et n'a pas d'inconvénient grave, mais il reste rejeté, sans raisons valables, par de nombreux « experts ». Ce RFC a mis du temps à sortir (il est courant à l'IETF que le texte de la norme vienne très longtemps après le déploiement) mais il changera peut-être cette perception.

Faites l'expérience vous-même : sur un MTA typique qui n'a pas encore le greylisting, activez-le, vous stopperez entre le tiers et les deux tiers du spam avant même que le premier octet de données n'ait été transmis. Si vous souhaitez, avant ou après, vous informer en détail, vous pouvez lire cet excellent RFC 6647, « Tout ce qu'il faut savoir sur le greylisting ». Il documente enfin officiellement une pratique courante depuis de nombreuses années.

Le principe du greylisting peut se résumer ainsi : on va refuser temporairement l'accès au serveur de messagerie à certains clients. Les clients normaux réessaieront, ce qu'une partie des spammeurs ne feront pas. On en sera ainsi débarrassé. La différence entre les mises en œuvre du greylisting se situe essentiellement dans les critères utilisés pour rejeter, puis pour accepter, un client SMTP.

L'idée est donc de considérer qu'un client « nouveau » est soumis au greylisting jusqu'à ce qu'il devienne « connu ». Une fois connu, on pourra le juger, par exemple sur les messages qu'il envoie. Ces mécanismes de réputation ne prenant pas en compte les nouveaux arrivants, le greylisting sert à les gérer en attendant. Sur la base de ce concept très général, le greylisting tel que déployé actuellement, consiste à renvoyer un code d'erreur SMTP, indiquant une erreur temporaire (code commençant par 4), à tout nouveau client SMTP. Les spammeurs utilisent souvent des logiciels spéciaux qui, pour de bonnes raisons, ne retentent pas de délivrer le message en cas d'erreur temporaire. Leur renoncement diminue la quantité de spam reçue. Les MTA ordinaires mettent le message dans une file d'attente, puis réessaient (c'est une fonction de base du courrier électronique, on essaie jusqu'à ce que ça passe) et verront donc leur message délivré car, au bout d'un moment, le greylisteur les considérera comme connus.

Plongeons maintenant dans les détails, après avoir relu les RFC 5322 et RFC 5598.

Il y a plusieurs types de greylisting et la section 2 en donne une liste. D'abord, ceux qui décident uniquement sur la base des informations de connexion (l'adresse IP et, peut-être, le nom obtenu par une requête de traduction d'adresse en nom). Le greylisting garde ensuite en mémoire les adresses des sources de courrier. Il refuse (code SMTP 421 ou équivalent) tant qu'une source n'a pas été vue depuis au moins N minutes (avec N variant typiquement entre 10 et 30).

En général, l'information est automatiquement retirée de la base lorsqu'on n'a pas vu cette source depuis X jours (typiquement entre 15 et 60). L'émetteur occasionnel devra donc montrer patte blanche à nouveau.

Naturellement, ce mécanisme peut être combiné avec une liste noire d'adresses IP (n'imposer le greylisting qu'à celles qui sont sur la liste noire) ou une liste blanche (dispenser du greylisting celles qui sont sur la liste blanche).

Avec le logiciel Postgrey, on peut avoir ce comportement (ne prendre en compte que l'adresse IP, pas le MAIL FROM et le RCPT TO), en utilisant l'option --auto-whitelist-clients (l'idée est que, si un MTA réessaie plusieurs fois, il ne sert à rien de le tester pour chaque adresse, il a montré qu'il était un « vrai » MTA.)

En laissant le client SMTP aller plus loin, et continuer la session, on peut récolter des informations supplémentaires, qui peuvent servir de paramètres au processus de décision du greylisteur. C'est ainsi qu'on peut attendre le salut SMTP (EHLO ou bien le vieux HELO) et utiliser alors comme identificateur de la source SMTP le couple {adresse IP, nom annoncé par EHLO}. Cela permet, par exemple, de différencier deux clients SMTP situés derrière le même CGN et ayant donc la même adresse IP publique. Autrement, toutes les machines derrière un routeur NAT bénéficieraient du passage de la première machine.

En continuant, on peut aussi récolter l'adresse de courrier émettrice (commande SMTP MAIL FROM) et la ou les adresses de courrier de destination (RCPT TO). Un greylisteur qui est allé jusque là peut donc utiliser le triplet {adresse IP, expéditeur, destinataire}. C'est la politique la plus courante. C'est par exemple ce que fait par défaut Postgrey, déjà cité, qui journalise ces informations (voir l'exemple plus loin) pour pouvoir analyser ce qui s'est passé.

Voici d'ailleurs un exemple de session SMTP. Le client est nouveau et donc greylisté :


% telnet mail.bortzmeyer.org smtp
Trying 2001:4b98:dc0:41:216:3eff:fece:1902...
Connected to mail.bortzmeyer.org.
Escape character is '^]'.
220 mail.bortzmeyer.org ESMTP Postfix
EHLO toto.example.net
250-mail.bortzmeyer.org
250-PIPELINING
250-SIZE 10000000
250-VRFY
250-ETRN
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
MAIL FROM:<foo@example.net>
250 2.1.0 Ok
RCPT TO:<stephane+blog@bortzmeyer.org>
450 4.7.1 <stephane+blog@bortzmeyer.org>: Recipient address rejected: Greylisted by greyfix 0.3.9, try again in 300 seconds.  See http://www.kim-minh.com/pub/greyfix/ for more information.

Cinq minutes après, le client réessaie et est accepté :


% telnet mail.bortzmeyer.org smtp
Trying 2001:4b98:dc0:41:216:3eff:fece:1902...
Connected to mail.bortzmeyer.org.
Escape character is '^]'.
220 mail.bortzmeyer.org ESMTP Postfix
EHLO toto.example.net
250-mail.bortzmeyer.org
250-PIPELINING
250-SIZE 10000000
250-VRFY
250-ETRN
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
MAIL FROM:<foo@example.net>
250 2.1.0 Ok
RCPT TO:<stephane+blog@bortzmeyer.org>
250 2.1.5 Ok
DATA
354 End data with <CR><LF>.<CR><LF>

En pratique, la grande majorité des logiciels de greylisting ne va pas plus loin. Après tout, le but est de rejeter du spam sans consommer de ressources et donc en réduisant la durée de la session et la capacité réseau utilisée. Toutefois, le RFC cite la possibilité d'attendre encore un peu et d'aller jusqu'à la réception du message (commande SMTP DATA). Le greylisteur ne va pas forcément analyser le corps du message, il peut aussi attendre le DATA car certains clients bogués réagissent mal lorsque le refus de continuer la session arrive avant DATA. Mais le RFC note que cette analyse du contenu du message reste possible, bien que je ne connaissais pas de greylisteur qui le fasse. Mais Gabriel Kerneis m'en a cité un : sa-exim qui documente cette fonction. Et il y a aussi smtpf.

Naturellement, un greylisteur peut inclure d'autres informations dans sa prise de décision comme la présence de l'expéditeur dans une liste noire (RFC 5782) ou comme un motif dans le nom du client (on fait une requête pour traduire l'adresse IP en nom, et si dyn ou adsl sont dans le nom, on rejette temporairement).

Le greylisteur peut aussi avoir une liste d'exceptions, pour gérer les cas particuliers, par exemple ceux dont on sait qu'ils ne réessaient pas correctement, ou qui attendent trop longtemps avant de réessayer. Par exemple, pour Postgrey, on trouve dans le fichier /etc/postgrey/whitelist_clients une liste de domaines dont l'émetteur de courrier est défaillant (il ne réessaie pas) mais dont on souhaite recevoir les messages, par exemple :

...
# greylisting.org: Southwest Airlines (unique sender, no retry)
southwest.com
...

Comme toute technique de sécurité, le greylisting est un compromis : il a des bénéfices et il a des coûts. La section 3 est consacrée à l'examen de ces avantages et inconvénients (et la section 9 revient ensuite sur certains de ces choix). L'avantage principal est qu'une partie significative du spamware ne réessaie jamais, après le refus initial, et que la quantité de spam à traiter va donc diminuer.

L'inconvénient principal est que certains messages seront retardés. Le MTA typique réessaie par défaut au bout de 15 minutes mais c'est réglable et les gros hébergeurs de courrier augmentent en général cette durée, souvent jusqu'à 60 minutes, pour limiter la charge de leurs serveurs, dont la file d'attente est souvent très grosse. Pire, certains (comme le serveur de Southwest Airlines, cité plus haut) ne réessaient pas du tout. Dans ce dernier cas, ils sont en violation caractérisée de la norme SMTP et auront des problèmes avec bien d'autres choses que le greylisting (une coupure réseau, et hop, le courrier est fichu).

Ce problème du retard est-il sérieux ? Le courrier électronique a toujours été « au mieux », c'est-à-dire qu'une distribution immédiate ne fait pas partie du cahier des charges. Si des gens comptaient sur une délivrance instantanée, c'est qu'ils n'avaient pas compris le principe du courrier.

Le retard est de toute façon rare en pratique. Comme le greylisteur se souvient des émetteurs corrects (qui réessaient après la première rebuffade) qu'il a rencontrés, et comme la plupart des messages entrants viennent de correspondants réguliers, peu de messages sont vraiment retardés. Si on souhaite à tout prix réduire encore ce nombre, notamment en mettant en service un nouveau serveur, dont la mémoire est vide, on peut toujours envisager de pré-remplir la mémoire avec des adresses extraites du journal (le RFC cite cette possibilité, que je trouve bien compliquée et n'en valant pas la peine).

La section 4 décrit en détail les conséquences non souhaitées du greylisting. Comme pour les notices des médicaments qui préviennent des effets secondaires possibles, il faut la lire en mettant ces inconvénients en rapport des avantages (voir aussi la section 9.1, sur les compromis). Exemple de problème, si on a plusieurs serveurs de courrier (plusieurs entrées dans l'enregistrement MX), et s'ils ne partagent pas leur base d'émetteurs, un client SMTP qui, refusé par le premier, essaiera le second, puis le troisième, etc, sera ainsi retardé plusieurs fois. En parlant de MX secondaire, le RFC recommande également de configurer le primaire pour qu'il accepte les messages des secondaires sans greylisting (puisque le message a déjà été greylisté par le secondaire, a priori une machine de confiance).

Autre cas pathologique, celui d'une machine qui n'envoie du courrier que rarement. Ses informations expireront de la base avant le prochain envoi et elle sera donc souvent considérée comme « nouvelle » et donc greylistée.

Outre le retard, un effet parfois ennuyeux du greylisting est le réordonnancement des messages. Si Alice écrit à Bob et Charlie et que son émetteur est connu du MTA de Bob, mais pas de celui de Charlie, la délivrance à Charlie sera retardée. Si Bob répond à Alice, et que le MTA de Bob est connu de celui de Charlie, Charlie recevra la réponse de Bob avant le message original d'Alice. Une note personnelle au passage : cela montre l'importance des MUA qui remettent les messages dans l'ordre comme mutt avec son option set sort=date-sent (qui dépend d'un réglage correct de la date par l'expéditeur) ou set sort=threads (qui utilise les en-têtes du message comme References:).

Il y a aussi des problèmes qui sont de la faute du client SMTP. S'il ne réessaie pas, il aura des problèmes avec le greylisting mais aussi avec toute panne réseau temporaire. S'il considère tous les codes d'erreur SMTP comme permanentes (alors que la section 4.2.1 du RFC 5321 est bien clair que les codes de type 4xy sont des erreurs temporaires), il aura des problèmes avec le greylisting et avec certaines erreurs sur le MTA.

Si le client SMTP utilise une adresse d'expéditeur de courrier différente pour chaque essai (une idée très baroque mais tout existe sur l'Internet), et que le greylisteur utilise cette adresse pour déterminer si un envoi est nouveau, alors, le message ne passera jamais.

Enfin, les logiciels de test des adresses de courrier peuvent avoir des problèmes avec le greylisting comme Zonecheck et sa bogue #9544.

Après cette liste de problèmes possibles, les recommandations concrètes, pour que le greylisting apporte joie et bonheur et que les problèmes restent virtuels. Elles figurent en section 5 et les principales, tirées de la longue expérience du greylisting, sont notamment :

  • Mettre en œuvre le greylisting en utilisant comme tuple définissant un visiteur le triplet {adresse IP source, adresse de courrier en MAIL FROM, première adresse de courrier dans le RCPT TO}. L'inclusion des adresses de courrier a notamment pour but de limiter le réordonnancement des messages. Une fois que ce test a été passé une fois, autoriser l'adresse IP quelles que soient les adresses (le MTA client a montré qu'il réessayait, de toute façon).
  • Permettre à l'administrateur système de configurer la période de quarantaine imposée au nouveau client. Le RFC définit une valeur par défaut souhaitable comme étant entre 1 minute et 24 heures (oui, c'est large). (Avec Postgrey, c'est l'option --delay.)
  • Supprimer les entrées de la base au bout d'une période d'inactivité configurable (par défaut, d'au moins une semaine, dit le RFC). (Avec Postgrey, c'est l'option --max-age.)
  • Considérer comme adresse IP de la source un préfixe entier (par exemple un /24 pour IPv4), pas juste une adresse, pour le cas des pools de serveurs SMTP (le second essai ne viendra pas forcément de la même machine). Cela réduit également la taille de la base nécessaire, ce qui peut être très important pour IPv6 (cf. section 7, ainsi que la section 9.2) où le nombre d'adresses potentielles est bien plus grand. (Postgrey a une option limitée, --lookup-by-subnet, mais où la longueur du préfixe est fixe, 24 bits en IPv4. Greyfix est plus souple.)
  • Permettre de définir une liste blanche d'adresses autorisées à passer outre. (Chez Postgrey, ce sont les fichiers de configuration comme /etc/postgrey/whitelist_clients.)
  • Ne pas faire de greylisting sur le service de soumission de courrier (RFC 6409).

En revanche, notre section 5 ne recommande pas de valeur particulière pour le code de retour SMTP lorsqu'on refuse temporairement un client. 421 et 450 semblent les deux choix possibles (RFC 5321, section 4.2.2).

SMTP permet de mettre dans la réponse, outre un code numérique, un court texte. Faut-il dire explicitement que du greylisting est en action, ce qui peut aider un spammeur ? Le RFC estime que oui, pour être sympa avec les utilisateurs légitimes (c'est ce que font les deux logiciels de greylisting montrés en exemple dans cet article).

La section 6 du RFC est consacrée à la question de la mesure de l'efficacité du greylisting. Elle suggère une expérience intéressante que, à ma connaissance, personne n'a tenté : regarder si les adresses IP greylistées (et qui ne réessaient pas) sont plus souvent présentes que les autres dans les grandes DNSBL. Une corrélation indiquerait qu'on gêne bien surtout les spammeurs.

Il existe aujourd'hui des mises en œuvre du greylisting pour à peu près tous les MTA possibles. Pour Postfix, les deux solutions les plus courantes en logiciel libre sont Greyfix et Postgrey. On configure Greyfix en indiquant dans le master.cf de Postfix :


greyfix    unix  -       n       n       -       -       spawn
  user=nobody argv=/usr/local/sbin/greyfix --greylist-delay 300 --network-prefix 28

Les deux options indiquées ici lui imposent de ne pas accepter un nouveau client avant 300 secondes, et de considérer toutes les adresses d'un même /28 comme équivalentes. (Greyfix peut aussi le faire en IPv6, avec --network6-prefix.). Un nouveau client rejeté est journalisé ainsi :


May 29 14:59:32 aetius postfix/smtpd[25150]: NOQUEUE: reject: RCPT from unknown[117.214.206.76]:4974: 450 4.7.1 <w3c@bortzmeyer.org>: Recipient address rejected: Greylisted by greyfix 0.3.9, try again in 300 seconds.  See http://www.kim-minh.com/pub/greyfix/ for more information.; from=<viagra-soft.pills@peoplecube.com> to=<w3c@bortzmeyer.org> proto=ESMTP helo=<rkktfe.com>

Pour Postgrey, qui tourne comme un démon séparé, ici sur le port 10023, la configuration se fera dans le main.cf :


smtpd_recipient_restrictions = permit_mynetworks, \
            check_policy_service inet:127.0.0.1:10023

Et un client rejeté produira :


May 28 16:08:33 lilith postfix/smtpd[20582]: NOQUEUE: reject: RCPT from 241.146.12.109.rev.sfr.net[109.12.146.241]:3964: 450 4.2.0 <info@generic-nic.net>: Recipient address rejected: Greylisted, see http://postgrey.schweikert.ch/help/generic-nic.net.html; from=<banderolepub01@gmail.com> to=<info@generic-nic.net> proto=SMTP helo=<3lyw4>
May 28 16:08:33 lilith postgrey[1447]: action=greylist, reason=new, client_name=241.146.12.109.rev.sfr.net, client_address=109.12.146.241, sender=banderolepub01@gmail.com, recipient=info@generic-nic.net 

Une question un peu philosophique, maintenant, que ne traite guère notre RFC. Pourquoi est-ce que les logiciels de spam courants ne réessaient pas, après l'erreur temporaire reçue ? Cela peut sembler déroutant puisque, de leur point de vue, ce serait la solution évidente au greylisting. Il y a plusieurs raisons à cette passivité. L'une est que le greylisting n'est pas universellement déployé. S'il l'était, les choses changeraient peut-être (finalement, était-ce une bonne idée de publier ce RFC ?) Ce point de vue est par exemple développé dans l'Internet-Draft draft-santos-smtpgrey. Ensuite, les spammeurs visent typiquement le volume, pas la qualité. Pourquoi s'embêter à réessayer alors qu'il est bien plus efficace, en terme de volume, de passer tout de suite à la victime suivante dans la liste ? Mais il y a aussi sans doute aussi crainte d'être repérés s'ils essaient : un zombie essaie en général d'être discret.

De bonnes lectures :

Merci à Kim-Minh Kaplan pour sa relecture.


Téléchargez le RFC 6647


L'article seul

RFC 6646: DECoupled Application Data Enroute (DECADE) Problem Statement

Date de publication du RFC : Juillet 2012
Auteur(s) du RFC : H. Song, N. Zong (Huawei), Y. Yang (Yale University), R. Alimi (Google)
Pour information
Réalisé dans le cadre du groupe de travail IETF decade
Première rédaction de cet article le 10 juillet 2012
Dernière mise à jour le 20 septembre 2012


Le groupe de travail DECADE de l'IETF travaillait à optimiser les applications pair-à-pair notamment en leur permettant de stocker facilement des données dans le réseau (on devrait dire le cloud, pour que ce RFC se vende mieux). Ce RFC décrit précisement les problèmes que DECADE essayait de résoudre, les solutions étant prévues pour de futurs documents. Le principal problème identifié est de doter les applications P2P d'accès à des caches dans le réseau, évitant d'utiliser de manière répétée des liens coûteux et/ou lents. DECADE ayant été fermé en septembre 2012, le projet ne se conclura sans doute pas.

Ce n'est pas que ces caches n'existent pas déjà : des tas d'applications en ont. Mais ils souffrent de limites : étant souvent spécifiques à une application (BitTorrent, FlashGet, Thunder, etc), ils ne peuvent pas être réutilisés via un protocole standard, et ils n'ont pas de mécanismes de contrôle d'accès permettant, par exemple, de mettre des données dans le cache mais de limiter leur accès à certains.

Le pair-à-pair sert à beaucoup de choses (deux cas connus sont le partage de fichiers, et le streaming vidéo) et ces usages sont souvent très consommateurs de ressources réseau. Cette consommation justifie qu'on travaille activement à limiter le gaspillage. C'est particulièrement gênant pour « le dernier kilomètre », la ligne, relativement lente, qui connecte M. Toutlemonde à son FAI. Les accès actuellement commercialisés sont presque toujours asymétriques (bien plus de capacité dans le sens TF1->temps-de-cerveau que dans le sens citoyen-producteur->réseau). Si M. Toutlemonde a un gros fichier sur le disque dur de son PC à la maison, et que dix personnes le téléchargent, le gros fichier encombrera dix fois l'accès « montant » de M. Toutlemonde, à son grand dam. Il est ainsi courant que la grande majorité de la capacité montante soit prise par le pair-à-pair. M. Toutlemonde pourrait « téléverser » le fichier une fois pour toutes chez un hébergeur situé « dans le nuage » mais attention : pour qu'il conserve les avantages du pair-à-pair, cela devrait être intégré dans les applications, sans qu'il y ait besoin d'un compte Dropbox (avec acceptation de conditions d'usage qui disent que le gérant du nuage fait ce qu'il veut des données), d'un téléversement explicite, etc. Bref, que cela se fasse tout seul.

Un problème analogue à celui de M. Toutlemonde est celui de l'hébergeur dont un client a un fichier qui intéresse dix personnes à l'extérieur de l'hébergeur. Faire passer le fichier dix fois sur les coûteux liens de transit n'est pas une utilisation géniale de la capacité réseau... À noter qu'une autre voie d'optimisation, complémentaire de celle de DECADE, est celle du groupe de travail ALTO, qui consiste à faciliter la découverte de ressources proches (« télécharger localement »), comme décrit dans le RFC 5693. ALTO ne fonctionne que si le contenu est déjà disponible localement. Sinon, DECADE prend le relais. Deux autres efforts IETF qui ont un rapport avec DECADE, et lui sont complémentaires, sont PPSP, sur la conception d'un protocole de streaming en pair-à-pair (RFC 7574), et LEDBAT, sur des mécanismes permettant à des applications non critiques de céder automatiquement les ressources réseau aux autres (RFC 6297 et RFC 6817).

On l'a vu, il existe déjà des applications pair-à-pair qui ont des formes de cachage des données. Mais chacune nécessite d'être adaptée à un protocole pair-à-pair particulier, alors que le travail de DECADE est plutôt de chercher des solutions génériques, qui pourraient convenir à tout nouveau protocole. Une telle solution générique n'existe pas actuellement. Mais des projets ont déjà été définis comme les Data Lockers. Avec un tel système, le PC de M. Toutlemonde pourrait téléverser le fichier dans le nuage, là où la capacité réseau est meilleure, et les pairs de M. Toutlemonde aller le chercher là-bas, sans que M. Toutlemonde ait d'action explicite à faire, et sans qu'il gaspille les ressources du dernier kilomètre.

L'exercice de DECADE sera donc de définir un protocole d'accès standard à ces ressources de stockage dans le nuage. Ce protocole comportera deux parts : la signalisation (permettant de découvrir les caractéristiques de ces ressources) et le transfert permettant de lire et d'écrire le contenu. La difficulté sera d'identifier ce qui est suffisamment commun chez tous les protocoles, pour faire l'objet d'une normalisation. Et le protocole devra être assez souple pour s'adapter à des applications pair-à-pair qui ont des caractéristiques très différentes.

Une étude a déjà été faite par le groupe de travail DECADE sur les systèmes de stockage des données en ligne. Documentée dans le RFC 6392, elle liste les systèmes existants sur lequels aurait pu être basé le futur protocole DECADE.

Si cela vous semble encore un peu flou, vous pouvez sauter à la section 4 qui présente des études de cas pour certaines applications. Par exemple, pour BitTorrent, ce qui est envisagé est de modifier les pairs pour qu'ils envoient les blocs de données (l'unité de transfert de base de BitTorrent) non pas à chaque autre pair mais à un cache dans le réseau, en indiquant au pair où le bloc a été mis.

Un autre cas étudié est celui des distributeurs de contenu (par exemple une vidéo) et qui voudraient le mettre le plus proche possible des « globes oculaires » (les consommateurs de contenu). Garder la vidéo sur son petit site Web mal connecté ne permettra pas une distribution efficace. Faire appel à un CDN imposera l'utilisation de l'interface spécifique de ce CDN, et tout sera à recommencer en cas de changement de fournisseur. Le protocole standard mentionné plus haut résoudrait ce problème. Pour ce cas, encore plus que pour celui du pair-à-pair, il est important que celui qui met des données dans le réseau puisse indiquer les règles d'accès (par exemple, ne distribuer qu'à des utilisateurs identifiés).

Tout cela, vous vous en doutez, soulève plein de problèmes de sécurité. La section 5 les passe en revue. D'abord, il y a un risque évident de déni de service, par exemple avec un méchant stockant tellement de données qu'il remplit tout le nuage et ne laisse rien pour les autres. Il est donc crucial d'avoir des mécanismes d'authentification et d'autorisation.

Ensuite, lorsqu'on dit « distribution de contenu multimédia », « partage en pair-à-pair », on peut être sûr que des hordes de juristes vont accourir et réclamer que les règles définies par l'industrie du divertissement soient automatiquement mises en œuvre par les systèmes techniques, ici par le stockage dans le nuage. (Par exemple, distribution du contenu à certains pays seulement, pour permettre de faire payer plus un sous-ensemble des pays.) Le RFC dit sagement que ce genre de demandes est hors-sujet pour le projet DECADE.

Le fournisseur du système de stockage va en apprendre beaucoup sur les utilisateurs, ce qui peut menacer leur vie privée. Même si le contenu est chiffré, le fait que N personnes demandent le même fichier est déjà une indication utile (qu'elles ont les mêmes centres d'intérêt). Un autre risque avec un fournisseur de stockage méchant est qu'il modifie le contenu des fichiers qu'on lui a confié. Le RFC ne fournit pas de solutions pour ces deux derniers problèmes (une signature cryptographique permettrait de traiter le second).

Bref, ce n'est pas le travail qui manquait pour le groupe DECADE. Il travaillait sur les trois futurs RFC de cahier des charges pour le protocole d'accès au stockage, de description de l'architecture du système, et de l'intégration avec les protocoles existants, comme BitTorrent. Mais les difficultés colossales de ce travail ont eu raison du groupe, qui a été dissous en septembre 2012. (Après coup, le travail déjà fait a été publié dans le RFC 7069.)


Téléchargez le RFC 6646


L'article seul

RFC 6640: IETF Meeting Attendees' Frequently Asked (Travel) Questions

Date de publication du RFC : Juin 2012
Auteur(s) du RFC : W. George (Time Warner Cable)
Pour information
Première rédaction de cet article le 25 juin 2012


Il n'y a pas que de gros RFC sérieux, détaillant pendant des dizaines de pages des protocoles compliqués. L'IETF est aussi une occasion de nombreuses rencontres dans le Vrai-Monde-Physique, grâce à ses réunions qui se tiennent trois fois par an dans des lieux éloignés (du point de vue de l'auteur du RFC et de ses lecteurs). Pour diminuer le stress de l'ingénieur en déplacement, il faut lui fournir de l'information. Laquelle ? Ce RFC répond à la question.

Il ne contient pas les réponses aux questions des étrangers en visite. Ces réponses dépendent du pays visité (et elles changent vite alors que les RFC sont statiques). Mais il liste les questions, de manière à ce que les indigènes puissent documenter les points importants de leur beau pays.

En effet, il y a toujours des volontaires locaux qui montent un site Web ou un Wiki pour présenter de l'information sur le site de la réunion. (Le RFC en donne des exemples.) S'ils suivent ce RFC, ils sont sûrs de n'oublier aucune question. Le RFC liste les grands sujets :

  • Lister les aéroports les plus proches (avec évidemment leur code IATA puisque les participants à l'IETF les utilisent fréquemment pour nommer leurs routeurs et serveurs),
  • Le meilleur moyen de se rendre de l'aéroport au lieu du meeting (la seule fois où je me suis fait agresser, pendant une réunion IETF, c'était dans le métro de Prague, où j'étais encombré de bagages).
  • Des cartes à imprimer avec les adresses importantes, dans l'écriture locale, pour montrer au chauffeur de taxi. J'étais très content de les avoir, en Chine ou au Japon.
  • La nourriture, le grand sujet de discussion sur la liste de diffusion des participants au meeting, les ingénieurs n'ont pas d'estomacs virtuels, et il en faut, des cookies, pour nourrir un participant à l'IETF. Les habitués d'autres conférences internationales noteront qu'il n'y a pas de déjeûner servi pendant les réunions IETF, il faut se débrouiller dans les environs, ce qui anime de nombreux débats sur la liste. Le RFC précise aussi qu'il faut indiquer les restaurants calmes, au cas où des participants veuillent travailler à un protocole compliqué (bien des protocoles TCP/IP ont été conçus dans un restaurant).
  • Les prises électriques, bien sûr, car chaque membre de l'IETF se déplace avec de nombreux engins gourmands à brancher, et préfère manquer de nourriture que d'électricité pour son ordinateur. Heureusement, il existe un excellent site Web sur ce sujet. Dans la même veine, le RFC rappelle aux auteurs de sites Web ou de Wikis d'information que les participants apprécieront certainement des informations sur l'achat de cartes SIM ou les offres d'abonnement 3G locales. Même chose pour les boutiques de matériel (un autre grand classique de la liste de diffusion du meeting est « Cherche adaptateur secteur pour mon Dell Vostro, j'ai perdu le mien, une boutique qui aurait ça pas loin ? »)
  • Les sujets désagréables comme les escroqueries locales ou bien ce que le RFC appelle « la faune hostile » (les réunions IETF se tenant toujours dans les grandes villes, aucun participant n'a jamais été mangé par un lion ou renversé par un rhinocéros).

Bref, un RFC pour les aventuriers, les explorateurs et les curieux. Voyagez, vous ne le regretterez pas.


Téléchargez le RFC 6640


L'article seul

RFC 6637: Elliptic Curve Cryptography (ECC) in OpenPGP

Date de publication du RFC : Juin 2012
Auteur(s) du RFC : A. Jivsov (Symantec Corporation)
Chemin des normes
Première rédaction de cet article le 12 juin 2012


Le format OpenPGP, normalisé dans le RFC 4880, permet de choisir parmi plusieurs algorithmes de cryptographie, afin de pouvoir suivre les progrès de la cryptanalyse. Notre tout nouveau RFC ajoute à la liste de ces algorithmes des algorithmes à courbes elliptiques, venant s'ajouter aux traditionnels RSA et DSA. Il a par la suite été intégré à la nouvelle version de la norme OpenPGP, dans le RFC 9580.

La section 3 rappelle deux ou trois choses sur les courbes elliptiques. Celles-ci sont décrites dans le RFC 6090 mais pour ceux et celles qui voudraient un cours plus scolaire, ce RFC recommande le Koblitz, « A course in number theory and cryptography », chapitre VI « Elliptic Curves » (ISBN: 0-387-96576-9, Springer-Verlag, 1987). La motivation principale pour utiliser les courbes elliptiques est qu'elles fournissent une alternative à l'augmentation régulière de la taille des clés RSA, augmentation rendue nécessaire par les avancées de la cryptanalyse. La section 13 de ce RFC fournit une estimation quantitative : la courbe elliptique P-256, avec ses 256 bits, fournit à peu près la résistance d'une clé RSA de 3 072 bits. Et la P-384 fournit environ l'équivalent de 7 680 bits RSA.

La NSA a listé une série d'algorithmes à courbes elliptiques recommandés, sous le nom de Suite B. Celle liste comprend deux algorithmes, ECDSA et ECDH, et trois courbes elliptiques (cf. norme NIST FIPS 186-3) P-256, P-384 et P-512. Ce RFC décrit donc comment intégrer la suite B au format ouvert et normalisé OpenPGP. Les deux algorithmes ont reçu les numéros 19 (pour ECDSA) et 18 (pour ECDH).

Si vous voulez l'encodage exact des paramètres de la courbe elliptique dans les données, voir les sections 6 à 8 de notre RFC. L'encodage des clés cryptographiques figure en section 9.

Au moins deux mises en œuvre d'OpenPGP ont déjà du code pour ces courbes elliptiques, celle de Symantec et le logiciel libre GnuPG. Pour ce dernier, le code est déjà dans la version de développement (tête du dépôt git) mais pas encore dans la dernière version officiellement publiée (la 2.0.19).


Téléchargez le RFC 6637


L'article seul

RFC 6635: RFC Editor Model (Version 2)

Date de publication du RFC : Juin 2012
Auteur(s) du RFC : O. Kolkman (IAB), J. Halpern (Ericsson)
Pour information
Première rédaction de cet article le 12 juin 2012


L'articulation compliquée entre l'IETF qui produit les normes TCP/IP et le RFC Editor qui les publie, n'a jamais cessé de faire couler de l'encre (ou d'agiter des électrons). Dans ce document, l'IAB décrit un modèle pour le RFC Editor, modèle où les fonctions de ce dernier sont éclatées en plusieurs fonctions logiques. Elles peuvent ainsi être réparties entre plusieurs groupes. Ce modèle « v2 » est une version légèrement modifiée de la première description (« v1 »), qui figurait dans le RFC 5620. À son tour, il a été remplacé (mais sans changement fondamental du modèle) par le RFC 8728.

Le document de référence actuel est le RFC 8729. Comme le rappelle la section 1, il décrit les tâches du RFC Editor de manière globale, comme si c'était forcément une seule entité (c'était, à l'origine, une seule personne, Jon Postel). La section 2 note que la tâche de RFC Editor est actuellement une partie de l'IASA et financée par son budget.

La même section 2 s'attaque à la définition du rôle du RFC Editor sous forme de fonctions séparées. Le RFC 5620 avait été le premier à décrire ces fonctions. Elles sont ici légèrement modifiées, compte-tenu de l'expérience et des problèmes rencontrés, problèmes de communication qui n'existaient évidemment pas lorsque Postel faisait tout lui-même. (Notez que notre RFC 6635 ne donne malheureusement pas la liste des changements les plus importants, par rapport à la v1 du RFC 5620. Il est vrai qu'il n'y a rien de crucial, juste de la cuisine organisationnelle.) Le terme de RFC Editor désigne collectivement toutes ces fonctions. L'IAB voit maintenant trois fonctions (voir aussi le dessin 1 de notre RFC) :

  • Éditeur de la série des RFC,
  • Producteur des RFC,
  • Publieur des RFC,
  • Enfin, l'éditeur des contributions indépendantes, qui était présent dans l'ancien RFC 5620 est désormais décrit à part, dans le RFC 6548.

Chaque section va ensuite détailler ces tâches. Il y a également des rôles de supervision, tenus par l'IAB (RFC 2850) et l'IAOC (RFC 4071).

L'Éditeur de la série des RFC (RFC Series Editor, actuellement Heather Flanagan ) est décrit en premier, en section 2.1. Il est responsable du travail à long terme, il doit définir les principes qui assurent la pérennité des RFC, réfléchir à la stratégie, développer le RFC 7322, le guide de style des RFC (ce qui inclus les délicates questions du format, de la langue des RFC, etc), etc. Il sert aussi de « visage » aux RFC, vis-à-vis, par exemple, des journalistes. L'Éditeur est censé travailler avec la communauté IETF pour les décisions politiques.

Le RFC 6635 évalue la charge de travail à un mi-temps, ce qui me semble très peu. Notre RFC décrit les compétences nécessaires (section 2.1.6) pour le poste d'Éditeur de la série des RFC, compétences en anglais et en Internet, capacité à travailler dans l'environnement... spécial de l'IETF, expérience des RFC en tant qu'auteur souhaitée, etc.

Le travail quotidien est, lui, assuré par le Producteur des RFC (RFC Production Center) dont parle la section 2.2. C'est un travail moins stratégique. Le Producteur reçoit les documents bruts, les corrige, en discute avec les auteurs, s'arrange avec l'IANA pour l'allocation des numéros de protocoles, attribue le numéro au RFC, etc.

Les RFC n'étant publiés que sous forme numérique, il n'y a pas d'imprimeur mais le numérique a aussi ses exigences de publication et il faut donc un Publieur des RFC (RFC Publisher), détaillé en section 2.3. Celui-ci s'occupe de... publier, de mettre le RFC dans le dépôt où on les trouve tous, d'annoncer sa disponibilité, de gérer l'interface permettant de soumettre les errata, de garder à jour ces errata, et de s'assurer que les RFC restent disponibles, parfois pendant de nombreuses années.

Chacune de ces fonctions pourra faire l'objet d'une attribution spécifique (à l'heure actuelle, les fonctions de Producteur et de Publieur sont assurées par le même groupe à l'AMS). La liste à jour peut être vue sur le site officiel.

Un comité joue un rôle de supervision et de contrôle du RFC Editor : le RSOC (RFC Series Oversight Committee) est décrit en section 3.

Combien cela coûte et qui choisit les titulaires des différentes fonctions ? La section 4 décrit ce rôle, dévolu à l'IAOC (RFC 4071). Le budget est publié en sur le site de l'IAOC ainsi que l'évaluation du RFC Editor. On peut aussi trouver cette information, ainsi que plein d'autres sur le fonctionnement du RFC Editor, via le site officiel).


Téléchargez le RFC 6635


L'article seul

RFC 6633: Deprecation of ICMP Source Quench messages

Date de publication du RFC : Mai 2012
Auteur(s) du RFC : F. Gont (UTN-FRH / SI6 Networks)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF tsvwg
Première rédaction de cet article le 29 mai 2012


Il y avait belle lurette que les messages ICMP « Répression de la source » (Source Quench) n'étaient plus utilisés. Ces messages devaient servir, à l'origine, à signaler à un émetteur qu'il exagérait et qu'il devrait ralentir l'envoi de données. Divers problèmes, notamment de sécurité, font que ces messages sont désormais ignorés par toutes les mises en œuvre de TCP/IP. Mais cet abandon de fait n'avait jamais été documenté. Voilà qui est fait, ce RFC 6633 marque donc l'abandon officiel de la répression de la source.

À l'origine, cette répression (quench) avait été normalisée dans le RFC sur ICMP pour IPv4, le RFC 792. De type 4 et de code 0, le message Source Quench était censé limiter la congestion en disant à l'émetteur qu'un récepteur n'arrivait plus à suivre. Inefficace et injuste, le Source Quench n'a jamais été très utilisé. Les routeurs ont officiellement arrêté de s'en servir avec le RFC 1812, dès 1995. Ce RFC notait déjà les limites et problèmes du Source Quench (dans sa section 4.3.3.3, qui fournissait des références).

En outre, les messages Source Quench, n'étant pas authentifiés, posaient un gros problème de sécurité : un méchant pouvait générer de faux messages pour réduire le débit de son ennemi, comme expliqué dans le RFC 5927 (et la section 8 de notre RFC). C'est d'ailleurs à cause de cela que des IDS comme Snort couinent lorsqu'ils voient passer des messages de répression de la source (voir Anderson, D., Fong, M., et A. Valdes, « Heterogeneous Sensor Correlation: A Case Study of Live Traffic Analysis », Proceedings of the 3rd Annual IEEE Information Assurance Workshop New York, NY, USA, 2002).

Restaient les protocoles de transport. Le RFC 1122 disait dans sa section 4.2.3.9 que les machines terminales devaient réagir aux Source Quench en diminuant le débit émis. La méthode recommandée pour TCP était de revenir au démarrage en douceur (RFC 5681).

De fait, le problème est réglé depuis longtemps, comme le documentait le RFC 5927 : les mises en œuvre de TCP et autres protocoles de transport ignorent les messages Source Quench depuis au moins 2005, RFC 1122 ou pas RFC 1122. L'annexe A de notre RFC 6633 fait le tour des implémentation TCP/IP et note que Linux a commencé à ignorer ces messages en 2004, FreeBSD, NetBSD et Solaris depuis 2005, etc. Voici par exemple ce que fait NetBSD (fichier sys/netinet/tcp_subr.c, routine tcp_ctlinput() :

if (cmd == PRC_QUENCH)
	/* 
	 * Don't honor ICMP Source Quench messages meant for
         * TCP connections.
         */
	return NULL;

Bref, ce RFC ne fait que documenter l'état des choses déjà existant.

En outre, ces messages Source Quench sont largement filtrés et ont donc peu de chances d'atteindre les machines qui émettent les données. Une étude de 1994 (Floyd, S., « TCP and Explicit Congestion Notification », ACM CCR Volume 24, Issue 5) notait déjà qu'on trouvait très peu de tels messages dans la nature. À la place, les routeurs sont censés utiliser ECN (RFC 3168) et (même si le RFC ne le rappelle pas), les machines terminales doivent de toute façon réagir aux pertes de paquets en ralentissant leur émission (RFC 5681).

Donc, le Source Quench est désormais officiellement abandonné. La section 3 de notre RFC modifie le RFC 1122 en demandant aux machines terminales de ne pas émettre de tels messages et d'ignorer ceux qu'elles recevraient. La section 4 fait de même pour les routeurs. La section 9 demande à l'IANA de marquer ces messages comme abandonnés dans le registre ICMP.

Il n'y avait pas de règle précise dans le passé pour d'autres protocoles de transport comme UDP ou SCTP. Les sections 5 et 6 de notre RFC leur applique la même règle : il faut ignorer complètement les messages de répression de la source qu'on pourrait recevoir.

Ah, et puis quelqu'un avait proposé une utilisation des messages Source Quench dans le RFC 1016. Suivant l'idée générale d'abandonner ces messages, la mise en œuvre de ce RFC est donc désormais déconseillée (cf. section 7).

De toute façon, le problème aurait disparu avec IPv4 : IPv6, lui, n'a jamais eu de message Source Quench (RFC 4443).


Téléchargez le RFC 6633


L'article seul

RFC 6632: An Overview of the IETF Network Management Standards

Date de publication du RFC : Juin 2012
Auteur(s) du RFC : M. Ersue (Nokia Siemens Networks), B. Claise (Cisco)
Pour information
Réalisé dans le cadre du groupe de travail IETF opsawg
Première rédaction de cet article le 2 juin 2012


Selon une vieille blague de l'informatique, « ce qu'il y a de bien avec les standards, c'est qu'il y en a beaucoup parmi lesquels choisir. » Cette blague a été reprise dans un célèbre dessin de xkcd. Le but de ce RFC est-il de prendre le relais en montrant la variété des normes IETF relatives à la gestion des réseaux TCP/IP ?

En fait, non. Le but est de s'arrêter deux secondes de développer des nouveaux protocoles et de regarder ce qui existe (il y a donc une imposante bibliographie, reflet des très nombreux RFC cités). À une époque, il y avait un rêve, celui d'un protocole unique pour la gestion des réseaux (cela devait être SNMP). L'évolution des choses fait qu'aujourd'hui, l'architecte réseaux a à sa disposition plusieurs protocoles, dont les rôles se recouvrent en bonne partie. Même chose pour le membre de l'IETF qui développe un nouveau protocole et cherche des mécanismes de gestion de ce protocole. Ce RFC est donc juste un moyen de les aider à y voir plus clair. Il peut ausssi servir aux autres SDO qui veulent se renseigner sur le travail déjà existant, pour éviter de le dupliquer. Le lecteur pressé peut sauter tout de suite à l'annexe A du RFC (résumée à la fin de cet article), qui classe rapidement les protocoles avec des tableaux synthétiques.

D'abord, c'est quoi, la gestion des réseaux ? Ce sont l'ensemble des méthodes et techniques mises en œuvre par l'administrateur réseaux pour s'assurer que le réseau va bien, prévoir ses évolutions, et réparer ses pannes. Cela va du bon vieux ping aux mécanismes les plus complexes. (Si vous suivez les débats sur la neutralité de l'Internet, vous êtes peut-être déjà tombé sur des termes comme « services gérés » ou « gestion de trafic ». Il faut savoir que ces termes relèvent de la propagande des opérateurs réseaux, qui cherchent à justifier des services privilégiés - et plus chers - en prétendant qu'ils seraient « gérés », comme si le reste de l'Internet marchait tout seul. Les termes corrects sont « services privilégiés » et « discrimination de trafic ».)

Il y a déjà eu des RFC analogues à celui-ci (section 1.2). Par exemple, le RFC 6272 faisait le tour de tous les protocoles TCP/IP (y compris ceux sur la gestion de réseaux) dans le contexte de la Smart grid. Le RFC 3535 rendait compte d'un atelier de l'IAB consacré à la gestion de réseaux, qui avait examiné la situation en 2002. Le RFC 5706 posait les règles relatives à la gestion pour tous les nouveaux protocoles IETF, imposant qu'ils prennent en compte cette gestion dès le premier RFC. Enfin, les RFC 4221 et RFC 6371 décrivent le cas spécifique de la gestion des réseaux MPLS et sont à l'origine d'un conflit de compétences avec l'UIT qui dure encore aujourd'hui (cf. RFC 5704). Plusieurs Internet-Drafts sont également en cours de rédaction sur ce sujet de l'OAM (Operations, Administration and Maintenance, ce sigle est souvent utilisé dans le monde MPLS pour parler de la gestion des réseaux).

La section 2 de notre RFC couvre les protocoles de gestion généralistes, qui peuvent servir à tout. Le premier est évidemment SNMP (section 2.1). Il s'agit en fait d'une structure modulaire, avec un modèle de données (les fameuses MIB), un mécanisme d'encodage de ces données sur le réseau et un protocole, SNMP. Le RFC de description général est le RFC 3410, pour SNMPv3. Un réseau est vu par SNMP comme un ensemble de machines gérées (les agents), une ou plusieurs machines de gestion (le ou les managers) et le protocole utilisé entre les deux (SNMP). Les variables exportées par l'agent sont décrites dans une MIB, et il en existe des dizaines de normalisées et encore plus de privées.

SNMP v1 (RFC 1157) et v2 avaient de sérieuses limites en matière de sécurité, la version officielle aujourd'hui est donc la v3, normalisée dans le RFC 3411 (mais la v1 reste très utilisée). SNMP est présent partout, pour lire les valeurs des variables des équipements réseaux, faire des statistiques, aider à déboguer les pannes, etc. C'est un des grands succès de l'IETF.

Pour décrire les données récupérées en SNMP, un cadre standard existe nommé SMI (Structure of Managed Information), actuellement en version 2, normalisée dans les RFC 2578 et RFC 2579. Ces RFC définissent entre autre le langage dans lequel sont écrits les MIB.

SNMP est, on l'a vu, très répandu, et le RFC lui consacre à juste titre de nombreuses pages, parlant de sa sécurité, du mécanisme de transport, etc. Un autre protocole très populaire pour la gestion de réseaux est syslog (section 2.2). Il est concurrent de SNMP pour le signalement de problèmes (les traps de SNMP) mais, autrement, il ne remplit pas le même rôle. syslog sert à une machine à transmettre de l'information (pas forcément une panne) en temps réel, à des fins d'alarme ou de journalisation. Décrit d'abord dans le RFC 3164, il est désormais normalisé (sous une forme bien plus riche) dans le RFC 5424. Le syslog traditionnel des débuts ne prévoyait pas de structure pour le message envoyé : c'était juste du texte libre. Le RFC 5424 a introduit la notion de messages syslog structurés, analysables par un programme.

Si syslog est très répandu (on trouve des récepteurs syslog en logiciel libre sur tous les Unix, tous les routeurs savent émettre du syslog, etc), je ne suis pas sûr que les extensions modernes, encore peu implémentées, soient souvent utilisées.

Autre protocole très répandu dans la boîte à outils de l'administrateur réseaux, IPFIX (souvent désigné par son ancien nom, NetFlow). La section 2.3 décrit son rôle : IPFIX permet de récolter de l'information statistiques sur les flots de données qui sont passés par un routeur (« [2001:db8:1::42]:35612 a parlé à [2001:db8:cafe::1337]:80 et il a reçu 935 ko ») et de la transmettre à une machine de gestion. Avoir des compteurs par flot (un flot étant typiquement une connexion TCP complète) permet d'avoir une information plus légère que si on transmettait des données sur chaque paquet.

L'architecture d'IPFIX est décrite dans le RFC 5470 et le protocole est dans le RFC 7011. L'ancien Netflow, lui, était décrit dans le RFC 3954. IPFIX/Netflow est très répandu et la plupart des opérateurs l'utilisent pour suivre l'activité de leurs réseaux. (Le logiciel libre ntop le parle, entre autres.)

Si on veut suivre les paquets individuels, il y a le protocole PSAMP (Packet SAMPling) du RFC 5474. Il permet d'utiliser le protocole d'IPFIX pour transmettre des données sur les paquets (qu'on a pu, pour limiter le trafic, échantilloner, comme bien expliqué dans le RFC 5475).

IPFIX, syslog et SNMP (tel que réellement utilisé dans la plupart des cas, sans ses fonctions d'écriture) ne font que lire les informations. Si on veut les modifier, si on veut changer la configuration d'un routeur, par exemple, que fait-on ? SNMP avait théoriquement un mécanisme pour cela mais, en pratique, il n'est que très rarement utilisé. L'atelier de l'IAB raconté dans le RFC 3535 identifiait ce manque (section 2.4) et l'un des résultats a été le protocole NETCONF normalisé dans le RFC 6241. NETCONF permet d'envoyer des commandes de configuration (encodées en XML) à un équipement réseau. Relativement récent, NETCONF n'est pas encore d'usage universel.

Pour décrire les données manipulées par NETCONF, l'IETF a un langage, YANG (RFC 6020). Celui-ci dispose d'un certain nombre de types de données pré-existants, normalisés dans le RFC 6991. Ces types sont évidemment proches de ceux que le SMI v2 avait déjà, pour SNMP. Idéalement, il faudrait encore ajouter une traduction standard de SMI vers YANG, afin de pouvoir récupérer toutes les MIB existantes. Pour l'utilisation de NETCONF et de YANG dans une solution globale, voir le RFC 6244. YANG est encore plus récent que NETCONF et encore peu déployé.

Tous ces protocoles, SNMP, syslog, NETCONF, etc, sont génériques et peuvent servir à gérer des tas de protocoles différents. La section 3 couvre au contraire les protocoles de gestion spécifiques, liés à une tâche donnée. Elle commence avec les protocoles de gestion de l'allocation d'adresses IP (section 3.1). D'abord, DHCP (RFC 2131 et RFC 8415). Il permet de transmettre à une machine son adresse IP mais aussi plein d'autres informations de configuration comme le résolveur DNS à utiliser (RFC 3646). DHCP n'offre aucun mécanisme de sécurité et le RFC rappelle donc qu'il vaut mieux ne l'utiliser que sur des réseaux dont l'accès physique est contrôlé.

Les adresses IP peuvent aussi être configurées automatiquement, sans serveur, dans le cadre décrit par le RFC 5889.

Depuis de nombreuses années, l'Internet est en cours de transition (très lente) d'IPv4 vers IPv6. Cette transition a donné naissance à tout un ensemble de techniques spécifiques, à commencer par le RFC 4213.

Une part importante de la gestion des réseaux est la mesure des performances (section 3.4). Ce n'est pas tout d'aller bien, il faut encore aller vite. Un groupe de travail IETF spécialisé, IPPM existe depuis longtemps pour développer des métriques (des grandeurs mesurables et rigoureusement définies) pour les réseaux TCP/IP. Il a produit un document de cadrage (RFC 2330), un document sur le développement de nouvelles métriques (RFC 6390), et de nombreuses métriques comme le délai de transmission (RFC 7679), le taux de pertes (RFC 7680), la mesure de la duplication de paquets (RFC 5560), etc. Pour pouvoir mesurer effectivement ces métriques, plusieurs protocoles ont été créés comme OWAMP (One-way Active Measurement Protocol, RFC 4656).

Toujours dans cette section de protocoles divers, une part importante est dédiée à RADIUS (RFC 2865), protocole permettant l'authentification d'un client, connecté à un NAS (Network Access Server), et utilisant un serveur d'authentification partagé entre plusieurs NAS. RADIUS permet par exemple à un FAI de centraliser l'authentification afin d'éviter que chaque NAS ait une base d'utilisateurs différente. Il est très largement utilisé aujourd'hui. De nombreux RFC sont venus lui ajouter telle ou telle fonction, ou guider les programmeurs (RFC 5080).

Officiellement, RADIUS a un concurrent, Diameter (RFC 6733). Conçu après, incompatible avec la base déployée, censé résoudre des problèmes réels ou supposés de RADIUS, Diameter n'a guère eu de succès. Le RFC oublie complètement de mentionner cet échec ; RADIUS est simple et facilement implémentable, Diameter, grosse usine à gaz, ne l'a jamais réellement concurrencé.

La section 3 décrit encore plusieurs autres protocoles peu connus, mais j'arrête ici. Il y a un autre gros morceau à avaler, les modèles de données pour la gestion de réseaux (section 4). Ils sont très nombreux et couvrent beaucoup d'aspects de la gestion de réseaux. Un de mes préférés est le peu connu RMON (RFC 2819), qui modélise des sondes réseaux. Il permet de déclencher à distance, avec SNMP, des mesures du réseau.

L'annexe A, présentée au début, est une sorte de résumé pour lecteurs pressés. Elle classe les différents protocoles de gestion de réseaux (rappelez-vous que la liste est longue) selon divers critères (fonctionnement en push ou en pull, passif ou actif, extensibilité de leur modèle de données, etc)

Le premier tableau, en A.1, classe les protocoles selon leur place dans le chemin des normes (cf. RFC 2026, notre RFC ne tient pas encore compte de la réduction de ce chemin à deux entrées, dans le RFC 6410). Ainsi, SNMP est Internet standard (norme au sens propre) alors qu'IPFIX n'est que Proposed standard (projet de norme) et que DHCP n'a jamais décollé de la première étape, Draft standard (proposition de norme), en dépit de son très vaste déploiement.

Autre façon de classer, en A.2, selon les tâches à accomplir. Syslog et SNMP permettent la surveillance du réseau mais SNMP permet en outre d'agir sur la configuration de celui-ci (en pratique, il n'est guère utilisé pour cette tâche). NETCONF peut faire de la configuration, mais, si on veut mesurer les performances, ce sont SNMP et IPFIX.

Comment ces protocoles font-ils leur travail (A.3) ? SNMP et NETCONF sont pull (la machine de gestion décide quand agir), Syslog, RADIUS ou IPFIX sont purement push (ils réagissent aux événements extérieurs). Notez que SNMP a aussi une fonction Push, les notifications (auutrefois nommées traps).

Autre façon de les regarder travailler (A.4), certains protocoles sont actifs posant des questions au réseau (ping et traceroute - RFC 1470, BFD - RFC 5880, OWAMP, etc). D'autres sont passifs, observant simplement le réseau (IPFIX, PSAMP, etc).

Le travail de gestion des réseaux ne s'arrêtera jamais. Il y aura toujours de nouveaux problèmes et de nouvelles solutions. L'annexe B décrit un travail récent à l'IETF, la gestion de l'énergie, préoccupation désormais très forte, en raison de l'augmentation des coûts de l'électricité et des soucis écologiques plus présents (menant par exemple à des lois plus strictes). Actuellement, dans la gestion de réseaux, il est rare que la consommation électrique soit prise en compte. Les serveurs ne distribuent pas cette information et les logiciels de gestion ne la demandent pas. On surveille le taux de pertes de paquets, le débit, mais pas la consommation électrique au niveau de chaque machine.

Une des difficultés pour effectuer cette mesure est que la consommation électrique est souvent mieux mesurée en dehors de la machine, par exemple par une source PoE, ou bien par un bandeau électrique « intelligent ». Il faut donc travailler, entre autres, sur la liaison entre une machine et sa consommation. C'est la tâche du groupe de travail IETF EMAN (cf. RFC 6988 et RFC 7326, publiés depuis).


Téléchargez le RFC 6632


L'article seul

RFC 6608: Subcodes for BGP Finite State Machine Error

Date de publication du RFC : Mai 2012
Auteur(s) du RFC : J. Dong, M. Chen (Huawei Technologies), A. Suryanarayana (Cisco Systems)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF idr
Première rédaction de cet article le 7 mai 2012


Un très court RFC pour enrichir la liste des codes d'erreur qu'un routeur BGP peut envoyer à son pair en cas de problèmes dans l'automate à états finis du protocole. Cela devrait permettre d'améliorer les messages d'erreur vus par les opérateurs de routeurs.

La section 4.5 du RFC 4271 (qui normalise BGP), indique le mécanismes des codes d'erreur à envoyer à un pair en cas de problèmes. Il y a les codes (1 pour une erreur dans l'en-tête d'un paquet, 2 pour une erreur à l'ouverture d'une session, 3 pour une erreur lors du traitement d'une mise à jour des routes, etc) et les sous-codes, dont la signification dépend du code. Ainsi, lorsque le code vaut 2 (erreur lors d'une ouverture de session BGP entre deux pairs), un sous-code 2 indique que le numéro d'AS du pair n'est pas celui qui était configuré (tcpdump affiche cette erreur avec BGP (NOTIFICATION: error OPEN Message Error, subcode Bad Peer AS). Lorsque le code d'erreur est 3 (erreur lors d'un message UPDATE), le sous-code 2 veut dire, par contre, qu'un attribut BGP envoyé par le pair est inconnu.

Un des codes d'erreur est 5, problème dans l'automate à états finis : typiquement, un message a été reçu alors qu'il n'aurait pas dû l'être, vu l'état actuel de l'automate. Mais ce code 5 n'avait pas de sous-code (cf. RFC 4271, section 6.6) et il était donc difficile de connaître le problème exact. Ce RFC comble ce manque.

Les nouveaux sous-codes sont donc (la liste des états de l'automate est dans le RFC 4271, section 8.2) :

  • 0 : erreur non spécifiée (la situation actuelle).
  • 1 : message inattendu alors que l'envoyeur de l'erreur était dans l'état OpenSent. Par exemple, si un routeur est dans l'état OpenSent (message OPEN envoyé mais pas encore de réponse favorable) et reçoit un message UPDATE (mise à jour des routes, ne devrait être envoyé que si la session est opérationnelle), alors il renverra un message NOTIFICATION avec le code à 5 et le sous-code à 1.
  • 2 : message inattendu alors que l'envoyeur de l'erreur était dans l'état OpenConfirm,
  • 3 : message inattendu alors que l'envoyeur de l'erreur était dans l'état Established (session BGP opérationnelle). Ce serait le cas, par exemple, d'un message OPEN reçu dans cet état.

Ces sous-codes sont enregistrés à l'IANA et de nouveaux sous-codes ne pourront être ajoutés que via un RFC sur le chemin des normes (cf. RFC 5226).

L'annonce du RFC notait qu'il existait déjà deux mises en œuvre de ces sous-codes mais j'avoue ignorer desquelles il s'agit.


Téléchargez le RFC 6608


L'article seul

RFC 6606: Problem Statement and Requirements for 6LoWPAN Routing

Date de publication du RFC : Mai 2012
Auteur(s) du RFC : E. Kim (ETRI), D. Kaspar (Simula Research Laboratory), C. Gomez (Universitat Politecnica de Catalunya/i2CAT), C. Bormann (Universitaet Bremen TZI)
Pour information
Réalisé dans le cadre du groupe de travail IETF 6lowpan
Première rédaction de cet article le 29 mai 2012


Il y en a, des RFC produits par le groupe de travail 6lowpan, qui a pour tâche de normaliser des protocoles pour les LowPAN (Low-Power Wireless Personal Area Network), ces réseaux de toutes petites machines, limitées en puissance de calcul et en électricité (réseaux de capteurs industriels, par exemple). Parmi les questions soulevées par les LowPAN, le routage. Les liens radio 802.15.4 entre les machines ont une portée limitée et la communication entre deux machines quelconques du LowPAN nécessite parfois une transmission par un ou plusieurs routeurs intermédiaires. Les normes des couches basses, comme IEEE 802.15.4 ne spécifient pas de mécanisme pour gérer ce routage. Ce RFC 6606 est le cahier des charges pour les protocoles de routage du LowPAN, protocoles qui seront établis par d'autres groupes comme Roll, qui travaille sur un problème plus général que celui des seuls LowPAN et a normalisé le protocole RPL dans le RFC 6550. Notez qu'il y a eu d'autres RFC proches comme le RFC 5826 qui se focalise sur le cas particulier de la domotique, ou le RFC 5673, pour les réseaux industriels.

Pour réviser les caractéristiques des machines d'un LowPAN, le mieux est de lire le RFC 4919. Pour savoir comment IPv6 (le 6 dans le nom du groupe 6lowpan) fonctionne sur un LowPAN, c'est le RFC 4944. Un point important à garder en tête avant d'étudier le routage est que ce dernier consomme des ressources (courant électrique, par exemple) et qu'il faut donc limiter cette fonction aux machines les mieux pourvues.

La norme de couche 2 IEEE 802.15.4, sur laquelle s'appuient les LowPAN ne dit pas comment les topologies sont établies puis maintenues. Et elle ne spécifie pas de protocole de routage. Dans un LowPAN, on distingue traditionnellement deux formes de « routage », une en couche 2, le mesh under (brièvement mentionné dans le RFC 4944 : tout le LowPAN est un seul réseau IP), et une en couche 3 (la seule qu'on devrait normalement appeler « routage »), le route over. Le groupe Roll cité plus haut ne travaille que sur le route over (le « vrai » routage) mais notre RFC 6606 couvre les deux formes. Pour le routage, l'IETF a déjà des tas de protocoles (comme OSPF). Mais aucun ne convient aux LowPAN, en raison de leurs caractéristiques propres (notamment les faibles ressources en processeur et en puissance électrique, et le problème spécifique posé par l'hibernation).

Le RFC 4919 formulait déjà des exigences spécifiques pour les protocoles de routage du LowPAN : minimisation de la consommation de ressources, et acceptation des machines qui hibernent pendant la majorité du temps. Ce RFC 6606 reprend et détaille ces exigences.

Notez que, dans un LowPAN typique, les adresses allouées aux machines n'ont aucune chance de suivre la topologie du réseau. Il n'y a donc pas de possibilité de router par préfixe IP, d'agréger des préfixes adjacents, etc.

Il y a beaucoup de sortes de LowPAN, d'autant plus qu'on en est aux débuts et qu'on ne sait pas encore tout. La section 4 détaille les caractéristiques des différents types de LowPAN qui peuvent avoir une influence sur les algorithmes de routage. Par exemple, le nombre de machines est un des principaux (un algorithme d'inondation n'est envisageable que dans les petits réseaux). Or, un LowPAN peut aller de deux machines (cas de capteurs dans le corps humain, les Body Area Network) à des millions de machines (grande usine).

Et c'est à partir de la section 5 qu'on en arrive aux exigences explicites pour l'algorithme de routage. Elles sont numérotées Rn, de R1, à R18 mais, rassurez-vous, je ne les expliquerai pas toutes.

R1 est liée à la taille des machines du LowPAN. Elle exige un mécanisme de routage qui convienne à ces toutes petites machines. Par exemple, certaines auront si peu de mémoire qu'il faudra limiter la table de routage à 32 entrées. Le système de routage doit donc permettre de stocker une table partielle, ou fortement résumée (voir aussi R10). Pour donner une idée des contraintes, certaines machines auront entre 4 et 10 ko de mémoire vive, et seulement 48 à 128 ko de mémoire Flash, pour stocker le code du programme de routage. Un MICAz a 4ko/128ko, un TIP700CM 10ko/48ko. Il faudra donc des algorithmes simples, pour que le code tienne dans ces mémoires.

L'exigence R2 porte sur la consommation électrique : il faut un mécanisme qui la limite. Par exemple, un paquet de diffusion va potentiellement réveiller toutes les machines du lien, les forçant à traiter ce paquet. Il faut donc les éviter. Même si le temps de processeur est à économiser, il faut se rappeler que la principale cause de consommation d'électricité, de loin, est la radio. Celle du TR1000 consomme 21 mW en transmission et 15 mW en réception.

Le LowPAN fonctionnant sur 802.15.4, il doit tenir compte des caractéristiques de celui-ci. Par exemple, R3 demande que les paquets de contrôle du protocole de routage tiennent dans une seule trame 802.15.4 pour éviter toute fragmentation. D'autre part, 802.15.4 a des caractéristiques de taux de pertes et de latence qui peuvent éliminer certains algorithmes (R4 et R5 pour les détails).

Les machines d'un LowPAN étant typiquement peu fiables (déplacement, extinction, panne), les protocoles de routage doivent se préparer à trouver des routes alternatives (exigence R6). Le RFC demande moins de deux secondes de convergence si le destinataire d'un paquet s'est déplacé et seulement 0,5 seconde si seul l'expéditeur a bougé (voir aussi le RFC 5826).

Les liens radio ayant souvent des caractéristiques asymétriques, R7 demande que les protocoles de routage fonctionnent quand même dans ces conditions. Cela veut dire, par exemple, que le coût d'un lien doit être une paire {coût aller, coût retour}.

Chaque machine, dans un LowPAN, a droit à un sommeil fréquent (99 % de sommeil n'est pas impossible), pour économiser sa batterie (des capteurs industriels doivent parfois tenir cinq ans sans changement de batterie). R8 en tire les conséquences en rappelant que le routage doit marcher même si certains nœuds hibernent. Et le calcul des coûts de routage doit inclure celui de la consommation électrique (il faut éviter de choisir comme routeurs les machines limitées en énergie).

La taille des LowPAN variant considérablement, le protocole de routage doit marcher aussi bien pour un réseau urbain de plusieurs millions de machines (RFC 5548) que pour un réseau de 250 machines dans une maison (RFC 5826). Rappelez-vous les contraintes de taille mémoire : pas question de stocker une table de routage d'un million d'entrées en mémoire !

Les machines se déplacent, dans un LowPAN. Dans les environnements industriels, il faut que le réseau fonctionne malgré des déplacements jusqu'à 35 km/h (RFC 5673). Aujourd'hui, on en est loin mais, en tout cas, R12 exige des protocoles qui gèrent des réseaux qui changent, avec des machines qui bougent.

Et la sécurité, problème très crucial et très difficile pour les LoWPAN (un réseau sans-fil est toujours plus vulnérable) ? Non seulement un attaquant qui viserait le routage pourrait sérieusement perturber les communications entre les machines, mais il pourrait indirectement vider la batterie de certaines, réalisant ainsi une attaque par déni de service très efficace. L'exigence R14 impose donc aux protocoles de routage candidats de fournir des services de confidentialité, d'authentification et de vérification de l'intégrité des messages. C'est beaucoup, vous trouvez ? Et pourtant cela ne protège pas contre tout (par exemple contre une machine authentifiée, mais malveillante). De toute façon, il ne faut pas se faire d'illusion : compte-tenu du coût élevé (en processeur et donc en énergie électrique) de la plupart des techniques de sécurité (notamment de la cryptographie à clé publique), le routage des LowPAN restera très peu protégé. Le RFC n'espère qu'un compromis raisonnable (un peu de sécurité, si ça ne coûte pas trop cher).

Il semble donc, note le RFC, que cela exclut IPsec, alors qu'il serait une solution élégante au problème, car il est bien trop consommateur de ressources et trop compliqué du point de vue de la gestion des clés.

À noter que 802.15.4 dispose de mécanismes de sécurité propres. S'ils sont activés, des protocoles comme NDP deviennent relativement sûrs. (La section 6 est également à lire, si on s'intéresse à la sécurité.)

Enfin, après la sécurité, la gestion : le RFC 5706 impose de la prendre en compte dès la conception du protocole. L'exigence R18 demande donc que le futur protocole de routage des LowPAN soit gérable (test de l'état de la table de routage, compteurs d'erreurs, etc).


Téléchargez le RFC 6606


L'article seul

RFC 6605: Elliptic Curve Digital Signature Algorithm (DSA) for DNSSEC

Date de publication du RFC : Avril 2012
Auteur(s) du RFC : P. Hoffman (VPN Consortium), W. Wijngaards (NLnet Labs)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dnsext
Première rédaction de cet article le 13 avril 2012


Le mécanisme de sécurité DNSSEC permet évidemment de choisir entre plusieurs algorithmes de signature cryptographique, à la fois pour pouvoir faire face aux progrès de la cryptanalyse et pour pouvoir choisir en fonction de critères particuliers (taille des clés, temps de signature et de vérification, etc). La palette de choix s'agrandit avec ce RFC qui normalise l'usage d'ECDSA, un algorithme à courbes elliptiques (le deuxième dans DNSSEC après le RFC 5933).

DNSSEC est normalisé dans le RFC 4033 et les suivants. Il permet d'authentifier les enregistrements DNS par une signature cryptographique et l'algorithme de loin le plus fréquent aujourd'hui est RSA, avec des clés de 1024 ou 2048 bits. Beaucoup de gens préfèrent les courbes elliptiques, décrites dans l'excellent RFC 6090. Notre RFC étend donc la liste des algorithmes disponibles à :

  • ECDSA avec la courbe P-256 et l'algorithme de condensation SHA-256. On considère généralement que cette courbe a à peu près la résistance de RSA avec des clés de 3072 bits.
  • ECDSA avec la courbe P-384 et l'algorithme de condensation SHA-384.

ECDSA est normalisé dans FIPS 186-3. Les paramètres des courbes sont pris dans le RFC 5114.

Les clés ECDSA et les signatures étant bien plus petites que celles de RSA, on peut espérer des économies sur la capacité réseau. Signer est également bien plus rapide avec ECDSA (20 fois plus dans certains tests). Par contre, vérifier les signatures est plus long (5 fois plus dans certains tests) et le processeur des résolveurs DNS validants va donc souffrir.

Au passage, notre RFC normalise aussi (section 2) l'utilisation de SHA-384 dans DNSSEC, ce qui n'avait pas été fait précédemment (mais n'a aucun rapport avec les courbes elliptiques). SHA-384 était déjà décrit dans le RFC 6234 et DNSSEC a juste eu à lui ajouter un numéro de code, 4. (La première personne qui voit un DS de numéro 4 dans la nature est priée de me le signaler, pour ma collection.)

La section 4 décrit les formats utilisés pour DNSSEC. Une clé publique ECDSA est juste une valeur, notée Q, qu'on met telle quelle dans l'enregistrement DNSKEY. La signature, elle, est faite de deux valeurs, r et s. On les concatène simplement avant de les mettre dans le RRSIG. Les codes enregistrés pour les deux nouveaux algorithmes sont 13 pour ECDSA Curve P-256 with SHA-256 et 14 pour ECDSA Curve P-384 with SHA-384. (Là encore, si quelqu'un en trouve dans la nature, je suis preneur...)

La section 6 fournit des exemples. Voici une clé et le DS correspondant, avec le premier algorithme (notez la petite taille par rapport aux DNSKEY RSA) :

example.net. 3600 IN DNSKEY 257 3 13 (
           GojIhhXUN/u4v54ZQqGSnyhWJwaubCvTmeexv7bR6edb
           krSqQpF64cYbcB7wNcP+e+MAnLr+Wi9xMWyQLc8NAA== )

example.net. 3600 IN DS 55648 13 2 (
           b4c8c1fe2e7477127b27115656ad6256f424625bf5c1
           e2770ce6d6e37df61d17 )

Et les signatures qui l'utilisent (également toutes petites) :

www.example.net. 3600 IN A 192.0.2.1
www.example.net. 3600 IN RRSIG A 13 3 3600 (
           20100909100439 20100812100439 55648 example.net.
           qx6wLYqmh+l9oCKTN6qIc+bw6ya+KJ8oMz0YP107epXA
           yGmt+3SNruPFKG7tZoLBLlUzGGus7ZwmwWep666VCw== )

Question mises en œuvre, on notera qu'OpenSSL, bibliothèque utilisée par de nombreux programmes DNS, a ECDSA, avec nos deux courbes (au moins depuis la version 1.0.1, celle que j'ai testée). C'est apparemment activé par défaut (il faut faire un ./config no-ecdsa pour ne pas l'avoir). Voir le source dans crypto/ecdsa. Mais le code a été retiré de certains systèmes (comme Fedora) en raison des brevets, une infection fréquente pour les courbes elliptiques.

Dans les serveurs de noms, le seul à gérer déjà ECDSA semble être PowerDNS. BIND ne semble pas avoir encore ECDSA (version 9.9, la dernière officiellement publiée). Même chose pour Unbound dans sa version 1.4.16, la dernière. nsd comprend ECDSA depuis la version 3.2.11, publiée en juillet 2012. Enfin, pour Go-DNS, c'est en cours de développement. Enfin, pour la bibliothèque ldns, ECDSA a été ajouté dans la version 1.6.13, sortie en mai 2012. Pour les autres, il va donc falloir patienter un peu. Notez que certains des registres de noms de domaine ont une liste limitative des algorithmes acceptés et que cette liste ne comprend pas forcément déjà ECDSA.

Si vous voulez regarder une zone signée avec ECDSA (c'est très rare), il y a ecdsa.isc.org.


Téléchargez le RFC 6605


L'article seul

RFC 6604: xNAME RCODE and Status Bits Clarification

Date de publication du RFC : Avril 2012
Auteur(s) du RFC : Donald Eastlake 3rd (Huawei)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dnsext
Première rédaction de cet article le 14 avril 2012


Ce RFC est très court car il avait juste à répondre à une question simple : le DNS a des mécanismes (le plus connu est l'enregistrement CNAME) permettant à un nom de domaine de pointer vers un autre. Si, en suivant cette chaîne de noms, on rencontre une erreur, que doit indiquer le code de retour dans la réponse DNS ? Le résultat de la première requête de la chaîne ou bien celui de la dernière ? Le RFC tranche dans le sens de la grande majorité des résolveurs DNS actuels : le rcode doit être celui de la dernière requête de la chaîne.

C'est tout bête, mais ce cas n'était pas clairement spécifié dans les précédents RFC sur le DNS. Si on a par exemple, dans le DNS :

www.foobar.example. IN CNAME www.nothere.example.

Alors une requête AAAA www.foobar.example rencontrera l'alias et le résolveur continuera en demandant www.nothere.example. Si www.nothere.example n'existe pas, alors qu'on a demandé de l'information sur www.foobar.example, le code de retour doit-il être NXDOMAIN (ce nom n'existe pas) ou bien NOERROR (on a bien trouvé un enregistrement, ici le CNAME et www.foobar.example existe) ? Même chose avec d'autres types d'enregistrement « alias » comme DNAME. (CNAME redirige un nom, DNAME redirige les noms situés en dessous de lui.) On parle alors de xNAME pour désigner globalement tous les types « alias ». Notez bien que, quoique cela soit déconseillé, il peut y avoir une chaine de plus de deux xNAME.

Avant de voir le cas du code de retour (rcode dans la terminologie DNS, pour return code), la section 2 règle celui des bits de statut. Le bit AA (Authoritative Answer) est décrit dans le RFC 1035, section 4.1.1. Il indique que la réponse vient d'un serveur faisant autorité (pas d'un cache). Dans le cas d'une chaîne de xNAME, les AA peuvent être différents à chaque étape. Mais le RFC 1035 disait clairement que le bit dans la réponse était pour le premier nom mentionné dans la section Réponse du paquet. Rien ne change ici, la spécification était claire dès le début.

Le bit AD (Authentic Data) est plus récent. Normalisé dans le RFC 4035, section 3.2.3, il indique que la réponse est correctement signée avec DNSSEC. Là encore, la règle était claire dès le début : ce bit n'est mis que si toutes les réponses dans la section Réponse (et la section Autorité) sont authentiques.

Mais le vrai problème concerne le rcode (RFC 1035, section 4.1.1) car, là, le RFC original (voir aussi RFC 1034, section 4.3.2 et bon courage pour le comprendre) n'était pas clair. Le RFC 2308, dans sa section 2.1, dit qu'il faut fixer le code de retour en fonction de la dernière étape de la chaîne, tout en notant que tous les serveurs ne le font pas. La section 3 fixe donc des règles précises : lorsqu'on suit une chaîne, les étapes intermédiaires n'ont pas d'erreur. Il ne sert donc à rien d'indiquer le résultat de la première étape. Le code de retour doit donc être mis en fonction de la dernière étape uniquement. Dans l'exemple plus haut, le résultat de la requête AAAA www.foobar.example doit donc être NXDOMAIN (domaine inexistant).

Voilà, vous pouvez arrêter la lecture ici, l'essentiel du RFC est le paragraphe précédent. Mais la section 4 apporte quelques détails sur la sécurité. Par exemple, elle rappelle que des bits comme AA ou AD ne sont pas protégés par DNSSEC. Un attaquant a donc pu les changer sans être détecté. Si on veut être sûr de leur intégrité, il faut protéger la communication avec le serveur, par exemple avec le TSIG du RFC 8945 (ou bien que le client ignore le bit AD et valide lui-même avec DNSSEC).

Si vous voulez tester vous-même que votre résolveur obéit bien aux règles de ce RFC, vous pouvez tester avec dangling-alias.bortzmeyer.fr qui existe mais pointe vers un nom qui n'existe pas. Vous devez donc obtenir un NXDOMAIN, ce qui est le cas avec la plupart des résolveurs actuels (la question de l'implémentation de ce RFC ne se pose pas, le RFC a pris acte du comportement très majoritaire des logiciels).

Voici un exemple avec un résolveur correct (un Unbound) :


% dig AAAA dangling-alias.bortzmeyer.fr
...
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 45331
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 6, ADDITIONAL: 1


Téléchargez le RFC 6604


L'article seul

RFC 6598: IANA-Reserved IPv4 Prefix for Shared Address Space

Date de publication du RFC : Avril 2012
Auteur(s) du RFC : J. Weil (Time Warner Cable), V. Kuarsingh (Rogers Communications), C. Donley (CableLabs), C. Liljenstolpe (Telstra Corp), M. Azinger (Frontier Communications)
Première rédaction de cet article le 23 avril 2012


Après beaucoup de discussions pas toujours sereines, l'IESG a finalement décidé de publier ce très controversé RFC. Il réserve un préfixe IPv4, 100.64.0.0/10, aux services de partage d'adresses IP entre utilisateurs, les CGN (Carrier-Grade NAT). Ce faisant, il légitime ce concept de CGN, ce qui a déclenché la colère de beaucoup.

Voyons d'abord le paysage : les adresses IPv4 sont à peu près épuisées. Mais le déploiement d'IPv6 a pris beaucoup de retard et il n'est pas, à l'heure actuelle, prêt à prendre le relais. Plusieurs FAI, notamment en Asie, ont donc commencé à déployer des systèmes où l'abonné de base n'a aucune adresse IPv4 publique. Avant cela, M. Toutlemonde n'avait certes qu'une seule adresse publique et devait faire du NAT pour donner à toutes ses machines une connectivité Internet partielle. Mais, au moins, le partage d'adresses ne se faisait qu'entre habitants du même foyer, Aujourd'hui, par manque d'adresses IPv4, les déploiements en cours repoussent le NAT dans le réseau de l'opérateur (d'où le nom de CGN, Carrier-Grade NAT, voir par exemple le RFC 6264 ou bien le RFC 6888) et le partage d'adresses publiques se fait désormais entre abonnés n'ayant rien en commun. Désormais, si votre voisin télécharge illégalement, c'est peut-être sur vous que l'HADOPI tombera...

Le partage d'adresses (documenté dans le RFC 6269) n'est pas le seul inconvénient des CGN. Ces gros routeurs NAT, gardant en mémoire l'état des flux pour des centaines ou des milliers d'abonnés, diminuent la résistance aux pannes : si on redémarre l'un d'eux, tous les abonnés perdent leurs sessions en cours. Voilà pourquoi l'idée même de CGN (qui met de l'« intelligence » dans le réseau et non pas aux extrémités) hérisse tant de gens à l'IETF.

Si on fait quand même des CGN, se pose le problème de la numérotation des réseaux. Le réseau local de l'abonné (appelons-le M. Li car les CGN pour des accès Internet fixe sont aujourd'hui surtout répandus en Chine) est typiquement numéroté avec le RFC 1918. L'opérateur ne peut pas utiliser les adresses de ce même RFC pour son réseau, entre M. Li et le gros CGN, à cause du risque de conflit avec le réseau local de M. Li (sauf si l'opérateur contrôle ledit réseau, via ses boxes). Il ne peut pas utiliser des adresses IP publiques puisque, c'est le point de départ de toute l'histoire, celles-ci manquent. Il faut donc un « nouveau RFC 1918 ». C'est le rôle de ce RFC 6598, qui réserve un nouveau préfixe, 100.64.0.0/10, à cet usage. Il s'ajoute aux autres préfixes « spéciaux » du RFC 6890. Il servira aux machines entre le CPE (la box) et le routeur CGN et ne sera donc typiquement jamais vu sur l'Internet. À noter que ce préfixe n'a rien de particulier, à part son usage officiel : on pourrait parfaitement s'en servir pour autre chose que du CGN. Voici le nouveau préfixe, vu avec whois :

% whois 100.64.0.0 
NetRange:       100.64.0.0 - 100.127.255.255
CIDR:           100.64.0.0/10
OriginAS:
NetName:        SHARED-ADDRESS-SPACE-RFCTBD-IANA-RESERVED
NetHandle:      NET-100-64-0-0-1
Parent:         NET-100-0-0-0-0
NetType:        IANA Special Use
RegDate:        2012-03-13
Updated:        2012-03-15

Ah, pourquoi une longueur de 10 à ce préfixe ? Un préfixe plus court (comme un /8) aurait été difficile à trouver de nos jours, et un plus long (par exemple un /12), offrant moins d'adresses, aurait obligé les FAI, dans certaines régions très peuplées, à déployer des CGN emboités... Un /10, par exemple, suffit à desservir toute l'agglomération de Tokyo (un FAI japonais ne peut donc pas avoir un seul routeur CGN pour tous le pays).

La section 4 du RFC précise l'usage attendu : chaque FAI utilisera librement 100.64.0.0/10 et ce préfixe n'aura donc de signification que locale. Les adresses 100.64.0.0/10 ne doivent pas sortir sur l'Internet public (le mieux est de les filtrer en sortie et, pour les autres FAI, en entrée, car il y aura toujours des négligents). Ces adresses ne doivent pas non plus apparaître dans le DNS public. Les requêtes DNS de type PTR pour ces adresses ne doivent pas être transmises aux serveurs DNS globaux, comme celles pour les adresses du RFC 1918, elles doivent être traitées par les serveurs du FAI (cf. le RFC 7793). Comme pour le RFC 1918, c'est sans doute un vœu pieux, et il faudra sans doute que l'AS112 (voir le RFC 7534) prenne en charge ces requêtes.

La section 3 décrit plus en détail les alternatives qui avaient été envisagées et les raisons de leur rejet. La solution la plus propre aurait évidemment été d'utiliser des adresses IPv4 globales, attribuées légitimement au FAI. Mais l'épuisement d'IPv4 rend cette solution irréaliste. Déjà, extraire un /10 des réserves n'a pas été facile.

La solution qui est probablement la plus utilisée à l'heure actuelle est celle d'utiliser un préfixe IPv4 usurpé, en se disant « de toute façon, ces adresses ne sortiront jamais sur l'Internet donc quel est le problème ? » Se servir sans demander est certainement plus rationnel, économiquement parlant, que de supplier la bureaucratie d'un RIR pour avoir des adresses. Autrefois, les FAI qui numérotaient ainsi leur réseau interne se servaient de préfixes non alloués (provoquant pas mal d'accidents au fur et à mesure de leur allocation ; même s'il n'y a pas de fuite de ces adresses, les abonnés du FAI peuvent être dans l'impossibilité de communiquer avec le détenteur légitime). Aujourd'hui, ils regardent quels sont les préfixes alloués mais non routés et les utilisent. Inutile de dire que le RFC condamne cette pratique incivique.

Le RFC 1918 n'est, on l'a vu, possible que si le FAI contrôle complètement le réseau local de M. Li et sait donc quels préfixes sont utilisés sur celui-ci, et peut ainsi choisir des préfixes qui ne rentrent pas en collision. (Cela peut aussi marcher si la box sait bien se débrouiller lorsque le même préfixe est utilisé en interne et en externe, ce qui est le cas de certaines.)

Bref, l'allocation d'un nouveau préfixe semblait la seule solution raisonnable.

La section 5 du RFC est consacrée à une longue mise en garde sur les dangers associés aux CGN. Certaines applications peuvent avoir des mécanismes pour découvrir l'adresse externe de la machine sur laquelle l'application tourne (l'adresse qu'on verra sur l'Internet) et, ensuite, faire des choses comme de demander à un pair d'envoyer des données à cette adresse. Avec le CGN, cela a encore moins de chances de marcher que d'habitude car les applications actuelles ne connaissent pas encore 100.64.0.0/10 et considéreront que ces adresses sont globalement utilisables.

Parmi les applications qui ont de fortes chances de mal marcher dans le contexte du CGN, citons les jeux en ligne (si deux abonnés essaient de se connecter alors qu'ils sont derrière le même CGN et ont la même adresse publique), le pair-à-pair, et bien sûr les applications de téléphonie avec SIP, la géo-localisation (le CGN sera trouvé, pas la vraie machine), certaines applications Web qui restreignent les connexions simultanées en provenance de la même adresse IP, etc. Pour les applications de type pair-à-pair (échange de fichier, SIP), les techniques habituelles d'ouverture manuelle d'un port sur le routeur (« tout ce qui est envoyé au port 4554, transmets le à 10.4.135.21 ») ne marchent pas avec le CGN, l'utilisateur résidentiel n'ayant typiquement pas de moyen de configurer le routeur CGN.

Enfin, quelques bons conseils de sécurité forment la section 6 : ne pas accepter les annonces de route pour 100.64.0.0/10 à l'entrée d'un site, les paquets depuis ou vers ces adresses ne doivent pas franchir les frontières d'un opérateur, etc.

Voilà, comme indiqué, cela ne s'était pas passé tout seul et l'IESG avait même dû faire une longue note détaillant le pourquoi de sa décision et expliquant que, certes, il n'y avait pas de consensus en faveur de ce projet mais qu'il n'y avait pas non plus de consensus contre. L'argument « pour » était :

  • Les opérateurs vont déployer du CGN de toute façon. S'ils n'ont pas un préfixe dédié à cet usage, ils utiliseront des mauvaises méthodes, comme des préfixes squattés.

Les arguments contre étaient :

  • Toute mesure qui prolonge au delà du raisonnable l'usage d'IPv4 ne fait que retarder le déploiement d'IPv6. Les efforts devraient se porter sur ce déploiement, pas sur l'acharnement thérapeuthique !
  • Les opérateurs se serviront du nouveau préfixe pour étendre le RFC 1918, et pas pour l'usage attendu.

Pour d'autres articles sur ce sujet, voir celui sur le bon blog de Chris Grundemann (en anglais) ou bien celui de Jérôme Durand (en français).


Téléchargez le RFC 6598


L'article seul

RFC 6596: The Canonical Link Relation

Date de publication du RFC : Avril 2012
Auteur(s) du RFC : M. Ohye, J. Kupke
Pour information
Première rédaction de cet article le 9 avril 2012


Depuis le RFC 5988, il existe un mécanisme standard pour exprimer les types des liens entre deux ressources sur le Web. Ce très court RFC spécifie un nouveau type de lien, canonical, qui permet d'indiquer quel est l'URI canonique d'une ressource Web.

Le but de ces liens est de permettre d'exprimer l'idée « Quel que soit l'URI que vous avez utilisé pour arriver sur cette ressource, sachez que l'URI canonique, la référence, est celui indiqué par ce lien. » Cela permet notamment à un moteur de recherche de n'indexer les ressources que sous l'URI canonique (au cas où du contenu soit dupliqué sous plusieurs URI). Cela permet également à un navigateur de ne mémoriser que l'URI canonique, sans d'éventuels paramètres (options d'affichage, identificateurs de session et autres trucs qui viennent souvent polluer les URI).

L'auteur qui place un lien canonical doit donc veiller à ce que l'URI canonique désigne bien une ressource qui mérite ce titre (identique à la ressource de départ, ou un sur-ensemble de celle-ci, ce dernier cas est explicitement autorisé par le RFC). Voir la section 5 qui donne de bons conseils aux auteurs.

Par contre, l'URI canonique ne doit notamment pas :

  • Être la source d'une redirection HTTP (sinon, par définition, il n'est pas canonique).
  • Ne doit pas spécifier un URI canonique autre que lui-même (en d'autres termes, pas le doit de faire des chaînes).
  • Ne doit évidemment pas renvoyer 404 lorsqu'on essaie d'y accéder.

La section 4 donne des exemples concrets. Si la version canonique d'une ressource est désignée par l'URI http://www.example.com/page.php?item=purse, alors les URI http://www.example.com/page.php?item=purse&category=bags ou http://www.example.com/page.php?item=purse&category=bags&sid=1234 qui sont des URI possibles de la même ressource peuvent indiquer http://www.example.com/page.php?item=purse comme canonique.

Pour cela, deux techniques, le classique lien HTML avec l'attribut rel :


<link rel="canonical"
           href="http://www.example.com/page.php?item=purse">

Il est également utilisable en version relative :


 <link rel="canonical" href="page.php?item=purse">

Et la deuxième technique (pratique notamment pour les ressources qui ne sont pas en HTML, une image, par exemple), l'en-tête HTTP (section 3 du RFC 8288) :


Link: <http://www.example.com/page.php?item=purse>; rel="canonical"

Pour prendre un exemple réel, si on demande à Wikipédia (qui fait face à des homonymies nombreuses) l'URL http://fr.wikipedia.org/wiki/M%C3%A9lenchon, on est redirigé vers la page sur Jean-Luc Mélenchon qui contient :


<link rel="canonical" href="/wiki/Jean-Luc_M%C3%A9lenchon" />

qui indique que la page canonique est celle avec le nom complet.

Le nouveau type canonical est désormais enregistré à l'IANA.

Petit avertissement de sécurité (section 7). Si une ressource est modifiée par un attaquant, il peut mettre un lien vers un URI canonique de son choix. Bien sûr, il pourrait aussi massacrer complètement la ressource. Mais le changement d'URI canonique est discret et risquerait de ne pas être noté par un humain, alors même que certaines implémentations en tiendraient compte, par exemple pour apport du trafic à l'URI de l'attaquant.

Qui gère aujourd'hui ce type de liens ? Chez les moteurs de recherche, Google le fait (voir leurs articles « Specify your canonical », « Supporting rel="canonical" HTTP Headers », l'article de conseils pratiques « About rel="canonical" » et enfin « Handling legitimate cross-domain content duplication »). Pareil chez Yahoo (« Fighting Duplication: Adding more arrows to your quiver ») et Bing (« Partnering to help solve duplicate content issues »). Par contre, je ne sais pas si les sites de bookmarking comme del.icio.us ou SeenThis font ce travail de canonicalisation.


Téléchargez le RFC 6596


L'article seul

RFC 6591: Authentication Failure Reporting using the Abuse Report Format

Date de publication du RFC : Avril 2012
Auteur(s) du RFC : H. Fontana
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF marf
Première rédaction de cet article le 13 avril 2012


Le format ARF, normalisé dans le RFC 5965, permet d'envoyer des rapports structurés (analysables par un programme) à propos d'un message électronique abusif, spam ou hameçonnage, par exemple. Ce RFC 6591 spécifie une extension à ARF pour le cas où le problème avec le message est un échec d'un mécanisme d'authentification. On peut ainsi prévenir l'émetteur que quelqu'un essaie d'usurper son identité ou, plus fréquemment aujourd'hui, qu'il y a une erreur dans la configuration de ses mécanismes d'authentification.

Par exemple, si le message est authentifié par SPF (RFC 7208 et RFC 6652), il arrive assez souvent que l'émetteur se mette à utiliser un MTA non prévu et non listé dans l'enregistrement SPF. Si ce dernier se termine par un -all, l'usage de ce MTA va se traduire par une erreur d'authentification. L'extension ARF décrite ici permettra de transmettre un rapport à l'émetteur, pour qu'il corrige.

L'extension consiste en un nouveau type de rapport ARF, auth-failure (section 3.1), rejoignant les rapports existants (comme abuse ou fraud). Un rapport de ce type va comporter, dans sa seconde partie (celle qui est structurée, la première étant en langue naturelle et la troisième étant le message original), les champs suivants. À noter que certains étaient déjà définis par le RFC 5965 mais peuvent avoir des exigences différentes ici (par exemple, être obligatoires pour les rapports auth-failure alors qu'ils étaient optionnels pour les autres). Les nouveaux sont désormais dans le registre IANA. Commençons par les champs obligatoires :

  • Auth-failure: Nouveauté de ce RFC, il indique en un mot la raison de l'échec. Les valeurs possibles sont adsp (cf. RFC 5617), bodyhash (le condensat cryptographique du corps du message ne correspond pas à la signature), revoked (signature DKIM expirée), signature (signature DKIM invalide, cf. RFC 6651), spf (échec SPF, RFC 6652).
  • Authentication-Results: Normalisé dans le RFC 7001, il indique les paramètres d'authentification et les raisons de l'échec.
  • Reported-Domain: Le nom de domaine annoncé par l'expéditeur.

D'autres champs sont recommandés ou simplement optionnels :

  • Original-Envelope-Id: Un identifiant unique pour la transaction SMTP (cf. section 2.2.1 du RFC 3464)
  • Original-Mail-From:
  • Source-IP:
  • Delivery-Result: Ce dernier indique la décision qui a été prise après l'échec de l'authentification (jeter le message, le distribuer quand même, etc)

Il peut en outre y avoir des champs spécifiques à certaines techniques d'authentification. Par exemple, pour DKIM (RFC 6376), les champs DKIM-Domain:, DKIM-Identity: et DKIM-Selector: ou pour SPF le champ SPF-DNS:..

Voici un exemple (annexe B du RFC) de rapport ARF sur un échec d'authentification DKIM, par suite d'une incohérence entre le contenu effectif et ce qu'indiquait la signature :


   Message-ID: <433689.81121.example@mta.mail.receiver.example>
   From: "SomeISP Antispam Feedback" <feedback@mail.receiver.example>
   To: arf-failure@sender.example
   Subject: FW: You have a new bill from your bank
   Date: Sat, 8 Oct 2011 15:15:59 -0500 (CDT)
   MIME-Version: 1.0
   Content-Type: multipart/report;
     boundary="------------Boundary-00=_3BCR4Y7kX93yP9uUPRhg";
     report-type=feedback-report
   Content-Transfer-Encoding: 7bit

   --------------Boundary-00=_3BCR4Y7kX93yP9uUPRhg
   Content-Type: text/plain; charset="us-ascii"
   Content-Disposition: inline
   Content-Transfer-Encoding: 7bit

   This is an authentication failure report for an email message
   received from a.sender.example on 8 Oct 2011 20:15:58 +0000 (GMT).
   For more information about this format please see [this memo].

   --------------Boundary-00=_3BCR4Y7kX93yP9uUPRhg
   Content-Type: message/feedback-report
   Content-Transfer-Encoding: 7bit

   Feedback-Type: auth-failure
   User-Agent: Someisp!Mail-Feedback/1.0
   Version: 1
   Original-Mail-From: anexample.reply@a.sender.example
   Original-Envelope-Id: o3F52gxO029144
   Authentication-Results: mta1011.mail.tp2.receiver.example;
    dkim=fail (bodyhash) header.d=sender.example
   Auth-Failure: bodyhash
   DKIM-Canonicalized-Body: VGhpcyBpcyBhIG1lc3NhZ2UgYm9keSB0
     aGF0IGdvdCBtb2RpZmllZCBpbiB0cmFuc2l0LgoKQXQgdGhlIHNhbWU ...
   DKIM-Domain: sender.example
   DKIM-Identity: @sender.example
   DKIM-Selector: testkey
   Arrival-Date: 8 Oct 2011 20:15:58 +0000 (GMT)
   Source-IP: 192.0.2.1
   Reported-Domain: a.sender.example
   Reported-URI: http://www.sender.example/

   --------------Boundary-00=_3BCR4Y7kX93yP9uUPRhg
   Content-Type: text/rfc822-headers
   Content-Transfer-Encoding: 7bit

   Authentication-Results: mta1011.mail.tp2.receiver.example;
    dkim=fail (bodyhash) header.d=sender.example;
    spf=pass smtp.mailfrom=anexample.reply@a.sender.example
   Received: from smtp-out.sender.example
    by mta1011.mail.tp2.receiver.example
    with SMTP id oB85W8xV000169;
    Sat, 08 Oct 2011 13:15:58 -0700 (PDT)
   DKIM-Signature: v=1; c=relaxed/simple; a=rsa-sha256;
    s=testkey; d=sender.example; h=From:To:Subject:Date;
    bh=2jUSOH9NhtVGCQWNr9BrIAPreKQjO6Sn7XIkfJVOzv8=;
    b=AuUoFEfDxTDkHlLXSZEpZj79LICEps6eda7W3deTVFOk4yAUoqOB
    4nujc7YopdG5dWLSdNg6xNAZpOPr+kHxt1IrE+NahM6L/LbvaHut
    KVdkLLkpVaVVQPzeRDI009SO2Il5Lu7rDNH6mZckBdrIx0orEtZV
    4bmp/YzhwvcubU4=
   Received: from mail.sender.example
    by smtp-out.sender.example
    with SMTP id o3F52gxO029144;
    Sat, 08 Oct 2011 13:15:31 -0700 (PDT)
   Received: from internal-client-001.sender.example
    by mail.sender.example
    with SMTP id o3F3BwdY028431;
    Sat, 08 Oct 2011 13:15:24 -0700 (PDT)
   Date: Sat, 8 Oct 2011 16:15:24 -0400 (EDT)
   Reply-To: anexample.reply@a.sender.example
   From: anexample@a.sender.example
   To: someuser@receiver.example
   Subject: You have a new bill from your bank
   Message-ID: <87913910.1318094604546@out.sender.example>

   --------------Boundary-00=_3BCR4Y7kX93yP9uUPRhg--

Le but de l'authentification du courrier électronique étant d'améliorer la sécurité, il n'est pas étonnant que la section 6, considérée aux problèmes de sécurité, soit particulièrement détaillée. Quelques points à garder en tête, donc. Par exemple, les rapports ARF eux-même peuvent être des faux. Il ne faut agir de manière automatique sur un de ces rapports que s'ils ont été authentifiés d'une manière ou d'une autre. Ensuite, générer automatiquement des rapports ARF peut ouvrir une voie à l'attaque par déni de service : un méchant pourrait envoyer plein de messages délibèrement faux, pour déclencher l'émission massive de rapports ARF.

Il existe apparemment déjà au moins un générateur d'ARF qui gère cette extension. PayPal et Hotmail ont déjà annoncé leur intention de l'utiliser.


Téléchargez le RFC 6591


L'article seul

RFC 6590: Redaction of Potentially Sensitive Data from Mail Abuse Reports

Date de publication du RFC : Avril 2012
Auteur(s) du RFC : J. Falk (Return Path), M. Kucherawy (Cloudmark)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF marf
Première rédaction de cet article le 8 avril 2012


Il est fréquent qu'un message électronique contienne de l'information sensible ou personnelle, ne serait-ce que le nom des parties qui communiquent. Si ce message doit être transmis, comme faisant partie d'un rapport de problème, cette information doit être protégée. Ce RFC décrit un cadre général pour la retouche des messages. Le terme de « retouche » désigne l'opération d'occultation des parties confidentielles (notez que le redaction de l'original en anglais est un faux-ami, il ne signifie pas « rédaction »).

Le format ARF est normalisé dans le RFC 5965. Ce format standard permet de transmettre un rapport structuré (donc analysable automatiquement, par un programme) indiquant du spam, du hameçonnage ou tout autre abus. ARF permet également d'inclure dans le rapport le message qui a déclenché le processus de plainte. Mais ce message peut contenir des informations confidentielles, qu'on ne souhaite pas partager avec un tiers (sans compter les obligations légales comme, en France, la loi Informatique & Libertés). Le message est donc parfois retouché (redacted dans la langue de Katy Perry) avant d'être transmis. La section 8.5 du RFC 5965 décourage plutôt cette pratique (l'information occultée était peut-être nécessaire à la compréhension du rapport) mais cette approche « au diable la vie privée, la fin justifie les moyens » est très contestée et ce RFC 6590 adopte une vue plus raisonnable. L'occultation est désormais considérée comme justifiée.

L'important est donc plutôt de donner des conseils pratiques. Il y a des bonnes et des mauvaises façons d'occulter. Ainsi, remplacer toutes les parties locales des adresses (stephane+blog dans mon adresse stephane+blog@bortzmeyer.org) par la même chaîne de caractères (mettons xxxxx@bortzmeyer.org) fait perdre beaucoup d'information : on ne sait plus si deux rapports concernent le même utilisateur.

La section 3 de notre RFC conseille donc plutôt :

  • D'utiliser une transformation cohérente : deux chaînes identiques doivent donner le même résultat après occultation, et deux chaînes différentes doivent donner deux résultats différents.
  • De décider clairement quelles parties du message sont privées (par exemple, uniquement les parties locales des adresses, comme dans mon premier exemple) et de n'appliquer les transformations qu'à celles-ci.
  • De respecter la syntaxe des élements de protocole : si la transformation d'une partie locale d'une adresse donne une chaîne comportant un @ (caractère illégal dans une partie locale d'adresse), il faut l'encoder pour que l'adresse reste syntaxiquement légale, évitant ainsi de planter l'analyseur.

En appliquant ces règles, on a partiellement anonymisé le rapport, tout en permettant l'identification de tendances (par exemple, que le spam est plus souvent envoyé à certains utilisateurs).

Mais quelle opération de transformation utiliser ? Après la section 3 qui posait les principes, la section 4 s'occupe de technique. Ce RFC ne normalise pas une opération de transformation particulière. Si ROT13, qui est réversible, ne devrait pas être utilisé, les méthodes possibles incluent un hachage cryptographique (comme dans le RFC 2104) ou le remplacement des noms par un identifiant interne (numéro de client, par exemple).

Voici l'exemple qui figure dans l'annexe A du RFC. Le message de spam originel était :


From: alice@example.com
To: bob@example.net
Subject: Make money fast!
Message-ID: <123456789@mailer.example.com>
Date: Thu, 17 Nov 2011 22:19:40 -0500

Want to make a lot of money really fast?  Check it out!
http://www.example.com/scam/0xd0d0cafe

Ici, le récepteur, le FAI example.net est furieux et veut transmettre un rapport à example.com pour lui demander de faire cesser ces spams. example.net va occulter le nom du destinataire (son client), avec SHA-1 et la clé potatoes, qui sera concaténé au nom avant hachage, le résultat étant encodé en Base64. Cela donnera :

% echo -n potatoesbob | openssl sha1 -binary | openssl base64 -e 
rZ8cqXWGiKHzhz1MsFRGTysHia4=

On va pouvoir alors construire un rapport ARF incluant :


From: alice@example.com
To: rZ8cqXWGiKHzhz1MsFRGTysHia4=@example.net
Subject: Make money fast!
Message-ID: <123456789@mailer.example.com>
Date: Thu, 17 Nov 2011 22:19:40 -0500

Want to make a lot of money really fast?  Check it out!
http://www.example.com/scam/0xd0d0cafe

Attention, en pratique, il existe pas mal de pièges. Par exemple, comme le note la section 5.3, l'information confidentielle peut se trouver aussi à d'autres endroits et des techniques de corrélation peuvent permettre de retrouver l'information occultée. Globalement, les messages retouchés selon ce RFC ne fourniront pas une forte confidentialité. Ainsi, le champ Message-ID: peut permettre, en examinant le journal du serveur de messagerie (celui de example.com dans l'exemple précédent), de retrouver émetteur et destinataire. C'est pour cette raison que le RFC n'impose pas l'usage de la cryptographie : elle n'apporterait pas grand'chose en sécurité.

Même chose pour les informations non structurées, par exemple le texte du message : il peut contenir des indications permettant de remplir les cases occultées (section 6).

D'une manière générale, il faut garder en mémoire qu'il existe de puissantes techniques de désanonymisation comme illustré par exemple par les articles « A Practical Attack to De-Anonymize Social Network Users » de Gilbert Wondracek, Thorsten Holz, Engin Kirda et Christopher Kruegel ou bien « Robust De-anonymization of Large Sparse Datasets » de Arvind Narayanan et Vitaly Shmatikov.


Téléchargez le RFC 6590


L'article seul

RFC 6589: Considerations for Transitioning Content to IPv6

Date de publication du RFC : Avril 2012
Auteur(s) du RFC : J. Livingood (Comcast)
Pour information
Réalisé dans le cadre du groupe de travail IETF v6ops
Première rédaction de cet article le 23 avril 2012


Ce document rassemble un certain nombre d'analyses et de conseils sur la transition vers IPv6 pour les gens qui hébergent du contenu, typiquement les sites Web. Les gérants de ces sites souhaiteraient pouvoir rendre ce contenu accessible en IPv6, sans que cela entraîne de conséquences fâcheuses pour les lecteurs. Ce RFC décrit notamment la technique du whitelisting, qui consiste à ne renvoyer d'adresses IPv6 (les enregistrements AAAA du DNS) qu'à certains réseaux, identifiés comme mettant en œuvre correctement IPv6. Cette technique a été popularisée par Google mais elle est contestée. Le RFC estime qu'elle est acceptable et qu'il est utile d'informer, non pas les sites qui la pratiquent (ils connaissent déjà) mais la communauté Internet en général.

Bien sûr, ce RFC peut être utile à d'autres qu'aux gérants de sites Web. Mais il se focalise particulièrement sur leurs besoins. Un site Web se caractérise par un gros déséquilibre : au lieu de deux pairs qui veulent communiquer, on a un fournisseur de contenu, et des clients passifs, à qui on ne peut pas demander d'effectuer des réglages particuliers. Ça doit marcher, point. En outre, les sites Web à plus fort trafic sont souvent des entreprises commerciales, qui ne veulent pas prendre de risques et n'acceptent pas même un très faible pourcentage de clients pénalisés par IPv6.

Le but est donc de migrer de gros sites Web uniquement accessible en IPv4 (la grande majorité des gros sites Web à l'heure actuelle, la principale exception étant Google) vers un accès possible en IPv4 (protocole qui ne va pas disparaître de si tôt) et IPv6.

Mais quels sont les problèmes qu'IPv6 pourrait causer ? Le site Web typique publie son adresse dans le DNS. Pour l'adresse IPv4, il utilise un enregistrement de type A. Pour IPv6, de type AAAA. Ainsi, aujourd'hui, www.bortzmeyer.org annonce deux AAAA et un A :


% dig A www.bortzmeyer.org
...
;; ANSWER SECTION:
www.bortzmeyer.org.     42641   IN      A       204.62.14.153
...

% dig AAAA www.bortzmeyer.org
...
;; ANSWER SECTION:
www.bortzmeyer.org.     10222   IN      AAAA    2605:4500:2:245b::bad:dcaf
www.bortzmeyer.org.     10222   IN      AAAA    2001:4b98:dc0:41:216:3eff:fece:1902
...

Par contre, la très grande majorité des sites Web ne publient que des A, par exemple www.gouvernement.fr :


% dig A www.gouvernement.fr
...
;; ANSWER SECTION:
www.gouvernement.fr.    86383   IN      CNAME   www.premier-ministre.gouv.fr.
www.premier-ministre.gouv.fr. 86383 IN  CNAME   cdn2.cdn-tech.com.c.footprint.net.
cdn2.cdn-tech.com.c.footprint.net. 213 IN A     209.84.9.126
...

% dig AAAA www.gouvernement.fr 
...
;; ANSWER SECTION:
www.gouvernement.fr.    86358   IN      CNAME   www.premier-ministre.gouv.fr.
www.premier-ministre.gouv.fr. 86358 IN  CNAME   cdn2.cdn-tech.com.c.footprint.net.
...

Certains de ces sites sont simplement gérés par des incompétents ou des paresseux, qui ne peuvent pas ou n'envisagent pas de publier des enregistrements AAAA, qui permettraient à leur lecteurs d'accéder au contenu en IPv6. Mais, dans d'autres cas, l'administrateur du site Web connaît IPv6, a refléchi, et a décidé de ne pas publier le AAAA. Pourquoi ? Parce qu'il craint le problème du malheur des globes oculaires (eyeball misery ?). J'ai décrit ce problème dans un autre article et il fait en outre l'objet de deux autres RFC, les RFC 6555 et RFC 6556. En deux mots, le malheur des globes oculaires peut venir d'une connexion IPv6 cassée, ou simplement de qualité très inférieure. Si le site Web ne publie pas d'enregistrement AAAA, le client ne tentera pas de se connecter en IPv6 et sa connexion pourrie n'aura donc pas de conséquences négatives. Mais dès que le site Web publie son AAAA, patatras, l'expérience utilisateur se dégrade sérieusement et le pauvre client doit supporter des délais, voire des pannes.

Le problème n'arriverait pas si les administrateurs réseaux prenaient autant soin de la connexion IPv6 que de l'IPv4 mais ce n'est pas toujours le cas en pratique : quand un des deux protocoles marche nettement moins bien que l'autre, aujourd'hui, c'est presque toujours IPv6. Logiciels moins testés, surveillance moins sérieuse, moindre réactivité lors des pannes, sont la triste réalité d'IPv6 chez beaucoup d'opérateurs réseaux. Un autre problème est quantitatif : certaines bogues ne se déclenchent qu'à partir d'une certaine quantité de trafic et les tests en laboratoire ne les détectent donc pas. Si un gros site Web très populaire publie tout à coup des enregistrements AAAA, on peut imaginer que l'augmentation de trafic résultante plante des équipements réseaux qui marchaient l'instant d'avant. Ou, tout simplement, dépasse leur capacité (section 2.3 de notre RFC). Prenons l'exemple d'un FAI qui déploie 6rd (RFC 5969) et le fait tourner sur trois vieux PC avec Linux (le noyau Linux a désormais 6rd en standard), cela peut marcher très bien tant que les utilisateurs font un peu de ping6 et traceroute6, et ne pas suffire si tout à coup YouTube devient accessible en IPv6.

Bien sûr, tous les sites Web ne sont pas logés à la même enseigne, car ils n'ont pas tous le même public. http://www.ietf.org/ a un AAAA depuis très longtemps, sans problèmes. Mais son public, les gens qui suivent le travail de l'IETF, ne ressemble pas à celui de TF1 : il est nettement plus soucieux de la qualité de sa connexion et s'assure qu'elle marche en v4 et en v6. D'autres sites Web qui ont un public moins geek ne veulent pas prendre le moindre risque.

Quelle est l'ampleur de ce risque ? Quelques organisations ont fait des études sur le malheur des globes oculaires et trouvent jusqu'à 0,078 % de malheureux. C'est évidemment très peu mais cela fait encore trop de monde pour un gros site Web qui a des millions de visiteurs. (Voir les études « IPv6 & recursive resolvers: How do we make the transition less painful? », « Yahoo proposes 'really ugly hack' to DNS », « Evaluating IPv6 adoption in the Internet » et « Measuring and Combating IPv6 Brokenness ».) Le risque est donc jugé inacceptable par beaucoup de gérants de gros sites Web.

Bref, il faut trouver une solution. Sinon, le risque est que les gérants de sites Web les plus timides retardent éternellement la migration vers IPv6.

Alors, quelles sont les solutions possibles (section 4) ? Comme avec toutes les techniques de migration vers IPv6, il ne faut pas les appliquer toutes bêtement. Chacune a ses avantages et ses inconvénients et le choix de la meilleure technique dépend des caractéristiques du site Web qui veut se rendre accessible en v6. Première méthode, la plus satisfaisante techniquement, est de résoudre le problème à la source en s'assurant que tous les clients du site aient un IPv6 qui marche bien. C'est ainsi que cela fonctionne pour les sites Web qui visent un public technique, comme http://www.ietf.org/ : les problèmes sont discutés et résolus collecivement. C'est en effet la meilleure solution sauf qu'elle est souvent impossible : au contraire de ce qui se passe pour le site Web interne à une organisation, le site Web public typique n'a pas de contrôle sur la connectivité de ses clients, ni sur le logiciel utilisé (navigateur Web, par exemple). Toutefois, s'il s'agit d'un gros site très populaire, il peut influencer les utilisateurs en recommandant ou en déconseillant des logiciels, des FAI, ou des configurations, par exemple via une page Web d'aide sur le site.

Comme le problème, par exemple d'un FAI donné, a des chances de toucher tous les gros sites qui servent du contenu, ceux-ci peuvent aussi se coordonner pour faire pression sur le maillon faible. Ce genre de coordinations entre acteurs différents n'est jamais facile mais elle a eu lieu pour le World IPv6 Day . En deux mots, celle approche du problème est possible mais sans doute insuffisante.

Deuxième tactique possible, avoir des noms de domaine spécifiques à IPv6 (section 4.2). Par exemple, à la date d'écriture de cet article, Facebook n'a pas d'enregistrement AAAA pour www.facebook.com (attention, cela dépend du résolveur qui demande, pour les raisons expliquées plus loin) mais il en a un pour www.v6.facebook.com. Ainsi, l'utilisateur naïf ne risque pas d'avoir des problèmes IPv6 mais l'utilisateur plus tenté par la technique pourra essayer l'accès en IPv6 et aider au débogage initial. Cela permet une transition progressive, au lieu d'ouvrir les vannes en grand d'un coup. Et cela permet de tester la connectivité v6 du site, celle de certains de ses clients, d'introduire IPv6 en production (si le nom en question bénéficie de la même surveillance et des mêmes exigences de qualité de service que les noms classiques).

Mais cette méthode ne permet pas d'aller très loin : comme il faut une action consciente de l'utilisateur pour se connecter en IPv6, le trafic restera très limité. Comme la population de testeurs n'est pas représentative, les logiciels ou FAI qui sont peu utilisés par les utilisateurs geeks ne seront pas réellement testés. Cette technique ne peut donc convenir qu'au tout début de la migration.

Une autre méthode, qui a été mise au point et popularisée par Google, et qui est la plus détaillée dans ce RFC, est le whitelisting (section 4.3). Il s'agit de configurer les serveurs DNS faisant autorité pour le domaine, afin de ne renvoyer d'enregistrements AAAA qu'aux clients dont on sait qu'ils ont de l'IPv6 correct, et qui ont été placés sur une liste blanche, indiquant les réseaux jugés corrects. Notez bien que la liste indique des réseaux, pas des machines individuelles. Non seulement il serait humainement impossible de gérer une liste de machines, mais en outre le serveur DNS faisant autorité ne voit pas la machine individuelle, il est interrogé par les résolveurs, typiquement des machines du FAI.

Cette technique ressemble donc à celle de certains systèmes de load-balancing ou de CDN (cf. sections 4.3.2 et 4.3.3, ainsi que le RFC 1794), qui eux-aussi renvoient une réponse DNS différente selon le client. Cela évoque donc aussi le split DNS (section 4.3.4) décrit dans la section 3.8 du RFC 2775. Le split DNS (conçu à l'origine pour renvoyer des réponses différentes au client du réseau local, par exemple des adresses RFC 1918) a toujours été très contesté. Les objections des sections 2.1 et 2.7 du RFC 2956 concernent surtout le fait que le FQDN n'est plus un identificateur stable, si la résolution DNS dépend du client. Cette fragmentation de l'espace de nommage est la principale raison pour laquelle beaucoup de gens n'aiment pas le whitelisting.

Déployé par Google, le whitelisting est documenté dans l'article de C. Marsan « Google, Microsoft, Netflix in talks to create shared list of IPv6 users » et dans celui de E. Kline « IPv6 Whitelist Operations ». Son principe est donc « plutôt que de résoudre le problème, masquons-le ».

Voici le whitelisting en action : je demande l'adresse IPv6 de google.com depuis Free, qui est whitelisté.


% dig AAAA google.com
...
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
...
;; ANSWER SECTION:
google.com.             300     IN      AAAA    2a00:1450:4007:802::1005

Par contre, depuis Orange, on n'a pas de réponse.


% dig AAAA google.com
...
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
...

Notez bien que le whitelisting est complètement indépendant du protocole utilisé pour le transport de la requête DNS. Le fait que le résolveur utilise IPv4 ou IPv6 pour interroger le serveur faisant autorité n'implique rien quant aux capacités v4 ou v6 de la machine cliente (celle sur laquelle tourne le navigateur Web). La liste blanche contient donc aussi bien des adresses IPv4 qu'IPv6.

Par définition, le fait d'être dans la liste blanche nécessite une évaluation du réseau client. Sa maintenance est donc non triviale et consomme des ressources humaines, nécessite des mesures, etc. Google peut se le permettre, mais ce n'est pas accessible à tout le monde.

Notez que cette technique nécessite d'avoir le contrôle de tous les serveurs faisant autorité sur le domaine, y compris les secondaires. Et qu'elle n'est pas toujours mise en œuvre dans les logiciels serveurs typiques, il faut donc se préparer à programmer un peu. Je n'ai pas testé mais je suppose qu'on peut mettre en œuvre le whitelisting sur BIND en utilisant les vues, avec deux fichiers de zone (un avec AAAA et un sans) et en définissant une ACL pour la liste blanche, dirigeant ses membres vers la vue ayant les AAAA :

acl v6-whitelist {
                192.0.2.0/24; 
                2001:db8:3003::/48;
};
...
view "with-aaa" {
   match-clients { v6-whitelist; };
   zone "example.com" {
        ...
        file "/etc/bind/example.com-with-aaaa";
   };
};
view "external" {
   match-clients { any; };
   zone "example.com" {
        ...
        file "/etc/bind/example.com-without-aaaa";
   };
};

La solution n'est pas parfaite : un réseau peut avoir correctement déployé IPv6 mais un utilisateur peut avoir un navigateur Web qui a des problèmes avec IPv6. La liste blanche stockant des réseaux, les globes oculaires de cet utilisateur seront malheureux quand même. Mais cela reste une des meilleures solutions existantes.

Aujourd'hui, on l'a vu, cette solution est manuelle : les réseaux qui veulent être whitelistés soumettent leur candidature, sont évalués (ce qui peut nécessiter une interaction qui consomme donc également des ressources humaines du côté du FAI), et mis (ou pas) dans la liste. Dans le futur, on verra peut-être une automatisation de la procédure, avec des tests faits de temps en temps. Autre évolution possible, le passage en mode « liste noire » où tous les clients DNS recevraient l'enregistrement AAAA, sauf ceux explicitement listés dans la liste noire (section 4.4). Cela sera intéressant le jour où la majorité des FAI auront un IPv6 qui marche, et où seuls quelques maillons faibles subsisteront.

Un résumé des inquiétudes sur le whitelisting figure dans l'article de Brzozowski, J., Griffiths, C., Klieber, T., Lee, Y., Livingood, J., et R. Woundy, « IPv6 DNS Resolver Whitelisting - Could It Hinder IPv6 Adoption? ». Outre la fragmentation de l'espace de nommage, la principale inquiétude concerne l'introduction d'une nouvelle composante dans le réseau, qui rend le débogage plus compliqué (un principe cardinal de l'Internet est que les décisions « politiques » doivent être faites aux extrémités, pas dans des équipements intermédiaires, cf. RFC 3724 et l'article de Blumenthal, M. et D. Clark, « Rethinking the design of the Internet: The end to end arguments vs. the brave new world » et, sur le cas spécifique du DNS, la section 2.16 du RFC 3234.) Un bon exemple est donné par les résultats de dig cités plus haut : déboguer l'accès à Google va dépendre du réseau où on fait le dig. De beaux malentendus peuvent alors survenir. Mais le débat est complexe : s'il y a un large consensus sur l'importance de ne pas mettre trop d'état et de décisions dans les équipements intermédiaires (le principe « de bout en bout »), la discussion a toujours fait rage sur qu'est-ce qu'un équipement intermédiaire. Est-ce qu'un serveur DNS fait partie des middleboxes qui perturbent si souvent la connexion de bout en bout ?

Enfin, la dernière tactique de migration possible est le saut direct (section 4.5) : activer IPv6 sur le serveur, le tester, puis publier un AAAA normal. Cela n'est pas forcément si radical que ça car on peut le faire nom par nom (par exemple, pour static-content.example.com avant www.example.com) mais c'est quand même la méthode la plus audacieuse. À ne faire qu'une fois qu'on maîtrise bien IPv6. Relativisons tout de même les choses : des tas de sites Web vus par un public non technique (comme http://www.afnic.fr/) ont un AAAA depuis de nombreuses années et sans que cela crée de problèmes.

Si on est toutefois inquiets, on peut utiliser cette tactique, mais pendant une période limitée : on teste, on publie le AAAA pendant quelques heures, on arrête, on analyse les résultats, on corrige les éventuels problèmes et on recommence.

Pour les lecteurs pressés, la section 5 résume les étapes possibles d'un plan de transition. Là encore, pas question de l'appliquer aveuglément. Chacun doit l'adapter aux caractéristiques spécifiques de son réseau. Rappelez-vous en outre que le RFC cible les gros sites : la plupart des petits n'auront pas envie d'autant d'étapes. Voici ces étapes potentielles successives :

  • Uniquement IPv4 (malheureusement la situation de la grande majorité du Web aujourd'hui),
  • Activation d'IPv6 et publication par des noms spécifiques, genre www.ipv6.example.org,
  • Peut-être une étape de whitelisting avec gestion manuelle,
  • Peut-être suivi par une étape de whitelisting automatique,
  • Le whitelisting étant prévu pour être une étape temporaire, on va le couper, une fois les problèmes résolus. (Cela peut se faire lors d'une occasion un peu solennelle comme le World IPv6 Launch le 6 juin 2012.)
  • À partir de là, le site est complètement accessible en IPv6 (et en IPv4), avec le nom de domaine normal.
  • La section 6.3 discute du cas, très futuriste à l'heure actuelle, où certains auront une meilleur connectivité en IPv6 qu'en IPv4. Il faudra alors mettre au point des techniques de transition pour retirer l'accès IPv4 petit à petit.

Voici, vous connaissez maintenant l'essentiel. La section 6 du RFC liste quelques points de détail. Par exemple, contrairement à ce que certains pourraient croire au premier abord, le whitelisting est tout à fait compatible avec DNSSEC (section 6.1), puisqu'il se fait sur les serveurs faisant autorité. Ceux-ci peuvent donc parfaitement signer les deux versions de la réponse, avec ou sans AAAA, et ces deux réponses pourront être vérifiés comme authentiques.

Par contre, si un résolveur DNS s'avisait de faire des manipulations analogues au whitelisting, par exemple en retirant les réponses AAAA vers des clients qu'il sait ne pas gérer IPv6 correctement, alors, là, DNSSEC détecterait la manipulation comme une tentative d'attaque, et la réponse ne pourrait pas être validée.

On a vu que la gestion d'une liste blanche représentait un certain travail. Il est donc tentant de partager les résultats de ce travail entre plusieurs acteurs. Mais attention à le faire en respectant la vie privée (section 6.2). Il n'y a pas de problèmes avec les listes actuelles, dont la granularité ne descend pas jusqu'à l'individu, mais, si des listes plus précises devaient apparaître, ce problème est à garder en tête.


Téléchargez le RFC 6589


L'article seul

RFC 6586: Experiences from an IPv6-Only Network

Date de publication du RFC : Avril 2012
Auteur(s) du RFC : J. Arkko, A. Keranen (Ericsson)
Pour information
Première rédaction de cet article le 22 avril 2012


La plupart des RFC décrivent, de façon normative, un protocole ou un format qui sera ensuite déployé sur l'Internet. Mais ce document est différent : c'est un récit d'expérience, celle de deux courageux chercheurs qui, au péril de leur usage de Facebook et dans l'intérêt de la science, ont coupé IPv4 et n'ont accédé à l'Internet que via IPv6 pendant la durée de l'expérience. Les machines de l'expérience n'avaient plus du tout d'IPv4 et seule une fragile passerelle NAT64 les reliaient aux territoires barbares où régnait encore IPv4. Qu'est-ce qui marche dans ce cas ? Qu'est-ce qui ne marche pas ? Qu'est-ce qu'on peut améliorer ?

Deux réseaux ont été utilisés, un professionnel et un à la maison. Tous les deux étaient en double-pile (IPv4 et IPv6, cf. RFC 4213) depuis longtemps. Tous les deux avaient une connectivité IPv6 stable et correcte depuis des années. Il était donc temps de sortir de la « zone de confort » et d'essayer le grand large. Mais la majorité de l'Internet reste accessible en IPv4 seulement. C'est là qu'intervient NAT64 (RFC 6144), qui permet aux machines purement IPv6 d'accèder à des sites Web attardés en v4.

Ce n'est pas juste une expérience de démonstration pour montrer que les Vrais Hommes peuvent se passer du vieux protocole des mangeurs de yaourt. L'épuisement des adresses IPv4 fait que de plus en plus de FAI envisagent de déployer des réseaux uniquement IPv6, puisqu'ils n'ont plus la possibilité d'obtenir des adresses. Tester de tels réseaux en vrai est donc nécessaire. La conclusion est d'ailleurs que cela ne marche pas trop mal mais qu'il reste un certain nombre de petits problèmes qu'il serait bon de régler.

La section 3 du RFC explique l'environnement de l'expérience. Les deux réseaux (un à la maison et un au bureau) étaient un mélange classique de PC, d'appareils photos numériques, de gadgets électroniques divers et de petits routeurs du commerce, avec divers systèmes (Mac OS, Windows, Linux...). Les usages étaient également classiques, courrier, SSH, VoIP, jeu (pas dans le réseau de bureau, bien sûr), messagerie instantanée, un peu de domotique et bien sûr du Web. Il s'agissait de petits réseaux avec une dizaine d'utilisateurs au maximum.

Comme certains des utilisateurs des deux réseaux, des petits bras, avaient choisi de ne pas participer à l'expérience, il a fallu créer un réseau séparé pour celle-ci, avec un VLAN propre. Il n'y avait évidemment pas de serveur DHCP v4 sur ce réseau seulement des RA (Router Advertisement) v6.

On l'a vu, l'essentiel du Web aujourd'hui n'est accessible qu'en IPv4. Il a donc fallu mettre en place une passerelle NAT64 (RFC 6146). Elle incluait le serveur DNS64 (RFC 6147). L'installation et la configuration de cette passerelle étaient très simples pour un administrateur réseaux.

Le serveur DNS cité plus haut était publié via les RA (RFC 6106). (À noter que Windows écrit aussi à des serveurs DNS bien connus, fec0:0:0:ffff::1, fec0:0:0:ffff::2, et fec0:0:0:ffff::.) Trouver le serveur DNS dans un environnement IPv6 pur n'est pas trivial. Dans les environnements mixtes, il est fréquent que le résolveur DNS à utiliser par les clients ne soit publié qu'en v4, les clients demandant ensuite aussi bien les enregistrements A que les AAAA en IPv4. Ici, cette méthode n'était pas possible et les auteurs du RFC ont également testé avec DHCP v6 (RFC 8415). Un des charmes d'IPv6 est en effet qu'il existe deux façons de découvrir automatiquement le résolveur DNS local, via les RA ou bien via DHCP.

Le serveur DNS64 et la passerelle NAT64 fonctionnaient de la manière habituelle (RFC 6144) : si un client demandait un AAAA (adresse IPv6 dans le DNS) inexistant, le serveur DNS64 en synthétisait un, les paquets à destination de cette adresse étaient ensuite interceptés par la passerelle et NATés en IPv4 (la passerelle avait, elle, une adresse v4 publique). Les destinations ayant des AAAA étaient traitées normalement : la passerelle servait alors de simple routeur v6, le cas idéal d'une connectivité v6 complète.

Les résultats de l'expérience occupent le reste du RFC. La section 4 fournit une synthèse et la section 5 examine un par un les choses qui ont plus ou moins bien marché. Principale conclusion ; ça marche. Un des auteurs du RFC travaille dans un environnement IPv6 pur depuis un an et demi et est toujours vivant et en bonne santé. Certains points marchent particulièrement bien (aucun problème avec le Web). Sur un téléphone Symbian, toutes les applications ont marché (sur un Android, toutes les applications de base marchaient, mais après un bricolage pour permettre à la machine de trouver son résolveur DNS).

Les problèmes rencontrés se subdivisent en plusieurs catégories :

  • Les bogues pures et simples. Un logiciel gère théoriquement IPv6 mais, en pratique, on trouve des problèmes qui n'existent pas en v4. Ces bogues sont relativement fréquentes car trop peu de tests sont faits avec IPv6.
  • Pas d'IPv6 du tout, même en théorie. Cela arrive à des programmes antédiluviens (le RFC cite dict, un client RFC 2229) mais aussi, et là c'est inexcusable, à des programmes plus récents comme le logiciel privateur Skype, ou comme beaucoup de jeux.
  • Des problèmes liés au protocole. Dès que le protocole transmet des adresses IP, les ennuis commencent. La machine locale utilise IPv6, transmet l'adresse au pair v4 avec qui elle communique grâce au NAT64, pair qui n'arrive pas à répondre. Un exemple est fourni par certaines applications Web qui renvoient une page avec des URL utilisant des adresses IPv4 littérales (comme http://192.0.2.80/). Ce problème est rare mais très agaçant lorsqu'il se produit.
  • Problèmes situés quelque part dans la couche 3, le plus fréquent étant les problèmes de MTU causés par un pare-feu mal configuré.

Bref, aucun de ces problèmes n'était un problème fondamental d'IPv6 ou de NAT64, nécessitant de revisiter le protocole. C'était « uniquement » des questions de développement logiciel.

Maintenant, avec la section 5, voyons ces problèmes cas par cas. D'abord, ceux situés dans les systèmes d'exploitation. Par exemple, Linux ne jette pas l'information acquise par les RA lorsque la connectivité réseau change, il faut faire explicitement un cycle suspension/reprise. Ensuite, le démon rdnssd, censé écouter les annonces de résolveurs DNS faites en RA, n'était pas intégré par défaut sur Ubuntu et, de toute façon, ne semblait pas très fiable. Comme pas mal de problèmes rencontrés lors de cette expérience, il s'est résolu en cours de route, avec une nouvelle version du système. Mais tout n'est pas parfait, notamment le NetworkManager qui s'obstine à sélectionner un réseau sans-fil IPv4 qui n'a pas de connectivité externe, plutôt que le réseau IPv6 pur.

Les autres systèmes ont aussi ce genre de problèmes. Ainsi, avec Mac OS X, il faut dire explicitement au système qu'IPv4 est facultatif et qu'un réseau sans IPv4 ne doit pas être considéré comme cassé et à ignorer. Et passer d'un réseau v4 à v6 nécessite des manipulations manuelles.

Pour Windows 7, le problème était avec les résolveurs DNS : Windows les affichait mais ne les utilisait pas sans action manuelle.

Android a un problème analogue. Il peut faire de l'IPv6 mais il ne sait pas sélectionner les résolveurs DNS en IPv6. Par défaut, il lui faut donc un résolveur DNS v4. Heureusement, il s'agit de logiciel libre et les auteurs ont pu résoudre ce problème eux-même avec le nouveau logiciel DDD.

En conclusion, le RFC note que tous ces systèmes ont IPv6 à leur catalogue depuis des années, parfois de nombreuses années, mais tous ces problèmes donnent à penser qu'ils n'ont jamais été sérieusement testés.

La situation des langages de programmation et des API semble meilleure, par exemple Perl qui était un des derniers grands langages à ne pas gérer complètement IPv6 par défaut semble désormais correct.

C'est moins satisfaisant pour la messagerie instantanée et la voix sur IP. Les cris les plus perçants des utilisateurs impliqués dans l'expérience avaient été provoqués par Skype, qui ne marche pas du tout en IPv6 (il a fallu utiliser un relais SSH vers une machine distante). La légende comme quoi Skype marcherait toujours du premier coup en prend donc un... coup.

Parmi les autres solutions testées, celles passant par le Web marchaient (Gmail ou Facebook, par exemple), celles fondées sur XMPP également mais les solutions commerciales fermées comme MSN, WebEx ou AOL échouent toutes. Ces solutions sont mises en œuvre dans des logiciels privateurs (on ne peut donc pas examiner et corriger le source) mais l'examen du trafic réseau montre qu'il passe des adresses IPv4 entre machines, ce qui est incompatible avec NAT64.

Et pour les applications stratégiques essentielles, je veux dire les jeux ? Ceux utilisant le Web n'ont pas de problème, pour les autres, c'est l'échec complet. En outre, aucun des ces logiciels ne produit de messages de diagnostic utilisables et le débogage est donc très difficile. Au moment des premiers tests, ni Battlefield, ni Age of Empires, ni Crysis ne fonctionnaient sur le nouveau réseau. Depuis, World of Warcraft est devenu le premier jeu majeur qui marchait en IPv6. Les jeux dont le source a été libéré (comme Quake) ont également acquis cette capacité. Les autres feraient bien d'utiliser une API réseau plus moderne... (Cf. RFC 4038.)

Pendant qu'on en est au divertissement, que devient la musique en ligne ? La plupart des boutiques reposent sur le Web et marchent donc, sauf Spotify qui réussit l'exploit d'être un des rares services accessibles via le Web qui ne fonctionne pas en IPv6.

Moins bonne est la situation des appliances comme les webcams. La plupart ne parlent pas IPv6 du tout, sourds que sont leurs constructeurs chinois aux sirènes de la modernité.

Enfin, les problèmes ne sont pas forcément avec les matériels et logiciels du réseau local. Parfois, le problème est situé chez le pair avec qui on veut communiquer comme lorsque bit.ly (le RFC cite ce cas mais sans mentionner le nom comme si l'information n'était pas déjà publique...) avait publié un enregistrement AAAA invalide : NAT64 ne peut rien dans ce cas puisque la passerelle pense que le service est accessible en IPv6. C'est l'occasion de rappeler qu'il vaut mieux ne pas publier de AAAA que d'en publier un erroné.

On l'a vu, une bonne partie de la connectivité externe des deux réseaux de test dépendait de NAT64, puisqu'une grande partie de l'Internet n'est hélas pas joignable en IPv6. La section 6 tire le bilan spécifique de ce protocole et il est très positif : pas de problèmes de fond, juste quelques bogues dans l'implémentation, corrigées au fur et à mesure.

Le cas des adresses IPv4 littérales dans les URL est irrémédiable (le DNS n'est pas utilisé donc DNS64 ne peut rien faire) mais rare. Les deux seuls cas bloquants concernaient certaines pages YouTube (tiens, pourquoi est-ce que les erreurs de bit.ly sont mentionnées sans indiquer son nom, alors que YouTube est désigné dans le RFC ?) et une page de réservation d'un hôtel qui renvoyait vers un URL contenant une adresse IPv4. Les auteurs du RFC ont mesuré les 10 000 premiers sites Web du classement Alexa et trouvé que 0,2 % des 1 000 premiers ont un URL IPv4 dans leur page (pour charger du JavaScript, du CSS ou autre), et que ce chiffre monte à 2 % pour les 10 000 premiers (ce qui laisse entendre que les premiers sont mieux gérés). Cette stupide erreur n'empêchait pas le chargement de la page, elle privait juste le lecteur d'un bandeau de publicité ou d'une image clignotante. Ce n'est donc pas un problème sérieux en pratique.

Les auteurs ont également testé avec wget le chargement des pages d'accueil de ces 10 000 sites en comparant un accès IPv4, un accès IPv6 sans NAT64 et le réseau de test, IPv6 pur mais avec NAT64. En IPv4 pur, 1,9 % des sites ont au moins un problème (pas forcément la page d'accueil elle-même, cela peut être un des composants de cette page), ce qui donne une idée de l'état du Web. Le RFC note toutefois que certains problèmes peuvent être spécifiques à ce test, si le serveur refuse à wget du contenu qu'il accepterait de donner à un navigateur Web. wget avait été configuré pour ressembler à un navigateur (le RFC ne le dit pas mais je suppose que cela veut dire des trucs comme --user-agent="Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:11.0) Gecko/20100101 Firefox/11.0"). Mais cela ne suffit pas dans des cas comme l'absence d'une adresse pour un nom de domaine, qui ne gène pas le navigateur qui ajoute www devant à tout hasard, chose que ne fait pas wget.

Avec le réseau IPv6 pur, 96 % des sites échouent (ce qui est logique, vu le nombre de sites Web accessible en v6). Les sites Google étaient une des rares exceptions.

Avec le réseau IPv6 aidé de la passerelle NAT64, le taux d'échec est de 2,1 %, quasiment le même qu'en IPv4 pur (la différence venant surtout des adresses IPv4 littérales).

Sur quoi doivent porter les efforts de mesure futurs (section 7) ? Le RFC estime important de mesurer plus précisement les phénomènes à l'œuvre lors d'une connexion utilisant NAT64. Certains utilisateurs ont signalé des ralentissements, mais qui ne sont pas confirmés par une analyse des paquets et des temps de réponse. S'il se passe quelque chose qui ralentit, c'est plus subtil, et cela devrait être investigué.

Compte-tenu de cette expérience, quelles conclusions en tirer (section 8) ? Comme indiqué plus haut, la principale est qu'un réseau purement IPv6 est viable. (Le RFC ne le précise pas mais je rajoute : s'il est géré par un informaticien compétent et disponible. Cette expérience n'est pas encore reproductible par M. Toutlemonde.)

Seconde grande conclusion : il reste du travail, trop de petites bogues sont encore présentes, et à beaucoup d'endroits.

Bref, aujourd'hui, il reste prudent d'utiliser plutôt la double-pile (IPv6 et IP4) pour un réseau de production. Un réseau IPv6 pur, à part pour le geek, est surtout intéressant pour des environnements très contrôlés, comme par exemple celui d'un opérateur de téléphonie mobile qui fournirait un modèle de téléphone obligatoire, permettant de s'assurer que tous les clients aient ce qu'il faut.

Comme tout ne s'arrangera pas tout seul, nos héroïques explorateurs revenant de la terre lointaine et mystérieuse où tout ne marche qu'en IPv6 suggèrent des actions à entreprendre pour se préparer à notre future vie dans ce monde :

  • La découverte du résolveur DNS reste un des points qui marchent le plus mal, probablement parce qu'elle fonctionne bien en double-pile, masquant les problèmes IPv6. Par exemple, l'utilisation des annonces RA du RFC 6106 devrait être systématique et c'est loin d'être le cas, par exemple dans les divers systèmes utilisant Linux.
  • Autre problème, les divers network managers, ces logiciels qui règlent le ballet des différentes composants de l'accès au réseau : même lorsque le système dispose de tous les composants qui marchent en IPv6, le network manager ne les utilise pas toujours correctement. En essayant Ubuntu, par exemple, il est clair que ce système n'a jamais été testé dans un environnement purement IPv6.
  • Les pare-feux ont souvent des capacités IPv6 inférieures à celles qu'ils ont en v4.
  • Plusieurs applications que les utilisateurs considèrent comme très importantes (les jeux vidéo, par exemple) ne marchent pas du tout en IPv6 : du travail pour les programmeurs, qui devraient au miminum utiliser des API qui sont indépendantes de la version d'IP.

Le RFC note que pratiquement aucune de ces actions ne nécessite d'action dans le champ de la normalisation. Cela veut dire que toutes les normes nécessaires sont là, l'IETF a terminé son travail et c'est maintenant aux programmeurs et aux administrateurs réseaux d'agir.


Téléchargez le RFC 6586


L'article seul

RFC 6585: Additional HTTP Status Codes

Date de publication du RFC : Avril 2012
Auteur(s) du RFC : M. Nottingham (Rackspace), R. Fielding (Adobe)
Chemin des normes
Première rédaction de cet article le 1 mai 2012


Le protocole HTTP, normalisé dans le RFC 7230, utilise des réponses numériques sur trois chiffres pour indiquer le résultat de la requête. Certains de ces codes sont devenus célèbres comme le 404 pour une ressource non trouvée. Et comme l'Internet fonctionne avec des LOLcats, il existe même un ensemble de photos des réponses HTTP avec des chats (d'où sont tirées les images de cet article). Mais la liste des réponses possibles n'est pas figée et de nouveaux codes sont ajoutés de temps en temps. Ce RFC normalise quatre de ces codes.

Ces nouveaux codes permettent de préciser le code utilisé autrefois, qui était en général moins précis. Ainsi, les limiteurs de trafic utilisaient souvent, lorsqu'un client demandait trop de ressources, le code 403 (Interdiction), qui pouvait servir à bien d'autres choses. Ils ont désormais un code à eux, 429. Les nouveaux codes sont enregistrés à l'IANA.

Rappelez-vous bien que le premier chiffre indique la classe de l'erreur (RFC 7231, section 6) et qu'un serveur HTTP qui utilise un code nouveau n'a pas de souci à se faire : un client qui ne connaîtrait pas ce nouveau code peut le traiter comme le code générique commençant par le même chiffre. Pour reprendre l'excellent résumé de Dana Contreras, « HTTP response codes for dummies. 5xx: we fucked up. 4xx: you fucked up. 3xx: ask that dude over there. 2xx: cool ».

Premier cité (section 3), 428 Precondition Required (pas de jolie image de chat pour ce code). Pour éviter le problème de la « mise à jour perdue » (un client récupère une ressource Web, la modifie et la renvoie au serveur pour mise à jour, alors que, pendant ce temps, un autre client a fait pareil : l'un des deux va perdre sa mise à jour), certains serveurs HTTP exigent que les requêtes soient conditionnelles (par exemple avec le If-Match: de la section 3.1 du RFC 7232). Si le client n'a pas utilisé de condition, le serveur l'enverra promener avec ce code 428 (qui doit normalement être accompagné d'un message clair indiquant le problème) :


HTTP/1.1 428 Precondition Required
Content-Type: text/html

<html>
 <head>
  <title>Precondition Required</title>
 </head>
 <body>
  <h1>Precondition Required</h1>
   <p>This request is required to be conditional;
      try using "If-Match".</p>
 </body>
</html>

Deuxième code, 429 Too Many Requests (section 4) status-cat-429.jpg Il était apparemment assez répandu dans la nature mais n'était pas encore normalisé. C'est désormais fait et les limiteurs de trafic peuvent donc désormais dire clairement à leurs clients qu'ils exagèrent :


HTTP/1.1 429 Too Many Requests
Content-Type: text/html
Retry-After: 3600

<html>
   <head>
      <title>Too Many Requests</title>
   </head>
   <body>
      <h1>Too Many Requests</h1>
      <p>I only allow 50 requests per hour to this Web site per
         logged in user. Try again soon.</p>
   </body>
</html>

C'est uniquement un indicateur d'une décision prise par le serveur : le RFC n'impose pas aux serveurs un mécanisme particulier pour prendre cette décision. De même, le serveur n'est pas obligé de renvoyer quelque chose (ce qui consomme des ressources), il a le droit d'ignorer purement et simplement les requêtes excessives (section 7.2).

Troisième code, en section 5, 431 Request Header Fields Too Large status-cat-431.jpg Le protocole HTTP n'impose pas de limite à la taille des en-têtes envoyés lors d'une requête mais un serveur donné peut avoir une telle limite. Si elle est dépassée, il peut répondre 431. Le même code peut dire « taille totale des en-têtes trop grande » ou « taille d'un en-tête trop grande ». Dans ce dernier cas, la réponse doit indiquer quel en-tête :


HTTP/1.1 431 Request Header Fields Too Large
Content-Type: text/html

<html>
   <head>
      <title>Request Header Fields Too Large</title>
   </head>
   <body>
      <h1>Request Header Fields Too Large</h1>
      <p>The "Example" header was too large.</p>
   </body>
</html>

Ces trois premiers codes n'ont pas suscité de controverses particulières. Ce n'était pas le cas de 511 Network Authentication Required (section 6, pas de jolie image de chat pour ce code) qui indique que le client aurait dû s'authentifier. Le problème est d'architecture : ce code est utilisé pour les portails captifs qui, tant qu'on n'est pas authentifié, redirigent d'autorité toutes les requêtes HTTP vers un serveur permettant de s'authentifier. (Après l'authentification, l'adresse MAC est mémorisée par le routeur, qui ne redirige plus.) De tels portails violent sérieusement les bons principes d'architecture du Web. Mais ils existent et il était donc préférable qu'ils puissent répondre avec un code sans ambiguité. La réponse 511 inclut donc le lien vers la page de login. Elle ne doit jamais être envoyée par un serveur normal, uniquement par le relais détourneur.

Le RFC dit donc que les portails captifs sont le Mal (surtout pour les clients HTTP qui ne sont pas des navigateurs) mais que le 511 permettra de limiter les dégats. Au moins, curl ou wget comprendront tout de suite ce qui s'est passé.

Un exemple de réponse (notez l'élément <meta> pour les navigateurs) :


HTTP/1.1 511 Network Authentication Required
Content-Type: text/html

<html>
   <head>
      <title>Network Authentication Required</title>
      <meta http-equiv="refresh"
            content="0; url=https://login.example.net/">
   </head>
   <body>
      <p>You need to <a href="https://login.example.net/">
      authenticate with the local network</a> in order to gain
      access.</p>
   </body>
</html>

Les réponses 511 ou, plus exactement, les redirections forcées posent des tas de problèmes de sécurité. Par exemple, elles ne viennent pas du serveur demandé, ce qui casse certains mécanismes de sécurité de HTTP comme les cookies du RFC 6265. Un problème analogue survient si on utilise TLS car le certificat X.509 ne correspondra pas au nom demandé. L'annexe B du RFC détaille les problèmes de sécurité des portails captifs et les façons de les limiter. Cela va de problèmes esthétiques (la favicon récupérée depuis le portail et qui s'accroche ensuite dans le cache du navigateur) jusqu'aux protocoles de sécurité qui risquent de prendre la réponse du portail pour l'information qu'ils demandaient (P3P, WebFinger, OAuth, etc). Ces protocoles sont souvent utilisés par des applications HTTP qui ne passent pas par un navigateur (Twitter, iTunes, le WebDAV du RFC 4918, etc). En détectant le code 511, ces applications ont une chance de pouvoir réagir proprement (en ignorant les réponses transmises avec ce code).

À l'heure actuelle, je ne pense pas qu'il y ait beaucoup de hotspots qui utilisent ce code mais cela viendra peut-être. Mais je n'en suis pas sûr, ces portails captifs étant en général programmés avec les pieds, par un auteur anonyme à qui on ne peut jamais signaler les bogues. Et je ne sais pas quels sont les clients HTTP qui le reconnaissent et agissent intelligement. Si un lecteur courageux veut enquêter...

Les images de chats citées plus haut sont également accessibles via une API REST simple. Si vous préférez les chiens, ça existe aussi.


Téléchargez le RFC 6585


L'article seul

RFC 6582: The NewReno Modification to TCP's Fast Recovery Algorithm

Date de publication du RFC : Avril 2012
Auteur(s) du RFC : T. Henderson (Boeing), S. Floyd (ICSI), A. Gurtov (University of Oulu), Y. Nishida (WIDE Project)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF tcpm
Première rédaction de cet article le 7 avril 2012


Même les plus vieux protocoles, comme TCP, continuent à évoluer, dans l'environnement toujours changeant qu'est l'Internet. Pour lutter contre le principal ennemi d'un protocole de transport, la congestion, de nouveaux algorithmes sont régulièrement mis au point. Même des années après leur spécification, on trouve des choses à corriger ou améliorer. Ainsi, l'algorithme NewReno, originellement proposé par le RFC 2582 en 1999, puis normalisé par le RFC 3782 en 2004, voit avec ce nouveau RFC sa description évoluer très légèrement, pour répondre aux problèmes rencontrés.

La référence pour la lutte de TCP contre la congestion est le RFC 5681. Ce dernier spécifie quatre algorithmes possibles, et autorise des modifications limitées à ces algorithmes, par exemple en utilisant les accusés de réception sélectifs (SACK, RFC 2883) ou bien en utilisant les accusés de réception partiels (ceux qui ne couvrent pas la totalité des données encore en transit). C'est le cas de NewReno et ce RFC remplace l'ancienne définition de NewReno (celle du RFC 3782).

Un peu d'histoire de NewReno (section 1) : l'algorithme de retransmission rapide (Fast Recovery) de TCP avait d'abord été mis en œuvre dans une version de BSD connue sous le nom de Reno. (L'article original est toujours en ligne, ainsi qu'une comparaison des méthodes.) L'idée de base de la retransmission rapide est de retransmettre les accusés de réception lorsqu'arrivent des paquets dont les numéros de séquence sont supérieurs à ceux attendus (section 5 de notre RFC ; cette retransmission indique la perte de paquets intermédiaires). L'émetteur commence alors tout de suite à retransmettre, sans attendre l'expiration du délai de garde normal. Le problème est que l'émetteur ne sait pas exactement ce qu'il faut retransmettre. Par exemple, avec une MSS de 1460 octets et un numéro de séquence initial (ISN) de 67891, si un émetteur envoie cinq paquets, il sera satisfait lorsqu'il recevra un accusé de réception pour l'octet 75191. S'il reçoit des accusés de réception dupliqués pour l'octet 70811, cela veut dire que deux paquets sont arrivés, puis que le paquet n° 4 ou le n° 5 est arrivé, déclenchant l'émission des accusés de réception dupliqués. L'émetteur va alors retransmettre le paquet n° 3. Mais doit-il aussi renvoyer les n° 4 et n° 5 ? L'émetteur ne le sait pas, les accusés de réception n'indiquent pas les octets reçus hors-séquence, sauf à utiliser les SACK du RFC 2883. NewReno avait justement été conçu pour ce cas où on ne peut pas ou bien où on ne veut pas utiliser les accusés de réception sélectifs (SACK). Son principe est, pendant la retransmission rapide, de regarder si les accusés de réception couvrent tous les paquets transmis (accusé de réception pour l'octet 75191) ou bien seulement une partie (par exemple, accusé de réception pour l'octet 72271). Dans ce cas (accusés de réception partiels), on sait qu'il y a perte de plusieurs paquets et on peut retransmettre tout de suite (ici, le paquet n° 4).

NewReno est donc une légère modification, située uniquement chez l'émetteur, à l'algorithme de retransmission rapide (« OldReno » ?). Cette modification est déclenchée par la réception, une fois la retransmission rapide commencée, d'accusès de réception partiels. Elle consiste en la réémission de paquets supplémentaires, suivant le paquet qu'« OldReno » retransmettait déjà.

Si vous voulez tous les détails, la section 3 précise le nouvel algorithme. Comme il ne nécessite des modifications que chez l'émetteur des données, il n'affecte pas l'interopérabilité des mises en œuvre de TCP. Évidemment, SACK serait une meilleure solution, donnant à l'émetteur toute l'information nécessaire mais, en son absence, NewReno améliore les performances en évitant d'attendre inutilement l'expiration d'un délai de garde.

Il existe quelques variations à NewReno, moins importantes que la différence entre OldReno et NewReno. Ces variations possibles sont documentées dans l'ancien RFC, le RFC 3782 et citées dans l'annexe A.

NewReno est aujourd'hui bien établi et éprouvé. L'ancien RFC, le RFC 3782 contenait des éléments en sa faveur (notamment via des simulations), qui semblent inutiles aujourd'hui et ont donc été retirés.

Globalement, les principaux changements depuis le RFC 3782 sont le retrait de nombreuses parties qui n'apparaissent plus aussi importantes qu'à l'époque. Le lecteur qui veut approfondir le sujet, et pas uniquement programmer NewReno correctement, peut donc lire le RFC 3782 pour découvrir d'autres discussions. Autrement, les changements sont de détail, et résumés dans l'annexe B.

Merci à Didier Barvaux pour sa relecture.


Téléchargez le RFC 6582


L'article seul

RFC 6576: IPPM standard advancement testing

Date de publication du RFC : Mars 2012
Auteur(s) du RFC : R. Geib (Deutsche Telekom), A. Morton (AT&T Labs), R. Fardid (Cariden Technologies), A. Steinmitz (Deutsche Telekom)
Réalisé dans le cadre du groupe de travail IETF ippm
Première rédaction de cet article le 26 mars 2012


Pour déterminer si un protocole de communication est bien décrit dans les RFC qui le normalisent, l'IETF a une méthode simple, tester si les différentes mises en œuvre de ce protocole interopèrent proprement entre eux (par exemple, on vérifie qu'un client HTTP parle au serveur HTTP avec succès). Ce genre de tests est maintenant fréquent, et sert de base à l'avancement des RFC sur le chemin des normes (de simple proposition au statut de norme complète). Mais, lorsqu'un RFC spécifie, non pas un protocole mais une métrique, c'est-à-dire une grandeur mesurable, comment fait-on pour vérifier que le RFC est correct et est bien implémenté ? Ce nouveau RFC de l'inépuisable groupe de travail IPPM propose une solution : on mesure le même phénomène avec les différentes mises en œuvre et les chiffres obtenus doivent être identiques (ou suffisamment proches pour être statistiquement équivalents). Cette méthode permettra aux RFC décrivant les métriques d'avancer sur le chemin des normes : si les résultats sont les mêmes, on considérera que cela semble indiquer que la métrique est définie clairement et sans ambiguité. (Si les résultats sont différents, cela pourra être dû à une bogue dans l'un des systèmes, ou à un RFC confus, qui n'a pas été compris de la même façon par tous les développeurs.)

Le chemin des normes, qui comportait trois étapes du temps du RFC 2026, n'en a plus que deux depuis le RFC 6410. Un des critères d'avancement d'une norme est l'interopérabilité entre des mises en œuvre indépendantes. Cette interopérabilité devait autrefois se démontrer par des tests explicites (RFC 5657) mais, aujourd'hui, le simple déploiement massif suffit (nul besoin de tester HTTP pour voir tous les jours dans l'Internet que clients et serveurs se parlent...). Tout cela est très bien pour les protocoles de communication. Mais pour des métriques ? On peut avoir plusieurs mises en œuvre indépendantes, qui sont largement déployées, sans que cela ne prouve qu'elles soient cohérentes entre elles. La section 5.3 du RFC 5657 prévoit explicitement le cas des normes qui ne sont pas des protocoles de communication mais ne fournit guère de solutions. L'analyse du groupe IPPM est qu'il est quand même possible de tester explicitement des définitions de métriques et que l'identité (aux variations statistiques près) des chiffres obtenus par deux mesures du même phénomène réseau est l'équivalent de l'interopérabilité. (Notez qu'IPPM a aussi quelques protocoles à son actif, comme ceux du RFC 4656 et RFC 5357, dont l'interopérabilité peut être testée par des moyens classiques.)

Pour les métriques, l'idée va donc être de générer un phénomène réseau contrôlé, avant de le faire mesurer par les différents systèmes. (Mesurer un phénomène réel, non contrôlé, est plus difficile car cela implique que les différentes mesures soient parfaitement synchronisées, pour observer exactement la même chose. Tous les systèmes de mesure n'ont pas forcément ce mécanisme de synchronisation.) Un exemple complet figure dans l'annexe A, avec la métrique « délai d'acheminement », et c'est une lecture très recommandée si tout cela vous semble trop abstrait.

La section 2 détaille cette idée de base. Inspirée du RFC 2330, elle part du principe qu'une mesure doit être reproductible (on mesure le même phénomène deux fois, et les résultats doivent être identiques, aux fluctuations statistiques près). En pratique, mesurer exactement « le même phénomène » implique de prêter attention à de nombreux détails, par exemple à la stabilité des routes (sur l'Internet, le délai d'acheminement entre deux points peut varier brusquement, si BGP recalcule les routes à ce moment). D'autre part, si la métrique a des options, les deux mesures doivent évidemment utiliser les mêmes options. Et, en raison des variations du phénomène, l'échantillon mesuré doit être assez grand pour que la loi des grands nombres rende ces variations négligeables. La section 2 dit clairement qu'on n'envisage pas de mesurer des singletons (par exemple, pour le délai d'acheminement, le délai d'un seul paquet).

Une fois ces précautions comprises, comment détermine-t-on la conformité d'une mesure à la spécification de la métrique (section 3) ? D'abord, dans la grande majorité des cas, les critères de comparaison vont dépendre de la métrique, et doivent donc être définis spécifiquement pour chaque métrique (l'annexe A fournit un exemple complet). Ensuite, on va comparer deux mesures (qui peuvent avoir été faites dans le même laboratoire, ou bien dans des endroits différents.) La méthode statistique de comparaison recommandée est le test d'Anderson-Darling K. Entre deux mesures d'un même phénomène, on veut un niveau de confiance d'Anderson-Darling K d'au moins 95 %.

Selon l'environnement de test, il va falloir faire attention à des techniques comme la répartition de charge qui peuvent envoyer le trafic par des chemins distincts, une bonne chose pour les utilisateurs, mais une plaie pour les métrologues (cf. RFC 4928).

Compte-tenu de tous les pièges que détaille la section 3 (le gros du RFC), il est nécessaire de documenter soigneusement (RFC 5657 et section 3.5 de notre RFC) l'environnement de test : quelle était la métrique mesurée, quelle était la configuration de test, tous les détails sur le flot de paquets (débit, taille, type, etc).

Si on trouve des différences entre deux mesures de la même métrique, sur le même phénomène, alors il faudra se lancer dans un audit soigneux pour déterminer où était la racine du problème : bogue dans une implémentation ou manque de clarté de la spécification, cette seconde raison étant un bon argument pour ne pas avancer la métrique sur le chemin des normes et pour l'améliorer.

Si vous voulez en savoir plus que le test d'Anderson-Darling, il est documenté dans le rapport technique 81 de l'Université de Washington, par Scholz, F. et M. Stephens, « K-sample Anderson-Darling Tests of fit, for continuous and discrete cases ». Le test Anderson-Darling K est faisable en R : voir le paquetage « adk: Anderson-Darling K-Sample Test and Combinations of Such Tests ». Une implémentation d'Anderson-Darling K en C++ figure dans l'annexe B du RFC.

L'annexe A contient un exemple complet de test d'une métrique, en l'occurrence le délai d'acheminement d'un paquet, tel que défini par le RFC 2679 (le test complet sera documenté dans un futur RFC, actuellement l'Internet-Draft « Test Plan and Results for Advancing RFC 2679 on the Standards Track »). Par exemple, on met le délai d'attente maximum (une option de la métrique) à 2 secondes, on mesure un flot de paquets à qui on impose un délai d'une seconde, grâce à un dispositif qui introduit délibérement des problèmes réseaux (un impairment generator ; ce genre de traitement peut se faire sur un Unix courant), on vérifie qu'ils sont tous comptés, on passe le délai imposé à 3 secondes, et on vérifie qu'on n'obtient plus aucun résultat (la grandeur « délai d'acheminement » est indéfinie si le paquet n'arrive pas avant le délai maximum, RFC 2679, section 3.6).

Ce n'est évidemment pas le seul test. L'annexe A propose également de tester le délai d'acheminement (qui va jusqu'à la réception du dernier bit du paquet, RFC 2679, section 3.4) en faisant varier la taille des paquets, mettons à 100 et 1500 octets. Les implémentations testées doivent mesurer la même augmentation du délai d'acheminement (qui ne dépendra que du temps de transmission supplémentaire, que devra supporter le plus gros des paquets). Autre test, mesurer le délai, puis imposer un retard N, les différentes mesures doivent voir la même augmentation du délai.

Le premier RFC à avoir testé cette démarche a été le RFC 2679, dont le rapport d'avancement a été publié dans le RFC 6808.


Téléchargez le RFC 6576


L'article seul

RFC 6574: Report from the Smart Object Workshop

Date de publication du RFC : Avril 2012
Auteur(s) du RFC : H. Tschofenig (Nokia Siemens Networks), J. Arkko (Ericsson)
Pour information
Première rédaction de cet article le 13 avril 2012


Traditionnellement, les engins connectés à l'Internet étaient des ordinateurs généralistes, dotés de bonnes capacités de calcul et alimentés en courant électrique à volonté. Est-ce que la famille de protocoles TCP/IP convient toujours, lorsque les machines connectées sont des petits trucs avec un processeur ridicule, et alimentés par une batterie qu'il faut faire durer le plus longtemps possible ? C'était l'objet de l'atelier Interconnecting Smart Objects with the Internet qui s'est tenu à Prague le 25 mars 2011, à l'instigation de l'IAB. Le but était d'explorer cette question, de voir si la connexion à l'Internet de ces « objets malins » était triviale, possible avec quelques adaptations des protocoles ou, pourquoi pas, irréaliste sans des changements radicaux.

L'atelier a rassemblé près de cent participants (liste complète en annexe D), la plupart ayant déjà travaillé sur l'adaptation de TCP/IP à des objets contraints (en mémoire, en alimentation, etc). Ces objets peuvent être des capteurs, des actionneurs, etc. À côté d'eux, même un smartphone est riche en capacités CPU et en énergie électrique.

Rappelons que l'IAB, qui a produit ce RFC, est en charge du travail d'architecture à l'IETF. Ce comité ne s'occupe pas des protocoles individuels (dont le développement, dans les groupes de travail IETF, est piloté par l'IESG) mais du maintien et du développement d'une architecture saine pour l'Internet, avec une insistance sur le travail à long terme.

Une de ces questions à long terme est celle du passage d'un Internet composé uniquement d'ordinateurs à un Internet auquel sont attachés, entre autres, des engins qu'on qualifie du terme générique d'« objets » et qui ont en commun de sévères restrictions matérielles, rendant parfois difficile un attachement normal à l'Internet. Pour les développements liés à ces objets, les gens du marketing ont inventé le terme ridicule d'« Internet des objets » (IoT en anglais pour « Internet of Things »). Mais, même si le terme est grotesque, il y a une vraie question technique : l'Internet est-il accessible à des objets contraints en ressources ?

Connecter ces objets présente souvent des avantages (pour des capteurs, cela permet de les interroger à distance, alors qu'auparavant il fallait qu'un humain se déplace pour les lire), et certains le sont déjà, en utilisant des protocoles privés. Mais la tendance actuelle est de migrer vers les protocoles standard de l'Internet. Cela se reflète entre autres dans les groupes de travail IETF, dont plusieurs planchent sur cet Internet des Trucs : Constrained RESTful Environments (CoRE), IPv6 over Low power WPAN (6LowPAN), Routing Over Low power and Lossy networks (ROLL) ou Light-Weight Implementation Guidance (LWIG).

C'est que le travail d'ingéniérie n'est pas facile : il faut jongler entre des exigences contradictoires, la sécurité, le prix, l'utilisabilité, la protection de la vie privée (ces objets sont souvent liés à notre vie quotidienne), la longévité sous batterie, etc. (Le RFC cite, sur cette questions des exigences contradictoires, l'excellent article « Tussle in Cyberspace: Defining Tomorrow's Internet ».)

L'atelier de l'IAB partait de la constatation que les protocoles actuels de l'Internet, d'IPv4 à IPv6, d'UDP à TCP et jusqu'à bien sûr HTTP, fonctionnent même sur les objets contraints. Il en existe déjà dans la nature. Une première question était « quel bilan tirer de ces premiers déploiements ? ». Une autre était « quels sont les problèmes pas encore résolus ?  ».

En quoi ces objets sont-ils contraints ? Que leur manque-t-il exactement, par rapport à un ordinateur classique ? La section 2 détaille leurs propriétés :

  • Très limités en alimentation électrique, ces engins doivent se mettre en sommeil fréquemment. Cela fait un sérieux changement de paradigme pour les protocoles Internet, habitués aux ordinateurs toujours en marche.
  • Très limités en capacité réseau, ces objets ont souvent moins de 100 kb/s disponibles et parfois seulement 10 ou 20 ! En outre, leur connectivité est fréquemment affectée par des taux de pertes de paquets importants.
  • Très limités en mémoire, les appareils en question ne peuvent pas stocker du code ou des données compliquées. Par exemple, la carte Arduino n'a que 2 ko de RAM et 32 ko de mémoire flash.
  • Liée au problème de la consommation électrique, il y a aussi la faible capacité des processeurs. Pour moins consommer, ils sont souvent lents.
  • Peu ou pas d'interface utilisateur (encore moins qu'un routeur), et donc difficiles à configurer.
  • Enfin, il y a des limitations de taille physique. Si la traditionnelle carte ATX fait 305x244 mm, la CoreExpress, conçue pour l'embarqué, ne fait que 58x65 mm.

La loi de Moore, souvent citée pour relativiser ces limites, ne suffit pas. Les gains qu'elle permet sont souvent utilisés pour réduire coûts et consommation électrique, pas pour augmenter la puissance.

Place à l'atelier lui-même, maintenant. Avec 70 papiers acceptés (la liste complète figure en annexe B du RFC), il n'est pas facile à synthétiser. La section 3 de notre RFC essaie quand même d'indiquer les grands lignes de la réflexion. Quatre grandes questions structuraient l'atelier, les questions d'architecture, les points soulevés par les nœuds dormants, la sécurité et le routage. Commençons par l'architecture, section 3.1.

Première question d'architecture, parle-t-on de connecter ces objets contraints à l'Internet (singulier, et avec une majuscule, car c'est une entité unique comme l'Atlantique ou l'Himalaya) ou bien à des réseaux utilisant TCP/IP, mais qui ne sont pas forcément reliés à l'Internet ? Après tout, les capteurs et actionneurs dans une usine n'ont pas forcément besoin de se connecter à YouTube et, même si le RFC ne le rappelle pas, du point de vue sécurité, il est irresponsable de relier un SCADA à l'Internet. (Le RFC cite un cas moins grave, celui des fontaines devant l'hôtel Bellagio, à Las Vegas, fontaines qui sont électroniquement contrôlées à distance mais qui n'ont pas besoin d'être sur le même réseau que les clients dans leurs chambres, cf. l'exposé de B. Dolin à l'atelier.) Même chose pour les smart grids qui n'ont rien à gagner (et beaucoup à perdre) à être joignables depuis l'Internet. Bref, l'IETF doit-elle séparer clairement le cas des objets connectés à l'Internet et celui des objets reliés à TCP/IP ? Du point de vue purement économique, il est clair qu'il vaut mieux un seul réseau, comme l'a rappelé Cullen Jennings, qui prédisait que tour le monde serait connecté au même Internet, car c'était plus simple et moins coûteux.

Une autre question d'architecture fondamentale est celle des protocoles spécifiques à un domaine d'application. Prenons l'exemple d'une ampoule électrique du futur. Grâce aux normes, on la branche au réseau et elle acquiert une adresse IP (grâce à DHCP ou NDP), trouve un serveur DNS, on peut la pinguer. On peut même imaginer qu'elle ait un serveur HTTP et tout client HTTP peut alors s'y connecter. Mais pour une tâche simple pour laquelle elle est conçue, éclairer, il n'y a pas de norme. Une commande de base « allume-toi » n'est pas normalisée. Comment s'assurer que l'objet, non seulement sera connecté (ping), mais pourra interagir avec son environnement, selon ses capacités ? Les protocoles de couche 3, 4 et même 7 ne suffisent pas. Il va falloir mettre au point des modèles (des classes, dirait-on en programmation objet, dont le nom est bien adapté ici), pour exploiter ces objets « intelligents ».

Un des principes de base de l'Internet, qui est défié par l'arrivée massive des objets connectés, est celui comme quoi l'intelligence est uniquement aux extrémités et le réseau fournit uniquement un service de base (faire passer les paquets). Avec des objets assez limités en ressources, on pourrait imaginer de revisiter ce principe et de mettre de l'« intelligence » dans le réseau. Parmi les services pour lesquels ce serait un bon endroit, on peut imaginer :

  • La localisation, à savoir indiquer à l'objet où il se trouve. Il ne s'agit pas uniquement des coordonnées GPS mais aussi de l'environnement (« tu es dans un hôpital », « tu es dehors »).
  • Routage fondé sur les noms, où les couches basses sauraient utiliser directement le nom d'une ressource (par exemple « Lampe »), sans passer par des résolutions en identificateurs de plus bas niveau. C'est relativement simple à faire pour un petit réseau local, où un contrôleur peut diffuser à tous « Lampe, allume-toi », et où la lampe se reconnait et s'exécute, mais bien plus complexe dans les grands réseaux. La question n'a pas fait l'objet d'un consensus à l'atelier, loin de là.

Deuxième grande question après l'architecture, le sommeil des objets (section 3.2). Pour économiser l'énergie, beaucoup de ces objets contraints s'endorment souvent. Pour qu'une pile AAA tienne des mois, il faut que l'objet dorme pendant 99, voire 99,9 % du temps. Chaque bit, chaque aller-retour sur le réseau, et chaque milli-seconde d'activité radio (une activité qui consomme beaucoup de courant) est précieux. Or, la plupart des protocoles TCP/IP sont conçus autour de l'idée que les machines sont allumées en permanence, qu'elles peuvent garder un état et répondre à tout moment à un paquet, même non sollicité. Mais, lorsque la simple attente d'un éventuel message consomme du courant, cette idée n'est plus valable : les objets contraints sont plus souvent endormis qu'éveillés, contrairement aux ordinateurs classiques.

Pire, lorsqu'un nœud se réveille après une période de sommeil, son adresse IP a pu être prise par un autre. Il va donc devoir se lancer dans une procédure coûteuse pour obtenir une adresse. Il peut toutefois économiser des efforts s'il met en œuvre les méthodes DNS (Detecting Network Attachment) des RFC 4436 et RFC 6059. Autre piège, si l'objet est mobile, après son réveil, il a pu bouger pour un tout autre endroit.

Pour gérer ces machines « Belle au bois dormant », les solutions envisagées lors de l'atelier étaient :

  • Ne plus considérer comme acquis que les machines sont toujours allumées, lorsqu'on conçoit un protocole. Prévoir une réduction des fonctions du protocole, ou bien des intermédiaires, toujours allumés, qui reçoivent les messages et les stockent (on nomme cela un sleep proxy, comme dans la norme ECMA-393). Autre solution, que les machines communiquent leurs heures de réveil à leurs pairs, comme dans 802.11.
  • Réduire le prix d'une connexion initiale au réseau. Actuellement, l'arrivée sur un nouveau réseau (et un nœud mobile, lorsqu'il se réveille, doit toujours supposer qu'il est sur un nouveau réseau) met en jeu des protocoles coûteux en énergie comme DHCP ou NDP. Peut-on réduire ce coût, surtout pour les machines qui savent qu'elles ne sont pas mobiles ?
  • Réduire le coût des échanges de messages. Préferer les protocoles qui limitent le bla-bla (plus le dialogue est long, plus il faut rester allumé longtemps), les encodages qui ne consomment pas trop d'octets (donc, attention à XML),
  • Penser au coût total en énergie : le RFC cite l'exemple de l'absurdité de la domotique où des ampoules allumées et éteintes par un contrôleur consomment soi-disant moins d'énergie... alors que le bilan global est négatif, à cause de la consommation du contrôleur et du réseau.

Troisième grande question explorée lors de l'atelier, la sécurité (section 3.3). Il faut évidemment la prendre en compte dès le début (RFC 3552 et RFC 4101). L'idéal est que la sécurité soit intégrée dans le début, au lieu d'être une option qu'on oublie d'activer. Mais les défis pour les objets contraints sont énormes. Les calculs qu'impose la cryptographie ne vont pas dans le sens de l'économie d'énergie. D'autre part, l'absence d'une interface utilisateur commode limite sérieusement la configuration qui peut être faite (pas moyen de demander à l'administrateur d'entrer un mot de passe compliqué). Les protocoles de sécurité de l'IETF permettent de gérer tous les cas, mais ils peuvent être trop riches et on peut défendre l'idée de profils, de restrictions ne gardant, par exemple, que certains algorithmes de cryptographie. Le choix ne sera pas évident car il existe des exigences contradictoires. Par exemple, les algorithmes à base de courbes elliptiques (RFC 6090) sont souvent moins consommateurs de ressources matérielles mais sont bien plus encombrés de brevets.

Enfin, les objets communiquants ayant vocation à être partout (à l'usine, au bureau, mais aussi à la maison et, pourquoi pas, dans notre propre corps), les questions de protection de la vie privée sont cruciales. Pas question qu'un sniffer puisse espionner la communication entre le frigo et le supermarché, apprenant ainsi mes habitudes, mes heures de présence, etc. (Dans ce cas, le principal danger pour la vie privée vient probablement du supermarché et, là, le chiffrement des communications n'aide pas.)

Mais l'algorithme de cryptographie n'est pas tout : l'expérience de l'usage de la cryptographie dans l'Internet a montré que les problèmes de gestion des clés cryptographiques étaient souvent bien pires.

Enfin, dernière grande question analysée à Prague, le routage (section 3.4). Les objets communiquants peuvent être trop loin les uns des autres pour se parler directement et il peut être nécessaire de passer par un routeur. Comment les objets et les routeurs vont-ils apprendre les routes disponibles ? Il existe deux approches, mesh-under et route-over. La première n'est pas vraiment du routage, elle consiste à résoudre le problème au niveau 2. Les objets ont ensuite tous l'impression d'être sur le même réseau local. L'autre approche, le route-over, met en place des vrais routeurs IP. Cela implique donc un protocole de routage et celui officiel à l'IETF pour cette tâche est le RPL du RFC 6550 (mais il en existe d'autres, comme le Babel du RFC 8966).

Les protocoles de routage pour les objets contraints font face à de nombreux défis. Par exemple, en filaire classique, les caractéristiques (latence, perte de paquets) sont les mêmes pour toutes les machines attachées au même lien. Ici, c'est par contre loin d'être le cas. Le groupe de travail roll avait été formé pour étudier ce problème (qui avait déjà été abordé par le RFC 3561) et il avait produit plusieurs RFC de débroussaillage et de définition du problème (RFC 5867, RFC 5826, RFC 5673, RFC 5548), avant de définir RPL. Notez que le problème suscite des controverses. Un RFC d'étude comparée des différents protocoles de routage avait été abandonné par le groupe roll (manque de consensus pour avancer). Et, à l'atelier, les polémiques n'ont pas manqué, comme la défense d'AODV par Thomas Clausen dans son article.

Alors, à la fin, peut-on faire une synthèse ? La section 4 s'y essaie. Premier thème décrit, la sécurité. La consommation de temps de processeur (et donc d'électricité) par la cryptographie est une sérieuse limite à la sécurisation des objets communicants. La difficulté de la gestion des clés en est une autre. Notre RFC 6574 recommande d'y travailler sérieusement sur ce dernier point, en donnant comme exemple le mécanisme d'appariement de Bluetooth qui combine harmonieusement sécurité et simplicité. Un groupe de travail de l'IETF avait été formé sur cette question, enroll, mais avait échoué. Peut-être le travail devra-t-il être repris par le nouveau groupe lwig.

Quant à la question des algorithmes cryptographiques « développement durable » (à consommation de ressources réduite), un groupe de recherche de l'IRTF existe, cfrg. Par exemple, le futur SHA-3 a prévu de prendre en compte ce problème (dont l'importance n'était pas perçue pour les algorithmes précédents de la famille).

Assurer l'interopérabilité n'est pas évident lorsque des objets ont une mémoire limitée et ne peuvent pas stocker le code correspondant à tous les algorithmes existants. Le RFC rappelle que plus de cent algorithmes de cryptographie sont définis pour TLS, dont certains sont officiellement déconseillés depuis cinq ou parfois dix ans, mais toujours répandus dans la nature : une mise en œuvre de TLS qui veut être sûre de pouvoir communiquer avec tout le monde a besoin de les connaitre. Les nouveaux algorithmes à consommation d'énergie réduite pourraient encore aggraver ce problème. Faut-il créer un nouvel algorithme, avec les problèmes d'appropriation intellectuelle, avec les difficultés de déploiement, juste pour économiser 20 % de la consommation électrique ? Le RFC laisse entendre que le gain de consommation devrait être nettement plus élevé pour que le jeu en vaille la chandelle.

Un autre thème choisi pour la conclusion est justement celui de la consommation électrique. Il existe une liste de discussion active pour cela, recipe, et l'article de Margaret Wasserman à l'atelier fournit un bon point de départ pour ceux qui veulent s'engager dans ce travail.

Quant à la question du réseau « centré sur le contenu », le RFC conclut que c'est encore bien trop nébuleux et qu'il n'y a pas de travail concret de normalisation à envisager. Il s'agit de recherche pure pour l'instant.

Sur l'architecture, le RFC plaide en faveur d'un futur document de synthèse de l'IAB expliquant comment tous les protocoles Internet marchent ensemble dans ce contexte des objets contraints et communiquants. Le RFC 6272 fournit un bon exemple d'un tel travail.

Dans la lignée de l'exemple de l'ampoule électrique, le RFC insiste aussi sur l'importance de développer des modèles de données (« Une ampoule a deux états, allumé et éteint ») permettant de créer des applications (ici, de contrôle de l'ampoule). La question est « est-ce bien le travail de l'IETF, puisqu'il faut à chaque fois une expertise spécifique d'un domaine ? ».

Pour la partie « découverte » de services ou de machines, le RFC recommande de travailler avec mDNS ou équivalent.

Pour le routage, notre section de conclusion suggérait de travailler entre autres sur la question des « sous-réseaux couvrant plusieurs liens » (RFC 4903). L'essentiel du travail sur le routage pour les objets communiquants continue au sein du groupe roll.

Notez enfin le récent groupe de travail homenet qui travaille sur les problèmes de domotique (voir son RFC 7368).

La liste des présentations à l'atelier figure dans l'annexe B. On trouve en ligne la page officielle de l'atelier, les articles présentés (une impressionnante masse de bons documents à lire), les supports des présentations, et les notes prises pendant l'atelier.


Téléchargez le RFC 6574


L'article seul

RFC 6573: The Item and Collection Link Relations

Date de publication du RFC : Avril 2012
Auteur(s) du RFC : M. Amundsen
Pour information
Première rédaction de cet article le 7 avril 2012


Depuis le RFC 5988, il existe un mécanisme standard pour exprimer les types des liens entre deux ressources sur le Web. Ce très court RFC documente deux types récemment ajoutés, permettant de dire qu'une ressource (une page HTML, un fichier, etc) est membre d'une collection de ressources ou, à l'inverse, qu'une ressource désigne une collection et indique quels sont ses membres.

Ces deux types, collection et item (l'un étant le réciproque de l'autre) sont d'ores et déjà largement utilisées par d'autres normes comme OpenSearch (section 4.5.4.1 de la norme), Maze ou Collection+JSON.

La section 2 définit complètement ces deux relations. item est utilisé dans une ressource qui représente une collection, pour identifier les membres de cette collection. Un exemple en HTML pour un catalogue de produits serait, avec l'attribut rel :


   <h1>Product Group X Listing</h1>
     ...
     <a href="..." rel="item">View Product X001</a>
     <a href="..." rel="item">View Product X002</a>
     ...
 

Ce code exprime le fait que chacun des produits est un élement (item) de la collection qu'est la page qui contieent ce code.

Comme l'indique le RFC 8288 (successeur du RFC 5988), les liens peuvent se représenter autrement qu'en HTML (toutes les ressources Web ne sont pas forcément des pages en HTML), par exemple avec l'en-tête HTTP Link:. On peut donc avoir dans une réponse HTTP :


HTTP/1.1 200 OK
...
Link: <...>; rel="item"; title="View Product X001"
Link: <...>; rel="item"; title="View Product X002"

En section 2.2, on trouve le deuxième type de lien celui qui, en sens inverse du précédent, va d'un élément vers la(les) collection(s) dont il est membre :


   <a href="..." rel="collection">Return to Product Group X</a>

Là aussi, on peut utiliser les en-têtes HTTP :


HTTP/1.1 200 OK
...
Link: <...>; rel="collection"; title="Return to Product Group X"

Les deux types ont été ajoutés au registre IANA.


Téléchargez le RFC 6573


L'article seul

RFC 6570: URI Template

Date de publication du RFC : Mars 2012
Auteur(s) du RFC : J. Gregorio (Google), R. Fielding (Adobe), M. Hadley (MITRE), M. Nottingham (Rackspace), D. Orchard (Salesforce.com)
Chemin des normes
Première rédaction de cet article le 28 mars 2012


Beaucoup d'applications Web utilisent des URI (RFC 3986) qui peuvent être décrits par un gabarit (template), avec des variables qui seront incarnées pour produire l'URI final. Ce RFC, issu d'une coopération entre l'IETF et le W3C normalise un langage (déjà largement déployé) pour ces gabarits.

La section 1.1 du RFC fournit quelques exemples d'URI obéissant à un gabarit. Par exemple, des pages personnelles identifiées par le tilde :

http://example.com/~fred/
http://example.com/~mark/

ou des entrées d'un dictionaire :

http://example.com/dictionary/c/cat
http://example.com/dictionary/d/dog

ou encore un moteur de recherche :

http://example.com/search?q=cat&lang=en
http://example.com/search?q=chien&lang=fr

À chaque fois, le patron de conception sous-jacent est assez clair. Le langage décrit dans ce RFC 6570 permet d'abstraire ce patron dans un gabarit d'URI. Les trois exemples cités plus haut pourront être décrits :

http://example.com/~{username}/

http://example.com/dictionary/{term:1}/{term}

http://example.com/search{?q,lang}

Cela permet d'abstraire un URI, en montrant clairement au lecteur le processus de construction. Cela contribue donc à la création de beaux URL, qui ne sont pas simplement des identificateurs opaques, mais qui peuvent être compris par l'utilisateur du Web.

En dehors de l'intérêt intellectuel, quelle est l'utilité de ce système ? Il permet notamment la création automatique d'URI, à partir de gabarits et de valeurs pour les variables (comme la variable term dans le deuxième exemple ci-dessus). Les protocoles fondés sur REST en seront ravis. Ainsi, le gabarit http://www.example.com/foo{?query,number} combiné avec les variables {query: "mycelium", number: 100} va donner http://www.example.com/foo?query=mycelium&number=100. Si query n'était pas défini, cela serait simplement http://www.example.com/foo?number=100.

Pour prendre des exemples réels, on peut décrire les URL d'OpenStreetMap comme tirés du gabarit http://www.openstreetmap.org/?{lon,lat} et ceux de Wikipédia comme faits à partir de http://fr.wikipedia.org/wiki/{topic}.

La section 1.2 explique qu'il existe en fait plusieurs niveaux pour le langage de description de gabarits. Une mise en œuvre donnée s'arrête à un certain niveau, les premiers étant les plus simples. Le niveau 1 fournit simplement l'expansion des variables (qui sont placées entre accolades), avec échappement. Si var vaut "Bonjour le monde", l'expansion de {var} sera Bonjour%20le%20monde.

Le niveau 2 ajoute un opérateur + pour les variables pouvant contenir des caractères spéciaux, et le # pour les identificateurs de fragment. Si path vaut "/foo/bar", {path} est expansé en %2Ffoo%2Fbar alors que {+path} donnera /foo/bar. Et avec la variable var valant "Bonjour le monde", l'expansion de {#var} sera #Bonjour%20le%20monde permettant de construire des URI avec un identificateur pointant vers un point précis du document. Par exemple, les URL des Internet-Drafts dans la file d'attente de l'éditeur des RFC ont le gabarit http://www.rfc-editor.org/queue2.html{#draftname} avec, par exemple, draftname égal draft-ietf-lisp.

Au niveau 3, cela devient bien plus riche : on a plusieurs variables dans une expression (le gabarit map?{x,y} devient l'URI map?1024,768 si x=1024 et y=768). Et on gagne surtout les paramètres multiples (séparés par &) si utilisées dans les formulaires Web : le gabarit {?x,y} devient ?x=1024&y=768.

Enfin, le niveau 4 ajoute des modificateurs après le nom de la variable. Par exemple, : permet d'indiquer un nombre limité de caractères (comme dans le term:1 que j'ai utilisé au début, qui indique la première lettre). Et le * indique une variable composite (une liste ou un dictionnaire) qui doit être elle-même expansée. Si la variable couleurs vaut la liste {rouge, bleu, vert}, le gabarit (de niveau 1) {couleurs} donnera rouge,bleu,vert alors que la gabarit de niveau 4 {?couleurs*} vaudra ?couleurs=rouge&couleurs=bleu&couleurs=vert.

Des mécanismes similaires à ces gabarits existent dans d'autres langages comme OpenSearch ou WSDL. Par exemple, le gabarit décrivant les URL du moteur de recherche de mon blog a la forme http://www.bortzmeyer.org/search{?pattern} et, dans dans sa description OpenSearch, on trouve la même information (quoique structurée différemment).

Comme l'explique la section 1.3, cette nouvelle norme vise à unifier le langage de description de gabarits entre les langages, tout en restant compatible avec les anciens systèmes. Normalement, la syntaxe des gabarits d'URI est triviale à analyser, tout en fournissant la puissance expressive nécessaire. Il s'agit non seulement de générer des URI à partir d'un patron, mais aussi de pouvoir capturer l'essence d'un URI, en exprimant clairement comment il est construit.

La section 2 décrit rigoureusement la syntaxe. En théorie, un analyseur qui ne gère que le niveau 1 est acceptable. Toutefois, le RFC recommande que tous les analyseurs comprennent la syntaxe de tous les niveaux (même s'ils ne savent pas faire l'expansion), ne serait-ce que pour produire des messages d'erreurs clairs (« This feature is only for Level 3 engines and I'm a poor Level 2 program. » .

Cette section contient donc la liste complète des caractères qui ont une signification spéciale pour le langage de gabarits, comme +, ? ou &, ainsi que de ceux qui sont réservés pour les futures extensions (comme = ou @). En revanche, $ et les parenthèses sont exprèssement laissés libres pour d'autres langages qui voudraient décrire une part de l'URI.

Ensuite, la section 3 se consacre aux détails du processus d'expansion qui, partant d'un gabarit et d'un ensemble de valeurs, va produire un URI. Notez qu'une variable qui n'a pas de valeur ne donne pas un 0 ou un N/A ou quoi que ce soit de ce genre. Elle n'est pas expansée. Donc, le gabarit {?x,y} avec x valant 3 et y n'étant pas défini, devient ?x=3 et pas ?x=3&y=NULL. Si x n'était pas défini non plus, le résultat serait une chaîne vide (sans même le point d'interrogation).

Est-ce que ces gabarits peuvent poser des problèmes de sécurité ? La section 4 regarde cette question et conclus que cela dépend de qui fournit le gabarit, qui fournit les variables, et comment va être utilisé l'URI résultant (aujourd'hui, les mises en œuvre existantes les utilisent dans des contextes très variés). Par exemple, des variables contenant du code JavaScript peuvent être dangereuses si l'URI résultant est traité par ce langage. Des attaques de type XSS sont donc parfaitement possibles si le programmeur ne fait pas attention.

Pour les programmeurs, l'annexe A contient un ensemble de recommandations sur la mise en œuvre de ce RFC, ainsi qu'un algorithme possible pour cette mise en œuvre. Il existe plusieurs mises en œuvre de ce RFC. Malheureusement, toutes celles que j'ai essayées semblent limitées au niveau 1 et ne le disent pas clairement.

Le code Python en http://code.google.com/p/uri-templates/ (niveau 1 et un bout du niveau 2) :

import uritemplate
import simplejson
import sys

vars = {"foo": "bar/"}

def test_print(template):
    actual = uritemplate.expand(template, vars)
    print actual

test_print("http://www.example.org/thing/{foo}")
test_print("http://www.example.org/thing/{+foo}")

On obtient :

http://www.example.org/thing/bar%2F
http://www.example.org/thing/bar/

Avec le module Perl URI::Template (niveau 1), on peut écrire :

use URI::Template;
my $template = URI::Template->new( 'http://example.com/{foo}' );
my $uri      = $template->process( foo => 'Hello World/' );
print $uri, "\n";

Le code Haskell en http://hackage.haskell.org/cgi-bin/hackage-scripts/package/uri-template (niveau 1 seulement) écrit ainsi :

module Main(main) where

import Network.URI.Template

testEnv :: TemplateEnv
testEnv =
  addToEnv "foo" "Hello World/" $
    addToEnv "x" "1024" $
     addToEnv "y" "768" $
       newEnv

main :: IO ()
main = do
  putStrLn (expand testEnv "http://example.org/{foo}")
  return ()

Donne :

% runhaskell Test.hs
http://example.org/Hello%20World%2f

Téléchargez le RFC 6570


L'article seul

RFC 6569: Guidelines for Development of an Audio Codec Within the IETF

Date de publication du RFC : Mars 2012
Auteur(s) du RFC : JM. Valin (Mozilla), S. Borilin (SPIRIT DSP), K. Vos, C. Montgomery (Xiph.Org Foundation), R. Chen (Broadcom Corporation)
Pour information
Réalisé dans le cadre du groupe de travail IETF codec
Première rédaction de cet article le 27 mars 2012


Constatant l'absence d'un codec entièrement libre (pas plombé par des brevets, pas contrôlé par une société unique, implémentable en logiciel libre), l'IETF s'est lancée dans la spécification d'un codec satisfaisant. Le RFC 6366 donnait le cahier des charges technique du futur codec (le produit final, publié dans le RFC 6716) et ce nouveau RFC donne les considérations portant sur le processus de développement (processus déjà bien entamé) : méthodologie d'évaluation des propositions, mécanisme de vérification de la compatibilité des implémentations, questions de propriété intellectuelle. Une tâche difficile, accomplie dans une ambiance pas toujours sereine, les questions du multimédia étant toujours délicates.

Le développement d'un nouveau codec est une tâche d'ampleur, compte-tenu des exigences très strictes du RFC 6366 et du fait que le marché est déjà encombré de codecs complètement fermés, ou bien à moitié libres. L'IETF n'avait pas imposé que le codec libre soit entièrement nouveau : la sélection et/ou l'adaptation d'un codec existant sont des plans possibles. La section 2 du RFC résume le processus. Au moment où sort ce RFC, une partie des étapes a déjà été franchie. Les principales sont :

  • Documenter les exigences techniques (fait dans le RFC 6366, un document à lire, notamment pour se rappeler que l'économie de capacité réseau par la compression n'est qu'un des critères de qualité technique pour un codec, d'autres, comme la latence sont aussi importants),
  • Proposer des candidats répondant à ces exigences (voir par exemple l' Internet-Draft Definition of the Opus Audio Codec),
  • Compte-tenu de l'importance de l'appropriation intellectuelle dans ce secteur, pourri de brevets du sol au plafond, surveiller en permanence les divulgations de brevets, imposées par le RFC 3979, mais pas toujours respectées. Il est particulièrement important que ces divulgations soient faites à temps puisqu'elles peuvent sérieusement influencer les choix du groupe de travail.
  • Identifier forces et faiblesses de chaque proposition,
  • Créer le codec préféré, qui pourra incorporer des bouts des autres propositions,
  • Développer l'implémentation de référence et les mécanismes de tests permettant de s'assurer que toutes les mises en œuvre sont compatibles. (Ces mécanismes de test étaient un des points suscitant le plus de débats.)

Comment s'assurer, tout au long du développement, que le codec sera de qualité suffisante, pour ne pas avoir de mauvaise surprise à la fin du projet ? Il faudra tester le logiciel au fur et à mesure (section 3) en utilisant des méthodes comme PESQ (norme UIT P.862) et PEAQ (UIT BS.1387). Pour des changements plus fondamentaux, il faudra utiliser les méthodologies d'évaluation subjective comme MUSHRA (UIT BS.1534). Et, comme l'IETF travaille depuis toujours dans un environnement ouvert, il faudra bien sûr impliquer toute la communauté Internet dans ses essais (le code du codec Opus est donc librement accessible en http://git.xiph.org/?p=opus.git). C'est d'autant plus important que l'IETF n'a pas de « laboratoires de test » propres et que tous les tests devront être faits à l'extérieur (une raison de plus pour que l'implémentation de référence soit publiquement disponible).

La section 4 du RFC revient sur les détails de la spécification et sert de guide aux auteurs du futur RFC. Elle précise notamment ce que devrait imposer la spécification et ce qui devrait être laissé aux décisions des programmeurs. D'abord, la décision est prise que l'implémentation de référence aura le pas sur le texte de la spécification, en cas de désaccord. C'est inhabituel à l'IETF, où la règle est en général l'inverse, pour éviter que les particularités d'une implémentation ne figent la norme. Mais le monde des codecs est très complexe et la spécification complète et parfaite un art difficile. Au moins, en décrétant que « le code fait la loi », on est sûr d'avoir une référence précise en cas de litige.

Le principe général sera d'essayer de limiter les obligations dans la norme, donc de ne pas abuser des MUST du RFC 2119. En pratique, cela veut dire que seul le décodeur du flux audio aura besoin d'être rigoureusement défini, les encodeurs pourront s'améliorer avec le temps et faire des choix radicalement différents.

Avoir un programme comme description faisant autorité présente plusieurs risques. L'un d'eux est de « sur-spécification » : faudra-t-il qu'une implémentation compatible donne le même résultat, au bit près, que l'implémentation de référence ? Cela rendrait très difficile le travail des programmeurs pour certaines architectures (le couple CPU/DSP ne permet pas forcément de produire un résultat au bit près, en tout cas pas en gardant des performances maximales). Le principe est donc qu'il n'est pas nécessaire de faire exactement comme le programme de référence, mais de faire quelque chose qui n'est soit pas distinguable à l'oreille.

La section 5 est consacrée au problème douloureux mais, dans le secteur du multimédia, indispensable, de la propriété intellectuelle. Les effets néfastes de celle-ci sur la mise en œuvre et le déploiement des codecs audios sont bien connus. Par exemple, les coûts de licence des brevets éliminent les petits acteurs, qui sont souvent à l'origine de l'innovation. En outre, même si les conditions de la licence sont raisonnables financièrement, elles sont souvent incompatibles avec le logiciel libre (par exemple, exiger une licence pour la distribution, même si la licence est gratuite, empêche l'intégration du logiciel dans un logiciel libre, qui ne met aucune restriction à la distribution).

Bref, libre, c'est mieux que contraint. Des tas de codecs tout à fait valables techniquement posent des problèmes légaux, qui limitent leur déploiement. L'IETF rappelle donc dans ce RFC sa préférence pour des techniques non plombées par la propriété intellectuelle. Le problème est difficile à résoudre car à peu près tout a été breveté (les organismes de dépôt des brevets ne font aucun effort pour refuser les brevets futiles). Même si l'IETF adopte un codec qui semble non breveté, rien ne garantit qu'il ne sera pas frappé soudainement par un brevet sous-marin, un brevet auquel son détenteur ne donne aucune publicité, attendant qu'il soit déployé pour réclamer de l'argent.

Compte-tenu des brevets futiles (qui couvrent à peu près tous les algorithmes possibles et qu'on ne peut invalider que par un long et incertain procès), compte-tenu de l'état de l'art en matière de codec, compte-tenu du fait qu'une technologie peut être brevetée dans certains pays et pas d'autres, l'IETF ne promet donc pas de normaliser un codec complètement libre, ce qui serait une mission impossible (à part peut-être en se limitat à de très vieux codecs, conçus il y a tellement longtemps que tous les brevets ont forcément expiré). Mais elle promet de chercher sérieusement (même si les codecs libres ont de moins bonnes performances techniques) et, dans le pire des cas, de préférer les codecs où les licences des brevets sont gratuites (RF, pour royalty-free). Rappelez-vous toutefois que le plus gros problème pour obtenir une licence n'est pas forcément l'argent, cela peut être le processus bureaucratique de longues négociations avec un bataillon d'avocats qui ont beaucoup de temps libre et vous font lanterner. Il y a des licences gratuites qui coûtent très cher en temps passé !

Cela suppose évidemment que l'IETF soit au courant des brevets existants. Les participants à l'IETF doivent l'informer des brevets qu'ils connaissent (RFC 3979, section 6). Mais cette règle a déjà été violée. Par exemple, dans le cas du groupe de travail Codec, Huawei n'a publié son brevet US 8,010,351 que bien tard, en affirmant qu'il était dans le portefeuille d'une entreprise récemment acquise par Huawei.

D'autres SDO travaillent sur des codecs. Comment l'IETF doit-elle gérer ses relations avec ces organisations (section 6) ? On trouve dans la liste l'UIT (notamment le Study Group 16), le groupe MPEG de l'ISO, ETSI, 3GPP... L'IETF a déjà pris position nettement contre la concurrence des SDO et le développement non coordonné de protocoles, dans le RFC 5704. Ce RFC pose comme principe que, pour chaque protocole ou format, une et une seule SDO doit être responsable. Mais ce n'est pas un problème ici. Soit le groupe de travail codec approuve un codec existant, géré par une autre SDO et celle-ci continuera comme avant, l'IETF aura juste dit « le codec préféré de l'IETF est le codec XXX ». Soit l'IETF développe un nouveau codec (éventuellement dérivé, mais différent, d'un codec existant) et il n'y aura alors pas de concurrence. Les règles du RFC 5704 découragent le concurrence pour un même format ou protocole, pas pour une même catégorie (deux organisations peuvent travailler sur deux codecs différents, même si ces deux codecs visent le même « marché »).

L'IETF appelle bien sûr les experts en codecs audio des autres SDO à donner leur avis sur son travail mais considère que ce n'est pas indispensable : le groupe codec rassemble d'ores et déjà suffisamment de compétences. Cette participation éventuelle des autres SDO peut prendre la forme de contributions individuelles (un expert peut être membre à la fois du SG16 de l'UIT et du groupe codec de l'IETF), ou par le mécanisme plus formelle des liaisons. En tout cas, il existe des choses utiles chez les autres SDO (par exemple dans les mécanismes de test), comme documenté dans le RFC 3356.

Je l'ai indiqué, le groupe de travail codec a travaillé sous forte pression. Parmi les trolls des débats, je me souviens de la proposition que le problème du coût des licences soit relativisé, car un codec techniquement supérieur fait économiser de la capacité réseau (meilleure compression) et donc justifie de payer une licence...

Actuellement, dans la catégorie « nouveaux codecs », le groupe de travail n'a qu'un seul candidat, Opus (autrefois nommé Harmony) et qui a donc été normalisé finalement en septembre 2012 (RFC 6716). Si vous vous intéressez aux tests pratiques de ce codec, voir le document Summary of Opus listening test results.

.

Téléchargez le RFC 6569


L'article seul

RFC 6568: Design and Application Spaces for 6LoWPANs

Date de publication du RFC : Avril 2012
Auteur(s) du RFC : E. Kim (ETRI), D. Kaspar (Simula Research Laboratory), N. Chevrollier (TNO), JP. Vasseur (Cisco Systems)
Pour information
Réalisé dans le cadre du groupe de travail IETF 6lowpan
Première rédaction de cet article le 1 mai 2012


Vous ne connaissez pas encore le terme de LowPAN ? Ce n'est pas grave, c'est encore assez rare. Un LowPAN est un Low-Power Wireless Personal Area Network. En gros, c'est un ensemble de petites machines (très petites : pas des ordinateurs), disposant de peu de puissance électrique, connectées souvent sans fil, et cherchant à communiquer. Le groupe de travail IETF 6lowpan établit des normes de communication pour ces LowPAN, en utilisant IPv6 (d'où le 6 au début de son nom). Ce document est son quatrième RFC. Il explique les principes de base de son travail, à travers des scénarios d'utilisation des LowPAN.

Un LowPAN typique va être, dans une exploitation agricole, l'ensemble des capteurs qui mesurent l'humidité, et des actionneurs qui déclenchent l'arrosage. La section 1 explique les douleurs du LowPAN : machines ayant peu de ressources (processeur, mémoire, courant), et connectées par des liens lents et sujets aux parasites et aux coupures (WiFi, CPL). En général, on veut en prime que ces machines soient peu chères. Résultat :

  • Certaines machines du LowPAN peuvent n'avoir qu'un CPU 8-bits de 10 MHz. (Des plus chanceuses auront des CPU ARM de 32 bits à 50 MHz.)
  • Certaines n'auront que quelques kilo-octets de RAM et quelques dizaines de kilo-octets de ROM. Plus élaboré, le IMote a 64 ko de RAM et une Flash de 512 ko.
  • Fonctionnant souvent sur batterie, ces machines devront se limiter à une consommation de 10 à 30 mA pour la radio, limitant la puissance à 3 dBm et donc la portée à entre 30 et 100 mètres.
  • La capacité de ces liens radio peut être entre 20 et 250 kb/s.

Bref, on est très loin des ordinateurs portables ou même des smartphones. Et c'est pourtant dans ces machines qu'il va falloir faire tenir le code réseau. Deux bonnes lectures sur ces environnements si différents des machines sur lesquelles l'Internet a commencé : le RFC 4919 décrit plus en détail le monde des LowPAN, le RFC 4944 normalise l'utilisation d'IPv6 sur IEEE 802.15.4.

Il existe en fait beaucoup de LowPAN différents. Suivant le document «  The Design Space of Wireless Sensor Networks », la section 2 du RFC explique les axes sur lesquels se différencient les LowPAN : déploiement conçu dès le début ou bien incrémental, taille du réseau (10 machines ou 1000 ?), connectivité permanente ou intermittente (ce qui est courant lorsque les machines se déplacent), etc.

Bien, maintenant, assez de précautions, place au cœur du RFC, la section 3. Elle expose une partie des scénarios d'usage des LowPAN. Par exemple, en section 3.1, figure un usage souvent cité, la surveillance de bâtiments industriels. L'idée est que les capteurs dispersés un peu partout dans les bâtiments deviennent communiquants. Au lieu d'être relevés manuellement par un humain faisant sa ronde, ils transmettront d'eux-mêmes les résultats des mesures. De très nombreuses mesures peuvent être envisagées, comme les vibrations d'une machine (trop intenses, elles indiquent un problème) ou la température dans les entrepôts (attention à conserver la chaîne du froid). Les communications sans-fil sont ici cruciales car certaines parties de l'usine peuvent être difficiles à atteindre pour les câbles.

Comme exemple précis de ce type de surveillance, le RFC cite les salles de stockage d'un hôpital. Les globules rouges doivent être stockés entre 2 et 6°, les plaquettes entre 20 et 24°, et le plasma à -18°. Les capteurs de température sont disposés tous les 25 mètres environ, chaque emballage a une étiquette et des nœuds 6LowPAN sont placés dans les palettes. Par rapport aux axes de classification cités plus haut, on a un cas de déploiement planifié, avec un réseau de taille moyenne mais très dense, et peu de déplacements. Le débit attendu est faible mais les données peuvent être urgentes (alerte de réchauffement, par exemple). Les exigences de sécurité sont élevées. 6LowPAN peut-il convenir ? Oui, analyse cette section.

Autre cas, celui de la surveillance d'un bâtiment, pour veiller à son intégrité (section 3.2). Par exemple, un pont est construit et est truffé de capteurs et de machines LowPAN qui relèvent les capteurs et transmettent à un contrôleur. Le RFC part d'un pont de 1 000 m de long, avec 10 piliers. Chaque pilier a 5 capteurs pour mesurer le niveau de l'eau sont le pont et 5 autres qui mesurent les vibrations. Les machines LowPAN ne sont pas gênées par les murs du bâtiment, comme dans l'exemple précédent, et peuvent se voir à 100 m de distance. Tout est placé manuellement (attention à ne pas avoir un pilier dans la LoS) et ne bouge pas.

Le réseau est cette fois de petite taille, très statique. Mais sa sécurité est vitale. Dans ce cas simple, 6LowPAN convient bien (il faut juste faire attention aux placements des engins sur les piliers).

Pas d'article ou de document sur les LowPAN sans l'inévitable bla-bla sur la domotique et ses promesses d'un monde merveilleux où le réfrigérateur détectera la fin proche du stock de bières et en commandera d'autres. C'est le rôle ici de la section 3.3. Après la santé et les transports, où des vies humaines sont en jeu, cette section se penche sur le confort de l'occidental rose moyen, qui veut que sa maison high-tech s'occupe de tout pendant qu'il regarde le match de foot à la télé.

Il y a beaucoup de choses à mesurer dans une maison, la température, l'humidité, l'état des portes (ouvert ou fermé), la vidéo-surveillance (pendant qu'on est dans les délires de mauvaise science-fiction, transformons la maison en bunker avec caméra braquée sur les quartiers sensibles). En combinant avec l'idée de « Smart Grid » (réseau de distribution électrique doté de capacités de mesure et de transmission de l'information), on peut aussi imaginer de connecter ces informations avec celle du réseau électrique.

Du point de vue technique, les murs de la maison feront souvent obstacle aux communications sans fil. Le réseau devra donc permettre le routage, pour le cas où la machine qu'on veut joindre n'est pas directement visible (« Multi-hop routing »). Les fonctions de ce réseau de gadgets ne sont pas vitales, cette fois. Par contre, l'ergonomie est cruciale, le réseau devra être très simple à administrer.

Autre scénario d'usage, en section 3.4, l'assistance médicale. L'idée est de mettre les capteurs sur et dans le patient, de manière à pouvoir surveiller son état à tout moment. Pour une personne âgée à la maison, on peut imaginer quelques capteurs portés à même le corps et qui mesurent des choses commes les battements cardiaques, et d'autres capteurs dans la maison, captant les mouvements, par exemple pour pouvoir donner l'alerte en cas de chute. Les enjeux de sécurité, notamment de protection de la vie privée, sont très importants. Si le LowPAN est ici de petite taille, et que la mobilité est limitée, les contraintes de bon fonctionnement sont essentielles, puisqu'une vie humaine peut être en jeu.

Un scénario dans un univers plus technique est celui de l'automobile (section 3.5). Les nœuds LowPAN peuvent être inclus dans la route au moment de sa construction et surveiller les véhicules qui passent. Cela pose un sacré problème de durée de vie puisque les nœuds vont devoir durer autant que la route (typiquement, dix ans, avant la première réfection sérieuse qui permettra de les changer). Malgré cela, avec le temps, la densité des capteurs diminuera, au fur et à mesure des pannes. Les machines LowPAN de la route seront nombreuses mais statiques, celles des véhicules peu nombreuses mais très mobiles.

Enfin, le dernier exemple est un peu plus vert, puisqu'il concerne l'agriculture (section 3.6), celle qui, selon Jared Diamond, est à la base de la force des empires. L'idée est de mesurer à distance, via de nombreux capteurs, l'humidité, la température et l'état du sol, de manière à appliquer l'irrigation ou les pesticides au bon moment. Le RFC prend l'exemple d'une vigne de bonne taille (dans les huit hectares) où 50 à 100 machines de contrôle piloteront des centaines de capteurs. La principale difficulté, pour ces derniers, sera de résister à des conditions hostiles dehors (humidité, poussière, hommes et machines qui passent en permanence et font courir des gros risques aux fragiles capteurs), etc. Heureusement, les exigences de sécurité sont cette fois bien plus basses.

En parlant de sécurité, la section 4 y est entièrement consacrée. Elle rappelle que les machines d'un LowPAN sont souvent exposées dehors, et donc physiquement accessibles à un éventuel attaquant. Les méthodes de sécurisation doivent tenir compte de cela. La communication entre les machines du LowPAN est souvent par radio, médium qui n'offre aucune sécurité, permettant à l'attaquant de capter tout le trafic, voire d'injecter de fausses données. La cryptographie devient alors nécessaire.

Mais les machines d'un LowPAN ont des ressources, notamment d'énergie, très limitées. Elles sont donc vulnérables aux attaques par déni de service : des requêtes répétées et hop, la batterie est à plat. À cause de cela, les techniques de sécurité adoptées doivent être légères et ne pas abuser des ressources très limitées de ces petits engins. Par exemple, IPsec est probablement exagéré pour ces environnements, en raison des calculs qu'il entraîne. Cela doit évidemment s'adapter à l'usage envisagé : le nœud LowPAN qui allume une lampe n'a pas les mêmes contraintes de sécurité que celui qui contrôle un stimulateur cardiaque.


Téléchargez le RFC 6568


L'article seul

RFC 6564: An uniform format for IPv6 extension headers

Date de publication du RFC : Avril 2012
Auteur(s) du RFC : S. Krishnan (Ericsson), j h. woodyatt (Apple), E. Kline (Google), J. Hoagland (Symantec), M. Bhatia (Alcatel-Lucent)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF 6man
Première rédaction de cet article le 10 avril 2012


IPv6 permet l'insertion, entre l'en-tête de taille fixe du paquet, et les données de la couche 4, d'un ou plusieurs en-têtes d'extensions, qui modifient le comportement du paquet. L'analyse de ces en-têtes d'extension par un programme a toujours été difficile car ils n'ont pas un format cohérent. Ce RFC résout le problème en décrétant que, au moins pour les futurs en-têtes, ils devront suivre un format identique, permettant de les sauter sans même en comprendre le contenu.

Ces en-têtes d'extension sont normalisés dans la section 4 du RFC 2460. La plupart suivent le schéma « un octet pour indiquer le type de l'en-tête suivant, un octet pour indiquer la longueur de cet en-tête, puis les données » mais pas tous (notamment, l'en-tête de fragmentation a une syntaxe différente). Si on veut écrire un programme d'analyse des paquets IPv6, on doit donc connaître tous les types d'en-tête (il n'y en a, après tout, pas beaucoup) et traiter chacun spécialement. Mais cela ne résout pas le problème des futurs en-têtes : si un nouvel en-tête est créé (comme cela avait été le cas dans le RFC 5533), et qu'il commence à apparaître sur le réseau, les programmes d'analyse vont souffrir.

Outre les programmes d'analyse, on peut citer d'autres logiciels qui souhaitent regarder à l'intérieur des paquets, y compris avant que le paquet n'atteigne sa destination (section 1 du RFC). Par exemple les pare-feux veulent accéder à la couche transport, et ils doivent le faire à la vitesse du réseau physique (si on a un Ethernet 1 Gb/s, on veut que les paquets soient analysés au même rythme), ce qui implique le recours à des circuits électroniques relativement simples (les ASIC) qui n'ont pas la possibilité de faire tourner du code arbitrairement complexe. Or, aujourd'hui, tout nouvel en-tête IPv6 est à peu près sûr d'invalider ces pare-feux.

Ne peut-on pas s'en tirer en disant qu'il vaut mieux éviter de définir de nouveaux en-têtes d'extension ? C'est l'option que rappelle la section 3, qui note que l'en-tête Destination Options (section 4.6 du RFC 2460) est déjà très général : il permet d'inclure plusieurs options différentes, chacune identifiée par son type et encodée sous forme TLV. Le RFC recommande donc que les concepteurs de nouvelles idées pour IPv6 réutilisent l'en-tête Destination Options autant que possible. Au cas où un concepteur de protocole décide de créer un nouvel en-tête, il doit désormais expliquer en détail pourquoi l'en-tête Destination Options ne convient pas à son but.

Notez que l'en-tête Destination Options, comme son nom l'indique, ne doit normalement être traité que par la machine de destination (les routeurs, notamment, n'ont pas besoin de le gérer ou de le connaître, sauf à des fins de statistique). Si on veut transporter des options qui sont analysées par les routeurs, on a l'en-tête Hop-by-hop Options. En pratique, il n'est pas du tout évident que ce dernier fonctionne : comme chaque routeur du trajet doit en tenir compte, il ouvre une voie d'attaque possible et il semble que bien des routeurs l'ignorent complètement, voire jettent sans autre forme de procès les paquets qui le contiennent. Quoi qu'il en soit, notre RFC 6564 précise qu'il ne faut pas créer de nouveaux en-têtes ayant cette sémantique « examen par chaque routeur ». Non seulement la création d'en-têtes est déconseillée, mais elle ne doit se faire qu'avec la sémantique « examen par la destination seulement ».

Bien, maintenant qu'on a sérieusement refroidi les concepteurs de protocole qui auraient pensé à créer un nouvel en-tête, la section 4 fixe les règles à suivre au cas où on ne serait pas encore découragé. Les éventuels nouveaux en-têtes devront désormais tous suivre le modèle de la plupart des en-têtes existants et commencer par un octet indiquant l'en-tête suivant (typiquement, cela sera les données de la couche Transport, les valeurs possibles sont dans un registre), puis un octet indiquant la longueur de l'en-tête. Cela devrait rendre un peu plus facile l'analyse des futurs en-têtes, s'il y en a de créés.

Rappelez-vous que cela n'affecte que les futurs en-têtes. Pour analyser les existants (notamment l'en-tête Fragment qui ne suit pas ce schéma, cf. section 5), il faut garder le code existant. La section 6 rappele d'ailleurs que le traitement des en-têtes reste un problème pas complètement résolu pour les équipements intermédiaires, par exemple parce qu'il peut y avoir plusieurs en-têtes, chaînés, parce que leur ordre est important, et parce que le traitement des en-têtes peut influer celui de la charge utile. Personnellement, je pense que la première mise en œuvre d'IPv6 qui essaiera d'utiliser vraiment les en-têtes aura de vilaines surprises... Cela sera encore pire avec un nouvel en-tête, qui ne fait pas partie des anciens.

Notez aussi que tout le problème traité par ce RFC a une faible importance pratique : on ne trouve quasiment pas d'en-têtes d'extension dans les paquets IPv6 qui circulent aujourd'hui.

Donc, désormais, une implémentation d'analyse d'IPv6 (comme la mienne, que j'ai eu la flemme de modifier) peut adopter la stratégie suivante :

  • Si c'est un en-tête connu, le traiter selon sa spécification.
  • Si c'est un en-tête inconnu et que le next header est un en-tête connu ou bien un protocole de transport connu, sauter l'en-tête inconnu (en utilisant le second octet, qui indique la taille). C'est là la nouveauté de notre RFC 6564.
  • Si c'est un en-tête inconnu et que le suivant n'est pas connu non plus, le problème reste ouvert (tenter de suivre la chaîne ? C'est dangereux car on peut se retrouver au milieu d'un protocole de transport inconnu, pour lesquels les règles de notre RFC ne s'appliquent pas) et n'est pas modifié par notre RFC.

Téléchargez le RFC 6564


L'article seul

RFC 6563: Moving A6 to Historic Status

Date de publication du RFC : Mars 2012
Auteur(s) du RFC : S. Jiang (Huawei), D. Conrad (Cloudflare), B. Carpenter (Univ. of Auckland)
Pour information
Première rédaction de cet article le 13 mars 2012


Un peu de rangement dans le DNS : en 2000, un nouveau type d'enregistrement DNS, le A6, avait été créé pour gérer plus facilement les adresses IPv6 dans le DNS. N'ayant finalement pas marché comme espéré, il vient d'être officiellement abandonné. Le RFC 2874, qui le normalisait, devient « intérêt historique seulement ».

Le type officiel pour représenter les adresses IPv6 dans le DNS était le AAAA, introduit par le RFC 1886 (aujourd'hui RFC 3596). Très proche du type A d'IPv4, il n'offrait pas de services particuliers, par exemple pour gérer la rénumérotation d'un réseau. Si on avait dans son fichier de zone :

www    IN   AAAA   2001:db8:33::1
mail   IN   AAAA   2001:db8:33::fada

et qu'on passe du réseau 2001:db8:33::/48 au 2001:db8:bad::/48, il fallait faire un rechercher/remplacer pour changer toutes les adresses. Le type A6, du RFC 2874, fournissait un système plus souple, découplant le préfixe et l'adresse.

Évidemment, le fait d'avoir deux types pour les adresses IPv6 a entraîné pas mal de confusion (section 2.5). Il est même possible que cela ait contribué au retard du déploiement d'IPv6. En 2002, les RFC 3363 et RFC 3364 critiquaient A6 et il était reclassé « expérimental ». Cela n'a apparemment pas suffit à éclaircir les choses et notre RFC 6563 met aujourd'hui A6 comme « d'intérêt historique seulement », ce qui devrait enlever toute ambiguité. Le seul type pour représenter les adresses IP dans le DNS est donc AAAA.

Mais que reprochait-on à A6, finalement ? La section 2 de ce RFC résume les principaux problèmes (le RFC 3363 donne davantage de détails) :

  • Latence accrue au moment de la résolution de noms (puisque A6 implique plusieurs requêtes DNS non-parallélisables, et sur des serveurs différents),
  • Probabilité d'échec plus élevée (il suffit qu'une des sous-requêtes de la chaîne échoue pour que la résolution soit impossible),
  • Difficultés associées au franchissement de frontières administratives : certes, le principe même d'A6 était de permettre de déléguer plus facilement, en mettant les différents enregistrements nécessaires dans des organisations différentes. Mais l'expérience d'A6 (comme celle des enregistrements de colle dans la zone parente, ou celle des PTR de in-addr.arpa) a montré qu'il était très difficile de synchroniser de tels enregistrements « trans-frontières » et qu'ils se prêtaient mal à l'automatisation,
  • Complexité de la maintenance puisque le changement d'un composant A6 peut affecter de nombreuses adresses IP, qu'on ne voit pas (le reste des données peut être dans une autre zone, et même avoir des TTL différents, rendant la prévision des résultats difficile),
  • Et enfin risques de sécurité, la résolution d'un nom en adresse IPv6 dépendant de davantage d'acteurs ; la compromission de l'un d'eux pouvait affecter beaucoup de monde.

La section 3 décrit l'usage effectif d'A6, depuis que certaines versions de BIND (de 9.0 à 9.2, puis abandonné dans les versions ultérieures) ont ajouté la gestion de ce type d'enregistrements. De même, certaines versions de la GNU libc ont fait des requêtes A6. Mais, aujourd'hui, l'analyse du trafic sur deux serveurs DNS de la racine montre très peu de trafic a6 Les statistiques sur les serveurs de .fr gérés par l'AFNIC montrent que A6 n'a pas disparu. Il ne fait certes que 0,2 % des requêtes (contre 8 % pour AAAA) mais il est le dixième type d'enregistrement demandé, devant des types comme SPF, SSHFP, NAPTR ou DNSKEY, normalement bien plus « officiels ». Cela illustre le conservatisme des administrateurs système (qui gardent en production de très vieilles versions de leurs logiciels).

La section 4 expose les conséquences de la reclassification de A6 comme n'ayant qu'un intérêt historique. Les gérants de zone DNS doivent retirer ces enregistrements (s'ils existaient encore), les clients DNS doivent arrêter de demander des A6 et les serveurs DNS doivent désormais traiter ce type comme inconnu (RFC 3597) lors de la réception d'une requête. (Le type A6 faisait partie de ceux pour lesquels le serveur DNS devait faire un traitement spécial.) Comme c'est déjà largement le cas, ce RFC n'aura sans doute pas de conséquence pratique.


Téléchargez le RFC 6563


L'article seul

RFC 6561: Recommendations for the Remediation of Bots in ISP Networks

Date de publication du RFC : Mars 2012
Auteur(s) du RFC : J. Livingood (Comcast), N. Mody (Comcast), M. O'Reirdan (Comcast)
Pour information
Première rédaction de cet article le 20 mars 2012


Une des plus grosses menaces sur la sécurité de l'Internet réside dans les zombies, ces machines Windows contaminées par du logiciel malveillant et qui obéissent désormais à un maître qui leur ordonne, selon sa volonté, de lancer une dDoS, d'envoyer du spam, etc. Ce RFC documente le point de vue d'un gros FAI, Comcast, sur le problème. La partie que je trouve la plus riche est celle sur le difficile problème de la notification des utilisateurs.

Il n'existe pas de solution miracle contre les zombies. C'est comme cela que je lis ce document qui, malgré son nom, propose peu de remèdes. Et certaines des solutions relèvent plus d'une logique « business » (se débarrasser d'un problème) que d'une volonté d'améliorer l'Internet (le document se réclame du MAAWG, cartel de gros opérateurs très tentés par le nettoyage civilisateur).

Le RFC commence par un peu de terminologie (section 1). Bot est l'abrévation de robot et désigne dans ce RFC un zombie, une machine qui n'obéit plus à son propriétaire légitime mais au « maître des zombies » (bot master), qui les contrôle à distance. Le logiciel qui transforme une innocente machine en zombie a typiquement été installé en trompant l'utilisateur (« Click here to install over 200 000 HOT pictures of REAL CHICKS! »), ou bien en profitant d'une faille de sécurité de ses logiciels, ou encore en essayant plein de mots de passe jusqu'à en trouver un qui marche. Le RFC note qu'il existe des gentils robots (par exemple pour interagir automatiquement sur les canaux IRC) mais qu'il ne se consacre qu'aux méchants, aux robots malveillants. Petite colère au passage : le mot anglais malicious veut dire « malveillant » et pas « malicieux » comme on le voit souvent stupidement traduit.

Les bots sont ensuite regroupés en bandes, les botnets, un groupe de zombies obéissant au même maître. Les activités des botnets sont très variées, envoi de spam, de spim, de spit, dDoS, hébergement de relais ou de sites de hameçonnage, hébergement de contenu illégal, fraude aux clics, etc.

Pendant longtemps, le protocole de communication favori des bot herders (ceux qui créent les botnets et les entretiennent) était IRC (RFC 1459). Muni d'une seule machine maître (le C3C, Command and Control Center), le botnet était assez facile à neutraliser : une fois le maître déconnecté, les zombies ne savaient plus quoi faire. Aujourd'hui, les botnets sont plus perfectionnés : utilisation de protocoles plus variés (HTTP, plus discret et moins filtré, a remplacé IRC), souvent en pair à pair, le tout largement chiffré.

Quelles sont les conséquences des actions du botnet ? Pour les victimes (ceux qui reçoivent le spam ou qui sont attaqués par déni de service), elles sont évidentes (pour le spam, voir « Spamalytics: An Empirical Analysis of Spam Marketing Conversion »). Pour l'utilisateur de la machine, c'est surtout la consommation de ressources, qui diminue les performances attendues. Mais pour le FAI, ces zombies ont aussi un coût : capacité réseau utilisée mais aussi atteinte à la réputation du FAI. Ses adresses IP courent un risque élevé de se retrouver sur des listes noires dont il est difficile de sortir. Certaines des opérations du botnet peuvent mettre en danger des ressources Internet critiques (voir le « Emerging Cyber Threats Report for 2009 » et « Distributed Denial of Service Attacks: Explanation, Classification and Suggested Solutions" »).

Le FAI est évidemment bien situé pour détecter la présence de bots, et pour prévenir les utilisateurs. Notons toutefois que, le concept de neutralité du réseau étant tabou chez les FAI, les risques pour ladite neutralité si le FAI s'engage dans ce combat ne sont pas mentionnés dans le RFC.

Personne ne pense bien sûr que des solutions parfaites existent : la lutte entre les bot herders d'un côté, et les FAI et les utilisateurs de l'autre, n'est pas près de se terminer. Toutefois, affirme le RFC dans sa section 2, on peut espérer limiter les dégâts et réduire la taille des botnets, les rendant ainsi moins dangereux.

La section 3, consacrée à doucher les éventuels enthousiasmes, dit d'ailleurs bien que l'éradication des bots est une tâche difficile. Elle note que la seule méthode parfaite sur une machine est « Réinstallez votre système d'exploitation », un remède assez radical et donc peu susceptible d'être suivi... Et le RFC fait remarquer que même cette approche ne suffit pas (voir l'exposé « Persistent BIOS Infection », ou le cas d'engins fermés, comme certains smartphones ou consoles de jeu, où l'utilisateur n'a même pas la liberté d'installer le système d'exploitation).

Maintenant, place à l'action. La première étape est de détecter les zombies dans le réseau. Cela peut se faire par l'analyse passive du trafic, ou bien par les plaintes, même si peu de FAI les traitent. Idéalement, ces plaintes devraient être transmises sous un format structuré, permettant leur analyse automatique, comme les formats ARF (RFC 5965) ou IODEF (RFC 7970). Le document évoque aussi la possibilité de recherches actives, comme le permet un outil comme nmap, bien que de telles recherches ne soient pas forcément légales (cela dépend du pays, note le RFC). Le RFC déconseille néanmoins ces méthodes actives, pas tant sur leur caractère intrusif que sur leur inefficacité (le bot ne va pas forcément se signaler lors du balayage).

Le RFC insiste sur la nécessité de détecter vite, si nécessaire au détriment de la justesse des résultats (tirer d'abord, réflechir ensuite...)

Parmi les techniques passives disponibles, le document cite aussi l'analyse des flux Netflow (RFC 3954, mais depuis remplacé par le IPFIX du RFC 5470) ou bien les méthodes à base de DNS, très à la mode en ce moment, notamment grâce au travail des chercheurs de Georgia Tech (voir par exemple David Dagon, Wenke Lee, « Global Internet Monitoring Using Passive DNS », Cybersecurity Applications & Technology Conference for Homeland Security, 2009). Ces méthodes fondées sur l'observation du trafic DNS ont été utilisées dans le cas de Conficker (les zombies font des demandes de résolution pour les noms de domaine générés par l'algorithme de Conficker, ce dernier n'utilisant pas de noms câblés en dur, cf. l'excellent rapport « An Analysis of Conficker's Logic and Rendezvous Points »). Mais combien de FAI, qui n'arrivent déjà pas à fournir un service correct à leurs utilisateurs, ont les moyens, la compétence et le temps de mener ce genre d'études ?

Idéalement, le FAI devrait non seulement détecter mais également identifier l'infection spécifique, les remèdes pouvant varier.

La partie la plus intéressante du RFC, à mon avis, concerne la notification des utilisateurs. Comment les prévenir que leur machine, infectée, est devenue un zombie ? Et le faire de façon à ce qu'ils comprennent et agissent ? Toutes les techniques de communication possibles avec les utilisateurs sont soigneusement passées en revue, mais aucune ne semble parfaite.

Voici donc les principales techniques envisagées :

  • Courrier électronique. Un des problèmes est qu'il risque de ne pas être lu immédiatement. Un autre est qu'il soit classé comme spam. Enfin, les méchants peuvent essayer d'envoyer de faux messages pour brouiller les pistes (du genre « Nous avons reçu notification d'une alerte de sécurité sur votre compte, connectez-vous à http://igotyou.biz/phishing.asp pour indiquer vos coordonnées »...). Ce dernier point est notamment développé en section 9 : il est très difficile d'imaginer un système de notification qui ne puisse pas être détourné par les hameçonneurs.
  • Appel téléphonique. Ils coûtent cher (il n'y a pas que le prix de l'appel, il y a surtout celui de l'employé appelant, si on choisit de faire faire l'appel par des gens compétents). Ils peuvent être considérés comme du spam (par exemple, Bouygues Telecom appelle régulièrement ses clients pour proposer des offres commerciales nouvelles et sans intérêt, et le robot humain qui appelle, avec un fort accent étranger, n'est jamais capable de répondre à la moindre question concrète : de nombreux clients raccrochent donc dès la première minute de ces spams.). Pire, si l'utilisateur utilise un système de voix sur IP sur son ordinateur, le logiciel malveillant peut décider de ne pas répondre aux appels du FAI. Et puis, le téléphone est le plus mauvais média pour donner des instructions techniques complexes.
  • Courrier postal. Très cher et très lent.
  • Enfermement dans un jardin clos (walled garden). L'idée de base est de configurer les routeurs du FAI pour détourner automatiquement tout le trafic en provenance du bot. Les communications avec le port 80, celui de HTTP, sont alors transmises à un site Web portant le message de notification et les instructions pour remédier au problème. Le jardin peut être totalement clos ou bien laisser passer vers certains services externes (un exemple typique étant Windows Update). La méthode est très brutale mais efficace : l'utilisateur ne peut pas ne pas voir les messages et, en attendant, le bot ne peut plus faire grand mal. Mais, en raison de sa brutalité, elle soulève bien des problèmes. Par exemple, les services autres que le Web (pensons à la voix sur IP) sont coupés, sans avertissement possible. Si le FAI s'est trompé (et que la machine n'était pas réellement infectée), le client va être furieux, et à juste titre. On risque de devoir donc laisser passer certains services par la porte du jardin, et la maintenance de la liste de ces services va être coûteuse. Le FAI doit aussi décider sur quels critères il laissera l'utilisateur sortir du jardin clos. Sur sa simple parole ou bien après un examen (forcément très intrusif) de la machine (d'autant plus que l'utilisateur typique a plusieurs machines derrière le routeur NAT...) ? Et faut-il faire passer un test de Turing aux demandeurs pour vérifier que c'est bien l'utilisateur et pas le bot qui demande l'ouverture du jardin clos ?
  • Messagerie instantanée. C'est rapide et simple. Ce serait sans doute la méthode idéale si tous les utilisateurs utilisaient un tel service et y étaient connectés en permanence. Et il y a le risque de spim.
  • SMS. L'utilisateur lira probablement le message, et en peu de temps. Cela suppose que le FAI garde trace des numéros de téléphone de ses clients et que ceux-ci ne considèrent pas le message comme du spam. En outre, les contraintes de taille du SMS posent un drôle de défi au rédacteur du message.
  • Le RFC mentionne aussi la possibilité d'utiliser un canal public pour les notifications, par exemple d'utiliser un haut-parleur dans une gare ou un café pour crier « Votre attention, s'il vous plait, nous venons de découvrir que la machine 18:03:73:66:e5:68 est infectée par un logiciel malveillant. Son propriétaire est prié de la désinfecter de toute urgence. » Cela peut être utile dans ces environnements, où l'administrateur du réseau n'a pas de lien particulier avec ses utilisateurs et ne sait pas comment les contacter.

À noter que toutes ces méthodes ne produisent pas de bons résultats au cas, le plus fréquent aujourd'hui, où les adresses IP sont partagées. Dans une entreprise de 500 personnes, montrer la notification aux 500 utilisateurs alors que seul l'administrateur système peut agir est probablement contre-productif. Si le FAI connaît les coordonnées dudit administrateur, il vaut certainement mieux lui écrire directement.

Cette discussion (section 5) des difficultés à attirer l'attention de ses propres clients sur un problème sérieux est la plus concrète du document. Mais elle pose plus de questions qu'elle n'apporte de réponses. Vous vous demandez peut-être quelle solution a finalement retenue Comcast ? Décrite dans le RFC 6108, elle consiste à modifier le contenu des pages Web vues par l'utilisateur pour y insérer une fenêtre-polichinelle d'avertissement.

La seule section qui ait un rapport direct avec le titre (section 6), sur les remèdes est, par contre, très courte, peut-être à juste titre, étant donné la difficulté à traiter les zombies. On les a détecté, on a notifié l'utilisateur, maintenant, que faire ? Le RFC suggère aux FAI de créer un site Web dédié à cet usage, où utilisateurs et administrateurs système pourront accéder à diverses documentations et outils. Les textes visant les utilisateurs sont difficiles à écrire : il faut les motiver pour agir (le bot peut être très discret, et l'utilisateur n'a alors rien détecté de problématique pour lui), sans les paniquer, et il faut expliquer rapidement car l'utilisateur ne lira pas de longs textes. Le RFC cite comme exemple d'introduction pour capter l'attention : « What is a bot? A bot is a piece of software, generally installed on your machine without your knowledge, which either sends spam or tries to steal your personal information. They can be very difficult to spot, though you may have noticed that your computer is running much more slowly than usual or you notice regular disk activity even when you are not doing anything. Ignoring this problem is risky to you and your personal information. Thus, bots need to be removed to protect your data and your personal information. »

La tâche de désinfection peut être difficile (surtout sur des engins comme les consoles de jeu, qui ne donnent typiquement pas accès au système) et, dans tous les cas, l'utilisateur n'a en général pas de compétences techniques : les instructions de désinfection doivent donc être très concrètes et détaillées.

Donc, sous forme d'une liste, voici quelques-unes des étapes que le RFC recommande de ne pas oublier, dans les conseils donnés aux utilisateurs :

  • Faites des sauvegardes de vos fichiers (un bon avis, indépendamment de l'infection par le malware).
  • Mettez à jour votre système (Windows Update avec Microsoft Windows, par exemple).
  • Ne pas hésiter à demander l'aide d'un professionnel. Ce conseil du RFC est évidemment raisonnable (la tâche peut être trop complexe pour l'utilisateur ordinaire) mais me laisse perplexe : pour les soins aux machines de M. Toutlemonde, on trouve plein de gourous autoproclamés, dont les compétences en informatique sont en général à peine supérieures à celles de leurs clients. Ces derniers, ne connaissant pas le sujet, ne peuvent pas distinguer un vrai expert d'un Jean-Kevin Michu qui se prend pour un gourou parce qu'il a déjà installé une fois un Windows en partant de zéro. Ce problème me semble un des plus sérieux pour M. Toutlemonde « à qui faire confiance ? »
  • Si l'utilisateur a l'intention de porter plainte, il faut faire l'inverse : ne pas nettoyer la machine mais la laisser intacte pour l'enquête (comme la scène du crime entourée du ruban jaune, dans les séries policières états-uniennes). Aux États-Unis, l'organisme national en charge est l'Internet Crime Complaint Center. (Quel est l'équivalent en France ?) Le RFC note toutefois en termes diplomatiquement polis qu'il y a peu de chance que la police se dérange parce que M. Toutlemonde a un virus sur sa machine... (Et j'ajoute que c'est parce que la police est occupée avec des crimes plus graves comme par exemple le partage de la culture.)

Et si l'utilisateur ne peut pas ou ne veut pas réparer (section 7) ? Le RFC note que c'est évidemment un problème non-technique et a une approche très états-unienne, « shoot them » (supprimer l'abonnement et déconnecter l'utilisateur).

Le document rend aussi un hommage obligatoire à la nécessite de préserver la vie privée des utilisateurs (sections 4 et 10), sans trop s'attarder sur comment concilier surveillance rapprochée et respect de la vie privée. Un intéressant problème à la fois politique et légal. Voir aussi la section 8 sur les problèmes que pose le partage de données entre l'utilisateur, le FAI et éventuellement les autorités. L'annexe A donne une liste d'organisations privées qui peuvent être intéressés par ces données (liste de machines infectées, pour faire une liste noire, par exemple) et les publier.

À noter qu'une autre faiblesse de ce document est que, pour éviter de déchaîner les avocats de Microsoft, le fait que la quasi-totalité des zombies soient aujourd'hui des machines Windows est tout simplement absent...


Téléchargez le RFC 6561


L'article seul

RFC 6557: Procedures for Maintaining the Time Zone Database

Date de publication du RFC : Février 2012
Auteur(s) du RFC : E. Lear, P. Eggert
Première rédaction de cet article le 3 mars 2012


Vous aviez peut-être suivi l'affaire il y a quelques mois : une société d'astrologie (!) a fait un procès au responsable de la base de données des fuseaux horaires, base utilisée ensuite par des tas de logiciels dans le monde (notamment les logiciels libres). La société prétendait qu'elle était propriétaire des données. Comme le responsable de la base, Arthur David Olson, est un simple individu, sans moyens financiers (la justice, c'est seulement pour les riches), il a cédé. Désormais, cette base est gérée par l'IANA, et ce RFC documente les procédures de gestion.

La solution trouvée, confier cette base à l'ICANN, permet au moins de se mettre à l'abri des trolls, l'ICANN ayant beaucoup d'argent et d'avocats. Au moins, les millions de dollars stockés par l'ICANN, à titre de précaution juridique en cas de procès vont servir à quelque chose d'utile. Mais, en attendant, c'est un nouveau pan de la gouvernance de l'Internet qui passe d'un volontaire bénévole, aidé par quelques internautes, à une grosse bureaucratie politicienne, très lente et très chère.

Le registre est donc désormais en ligne à l'IANA. La section 7 du RFC discute les questions de propriété intellectuelle associées.

Quelques articles sur le sujet :


Téléchargez le RFC 6557


L'article seul

RFC 6556: Testing Eyeball Happiness

Date de publication du RFC : Avril 2012
Auteur(s) du RFC : F. Baker (Cisco)
Pour information
Première rédaction de cet article le 7 avril 2012


Le problème du bonheur des globes oculaires (eyeball happiness) fait l'objet de recherches actives en ce moment. Il s'agit de s'assurer que, lorsqu'un service Internet (par exemple un site Web) est accessible à la fois en IPv4 et en IPv6, l'utilisateur (le propriétaire des globes oculaires) sera heureux (il verra le site très vite), que sa connectivité IPv6 fonctionne correctement ou pas. L'incertitude à ce sujet est la principale cause du très faible nombre de sites Web qui ont un enregistrement AAAA (adresse IPv6) dans le DNS aujourd'hui.

Ce RFC ne propose pas de solution : issu de travaux menés notamment au sein du groupe de travail benchmarks de l'IETF, il propose simplement de mesurer ce bonheur des globes oculaires, de manière à ce qu'on puisse comparer les solutions. On pourra alors retenir les meilleures, de manière à faire sauter ce qui est aujourd'hui un sérieux obstacle au déploiement d'IPv6.

La section 1 du RFC résume le problème de base : si on a une connectivité où plusieurs préfixes IP sont possibles (un IPv4 et un IPv6, ou bien plusieurs IPv6), et que l'application choisit comme source le « mauvais » (celui qui a la moins bonne connectivité, voire pas de connectivité du tout), quelles seront les conséquences pratiques ? L'établissement de la session en sera-t-il ralenti ? Comment TCP va-t-il réagir (RFC 5461) ?

L'algorithme naïf pour l'application est de récupérer une liste d'adresses possibles pour la destination, via getaddrinfo(), et d'essayer chaque adresse successivement. Si certaines timeoutent, le temps total d'établissement de la connexion (attendre l'expiration du délai de garde, puis essayer l'adresse suivante) va largement dépasser les capacités de l'utilisateur même le plus patient (cela peut dépasser la minute, la valeur exacte dépend de nombreux paramètres). Les globes oculaires seront malheureux.

C'est à cause de cela que, alors que plus de 40 % des zones dans .fr ont une adresse IPv6 pour leur service DNS (mesures faites en janvier 2012), seules moins d'1 % en ont une pour leur service Web. C'est parce que le DNS a été prévu pour résister aux pannes dès le début (le résolveur se souvient de quelles adresses marchent, pour une zone) et que l'ajout d'un AAAA cassé n'a pas de conséquences graves. Au contraire, le Web n'a pas de mécanisme natif pour assurer la haute disponibilité et un AAAA cassé se paie très cher en temps d'attente pour les clients. Beaucoup de gérants de sites Web préfèrent donc ne pas courir le risque, même s'il ne frapperait qu'une petite minorité de leurs clients.

L'idée de ce RFC, présentée en section 2, est de quantifier ce problème. Le but est d'aboutir à des chiffres indiquant, pour un système donné (nommé Alice), le temps qu'il met à ouvrir une session avec un service (nommé Bob) dont certaines adresses sont incorrectes. Plusieurs cas d'incorrection peuvent se présenter :

  • Un routeur jette les paquets mais transmet un message ICMP administratively prohibited ou bien destination unreachable,
  • Un routeur jette silencieusement les paquets (cible DROP dans iptables par exemple),
  • Un programme intermédiaire génère un RST (reset) TCP,
  • Un problème de MTU fait que les paquets au delà d'une certaine taille ne sont pas transmis. Normalement, la découverte de la MTU du chemin (RFC 1191, RFC 1981) fait que ce problème ne doit jamais se produire. En pratique, des configurations incorrectes (blocage aveugle de tout ICMP) font qu'il arrive quand même.

Le test doit être fait pour tous ces cas car rien ne dit que l'application réagira de la même façon à tous ces problèmes. Le plus important est sans doute celui de la perte silencieuse des paquets, car c'est le pire : si l'application réagit bien même dans ce cas, elle s'en tirera sans doute dans les autres. Si on n'en teste qu'un, cela doit donc être celui-ci. (C'est ce que dit le RFC. En pratique, le cas des problèmes de MTU est souvent aussi grave, et il ne se détecte qu'après l'ouverture de la session, lorsqu'on commence à envoyer de gros paquets.)

La section 2.2 explique la procédure, notamment le fait qu'on intègre le temps de la requête DNS préalable (ce que je trouve contestable, mais les raisons ne sont pas expliquées). Les métriques elle-mêmes sont en section 2.3. On mesure le temps entre la première requête DNS et la fin de l'établissement de la connexion TCP, qui est le moment où l'application peut commencer à travailler. Cela se nomme le Session Setup Interval. Si on garde les temps minimum (meilleur cas, probablement celui où la première tentative réussie) et maximum (pire cas, lorsqu'il aura fallu essayer toutes les adresses de la cible), on les nomme Minimum Session Setup Interval et Maximum Session Setup Interval. Le reste du RFC est composé de détails concrets pour qui voudrait effectuer cette mesure. Telle qu'elle est définie (avec des notions comme « l'arrivée du dernier but »), elle n'est pas triviale, voire pas possible à mettre en œuvre sur une machine Unix normale.

Il existe aussi une métrique « qualitative », où on décrit le trafic observé (Attempt Pattern). Cela peut être simple (« Un paquet TCP SYN est envoyé successivement à toutes les adresses, à des intervalles de X milli-secondes ») mais aussi très complexe. Mon article sur les algorithmes en donne quelques exemples.


Téléchargez le RFC 6556


L'article seul

RFC 6555: Happy Eyeballs: Success with Dual-Stack Hosts

Date de publication du RFC : Avril 2012
Auteur(s) du RFC : D. Wing, A. Yourtchenko (Cisco)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF v6ops
Première rédaction de cet article le 7 avril 2012


Une question récurrente qu'IPv6 pose aux développeurs d'application et aux administrateurs système qui déploieront ces applications ensuite est celle d'une machine accessible à la fois en IPv4 et IPv6. Si le pair cherchant à joindre cette machine croit avoir IPv6 mais que sa connectivité ne marche pas, ou mal, l'application arrivera-t-elle à se rabattre en IPv4 très vite ou bien imposera-t-elle à l'utilisateur un long délai avant de détecter enfin le problème ? Cette question est connue comme « le bonheur des globes oculaires » (les dits globes étant les yeux de l'utilisateur qui attend avec impatience la page d'accueil de YouPorn) et ce RFC spécifie les exigences pour l'algorithme de connexion du client, afin de rendre les globes oculaires le plus heureux possible. (Il a depuis été remplacé par un RFC plus général, ne se limitant pas à IPv6, le RFC 8305.)

La section 1 rappelle les données du problème : on veut évidemment que cela marche aussi bien en IPv6 qu'en IPv4 (pas question d'accepter des performances inférieures) or, dans l'état actuel du déploiement d'IPv6, bien des sites ont une connexion IPv6 totalement ou partiellement cassée. Si un serveur a IPv4 et IPv6 et que son client n'a qu'IPv4, pas de problème. Mais si le client a IPv6, tente de l'utiliser, mais que sa connexion est plus ou moins en panne, ses globes oculaires vont souffrir d'impatience. Certains fournisseurs (notamment Google) ont résolu le problème en n'annonçant leur connectivité IPv6 (via le DNS et les enregistrements AAAA) qu'à certains réseaux, configurés manuellement après examen de la qualité effective de leur connectivité. Cette approche, nommée « whitelisting » ne passe évidemment pas à l'échelle. Même pour Google, c'est un travail colossal que d'évaluer le réseau de tous les sites Internet.

(À noter que deux lecteurs m'ont fait remarquer que YouPorn n'est pas un bon exemple, puisqu'il ne publie pas d'adresse IPv6. C'est vrai et cela montre que mes lecteurs connaissent bien YouPorn.)

La bonne solution est donc que l'application elle-même gère le problème (ou, sinon l'application elle-même, la bibliothèque logicielle qu'elle utilise et où se trouve la fonction de connexion). Il existe plusieurs algorithmes pour cela, déjà largement déployés. Ce RFC normalise les caractéristiques que doivent avoir ces algorithmes. Si on suit ce RFC, le trafic (IP et DNS) va légèrement augmenter (surtout si la connectivité IPv6 marche mal ou pas du tout) mais la qualité du vécu de l'utilisateur va être maintenue, même en présence de problèmes, ce qui compense largement. Autrement, il existerait un risque élevé que certains utilisateurs coupent complètement IPv6, plutôt que de supporter ces problèmes de délai de connexion.

La section 3 revient dans l'histoire, pour montrer que le problème n'est pas nouveau. En 1994, le RFC 1671 disait « The dual-stack code may get two addresses back from DNS; which does it use? During the many years of transition the Internet will contain black holes. » (Au passage, cela montre la stupidité de la légende, fréquemment entendue, comme quoi les problèmes de la transition IPv4->IPv6 n'auraient pas été étudiés à l'avance.) Tout le reste de notre RFC 6555 est consacré à répondre à cette question. La cible principale est composée des protocoles de transport avec connexion (TCP, SCTP), les protocoles sans connexion comme UDP soulevant d'autres questions (s'ils ont une sémantique requête/réponse, comme dans ICE, les algorithmes de ce RFC peuvent être utilisés).

Le RFC rejette l'idée d'utiliser des noms différents pour les deux familles (comme www.ipv6.example.com), car cela complique le partage de noms (envoi d'un URL à un copain, par exemple).

Donc, on a un nom de machine qu'on veut contacter, mettons www.example.com, avec deux adresses associées, une par famille (voir les sections 5.3 et 5.4 pour le cas avec plus de deux adresses). Avec l'algorithme naïf qu'utilisent certains logiciels, et une connexion IPv6 qui marche mal, voici la séquence d'évenements :

  • L'initiateur de la connexion utilise le DNS pour demander les enregistrements A (adresse IPv4) et AAAA (IPv6). (Notez qu'il n'existe pas de type de requête DNS pour avoir les deux enregistrements d'un coup, il faut donc deux requêtes. Voir aussi la section 5.4.)
  • Il récupère 192.0.2.1 et 2001:db8::1.
  • Il tente IPv6 (sur Linux, l'ordre des essais est réglable dans /etc/gai.conf). L'initiateur envoie un paquet TCP SYN à 2001:db8::1.
  • Pas de réponse (connexion IPv6 incorrecte). L'initiateur réessaie, deux fois, trois fois, faisant ainsi perdre de nombreuses secondes.
  • L'initiateur renonce, il passe à IPv4 et envoie un paquet TCP SYN à 192.0.2.1.
  • Le répondeur envoie un SYN+ACK en échange, l'initiateur réplique par un ACK et la connexion TCP est établie.

Le problème de cet algorithme naïf est donc la longue attente lors des essais IPv6. On veut au contraire un algorithme qui bascule rapidement en IPv4 lorsqu'IPv6 ne marche pas, sans pour autant gaspiller les ressources réseau en essayant par exemple toutes les adresses en même temps.

L'algorithme recommandé (section 4, cœur de ce RFC) aura donc la tête :

  • L'initiateur de la connexion utilise le DNS pour demander les enregistrements A (adresse IPv4) et AAAA (IPv6).
  • Il récupère 192.0.2.1 et 2001:db8::1. Il sait donc qu'il a plusieurs adresses, de famille différente.
  • Il tente IPv6. L'initiateur envoie un paquet TCP SYN à 2001:db8::1, avec un très court délai de garde.
  • Pas de réponse ? L'initiateur passe à IPv4 tout de suite. Il envoie un paquet TCP SYN à 192.0.2.1.
  • Le répondeur envoie un SYN+ACK en échange, l'initiateur réplique par un ACK et la connexion TCP est établie.

Si le répondeur réagit à une vitesse normale en IPv6, la connexion sera établie en IPv6. Sinon, on passera vite en IPv4, et l'utilisateur humain ne s'apercevra de rien. Naturellement, si le DNS n'avait rapporté qu'une seule adresse (v4 ou v6), on reste à l'algorithme traditionnel (« essayer, patienter, ré-essayer »).

La section 4 précise ensuite les exigences auxquelles doit obéir l'algorithme. D'abord, il est important de ne pas tester IPv4 tout de suite. Les premiers algorithmes « bonheur des globes oculaires » envoyaient les deux paquets SYN en même temps, gaspillant des ressources réseau et serveur. Ce double essai faisait que les équipements IPv4 du réseau avaient autant de travail qu'avant, alors qu'on aurait souhaité les retirer du service petit à petit. En outre, ce test simultané fait que, dans la moitié des cas, la connexion sera établie en IPv4, empêchant de tirer profit des avantages d'IPv6 (cf. RFC 6269). Donc, on doit tester en IPv6 d'abord, sauf si on se souvient des tentatives précédentes (voir plus loin la variante « avec état ») ou bien si l'administrateur système a délibérement configuré la machine pour préférer IPv4.

L'avantage de cet algorithme « IPv6 d'abord puis rapidement basculer en IPv4 » est qu'il est sans état : l'initiateur n'a pas à garder en mémoire les caractéristiques de tous ses correspondants. Mais son inconvénient est qu'on recommence le test à chaque connexion. Il existe donc un algorithme avec état, où l'initiateur peut garder en mémoire le fait qu'une machine (ou bien un préfixe entier) a une adresse IPv6 mais ne répond pas aux demandes de connexion de cette famille. Le RFC recommande toutefois de re-essayer IPv6 au moins toutes les dix minutes, pour voir si la situation a changé. De plus, un changement de connectivité (détecté par le DNA des RFC 4436 ou RFC 6059) doit entraîner un vidage complet de l'état (on doit oublier ce qu'on a appris, qui n'est plus pertinent).

Une conséquence de l'algorithme recommandé est que, dans certains cas, les deux connexions TCP (v4 et v6) seront établies (si le SYN IPv6 voyage lentement et que la réponse arrive après que l'initiateur de la connexion se soit impatienté et soit passé à IPv4). Cela peut être intéressant dans certains cas rares, mais le RFC recommande plutôt d'abandonner la connexion perdante (la deuxième). Autrement, cela pourrait entraîner des problèmes avec, par exemple, les sites Web qui lient un cookie à l'adresse IP du client, et seraient surpris de voir deux connexions avec des adresses différentes.

Voilà, l'essentiel du RFC est là. La section 5 donne quelques détails en plus. Par exemple, l'algorithme des globes oculaires heureux est astucieux, mais tend à masquer les problèmes. Si un site Web publie les deux adresses mais que sa connectivité IPv6 est défaillante, aucun utilisateur ne lui signalera puisque, pour eux, tout va bien. Il est donc recommandé que le logiciel permette de débrayer cet algorithme, afin de tester la connectivité avec seulement v4 ou seulement v6, ou bien que le logiciel indique quelque part ce qu'il a choisi, pour mieux identifier d'éventuels problèmes v6.

D'autre part, vous avez peut-être remarqué que j'ai utilisé des termes vagues (« un certain temps ») pour parler du délai entre, par exemple, le premier SYN IPv6 et le premier SYN IPv4. La section 5.5 donne des idées quantitatives en suggérant entre 150 et 250 ms entre deux essais (les navigateurs actuels sont plutôt du côté de 300 ms). C'est quasiment imperceptible à un utilisateur humain devant son navigateur Web, tout en évitant de surcharger le réseau inutilement. Les algorithmes avec état ont le droit d'être plus impatients, puisqu'ils peuvent se souvenir des durées d'établissement de connexion précédents.

Autre problème pratique, l'interaction avec la politique de sécurité des navigateurs Web (RFC 6454). Pour limiter les risques d'attaque par changement DNS (croire qu'on se connecte au même serveur HTTP alors que c'est en fait un autre), les navigateurs ne doivent pas changer de famille d'adresse (v4 en v6 ou réciproquement) une fois la session commencée.

Enfin, les implémentations. La section 6 donne les exemples de Firefox et Chrome, très proches de ce que décrit le RFC. D'autres possibilités sont disponibles en ligne, en Erlang ou en C. Une version pour Go avait été affichée en http://www.pastie.org/1528545 (en voici une sauvegarde locale).

Enfin, pour un exemple de test du malheur des globes oculaires, voir « Experiences of host behavior in broken IPv6 networks ». Ou bien « Evaluating the Effectiveness of Happy Eyeballs » qui contient d'intéressantes mesures.


Téléchargez le RFC 6555


L'article seul

RFC 6550: RPL: IPv6 Routing Protocol for Low power and Lossy Networks

Date de publication du RFC : Mars 2012
Auteur(s) du RFC : T. Winter, P. Thubert (Cisco Systems), A. Brandt (Sigma Designs), T. Clausen (LIX, École Polytechnique), J. Hui (Arch Rock Corporation), R. Kelsey (Ember Corporation), P. Levis (Stanford University), K. Pister (Dust Networks), R. Struik, JP. Vasseur (Cisco Systems)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF roll
Première rédaction de cet article le 26 mars 2012


Il y a beaucoup d'intérêt en ce moment pour un (largement mythique) « Internet des objets » qui mèle des fantasmes domotiques éculés (le réfrigérateur qui commande tout seul des bières à Carrefour via l'Internet, lorsqu'il est vide), l'arrivée massive d'ordinateurs qui ne sont pas considérés comme des ordinateurs (smartphones, tablettes, télévisions connectées), la connexion à des réseaux TCP/IP d'équipements très modestes, et la diffusion de plus en plus large d'étiquettes RFID. Pour les ordinateurs (un smartphone, bien plus puissant que l'ordinateur qu'embarquait les vaisseaux Apollo, mérite tout à fait ce titre), un des enjeux de l'Internet des objets est le routage des paquets IP. Ces « objets » ont des ressources électriques limitées, et sont souvent connectés par des liens radio de qualité médiocre. Les protocoles de routage traditionnels ne sont pas très adaptés à cette situation. Le groupe de travail ROLL de l'IETF travaille sur ce problème et vient de produire son protocole « officiel », RPL (Routing Protocol for LLNs où un LLN est un Low power and Lossy Network, un réseau où mêmes les routeurs ont peu de courant et où pas mal de paquets se perdent en route). Le groupe ROLL a déjà produit plusieurs RFC détaillant les demandes de ces LLNs : RFC 5867, RFC 5826, RFC 5673 et RFC 5548. Il a également normalisé l'algorithme de distribution utilisé par RPL, Trickle (RFC 6206).

Un exemple de LLNs est un groupe de capteurs dispersés un peu partout dans un bâtiment industriel : ce sont des petites machines par rapport au smartphone typique, fonctionnant sur batteries ou sur piles, ils doivent faire attention à leur consommmation électrique. Connectés par radios, ils n'ont en général pas la possibilité de parler directement aux gros routeurs de la salle machines, située à des dizaines de mètres. Certains des objets doivent donc tenir le rôle de routeur, relayant les communications de leurs camarades (la distinction entre routeur et machine terminale est d'ailleurs assez floue dans RPL). Il leur faut donc un protocole de routage pour trouver les chemins possibles et les protocoles existants comme OSPF n'ont jamais été conçus pour ce genre de missions (par exemple, OSPF émet des messages même lorsqu'il n'y a pas de changements, ce qui peut vider une batterie rapidement). Le « public » visé est donc composé de machines avec des processeurs 16bits, quelques ko de RAM et de Flash, dans des réseaux où il peut y avoir des milliers de tels engins.

RPL est la solution technique à ce problème du routage. Je préviens tout de suite mes fidèles lecteurs que ce RFC est très long et que je n'ai pas tout suivi, loin de là. Il n'y aura donc pas ici de cours sur RPL mais juste la mise en évidence de certains points intéressants (si vous ne lisez qu'une partie du RFC, la section 3 est une description de haut niveau de RPL). Notez qu'il existe d'autres protocoles de routage répondant à peu près à ce cahier des charges, notamment Babel (RFC 8966).

Pour distribuer l'information sur les routes et les routeurs, RPL utilise l'algorithme Trickle (RFC 6206).

RPL essaie de construire un graphe acyclique, qui est lui-même divisé en sous-graphes acycliques, chacun enraciné dans une et une seule destination (RPL les nomme DODAG pour Destination-Oriented Direct Acyclic Graphs). Tout le trafic pour une destination donnée a ainsi la garantie de l'atteindre, sans boucler. Le graphe est orienté : les informations de routage indiquent si le paquet progressera « vers le haut » ou bien « vers le bas » et cette orientation joue un rôle essentiel dans la prévention des boucles (section 11.2). L'annexe A décrit en détail un exemple de fonctionnement.

Pour optimiser les routes, RPL est paramétré avec une fonction nommée OF (pour Objective Function). Des concepts comme celui de distance sont définis par cette fonction. Des réseaux différents peuvent utiliser des OF différents (une qui cherche le chemin le plus court, une qui cherche à ne pas utiliser comme routeur les machines n'ayant pas de connexion au courant électrique, etc), même s'ils utilisent tous RPL. Ces fonctions sont enregistrées à l'IANA (section 20.5). La section 14 décrit les règles auxquelles doivent obéir ces fonctions.

RPL nécessite des liens bidirectionnels. Ce n'est pas toujours évident d'avoir de tels liens dans le monde des ondes radio. RPL doit donc tester la bidirectionnalité des liens avec un potentiel routeur, par exemple en utilisant le protocole du RFC 5881. Comme tout bon protocole TCP/IP, RPL peut fonctionner sur un grand nombre de modèles de réseaux physiques (cf. RFC 3819). Les communications du protocole RPL utiliseront ensuite des paquets ICMP (RFC 4443) de type 155.

Conçu pour des réseaux de machines ayant peu de capacités, et qu'on ne peut pas aller toutes configurer à la main, RPL a par défaut peu de sécurité. Dans le mode de base, n'importe quelle machine peut se joindre au réseau et se faire désigner comme routeur. Dans le mode « pré-installé », les machines doivent connaître une clé pour joindre le réseau. Dans le mode de sécurité maximale, dit « authentifié », il y a deux clés, une pour devenir un nœud ordinaire, et une pour devenir un routeur. (Voir la section 10 pour tous les détails sur la sécurité.)

RPL est un protocole de routage (routing), c'est-à-dire de construction de routes. Il ne change pas le modèle de transmission (forwarding) d'IP, celui que suivent les nœuds une fois les routes connues. Néanmoins, la section 11 donne quelques conseils intéressants sur la façon dont les machines peuvent limiter les problèmes lors de la transmission des paquets. Par exemple, une machine peut faire partie de plusieurs réseaux RPL (on dit « plusieurs instances RPL ») et elle doit faire attention en routant des paquets entre deux instances car les protections contre les boucles ne s'appliquent plus. Une solution possible est d'ordonner les instances (on peut transmettre les paquets destinés à un réseau seulement vers un réseau dont le numéro d'instance est supérieur).

L'ingénieur réseaux qui devra installer et configurer un réseau utilisant RPL peut aller regarder tout de suite la section 18 : elle explique la gestion de ces réseaux et les paramètres qu'on peut avoir à configurer, dans l'esprit du RFC 5706. Évidemment, c'est toujours préférable lorsqu'il n'y a rien à configurer et que cela marche tout seul (RFC 1958, section 3.8). C'est particulièrement vrai pour le type de réseaux auxquels est destiné RPL, des réseaux composés de nombreuses machines planquées un peu partout. Néanmoins, si on veut configurer, il y a quelques boutons à tourner comme le choix du numéro d'instance RPL (section 18.2.3) qui permet d'avoir plusieurs réseaux RPL différents dans un même endroit.

Enfin, la section 19 est la traditionnelle section sur la sécurité. Comme résumé au début de cet article, RPL offre forcément peu de sécurité : les réseaux ad hoc pour lesquels il est prévu ne s'y prêtent guère (difficulté à configurer chaque machine, par exemple pour y indiquer une clé, ou bien ressources limitées des machines, ce qui limite l'usage de la cryptographie). RPL fournit néanmoins des mécanismes de sécurité mais il est à parier qu'ils ne seront pas souvent déployés.

Comme souvent de nos jours, une bonne partie des efforts du groupe de travail a été dépensé en discussions sur les différentes brevets plombant le protocole. Il a finalement été décidé de foncer mais les juristes peuvent regarder les différentes prétentions à l'appropriation qui pèsent sur RPL.

Quelles implémentations sont disponibles ? Selon le groupe de travail, elles seraient déjà plus de dix, mais je n'ai pas de liste. Ce qui est sûr, c'est que deux tests d'interopérabilité ont déjà eu lieu, sous la houlette de l'IPSO et du consortium Zigbee. La section 16 intéressera certainement les implémenteurs car elle récapitule les choses importantes qu'il faut savoir pour que toutes les mises en œuvre de RPL coopèrent.

Un résumé de synthèse sur RPL est « "The Internet of Things" takes a step forward with new IPv6 routing protocol », écrit par un employé de Cisco (entreprise qui a fondé l'alliance IPSO en septembre 2008).


Téléchargez le RFC 6550


L'article seul

RFC 6548: Independent Submission Editor Model

Date de publication du RFC : Juin 2012
Auteur(s) du RFC : N. Brownlee (University of Auckland), éditeur pour l'IAB
Pour information
Première rédaction de cet article le 18 juin 2012


Si vous n'aimez pas les RFC de procédure, et que vous ne voulez que de la technique, rassurez-vous, ce document est court : il spécifie le rôle et les qualités de l'ISE (Independent Submission Editor), celui (ou celle) qui supervise les RFC qui ne passent pas par l'IETF. (Il a par la suite été remplacé par le RFC 8730.)

Comment, ça existe ? Tous les RFC ne naissent pas au sein d'un des nombreux groupes de travail de l'IETF ? Eh oui, c'est souvent oublié, mais c'est le cas, il existe une voie indépendante qui permet à des individus de publier un RFC, quel que soit l'avis de l'IETF. Cette voie est décrite dans le RFC 4846. Autrefois, il n'existait qu'un seul RFC Editor pour examiner et préparer tous les RFC. Mais cette tâche est désormais répartie entre plusieurs éditeurs spécialisés et l'ISE est en charge de la voie indépendante.

Ce mécanisme était décrit dans le RFC 5620 (modèle du RFC Editor, « v1 »), document désormais réparti entre plusieurs RFC comme le RFC 6635 (modèle du RFC Editor, « v2 ») et ce RFC 6548.

La section 2.1 décrit les qualifications attendues de l'ISE. Ce doit être quelqu'un d'expérimenté (senior), compétent techniquement dans les sujets traités à l'IETF (ce qui fait beaucoup !), connu et reconnu de la communauté IETF, sachant écrire et corriger, connaissant très bien l'anglais, et capable de travailler dans le milieu souvent agité de l'IETF.

Sa tâche principale (section 2.2) est de maintenir la qualité des RFC de la voie indépendante, par la relecture et l'approbation des documents, avant transmission au Producteur des RFC (RFC Production Center). Mais il doit aussi traiter les errata pour les RFC de la voie indépendante, contribuer à définir les évolutions de cette voie, interagir avec les autres acteurs des RFC, et fournir des statistiques à l'IAB et l'IAOC. Il peut se faire assister par un conseil consultatif, dont il nomme les membres « at the pleasure of the ISE », dit le RFC dans une jolie formule. Il y a aussi un conseil éditorial, également nommé par l'ISE (section 3 du RFC).

Le site officiel des RFC contient une page consacrée à la voie indépendante, si cela vous tente d'y publier.

L'ISE est nommé par l'IAB, selon une procédure analogue à celle du RFC 4333. Aujourd'hui, c'est Nevil Brownlee (l'auteur du RFC), qui joue ce rôle. Il a été reconfirmé le 5 février 2012, sa première désignation avait été en 2010.


Téléchargez le RFC 6548


L'article seul

RFC 6547: RFC 3627 to Historic Status

Date de publication du RFC : Février 2012
Auteur(s) du RFC : W. George (Time Warner Cable)
Pour information
Réalisé dans le cadre du groupe de travail IETF 6man
Première rédaction de cet article le 1 mars 2012


Un très court RFC qui se contente de déclarer formellement que le RFC 3627 n'a plus qu'un intérêt historique. La principale recommendation de ce vieux RFC, que les liens point-à-point ne soient pas numérotés en IPv6 avec un /127, a été annulée par le RFC 6164, qui recommande au contraire cette pratique.


Téléchargez le RFC 6547


L'article seul

RFC 6545: Real-time Inter-network Defense (RID)

Date de publication du RFC : Avril 2012
Auteur(s) du RFC : Kathleen M. Moriarty (EMC)
Chemin des normes
Première rédaction de cet article le 22 avril 2012


La sécurité, face aux innombrables attaques que connaissent les réseaux tous les jours, nécessite un échange d'information permanent. Ce RFC normalise donc un format permettant d'échanger et de traiter ce genre d'informations. Il sera donc peut-être un outil technique utile pour les CSIRT et les opérateurs.

La section 1 résume les problèmes de la sécurité des réseaux auxquels les opérateurs font face. Une fois l'attaque détectée, que ce soit un hameçonnage, une DoS ou une pénétration réussie dans un système connecté au réseau, il faut rédiger un rapport, transmettre à l'opérateur d'origine de l'attaque, demander à un opérateur amont de prendre des mesures pour limiter les dégâts, demander de continuer l'enquête en suivant la trace de l'attaquant, etc. Par exemple, si on veut suivre une trace de paquets dont l'adresse IP source est mensongère, et que le filtrage recommandé par le RFC 2827 n'est pas en place, il faut repérer par quel câble sont entrés ces paquets et envoyer ensuite à l'opérateur situé derrière une demande de continuation de l'enquête. Il n'y a pas de mécanisme formel pour cela. Ça se fait typiquement par téléphone ou par envoi d'un courrier en langue naturelle, ce qui augmente les coûts de traitement.

Le nouveau format, normalisé dans ce RFC 6545, se nomme RID pour Real-time Inter-network Defense et se base sur le format IODEF du RFC 5070 (désormais RFC 7970), qui lui-même utilise XML. L'apport par rapport à l'IODEF de base est de cibler la circulation d'informations en « temps réel ». RID avait d'abord été spécifié dans le RFC 6045, que notre RFC met à jour. À part le changement de statut (RID est désormais sur le chemin des normes), les changements (résumés dans la section 1.1) sont de peu d'importance.

RID vise donc à permettre la réponse immédiate à une attaque. Par exemple, lorsqu'une dDoS est perpétrée par un botnet, il faut certes retrouver les zombies mais aussi identifier le contrôleur qui les commande. RID permet de demander un suivi de la trace des premiers, puis ensuite du second.

L'opérateur a typiquement un système de gestion centralisé de son réseau, un NMS. Le futur IHS (Incident Handling System) qui recevra et enverra les messages RID devra être intégré à ce NMS. La détection de l'attaque pourra se faire manuellement, ou via un IDS mais cette question est hors-sujet pour RID, qui se contente de permettre le signalement d'attaques, une fois celles-ci détectées.

Quelles sont les obstacles que rencontrent les tentatives de remonter à la source d'une attaque ? La section 2 en donne une liste, et c'est une lecture très recommandée pour comprendre la variété des problèmes auxquels fait face l'opérateur réseau lors d'une attaque. Par exemple, certaines attaques utilisent tellement peu de paquets qu'il est difficile de les répérer. D'autre part, pour prendre rapidement une « empreinte » des paquets utilisés pour l'attaque, les techniques à base d'une fonction de hachage ont souvent été utilisées (cf. « Hash-Based IP Traceback »). Or, certaines attaques ont un contenu des paquets qui varie énormément et il est difficile de trouver une « signature » qui permettrait de dire à l'opérateur précédent « Voici ce que je cherche ». Les nombreuses techniques de traceback pour IP ont été utilisées pour déterminer quelles étaient les informations importantes à inclure dans RID. Ainsi, il est essentiel d'inclure beaucoup d'informations dans le message RID car les champs significatifs et l'attaque, permettant de repérer les paquets, peuvent être n'importe lesquels. RID permet même d'envoyer la totalité du paquet, si nécessaire.

Une fois que le message RID est prêt, que fait-on pour la communication avec les autres opérateurs et avec les CSIRT ? Les sections 3.1 et 3.2 font remarquer que le courrier électronique n'est pas forcément adapté car il peut être trop lent. Mais, de toute façon, il faut prévoir plusieurs canaux de communication car, en cas d'attaque, certains deviendront peut-être inutilisables. Un réseau distinct de celui utilisé pour le trafic « normal » peut donc être nécessaire (voir plus loin le commentaire de la section 9). Le RFC suggère qu'on peut profiter des négociations qui précèdent un accord de peering pour mettre en place un canal de communication sécurisé.

Recommandation utile ou vœu pieux ? En tout cas, la section 3.1 rappelle également que RID ne devrait être utilisé que pour lutter contre des attaques, et pas pour perpétuer des sabotages (en dénonçant un innocent dans l'espoir qu'il se fasse filtrer) ou pour censurer.

Maintenant, place au format utilisé (section 4), fondé sur IODEF (RFC 5070). Il y a cinq messages RID possibles :

  • Request où on demande à un partenaire d'examiner son réseau pour voir d'où venait l'attaque (l'idée est que, partant de celui qui a détecté l'attaque, on envoit des Request successifs en remontant peu à peu vers la source de l'attaque). Le même message sert si on a déjà identifié la source et qu'on veut juste davantage d'information.
  • Report où on transmet de l'information, sans demander d'action immédiate.
  • Query où on demande des détails sur une attaque dont on a entendu parler (les deux derniers types de message sont typiquement pour la communication avec un CSIRT).
  • Acknowledgment et Result servent à porter les résultats intermédiaires ou finaux.

La section 4.2 décrit plus en détail chacun de ces types.

La section 7 fournit plusieurs jolis exemples, que j'ai simplifié ici. Par exemple, une Request envoyé par un CSIRT qui a détecté une DoS et qui demande à un opérateur réseau de tracer l'attaque. Le message est composé d'un document RID puis du document IODEF qui décrit l'attaque :


<iodef-rid:RID> <!-- Le schéma est enregistré en
https://www.iana.org/assignments/xml-registry/ns.html -->
  <iodef-rid:RIDPolicy MsgType="TraceRequest" 
                       MsgDestination="RIDSystem">
    <iodef:Node>
      <iodef:Address category="ipv4-addr">192.0.2.3</iodef:Address>
    </iodef:Node>
    <iodef-rid:TrafficType type="Attack"/>
    <iodef:IncidentID name="CERT-FOR-OUR-DOMAIN">
      CERT-FOR-OUR-DOMAIN#207-1
    </iodef:IncidentID>
  </iodef-rid:RIDPolicy>
</iodef-rid:RID>
<!-- IODEF-Document accompanied by the above RID -->
<iodef:IODEF-Document>
  <iodef:Incident restriction="need-to-know" purpose="traceback">
    <iodef:DetectTime>2004-02-02T22:49:24+00:00</iodef:DetectTime>
    <iodef:StartTime>2004-02-02T22:19:24+00:00</iodef:StartTime>
    <iodef:ReportTime>2004-02-02T23:20:24+00:00</iodef:ReportTime>
    <iodef:Description>Host involved in DOS attack</iodef:Description>
    <iodef:EventData>
      <iodef:Flow>
        <iodef:System category="source">
          <iodef:Node>
            <iodef:Address category="ipv4-addr">192.0.2.35
...

Et la première réponse, qui indique que la demande de traçage a été approuvée :


<iodef-rid:RID>
  <iodef-rid:RIDPolicy MsgType="RequestAuthorization"
                       MsgDestination="RIDSystem">
    <iodef-rid:TrafficType type="Attack"/>
  </iodef-rid:RIDPolicy>
  <iodef-rid:RequestStatus AuthorizationStatus="Approved"/>
</iodef-rid:RID>

Et enfin la réponse finale :


<iodef-rid:RID>
  <iodef-rid:RIDPolicy MsgType="Result"
                       MsgDestination="RIDSystem">
    <iodef:Node>
      <iodef:Address category="ipv4-addr">192.0.2.67</iodef:Address>
    </iodef:Node>
    <iodef-rid:TrafficType type="Attack"/>
    <iodef:IncidentID name="CERT-FOR-OUR-DOMAIN">
      CERT-FOR-OUR-DOMAIN#207-1
    </iodef:IncidentID>
  </iodef-rid:RIDPolicy>
  <iodef-rid:IncidentSource>
    <iodef-rid:SourceFound>true</iodef-rid:SourceFound>
    <iodef:Node>
      <iodef:Address category="ipv4-addr">192.0.2.37</iodef:Address>
    </iodef:Node>
  </iodef-rid:IncidentSource>
</iodef-rid:RID>
<!-- IODEF-Document accompanied by the above RID -->
<iodef:IODEF-Document>
  <iodef:Incident restriction="need-to-know" purpose="traceback">
    <iodef:IncidentID name="CERT-FOR-OUR-DOMAIN">
      CERT-FOR-OUR-DOMAIN#207-1
    </iodef:IncidentID>
    <iodef:DetectTime>2004-02-02T22:49:24+00:00</iodef:DetectTime>
    <iodef:StartTime>2004-02-02T22:19:24+00:00</iodef:StartTime>
...
      <iodef:Expectation severity="high" action="rate-limit-host">
        <iodef:Description>
          Rate limit traffic close to source
        </iodef:Description>
      </iodef:Expectation>
      <iodef:Record>
        <iodef:RecordData>
          <iodef:Description>
            The IPv4 packet included was used in the described attack
          </iodef:Description>
          <iodef:RecordItem dtype="ipv4-packet">450000522ad9
          0000ff06c41fc0a801020a010102976d0050103e020810d9
          4a1350021000ad6700005468616e6b20796f7520666f7220
          6361726566756c6c792072656164696e6720746869732052
          46432e0a
          </iodef:RecordItem>
        </iodef:RecordData>
      </iodef:Record>
    </iodef:EventData>
    <iodef:History>
      <iodef:HistoryItem>
        <iodef:DateTime>2004-02-02T22:53:01+00:00</iodef:DateTime>
        <iodef:IncidentID name="CSIRT-FOR-OUR-DOMAIN">
          CSIRT-FOR-OUR-DOMAIN#207-1
        </iodef:IncidentID>
        <iodef:Description>
          Notification sent to next upstream NP closer to 192.0.2.35
        </iodef:Description>
      </iodef:HistoryItem>
      <iodef:HistoryItem action="rate-limit-host">
        <iodef:DateTime>2004-02-02T23:07:21+00:00</iodef:DateTime>
        <iodef:IncidentID name="CSIRT-FOR-NP3">
          CSIRT-FOR-NP3#3291-1
        </iodef:IncidentID>
        <iodef:Description>
          Host rate limited for 24 hours
        </iodef:Description>
      </iodef:HistoryItem>
    </iodef:History>
  </iodef:Incident>
</iodef:IODEF-Document>

L'entièreté du schéma XML, en xsd, figure en section 5.

Comme déjà noté, l'utilisation de ces messages RID ne va pas sans risques. La section 9 les analyse. D'abord, il faut évidemment un canal sécurisé pour les transmettre. Sécurisé au sens de :

  • Confidentiel, puisque les informations RID peuvent être très sensibles,
  • Fiable (disponible), puisque l'attaque rendra peut-être inutilisable les canaux normaux,
  • Authentifié, parce que ceux à qui on demande d'agir sur la base de messages RID voudront savoir à qui ils ont affaire.

Un canal physique dédié faciliterait l'obtention de ces propriétés mais n'est pas forcément réaliste. Le RFC recommande donc plutôt un tunnel chiffré. En combinant TLS sur le tunnel et les signatures XML du RFC 3275 sur le message, on atteint la sécurité désirée. Le protocole exact utilisé est normalisé dans un autre document, le RFC 6546. Bien qu'il utilise le chiffrement, RID ne repose pas uniquement sur la sécurité du canal et permet de chiffrer aussi le message par le chiffrement XML.

RID soulève aussi des questions liées à la protection de la vie privée et la section 9.5 les étudie. RID fournit le moyen de spécifier des détails comme l'extension du « domaine de confiance » à qui on peut envoyer les informations (élément PolicyRegion, section 4.3.3.3).


Téléchargez le RFC 6545


L'article seul

RFC 6544: TCP Candidates with Interactive Connectivity Establishment (ICE)

Date de publication du RFC : Mars 2012
Auteur(s) du RFC : J. Rosenberg (Skype), A. Keranen (Ericsson), B. Lowekamp (Skype), A. Roach (Tekelec)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF mmusic
Première rédaction de cet article le 20 mars 2012


Le protocole ICE, normalisé dans le RFC 8445, permet de traverser des obstacles comme les routeurs NAT, en essayant plusieurs techniques successives. ICE fonctionne en proposant une liste d'adresses candidates et en testant ensuite ces candidates (avec STUN, notamment) jusqu'à ce qu'on en trouve une qui passe. Dans le RFC originel sur ICE, ces candidates ne pouvaient être testées qu'en UDP. Désormais, notre RFC 6544 permet des candidates TCP (ainsi qu'un mélange des deux).

ICE vise surtout les applications pair-à-pair notamment pour le multimédia (par exemple, pour la télé-conférence). Pourquoi est-ce important de pouvoir faire du TCP ? La section 1 rappelle que certains protocoles ne marchent qu'avec TCP (comme le MSRP du RFC 4975) et que certains protocoles ont certes la possibilité d'utiliser UDP mais peuvent choisir TCP dans certains cas (RTP, RFC 4571, par exemple). C'est évidemment surtout utile dans le cas où on utilise TURN (RFC 5766), protocole qui est parfois le seul à passer certains routeurs NAT, en utilisant un relais TCP.

En général, pour les protocoles qui se servent d'ICE, UDP sera préférable (l'annexe A explique pourquoi). Dans les autres cas, ce nouveau RFC leur permet de faire enfin du TCP. (Et cette possibilité est désormais enregistrée à l'IANA.)

La section 3 résume les changements dans ICE liés à ce nouveau service. Mais c'est assez simple. Il y a trois sortes de candidats TCP, les actifs (qui vont ouvrir la connexion eux-mêmes), les passifs (qui attendent) et les S-O (Simultaneous Open) qui peuvent faire les deux. Dans la liste testée, le type du candidat est indiqué et ICE, pour tester une adresse, va évidemment les apparier en fonction du type (une adresse active avec une passive mais pas avec une autre active, par exemple). Le reste sera fait par de l'ICE normal, comme en UDP. Un petit piège : les messages STUN utilisés par ICE sont sur le même port que le trafic applicatif. Pour un protocole à messages comme UDP, il fallait donc marquer les messages pour les distinguer du trafic STUN. Pour un protocole à flot continu de données, comme TCP, il a fallu introduire un marquage, celui du RFC 4571 (conçu pour RTP mais qui peut être utilisé avec tout flot TCP).

Les détails de l'offre initiale figurent en section 4, par exemple la priorité accordée à UDP, lorsque le choix existe. S'il n'existe pas, on utilisera TCP, avec une adresse active, qui a plus de chances de pouvoir sortir du NAT.

Comme avec UDP, l'offre d'adresses candidates est encodée en SDP, avec un nouvel attribut pour différencier les adresses utilisées en TCP selon qu'elles soient actives ou passives. L'annexe C du RFC contient plusieurs exemples de descriptions SDP, par exemple, pour un appel audio :

   v=0
   o=jdoe 2890844526 2890842807 IN IP4 10.0.1.1
...
   m=audio 45664 TCP/RTP/AVP 0
...
   a=connection:new
   a=candidate:1 1 TCP 2128609279 10.0.1.1 9 typ host tcptype active
   a=candidate:2 1 TCP 2124414975 10.0.1.1 8998 typ host tcptype passive
   a=candidate:3 1 TCP 2120220671 10.0.1.1 8999 typ host tcptype so
...

Cet exemple ne montre que des candidats TCP, un de chaque sorte.

Et comment trouver toutes les adresses candidates possibles ? La section 5 donne quelques idées. Attention, plus il y a de candidates, et comme il faut tester chaque couple possible source/destination, plus les tests seront longs.

Les fanas de programmation noteront l'annexe B, qui explique que les opérations à effectuer avec ICE ne correspondent pas tout à fait à l'utilisation habituelle des sockets. Notamment, il s'agit, sur la même socket, d'initier des nouvelles connexions (vers le serveur STUN) et d'en recevoir (depuis les pairs distants). Le pseudo-code suivant est suggéré :

for i in 0 to MAX
      sock_i = socket()
      set(sock_i, SO_REUSEADDR)
      bind(sock_i, local) /* Réserver les "sockets" et les lier à un
      port */

   listen(sock_0)
   connect(sock_1, stun)
   connect(sock_2, remote_a)
   connect(sock_3, remote_b)

Téléchargez le RFC 6544


L'article seul

RFC 6541: DKIM Authorized Third-Party Signers

Date de publication du RFC : Février 2012
Auteur(s) du RFC : M. Kucherawy (Cloudmark)
Expérimental
Première rédaction de cet article le 1 mars 2012


Depuis la sortie de la norme DKIM d'authentification du courrier électronique (originellement RFC 4871, désormais RFC 6376), il y a des incompréhensions sur ce que DKIM garantit réellement. Beaucoup d'utilisateurs croient que, lorsqu'un message prétend venir de joe@example.net et qu'il est signé par DKIM, on peut être sûr que le message vient de joe@example.net. Rien n'est plus faux. DKIM garantit tout autre chose. Il dit que l'identité du domaine signeur, dans le champ DKIM-Signature:, est correcte, et que ce domaine prend la responsabilité du message. Résultat, il y a un fossé entre ce qu'espère l'utilisateur et ce que DKIM livre effectivement. Ce RFC expérimental propose une solution pour combler ce fossé.

Voici une signature DKIM typique, envoyée par le service 23andme :


From: 23andMe Research Team <donotreply@23andme.com>
...
DKIM-Signature: v=1; q=dns/txt; a=rsa-sha256; c=relaxed/relaxed; s=132652; d=23andme.ccsend.com;
        h=to:subject:mime-version:message-id:from:date:sender:list-unsubscribe:reply-to;
        bh=87HtUCQR/Puz+14IeKPwOPzfeG32vY3BDJBMB74Kv+w=;
        b=Omftsz+Y3ZbbSbaPWZadKuy8aP35ttpXKTTPdjY4VGttx82q5igLb2r14U3sFI7a+9OXpKODHqOC3HKz1hPQ3GW1L...

On y voit que le domaine 23andme.ccsend.com prend la responsabilité de ce message (on peut vérifier l'authenticité de cette déclaration en vérifiant cryptographiquement la signature, qu'on a récupéré dans le DNS, pour le nom 132652._domainkey.23andme.ccsend.com) mais que le message dit avoir été envoyé par 23andme.com. Peut-on vérifier cette prétention ? Non, pas avec DKIM. Celui-ci ne fournit, et c'est un choix de conception délibéré, aucun mécanisme pour lier la signature à l'« identité » de l'émetteur (notez au passage que le concept d'identité d'un émetteur de courrier est déjà très flou).

Notre RFC 6541 propose un moyen de faire cette liaison : un domaine peut publier dans le DNS qu'il autorise des tiers à signer ses messages et à les garantir ainsi.

DKIM permettait déjà de déléguer la signature à des tiers (RFC 6376, sections 2.6 et 3.5) mais pas de dire « je fais entièrement confiance à tel domaine pour signer mes messages). C'est ce que fournit cette nouvelle norme, ATPS (Authorized Third-Party Signers).

Quels sont les parties en présence (sections 2 et 3) ?

  • L'émetteur du message est celui dont le domaine apparait dans le From: du message (RFC 5322).
  • Le signeur est un tiers autorisé à signer avec DKIM. Il met son propre domaine dans le champ d= de la signature.
  • Le vérificateur est le récepteur du message, qui voudrait bien vérifier que le message vient effectivement du domaine de l'émetteur.

Dans le monde réel, l'émetteur va par exemple être une entreprise avec une infrastructure de messagerie sommaire, ne permettant pas de signer, et le signeur ATPS va être son sous-traitant. Pour faire connaître cette relation d'affaires entre l'émetteur et son sous-traitant, ATPS permet à l'émetteur de publier dans le DNS un enregistrement TXT annonçant ce lien. Le vérificateur pourra alors récupérer cet enregistrement et se dire « le message est signé par provider.example, le message prétend être émis par customer.example, or le domaine customer.example contient bien un enregistrement ATPS désignant provider.example comme signeur autorisé  »

La section 4 contient les détails techniques du protocole. D'abord, quel va être le nom de l'enregistrement TXT dans le domaine émetteur ? (Au fait, l'annexe B explique pourquoi utiliser TXT et pas un nouveau type.) Il peut être directement le nom du domaine du signeur mais aussi une version encodée de ce nom. Ensuite, que contient la signature DKIM en cas d'utilisation d'ATPS ? Deux nouveaux champs, atps= et atpsh= (désormais dans le registre IANA) apparaissent. Si le champ d= contiendra, comme avant, le nom de domaine du signeur, le nouveau champ atps= contiendra le nom de domaine de celui pour lequel on signe, l'émetteur. Le vérificateur testera si la valeur d'atps= correspond à l'en-tête From: (ATPS est ignoré s'ils ne correspondent pas), fait une requête DNS pour le type TXT, et vérifie qu'on obtient bien une réponse positive.

Le nom de domaine interrogé pour le type TXT est, dans le cas le plus simple, le DOMAINE-SIGNEUR._atps.DOMAINE-ÉMETTEUR. Si atpsh= contient autre chose que none, alors DOMAINE-SIGNEUR est remplacé par un condensé de son nom.

S'il y a une réponse positive, c'est-à-dire un enregistrement TXT, c'est que c'est bon (pour plus de sécurité, l'enregistrement TXT doit contenir d=DOMAINE-SIGNEUR). Si on récupère NXDOMAIN (nom non existant) ou bien NOERROR mais pas d'enregistrement TXT, c'est que la vérification a échoué. Le signeur n'est en fait pas autorisé à signer pour l'émetteur (section 5). Le vérificateur peut prendre une décision comme de mettre un résultat d'authentification dans les en-têtes du message (cf. section 8.2 pour la création d'un nouveau type d'authentification, dkim-atps, mis dans le registre IANA nomalisé par le RFC 7001).

Et les ADSP (Author Domain Signing Practices) du RFC 5617 ? Ce protocole permet à un domaine émetteur d'annoncer si ses messages sont signés ou non avec DKIM. La section 6 de notre RFC prévoit qu'ATPS doit être testé avant ADSP.

Ce RFC est seulement expérimental. L'idée même d'ATPS est fortement contestée (les questions de sécurité et de confiance sont toujours sensibles...) et le besoin s'est fait sentir d'un essai en vrai, pour déterminer si ATPS marche bien ou pas. ATPS est déjà mis en œuvre dans OpenDKIM (il faut configurer avec les options --enable-atps --enable-xtags), bibliothèque utilisée notamment par sendmail. Il inclut même un outil pour générer les enregistrements TXT. Les auteurs d'ATPS ont promis de tester et de décrire dans un document ultérieur le résultat de ces tests.

Quelques points particuliers de sécurité (section 9) :

  • La condensation des noms des domaines signeurs avant de faire la requête DNS ne vise pas à fournir la moindre confidentialité, mais simplement à obtenir des noms de taille fixe et connue, ce qui est plus pratique pour les requêtes DNS.
  • Et, naturellement, publier un enregistrement ATPS revient à sous-traiter une partie de sa sécurité au signeur. Comme toute sous-traitance, il faut donc bien vérifier à qui on fait confiance.

Notez que le RFC ne fournit pas un seul exemple complet de signature avec ATPS et je n'en ai pas encore trouvé dans ma boîte aux lettres.


Téléchargez le RFC 6541


L'article seul

RFC 6540: IPv6 Support Required for all IP-capable Nodes

Date de publication du RFC : Avril 2012
Auteur(s) du RFC : W. George (Time Warner Cable), C. Donley (Cablelabs), C. Liljenstolpe (Telstra), L. Howard (Time Warner Cable)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF intarea
Première rédaction de cet article le 13 avril 2012


Il y a plusieurs façons de présenter ce RFC qui décrète que toute machine IP doit être capable de faire de l'IPv6. Le meilleur angle, je trouve, est de dire que c'est un RFC contre la publicité mensongère : dans l'Internet d'aujourd'hui, IP ne veut plus seulement dire IPv4. Vendre une machine ou un logiciel comme étant capable de parler IP, alors qu'elle ou il ne fait pas d'IPv6 est mensonger.

Bien sûr, en pratique, il est peu probable que ce RFC change grand'chose : les vendeurs continueront à fourguer des produits incapables de parler IPv6, protocole pourtant normalisé depuis seize ans, avec la sortie du RFC 1883 (depuis remplacé par le RFC 2460). Mais, au moins, ils ne pourront plus dire qu'il y avait une ambiguité et que certains RFC anciens parlent de « IP » pour désigner IPv4. Désormais, il est clair que « IP » veut dire IPv6 et (bien que le RFC ne le spécifie pas), si on est seulement IPv4, cela doit être annoncé comme tel et non pas sous l'étiquette « IP ».

Le succès d'IPv4 est incontestable. Il est désormais déployé absolument partout, malgré les vigoureuses oppositions des telcos traditionnels, relayés par pas mal de gouvernements (souvenez-vous des ridicules campagnes de promotion de l'ATM, censé barrer la route à IP). Mais c'est ce succès même qui a condamné IPv4. Le stock d'adresses disponibles est désormais épuisé. Un certain nombre de techniques ont été développées par acharnement thérapeutique, pour essayer de gagner encore quelques années, comme le NAT444. Toutes ont de sérieux inconvénients (cf. RFC 6269 pour un exemple).

La solution correcte, qui évite de fragiliser l'Internet par l'empilement de techniques de transition et/ou de coexistence est donc de déployer IPv6. Mais cela ne s'est pas fait tout seul. L'absence, ou la mauvaise qualité, de mise en œuvre d'IPv6 dans les logiciels a longtemps retardé ce protocole. Beaucoup de fournisseurs de logiciels se sont comportés comme si « IP » se réduisait à IPv4, IPv6 étant une addition possible mais facultative. Pendant de nombreuses années, Cisco exigeait une licence supplémentaire payante pour l'activation d'IPv6 dans IOS... Bref, des engins étaient vendus comme « IP » alors qu'ils n'étaient qu'« IPv4 ». Le problème continue aujourd'hui, empêchant la migration de progresser.

C'est particulièrement gênant dans le domaine des équipements proches du consommateur : ce dernier, à juste titre, ne se soucie pas de la version du protocole IP installé. IPv6 a été conçu justement pour ne pas changer le modèle de fonctionnement d'IP et il n'y a donc aucun avantage, pour M. Toutlemonde, à migrer vers IPv6. La migration, décision technique, ne devrait pas dépendre d'un choix explicite du consommateur, surtout si on le fait payer pour cela, comme le faisait Cisco. La migration devrait se faire au fur et à mesure que les vieilles machines et vieux logiciels sont remplacés, sans que M. Toutlemonde ne s'en rende compte.

À la décharge des vendeurs, il faut noter que tous les RFC, même ceux encore en vigueur, ne sont pas clairs là-dessus. Par exemple, le RFC 1812, qui établit les règles pour les routeurs IPv4, utilise souvent le terme IP pour désigner IPv4. Même chose pour le RFC 1122, qui normalise les machines terminales et ne mentionne pas IPv6. Aujourd'hui, le terme « IP », dans un RFC, peut indiquer IPv4 seul, IPv6 seul ou bien les deux.

À noter qu'IPv6 a aussi ses RFC de résumé des exigences, comme les RFC 4294 et RFC 7084.

La section 2 de notre RFC pose donc la règle : « IP implique IPv6 ». Plus précisément :

  • Les nouvelles mises en œuvre d'IP (ou les mises à jour majeures) doivent inclure IPv6.
  • La qualité du support IPv6 doit être égale ou supérieure à celle d'IPv4. On en est très loin aujourd'hui : poussés par des cahiers des charges qui exigent IPv6, certains vendeurs ajoutent un support minimum, permettant de cocher la case « IPv6 » lors de la réponse à un appel d'offres, mais en fournissant du logiciel bogué et lent.
  • L'activation ou la configuration d'IPv4 ne doit pas être nécessaire.

Évidemment, ce n'est qu'un RFC. Bien des vendeurs l'ignoreront. Espérons toutefois qu'il contribuera à une meilleure information des consommateurs.

Ce document était loin d'être consensuel à l'IETF. Beaucoup de gens critiquaient le principe même d'un document d'exhortation, qui risque fort de n'être qu'un rappel de plus. Toutefois, les partisans de ce document étaient actifs et les opposants ne voyaient pas d'inconvénients graves à la publication.


Téléchargez le RFC 6540


L'article seul

RFC 6538: HIP Experiment Report

Date de publication du RFC : Mars 2012
Auteur(s) du RFC : T. Henderson (Boeing), A. Gurtov (HIIT)
Pour information
Réalisé dans le cadre du groupe de recherche IRTF hiprg
Première rédaction de cet article le 25 mars 2012


Le protocole HIP, normalisé dans le RFC 4423, est maintenant stable depuis des années et a fait l'objet de plusieurs essais sur le terrain. Ce RFC de l'IRTF documente certains de ces essais concrets et indique les leçons à en tirer.

Le groupe de recherche hip de l'IRTF a travaillé sur ce sujet de 2004 à 2009. Pendant cette période, un certain nombre de mises en œuvre de HIP ont été programmées et plusieurs bancs de test ont été montés. La section 7 du RFC donne une liste exhaustive des expériences menées, notamment chez Boeing et dans le projet InfraHIP, qui gère des serveurs HIP publics. (Notez que, HIP fonctionnant au dessus d'IP, deux machines HIP peuvent communiquer au dessus de l'Internet public sans problème.) Ce RFC est le compte-rendu de ces expériences, sur les points suivants :

  • Implémenter HIP, qu'est-ce que ça coûte, comme efforts ?
  • Déployer HIP, quels sont les problèmes ?
  • Une fois que HIP marche, quelles conséquences pour les applications ?
  • Qu'en pensent les opérateurs ?
  • Et la vie privée, que va-t-elle devenir ?

D'abord, la mise en œuvre (section 2). HIP est un protocole pour les machines terminales, pas pour les routeurs. Implémenter HIP, c'est donc modifier Linux ou Windows, sans toucher à ses Cisco ou D-Link. Il existe aujourd'hui trois de ces modifications sous une licence libre :

L'expérience montre bien qu'implémenter un nouveau protocole n'est pas du yakafokon et que plein de pièges insoupçonnés se cachent dans le code. La section 2.1 résume ce qu'il faut modifier au noyau pour intégrer HIP. Les applications fonctionnent comme avant, un HIT (le condensat cryptographique d'une clé HIP) ayant la même forme qu'une adresse IPv6 (avec le préfixe ORCHID du RFC 4843). En section 2.2, c'est le cas d'une implémentation en dehors du noyau qui est couvert (notez que certaines mises en œuvre d'HIP sont mixtes, par exemple avec le traitement des paquets dans le noyau et la cryptographie dans un démon à part). Cela permet de faire fonctionner HIP sur des systèmes qu'on n'a pas le droit de modifier comme Microsoft Windows.

Dans tous les cas, quels ont été les problèmes rencontrés ? En l'absence de système de résolution, manipuler les HIT à la main, se les échanger, etc, a été pénible. Des systèmes de résolution existent désormais (mettre les HIT dans le DNS sous forme d'enregistrements AAAA, comme le propose le RFC 5205, utiliser une DHT dédiée à HIP, etc) et OpenHIP les a tous programmés. Et il y a aussi le mode opportuniste de HIP, où on se connecte sans connaître a priori le HIT du pair. Mais aucune solution n'est à 100 % parfaite.

Le mode opportuniste du RFC 5201, section 4.1.6 a posé des problèmes avec l'interface sockets, car le HIT du pair distant n'est pas encore connu au moment du connect(). De toute façon, ce mode a l'inconvénient de ne pas être très sécurisé (il fonctionne en mode TOFU - Trust On First Use - puisque, la première fois qu'on parle à un pair, on doit accepter son HIT en lui faisant une confiance aveugle). HIPL a mis en œuvre ce mode. OpenHIP également, avec une option explicite (-o), débrayée par défaut. Le problème de sécurité est particulièrement crucial lorsqu'il s'agit d'applications traditionnelles, qui ne connaissent pas HIP et ne peuvent donc pas formuler de souhaits, ou interactivement demander confirmation à l'utilisateur, ce que peuvent faire les applications récentes qui utilisent le RFC 6317.

Quant au DNS, certains administrateurs de zones DNS n'ont pas aimé qu'on mette des HIT sous le nom d'AAAA, arguant que c'était un détournement de la sémantique du AAAA.

Autre problème, lorsqu'on connait le HIT du pair (on ne fait donc pas de mode opportuniste) mais pas son adresse IP. Pour lui envoyer des paquets, il faudra alors une résolution, pour trouver cette adresse. Des essais ont été faits avec OpenDHT, ou bien avec le DNS. HIPL a même tenté, pour le cas particulier du LAN, d'envoyer un paquet de diffusion, un peu comme on fait en NDP. Cela a paniqué certains antivirus Windows qui considéraient toute diffusion avec un protocole inconnu comme un danger.

Parmi les nombreuses autres questions que décrit le RFC en tenant compte de l'expérience des programmeurs HIP, celui de la gestion des HI (Host Identifiers, l'identité d'une machine HIP, dont le HIT est le condensat cryptographique). Une machine peut avoir plusieurs identités (par exemple pour protéger la vie privée, voir plus loin), et laquelle doit-elle utiliser lorsqu'elle se connecte à un pair ? Dans quelle mesure le choix doit-il être fait par l'utilisateur ? (Intéressant problème d'interface.) Plus gênant, puisque HIP repose sur des clés cryptographiques, comment stocker les clés privées sur la machine ? Toutes les implémentations actuelles utilisent un fichier appartenant à root en mode 0600 (ce qui interdit la lecture par les utilisateurs ordinaires). Cela ne suffit pas si, par exemple, un attaquant a un accès physique à la machine. La solution serait alors de stocker les clés dans un TPM mais aucune mise en œuvre de HIP n'a encore tenté le coup.

Cette section comprend également un problème qui, à mon avis, est plutôt de déploiement que de programmation, l'interaction avec les pare-feux. HIP est un protocole (le numéro 139 des protocoles IP, TCP étant 6, UDP 17 et OSPF 89) marqué comme expérimental et qui est globalement peu connu. Il n'y a donc pas de règle pour lui dans les règles configurées par défaut et le pare-feu refusant tout ce qui n'est pas explicitement autorisé, les paquets HIP se retrouvent bloqués. Il n'est pas forcément trivial de modifier les règles sans tout casser (le RFC rapporte que celles par défaut de SUSE ont plus de cent entrées) et, de toute façon, l'utilisateur qui veut déployer HIP n'a pas forcément le contrôle du pare-feu. Heureusement, HIP peut tourner sur UDP (au lieu de directement sur IP) ce qui limite les problèmes.

Bien que HIP ait été surtout conçu pour IPv6, et que son déploiement massif ne semble pas devoir précéder celui d'IPv6, toutes les mises en œuvre de HIP ont choisi de gérer également IPv4. Comme on ne peut absolument pas faire rentrer un condensat cryptographique sérieux dans les 32 bits d'une adresse IPv4, il faut ajouter le concept de LSI (Local Scope Identifier), un alias local à la machine pour référencer un HI donné.

Plus amusant, HIP permet également de faire tourner des applications IPv6 sur un réseau IPv4 (et réciproquement), ce qui fonctionne sur tous les codes cités.

Bref, les programmeurs ont bien travaillé et HIP fonctionne sur plusieurs plate-formes. Quelles leçons peuvent être tirées ? Il n'y a pas eu beaucoup de tests de performances, notamment pour comparer les implémentations en mode noyau et en mode utilisateur. Il semble que, sur une machine généraliste et pour des usages typiques, le mode utilisateur (le plus lent) est acceptable.

Le choix entre les deux modes peut dépendre de bien d'autres choses. Par exemple, HIPL avait une mise en œuvre des fonctions de gestion de clés dans le noyau, mais les développeurs du noyau Linux l'ont rejeté, arguant que d'autres protocoles comme IKE faisaient cette gestion en mode utilisateur et qu'il n'y avait pas de raison de l'intégrer dans le noyau. (Il faut dire aussi que c'était un gros patch, qui touchait à beaucoup d'endroits du noyau.)

La section 3 aborde ensuite les points liés au déploiement, notamment à l'effet sur les infrastructures. La section sur le DNS (extensions HIP du RFC 5205) est curieusement incompréhensible (qu'est-ce qu'un binary blob format ?) mais, de toute façon, les serveurs DNS peuvent servir des types de données qu'il ne connaissent pas, donc peu de problèmes à attendre.

Plus sérieux, le cas des middleboxes. Les NAT sont hostiles à HIP comme à beaucoup de choses (problème décrit dans le RFC 5207). HIP peut par exemple chiffrer même la connexion initiale, empêchant le routeur NAT de comprendre ce qui se passe. Le mécanisme de rendez-vous du RFC 5204 pourrait aider à résoudre les problèmes du NAT mais il n'a pour l'instant été testé qu'en laboratoire.

Et l'infrastructure de résolution ? Une mise en œuvre de résolution de HIT en adresses IP via OpenDHT a été faite pour HIPL et OpenHIP. OpenDHT est désormais arrêté mais un nouveau projet a pris le relais, Hi3, qui tourne sur PlanetLab. Au cours des premiers essais, le débogage s'est révélé très pénible, et les middleboxes qui bloquent tout une énorme source de frustration.

Une solution d'avenir pourrait être de mêler DNS (déploiement massif, compatibilité avec le logiciel existant) et DHT (bonne résistance aux pannes, bonne efficacité même dans un espace plat, celui des clés cryptographiques). Par exemple, une organisation ferait tourner une DHT pour stocker les HI ou les HIT de ses machines, connectée avec le DNS pour les clients extérieurs. Ensuite, ces DHT locales pourraient être interconnectées petit à petit. Un test a été fait en modifiant BIND pour qu'il interroge une DHT (Bamboo) pour les HIT. Les performances ont été plutôt mauvaises, et se dégradant vite avec la charge, donc des travaux supplémentaires sont nécessaires.

Et pour les applications  ? L'expérience du déploiement d'IPv6 a montré qu'il était plus facile de mettre à jour l'infrastructure que les applications. La section 4 explore les conséquences de HIP sur celles-ci. Il y a deux sortes d'applications : celles qui connaissent HIP et celles qui ne le connaissent pas (la quasi-totalité, aujourd'hui : le RFC 5338 explique comment faire tourner HIP avec les applications traditionnelles).

Par exemple, HIPL a testé une bibliothèque dynamique (chargée avec LD_PRELOAD) qui change le comportement du résolveur, permettant aux applications de se connecter à un pair HIP sans s'en rendre compte. Un Firefox et un Apache non modifiés ont ainsi pu se parler en HIP. L'avantage de cette méthode est de permettre de choisir, application par application, qui va faire du HIP (cette finesse de choix pouvant être considérée comme un avantage ou comme un inconvénient). Une autre solution serait de passer par des relais applicatifs mais elle ne semble pas avoir été testée encore.

HIP a même réussi à fonctionner avec des applications qui utilisent des références (passer son adresse IP au pair pour qu'il vous envoie ensuite des messages) comme FTP. D'autres applications seraient peut-être moins tolérantes mais, de toute façon, en raison du NAT, les applications qui se servent de références ont déjà beaucoup de problèmes dans l'Internet d'aujourd'hui.

Une des raisons pour lesquelles il peut être intéressant de mettre une gestion de HIP explicite dans les applications est la performance : l'établissement d'une connexion est plus long en HIP et certaines applications (par exemple un navigateur Web) peuvent être très sensibles à cette latence supplémentaire. Elles pourraient alors choisir de laisser tomber la sécurité de HIP au profit de la vitesse.

Continuons dans les problèmes concrets : quelle va être l'expérience de l'administrateur réseaux qui, le premier, tentera de déployer HIP ? Pour l'instant, aucun ne l'a fait mais. HIP peut tourner entièrement dans les machines terminales, sans que le réseau soit impliqué. Si celui-ci l'est, il aura peut-être les problèmes suivants (détaillés en section 5) :

  • Choix des HI (Host Identities). Celles-ci peuvent être générées par les machines toutes seules, et c'est comme cela que tout le monde fait aujourd'hui. Mais certains administrateurs pourraient préférer le faire eux-même, de manière à connaître les HI de leur réseau. Par exemple, ils généreraient les HI, les signeraient éventuellement avec leur PKI, et les mettraient dans une base AAA, exportant ensuite la configuration d'équipements comme les pare-feux.
  • Le monde étant ce qu'il est, la sécurité que fournit HIP, surtout en combinaison avec le mode ESP d'IPsec (qui est très intégrée à HIP) peut ne pas plaire à tout le monde. Si Big Brother veut espionner le trafic, que va pouvoir dire l'administrateur réseaux ? Le groupe de recherche HIP n'a pas trouvé de solution à ce dilemne.
  • Autre question posée par le chiffrement, celui de la consommation de ressources, notamment pour les engins les moins pourvus comme les smartphones. Toutefois, au cours d'essais HIP et ESP avec une tablette Nokia N770, les performances sont restées acceptables (3,27 Mb/s en WiFi contre 4,86 sans HIP ni ESP). Le RFC ne dit pas quelle a été la consommation électrique....
  • Autre problème typique d'administrateur réseaux, le filtrage. Aujourd'hui, le filtrage va souvent contre la sécurité, par exemple bien des pare-feux bloquent IPsec ou HIP. Normalement, HIP améliore la sécurité puisqu'on peut authentifier les HI (les identités des machines, celles-ci signant leurs paquets). Il ne reste plus qu'à configurer les ACL du pare-feu pour filtrer en fonction du HI. Notons que, contrairement aux adresses IP, celles-ci ne sont pas agrégeables en préfixes et il faut donc typiquement une ACL par machine. Quant au filtrage par nom et plus par HI, il dépend d'un enregistrement sécurisé des HI dans le DNS, qui n'est pas disponible à l'heure actuelle.
  • Ceci n'a pas empêché l'université de Technologie d'Helsinski de modifier iptables pour produire un pare-feu HIP. Cela nécessite un état car le pare-feu doit se souvenir de l'échange initial HIP pour reconnaître ensuite les paquets chiffrés liés à cette session (le SPI IPsec figure dans les paquets HIP I2 et R2).

La section 6 du RFC s'attaque ensuite à un difficile problème, celui de la vie privée des utilisateurs. HIP permet enfin de doter chaque machine sur l'Internet d'une véritable identité, indépendante de sa position dans le réseau, qu'on peut vérifier avec la cryptographie. Mais ce gain en sécurité peut se payer en terme de vie privée : si mon ordinateur portable a HIP, je me connecte à un site Web HIP depuis chez moi, et depuis l'hôtel et, sans cookies ou autres techniques de suivi Web, le serveur peut reconnaitre que c'est la même machine (les adresses autoconfigurées d'IPv6 avaient un problème du même genre, qui a été résolu par le RFC 4941).

Pire, dans certains cas, un tiers qui écoute le réseau peut apprendre l'identité des deux machines, même si le reste de la session est chiffré.

HIP permet d'utiliser des HIT non publiés (RFC 5201, sections 5.1.2 et 7) mais cela suppose que le destinataire les accepte (ce qui serait logique pour un serveur public, qui ne se soucie pas en général de l'identité de ses clients). Globalement, la protection de la vie privée dans HIP n'est pas encore suffisante mais des travaux sont en cours. Mon opinion personnelle est que la meilleure solution serait analogue à celle du RFC 4941 : des identificateurs jetables, créés pour une courte période (voire pour une seule session) et abandonnés après. Cela nécessite de faire attention aux autres identificateurs (comme l'adresse IP) qui doivent changer en même temps que le HI (sinon, l'attaquant pourrait faire le rapprochement). L'Université Technologique d'Helsinski a déjà une mise en œuvre expérimentale de cette idée.

HIP n'est pas la seule architecture de séparation du localisateur et de l'identificateur. La section 8 du RFC résume les autres expériences en cours. Il ne va pas de soi que cette séparation soit une bonne idée. C'est même un point de vue très controversé, comme l'avait montré l'échec du NSRG (Name Space Research group). Parmi les efforts récents :

  • Les groupes de travail multi6 et shim6 qui ont mené au RFC 5533, solution qui a des ressemblances avec HIP (d'ailleurs, OpenHIP implémente à la fois HIP et shim6), ce qui a permis de concevoir des API proches (RFC 6316 et RFC 6317).
  • Le groupe de recherche RRG a exploré de nombreuses solutions pour le routage de demain, comme LISP ou ILNP, documentant le résultat dans le RFC 6115.

Téléchargez le RFC 6538


L'article seul

RFC 6537: Host Identity Protocol Distributed Hash Table Interface

Date de publication du RFC : Février 2012
Auteur(s) du RFC : J. Ahrenholz (Boeing)
Expérimental
Réalisé dans le cadre du groupe de recherche IRTF hiprg
Première rédaction de cet article le 1 mars 2012


Dans tout protocole réseau séparant le localisateur et l'identificateur, il y a une grosse question : comment relier les deux ? Comment, lorsqu'on ne connait que l'identificateur d'une machine, trouver son localisateur afin de lui envoyer un paquet ? Le protocole HIP a plusieurs solutions possibles et ce RFC de l'IRTF en propose une nouvelle : faire appel à une DHT.

Dans HIP, l'identificateur est la partie publique d'une clé cryptographique, et le localisateur une adresse IP. Notre RFC 6537 propose de stocker la correspondance entre les deux dans une DHT. En outre, un second service est proposé, celui permettant de trouver l'identificateur à partir d'un nom de domaine. En fait, ce RFC ne décrit pas tellement la DHT, mais simplement l'interface entre la machine HIP et un service de résolution (qui pourrait aussi bien être mis en œuvre autrement ; le titre du RFC est donc trompeur).

Pourquoi, d'ailleurs, une DHT ? Comme l'expose la section 1, une des bonnes raisons est que l'espace de nommage des identificateurs est plat : il n'y a pas de hiérarchie permettant des résolutions efficaces comme avec le DNS. Les DHT permettent justement de résoudre des noms situés dans un espace plat aussi efficacement que les protocoles reposant sur des noms hiérarchiques.

Petit détail au passage, le protocole de ce RFC n'utilise pas directement les identificateurs (HI pour Host Identifier) mais leur condensat, le HIT (Host Identifier Tag). Il y a donc deux services, nom->HIT et HIT->adresses.

Le DNS est très optimisé depuis longtemps (et il existe un autre travail en cours pour résoudre les identificateurs HIP en localisateurs avec le DNS) mais explorer de nouvelles techniques est toujours intéressant. Il s'agit donc d'un travail plutôt expérimental, où plein de questions n'ont pas encore de réponse.

Une expérience concrète a été faite en utilisant la DHT Bamboo, écrite en Java, et qui formait la base du service OpenDHT (service qui tournait sur PlanetLab et a été fermé en 2009). Comme toute DHT, ou d'ailleurs comme toute table (les dictionnaires de Python, les hashes de Perl, les java.util.Dictionary de Java, etc), OpenDHT fournissait trois primitives, put, get et remove. La première permet de stocker une valeur, sous un certain index (on dit souvent « clé » mais je l'ai évité pour ne pas risquer une confusion avec les clés cryptographiques), la seconde de récupérer une valeur dont on connait l'index, et la troisième (rm dans la documentation) de supprimer une valeur. Dans OpenDHT, ces trois primitives étaient appelées via le protocole XML-RPC.

La section 2 décrit précisement cette interface XML-RPC. Elle avait été choisie parce qu'OpenDHT fournissait un service simple et gratuit accessible aux chercheurs. Les index pouvaient avoir jusqu'à 20 octets, les valeurs jusqu'à 1024. Toutes les entrées étaient temporaires, OpenDHT les supprimant au plus une semaine après leur insertion (un problème classique des DHT et du pair-à-pair en général est sa vulnérabilité aux méchants, ici à des machines insérant des quantités énormes de données pour faire une DoS).

Outre les paramètres cités plus haut (l'index et la valeur pour put, l'index pour get et rm), OpenDHT imposait quelques autres paramètres comme le TTL du précédent paragraphe, comme un identifiant de l'application, ou comme un mot de passe permettant de fournir un peu de sécurité.

Une fois qu'on a compris l'interface XML-RPC d'OpenDHT et ses paramètres, comment l'utilise-t-on pour HIP ? C'est l'objet de la section 3 et des suivantes. D'abord, on définit en section 3 une structure de données, le HDRR (HIP DHT Resource Record). Son format binaire est le même que celui d'un paquet HIP (RFC 5201, section 5, le HDRR a le numéro 20 dans le registre IANA), c'est-à-dire essentiellement une suite de paramètres encodés en TLV. Il n'a donc rien à voir avec le Resource Record DNS du RFC 5205.

Ces paramètres sont surtout des HI (Host Identifier, identificateurs), des HIT (rappelez-vous que c'est un condensat cryptographique du HI) et des localisateurs (les adresses IP, v4 ou v6). On peut aussi y trouver un certificat, au format du RFC 6253 ou une signature HIP. Ces deux derniers paramètres pourraient, dans une DHT spécialisée, être utilisée pour vérifier que la machine qui enregistre un localisateur pour un identificateur donné est bien autorisée à le faire (cd. RFC 7343, c'est une des forces de HIP, que d'avoir des clés cryptographique comme identificateur, cela permet de signer ses paquets et d'éviter ainsi l'usurpation). Toutefois, cela n'est pas mis en œuvre dans Bamboo, DHT généraliste qui ne sert pas qu'à HIP. Le problème de la DHT spécialisée en HIP est de toute façon plus complexe que cela : par exemple, les vérifications cryptographiques nécessaires faciliteraient une éventuelle attaque par déni de service contre la DHT (HIP évite ce problème par un protocole d'établissement de connexion conçu à cet effet, cf. RFC 5201, section 4.1.1).

Puis, la section 4 décrit le protocole de requête. Il fournit deux services :

  • Étant donné un nom, trouver le HIT. Le nom est typiquement un FQDN. Notez que le RFC 5205 fournit une autre solution à ce problème, en utilisant le DNS.
  • Étant donné un HIT, trouver le ou les localisateurs.

Il n'y a pas de requête directe du nom vers les localisateurs. La première correspondance, nom->HIT, est supposée relativement stable (une machine HIP n'a guère de raisons de changer d'identificateur). La seconde correspondance est typiquement variable, voire très variable en cas de mobilité (RFC 5206).

Le reste, ce sont des détails techniques. Par exemple, l'index utilisé pour la requête à la DHT dans le premier cas n'est pas réellement le nom mais un SHA-1 du nom car les index OpenDHT sont limités à vingt octets. Autre point qu'il a fallu régler, les HIT sont typiquement représentés comme des adresses IPv6 ORCHID (RFC 7343), et donc tous les HIT commencent par les mêmes 28 bits (la longueur du préfixe ORCHID). Pour une DHT, qui utilise un hachage des index pour trouver le nœud responsable du stockage des données correspondantes, cela risquerait de causer une répartition très inégale, certains pairs de la DHT étant plus chargés que d'autres. Lors de la deuxième requête (HIT->localisateurs), on n'utilise donc comme index que les 100 derniers bits du HIT.

Une fois ces détails de syntaxe réglés, la section 5 décrit la chorégraphie des requêtes. D'abord, pour trouver un identificateur (ou bien son HIT) à partir d'un nom de domaine, faut-il utiliser le DNS, comme le prévoit le RFC 5205 ou bien le service DHT décrit dans ce RFC 6537 ? La réponse dépend des cas. Tout le monde n'a pas forcément le contrôle des serveurs de noms du domaine souhaité et, même si c'est le cas, tous les serveurs de noms ne permettent pas forcément d'ajouter des enregistrements DNS de type HIP dans leur domaine (testez avec l'interface de votre hébergeur DNS pour voir...) Donc, la solution DHT est intéressante au moins dans ces cas.

On l'a vu, les localisateurs changent, c'est normal. Quand faut-il faire la requête HI->localisateur ? Si on la fait très à l'avance, les localisateurs seront peut-être usagés lorsqu'on s'en servira. Si on la fait au moment de la connexion, on peut ralentir celle-ci de manière intolérable. Le RFC suggère donc de faire les requêtes à l'avance, et, si la première tentative de connexion échoue, de refaire une requête de résolution avant de tenter la deuxième connexion.

Les informations enregistrées dans OpenDHT ont une durée de vie (le paramètre ttl de la requête, mais la DHT peut aussi supprimer les données avant l'expiration de celui-ci, par exemple s'il faut faire de la place). Une machine HIP doit donc penser à mettre à jour régulièrement ses entrées dans la DHT, pour s'assurer qu'il y a toujours quelque chose. Et, naturellement, si l'information change, la machine doit prévenir la DHT dès que possible.

La DHT étant globale, les adresses IP privées (RFC 1918) ne doivent pas être publiées dans la DHT. Si une machine HIP est coincée derrière un routeur NAT, elle doit, si elle veut être contactée, enregistrer l'adresse du serveur HIP de rendez-vous (RFC 5204).

OpenDHT présentait quelques particularités qui pouvaient surprendre la machine HIP tentant de stocker ses identificateurs et localisateurs. Par exemple, un put ne remplace pas la donnée précédente, il s'y ajoute. Et rien ne garantit que l'ordre dans lequel seront renvoyés les HDRR sera celui dans lequel ils ont été insérés. Il faut donc identifier le plus récent (le HDRR a un paramètre Update ID, dont je n'avais pas encore parlé, juste pour cela). Le mieux serait de penser à faire le ménage et virer explicitement ses vieilles informations.

Notez d'ailleurs que, le nom n'étant pas authentifié, on peut voir plusieurs machines s'enregistrer sous le même nom. En attendant un système d'authentification du nom (certificat X.509 portant ce nom en sujet ?), il est recommandé de tester et de choisir un autre nom, si celui qu'on voulait est déjà pris (ce qui ne devrait pas arriver, avec les noms de domaine, mais la DHT ne vérifie pas que celui qui enregistre www.google.com a le droit).

Autre problème pratique, le choix de la passerelle XML-RPC vers OpenDHT. Il en existait plusieurs, d'une fiabilité douteuse (OpenDHT était un projet de recherche, qui ne visait pas à fournir un service fiable à 100 %) et le client doit donc être prêt à détecter une panne et à passer sur une autre passerelle (OpenDHT fournissait un service anycast, opendht.nyuld.net, qui facilitait cette tâche.)

À propos de qualité de service, le RFC note aussi qu'OpenDHT ne garantissait pas de temps de réponse, et que les opérations put et get peuvent être lentes, ce à quoi les clients de la DHT doivent se préparer.

Pour approfondir davantage les questions de sécurité (point faible classique de toutes les DHT), la section 7 fait un examen complet des problèmes que pose cette solution. Concernant le contenu de l'information, l'attaque peut être menée par un client de la DHT qui enregistre délibérement des informations fausses, ou bien par un pair participant à la DHT qui modifie les informations avant de les rendre. En l'absence d'un mécanisme tiers d'authentification des données (la DHT de CoDoNS utilisait DNSSEC pour cela), il n'y a pas grand'chose à faire. On l'a dit, c'est un problème récurrent avec toutes les DHT. Le RFC dit que les paranoïaques n'ont pas d'autres solutions que d'échanger les HIT à la main (ensuite, même si la DHT renvoie de mauvais localisateurs, le protocole HIP permettra de vérifier qu'on ne se connecte pas à une machine pirate). Dans le futur, une solution serait peut-être d'utiliser des certificats numériques.

Je l'ai dit, le protocole HIP garantit au moins, par la signature des paquets échangés lors de la connexion, qu'on se connecte bien à la machine possédant l'identificateur voulu. Pour un attaquant, enregistrer dans la DHT de fausses correspondances HIT->localisateur ne permet donc pas de détourner vers une machine pirate. Pour ce stade, la seule possibilité de l'attaquant est d'enregistrer plein de correspondances bidons, pour faire une attaque par déni de service.

La seule solution à long terme à cette attaque serait que la DHT vérifie les données avant de les enregistrer, et donc connaisse HIP. Elle pourrait tester que la signature incluse dans la requête corresponde à la clé publique (l'identificateur). Cette vérification laisserait la DHT vulnérable à d'autres attaques par déni de service, où l'attaquant ferait beaucoup de requêtes et imposerait donc beaucoup de vérifications. Pour parer cela, on peut imaginer une DHT qui impose que ses clients la contactent en HIP, réutilisant ainsi les protections anti-DoS de HIP. Et cela permettrait de s'assurer que le client n'enregistre des localisateurs que pour lui.

À noter enfin que OpenLookup est un exemple d'un service fournissant la même interface qu'OpenDHT même si, derrière, ce n'est pas une DHT.


Téléchargez le RFC 6537


L'article seul

RFC 6534: Loss Episode Metrics for IPPM

Date de publication du RFC : Mai 2012
Auteur(s) du RFC : N. Duffield (AT&T Labs-Research), A. Morton (AT&T Labs), J. Sommers (Colgate University)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF ippm
Première rédaction de cet article le 7 mai 2012


Le RFC 7680 définissait une métrique (une grandeur mesurable et spécifiée rigoureusement) pour le taux de pertes de paquets entre deux points du réseau. Mais un certain nombre de logiciels ne sont pas sensibles uniquement à la moyenne du taux de pertes mais aussi à sa répartition. Sur un flot de cent paquets, ce n'est pas la même chose d'en perdre trois, répartis au hasard, et d'en perdre trois de suite, par exemple pour certains protocoles multimédia qui encodent les différences entre paquets. Ce nouveau RFC définit donc des métriques pour caractériser les épisodes, ces pertes consécutives de paquets.

Par exemple, au taux de pertes moyen du RFC 7680, il serait intéressant d'ajouter la durée maximale d'un épisode, ou bien la durée moyenne d'un épisode. Prenons les deux flots suivants, où OK indique un paquet arrivé et LOST un paquet perdu : OK - OK - LOST - LOST - LOST - OK - OK - OK - LOST - OK, puis LOST - OK - LOST - OK - LOST - OK - LOST - OK - OK - OK.Le taux de pertes moyen (Type-P-One-way-Packet-Loss-Average du RFC 7680) est de 0,4 (40 % de paquets perdus) dans les deux cas. Mais la longueur maximale d'un épisode est de 3 dans le premier cas et de 1 dans le second, ce qui peut être important pour certains protocoles, et n'apparaissait pas dans la moyenne. Ainsi, un flux MPEG comporte des trames plus importantes que les autres, les I-frames, et la perte de paquets immédiatement consécutifs à la perte d'une I-frame est peu importante (sans la I-frame, ils ne servent à rien).

Première leçon à tirer de ce simple exemple, la notion de perte de paquets est une notion complexe dans l'Internet, où le trafic connaît des pics brutaux. Le modèle trivial de Bernoulli, où chaque perte est indépendante des autres, est clairement inadapté. De la même façon, comme illustré au paragraphe précédent, la simple moyenne n'est pas une description quantitative suffisante du phénomène. Des modèles plus markoviens ont été proposés (voir section 7), avec la notion d'épisode (période pendant laquelle on perd tous les paquets), en modélisant par des transitions entre une période normale et un épisode de pertes. Des RFC comme le RFC 3357 ou le RFC 3611 avaient déjà exploré cette voie. Mais ces modèles ne semblent pas avoir démontré d'intérêt pratique. L'approche de notre RFC est plus empirique : observer et quantifier le phénomène, sans chercher à le modéliser. Plusieurs mesures ont déjà été proposées comme l'IDC (Index of Dispersion of Counts) mais avec peu de succès. Notre RFC représente donc une nouvelle tentative pour décrire ce phénomène.

Ce RFC 6534 utilise des paires de paquets, l'intervalle entre deux paquets indiquant la résolution temporelle de la mesure (les épisodes plus courts que cet intervalle ne seront pas vus). Première métrique définie, qui sert de base (section 2), Type-P-One-way-Bi-Packet-Loss. (Un Bi-Packet = une paire.) La mesure donne (0, 0) si les deux paquets sont arrivés, (1, 1) si les deux sont perdus, etc. (Ce n'est peut-être pas intuitif mais le chiffre binaire indique s'il y a eu une perte, donc 0 signifie le succès de la transmission.)

Ensuite, comme pour le RFC 7680, des métriques moins élémentaires et plus utiles sont spécifiées à partir de celle-ci. La section 3 définit Type-P-One-way-Bi-Packet-Loss-Stream, une suite de résultats de la métrique précédente. Pour le premier exemple de cet article, ce sera ((0, 0), (0, 1), (1, 1), (1, 1), (1, 0), (0, 0), (0, 0), (0, 1), (1, 0)). (0, 1) indique une transition vers un épisode de perte, (1, 0) la fin de cet épisode. La section 4 précise la même suite pour le cas où les intervalles de temps entre paquets forment une distribution géométrique.

Jusque là, l'intérêt pratique de ces définitions semble faible. Avec la section 5, on en arrive presque à des métriques utilisables (mais patientez encore un peu, le RFC parle de « proto-métriques » pour la section 5). Par exemple, Loss-Pair-Counts indique les fréquences de chaque paire (dans l'exemple précédent 2/9 - 22 % - de (1, 1), 3/9 de (0, 0), 2/9 de (1, 0) et 2/9 de (0, 1). Bi-Packet-Loss-Episode-Duration-Number, elle, caractérise la longueur des épisodes (2 ici, car on ne compte pas le premier paquet des épisodes de perte).

Et ensuite, en section 6, on définit les métriques de plus haut niveau, la Type-P-One-way-Bi-Packet-Loss-Geometric-Stream-Ratio pour le pourcentage de paquets perdus, la Type-P-One-way-Bi-Packet-Loss-Geometric-Stream-Episode-Duration pour la durée (en secondes) des épisodes, la Type-P-One-way-Bi-Packet-Loss-Geometric-Stream-Episode-Frequency la fréquence des épisodes de perte, etc.

Voilà, nous avons maintenant nos métriques (je vous ai épargné la définition rigoureuse, indispensable mais aride : lisez le RFC pour la connaître).

Ah, un mot pour les juristes : il y a même eu des requins pour breveter des métriques, et des bureaux des brevets pour l'accepter. Voir la déclaration #1354.


Téléchargez le RFC 6534


L'article seul

RFC 6533: Internationalized Delivery Status and Disposition Notifications

Date de publication du RFC : Février 2012
Auteur(s) du RFC : C. Newman (Sun Microsystems), A. Melnikov (Isode)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF eai
Première rédaction de cet article le 18 février 2012


Dans l'ensemble des RFC sur l'internationalisation des adresses de courrier électronique, ce document traite le cas des accusés de réception (MDN, pour Message Disposition Notification) et avis de non-remise (DSN pour Delivery Status Notification).

Puisque les RFC 6531 et RFC 6532 permettent désormais d'utiliser des adresses de courrier électroniques internationalisées, c'est-à-dire utilisant tout le jeu de caractères Unicode, il faut prévoir le cas où les courriers provoquent l'envoi d'avis de remise ou de non-remise (DSN pour Delivery Status Notification, RFC 3461 et RFC 3464) et d'accusés de réception (MDN, pour Message Disposition Notification, RFC 8098). C'est l'objet de ce RFC, qui met à jour les anciens documents qui limitaient ces accusés et avis au jeu ASCII. Il fait suite au RFC 5337, qui n'était qu'expérimental. Désormais, les adresses de courrier en Unicode font partie des normes de l'Internet.

Le format des DSN dans le RFC 3464 parle de « types d'adresse ». Les adresses en UTF-8 du RFC 6532 sont un nouveau type d'adresses. Si le serveur SMTP accepte l'extension SMTPUTF8 du RFC 6531 et l'extension DSN du RFC 3461, il doit permettre d'utiliser ce type dans le paramètre ORCPT (Original Recipient, section 4.2 du RFC 3461). Si le serveur n'accepte pas SMTPUTF8, l'adresse à utiliser dans les DSN doit être encodée en 7bits, selon les règles exposées dans cette section 3. Par exemple, stéphane@bortzmeyer.org peut s'écrire st\x{E9}phane@bortzmeyer.org. (La section 3 détaille plus complètement le traitement des adresses UTF-8, et notamment les différentes formes qu'elles peuvent prendre, et les encodages de certains caractères, comme l'espace ou la barre oblique inverse, normalisé par le RFC 3461.)

Une fois réglé le problème de la représentation des adresses, la section 4 traite les DSN en UTF-8. Les DSN traditionnels étaient composés d'un objet MIME de type multipart/report (RFC 6522) comportant trois objets décrivant le problème (un objet conçu pour être lu par un humain, un message/delivery-status et le message originel, message/rfc822). Pour le courrier internationalisé, de nouveaux types ont été créés :

  • message/global-delivery-status qui, contrairement à son prédécesseur message/delivery-status, accepte l'UTF-8 et permet donc de placer directement les adresses UTF-8, sans encodage en ASCII. En outre, il dispose d'un nouveau champ, Localized-Diagnostic, qui permet de stocker des messages lisibles par un humain. La langue de ces messages est indiquée par une étiquette de langue (RFC 5646). (Le champ Diagnostic-Code est désormais en UTF-8, mais dans la langue par défaut du système, cf. i-default dans le RFC 2277.)
  • message/global qui remplace message/rfc822 (dont le nom, hommage au vieux RFC 822, était de toute façon dépassé). À noter que le terme global (mondial) utilisé pour noter ce type avait fait l'objet de vives discussions et même d'un vote. Cet objet permet de transporter le message original (si on ne transporte que les en-têtes, on utilise message/global-headers).

On peut noter que la norme MIME (RFC 2046) interdisait l'usage de l'option Content-Transfer-Encoding pour les objets de type message/* mais cette règle a été assouplie par le RFC 5335.

La section 5 traite des MDN (Message Disposition Notification, RFC 3798). Ils ne sont pas très différents des DSN et ont un format très proche, avec un type MIME message/global-disposition-notification.

La section 6 traite des registres IANA. Le type « UTF-8 » est ajouté au registre des types d'adresses (section 6.1), et les nouveaux types MIME qui avaient été créés par les premiers RFC expérimentaux, comme message/global sont ajoutés au registre des types MIME (sections 6.3 à 6.5).

Enfin, la section 7 est dédiée aux questions de sécurité. Il y a les problèmes de sécurité classiques des DSN et des MDN : non authentifiés, ils permettent de faire croire qu'un message a échoué, alors qu'il a bien été délivré, ou le contraire. Et les DSN et MDN reçus sont souvent émis en réponse à des messages faux, qui n'avaient pas été émis par l'utilisateur. D'autre part, le RFC nous prévient que des DSN ou des MDN délibérement incorrects peuvent être envoyés par un attaquant dans l'espoir de profiter d'erreur dans la programmation des analyseurs, par exemple pour déclencher un débordement de tampon. Le risque est plus important s'il y a beaucoup d'encodage, le décodage pouvant faire varier la taille des données.

Quels sont les changements depuis le RFC expérimental, le RFC 5337 ? L'annexe A les résume, les principaux étant la suppression de tout ce qui concernait le mécanisme de repli (downgrade), mécanisme complexe qui avait été normalisé pour gérer les cas où un serveur sur le chemin ne pouvait pas transmettre les adresses en UTF-8. Trop délicat, ce mécanisme a été retiré de la version normalisée de ces adresses.


Téléchargez le RFC 6533


L'article seul

RFC 6532: Internationalized Email Headers

Date de publication du RFC : Février 2012
Auteur(s) du RFC : A. Yang (TWNIC), S. Steele (Microsoft), N. Freed (Oracle)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF eai
Première rédaction de cet article le 18 février 2012


Dans l'ensemble des RFC qui décrivent les adresses de courrier électronique internationalisées (c'est-à-dire pouvant utiliser tout le répertoire Unicode), celui-ci se consacre au nouveau format des en-têtes, complétant celui normalisé dans le RFC 5322.

Désormais, on peut avoir dans un message un en-tête comme :

From: Stéphane Bortzmeyer <stéphane@sources.org>

Oui, avec du vrai UTF-8, y compris dans l'adresse proprement dite, pas seulement dans les commentaires, et encore, à condition de les surencoder selon le RFC 2047 comme c'était le cas avant (méthode inélégante et inefficace). Cette possibilité d'utiliser directement UTF-8 avait été créée par le RFC 5335, qui n'avait que le statut « Expérimental ». Désormais, ce mécanisme est complètement normalisé, en partie parce que de plus en plus de logiciels savent traiter directement l'UTF-8.

L'un des éditeurs du RFC travaille à TWNIC, le registre chinois de .tw. Les Chinois ont, fort logiquement, été particulièrement actifs dans tout le processus EAI (Email Addresses Internationalization). Celui-ci visait à terminer l'internationalisation du courrier électronique, qui avait passé une étape décisive en novembre 1996, avec la sortie du RFC 2045 sur MIME. Mais cette norme MIME n'internationalisait que le corps des messages. EAI permet d'internationaliser également les en-têtes comme From:, Subject: ou Received: (mais pas, par exemple, Date:, qui restera en ASCII pur ; Date: est censé être analysé par le MUA et présenté ensuite à l'utilisateur dans sa langue).

EAI comprend plusieurs RFC, par exemple le RFC 6530 définit le cadre général, le RFC 6531, l'utilisation des adresses Unicode dans SMTP (avec l'extension SMTPUTF8), les RFC ou futurs RFC sur POP (RFC 5721) ou IMAP (RFC 5738) et notre RFC 6532, qui se concentre sur le format des messages. Il suppose que le transport sera « 8-bits clean », c'est-à-dire laissera passer les octets qui codent les données UTF-8 sans les modifier (le cas des vieux systèmes qui ne gèrent pas proprement les caractères non-ASCII est délibérement laissé de côté).

Concrètement, que change donc ce RFC ? La section 3 détaille ce qui est modifié, par extension de la grammaire du RFC 5322) :

  • La grammaire ABNF qui décrit les en-têtes est changée (sections 3.1 et 3.2) pour accepter des caractères UTF-8, de préférence normalisés en NFC (cf. RFC 5198). Déjà très complexe, cette grammaire devient ainsi réellement difficile.
  • L'en-tête Message-ID: est traité à part (section 3.3). Les caractères UTF-8 y sont autorisés mais déconseillés (le RFC rappelle que cet en-tête sert à former automatiquement d'autres en-têtes comme In-Reply-To:).
  • La syntaxe des adresses (telles qu'on les trouve dans des en-têtes comme From: ou To:) est modifiée pour accepter UTF-8. Pour les sites qui utilisent une adresse électronique comme identificateur, comme le fait Amazon.com, ce sera un intéressant défi !
  • Un nouveau type MIME est créé, message/global, pour permettre d'identifier un message EAI (section 3.7). Les messages de ce type ne doivent être transportés qu'avec des protocoles 8-bits clean comme celui du RFC 6531.
  • Les noms des en-têtes restent en ASCII seul, ce n'est que leur contenu qui peut être en UTF-8. Pour utiliser le vocabulaire du RFC 2277, les noms des en-têtes sont un élement de protocole, qui n'a pas besoin d'être exprimé dans la langue de l'utilisateur.

Parmi les conséquences pratiques de ce changement, il faut noter que les programmeurs qui écrivent des logiciels traitant le courrier doivent désormais gérer Unicode, même s'ils se contentent d'analyser les en-têtes... L'époque du courrier traité avec des scripts shell est bien passée.

Autre point important pour les programmeurs, les limites de taille des en-têtes (qui étaient de 998 caractères maximum et 78 recommandés) changent de sémantique (section 3.4) puisque, en UTF-8, un caractère ne fait plus forcément un octet. Les limites sont désormais de 998 octets et 78 caractères (cette seconde limite étant conçue pour tenir sur l'écran). Attention aussi à la section 4, qui rappelle le risque de débordement de tampons.

La section 4 liste également quelques conséquences pour la sécurité comme le fait qu'un mécanisme d'authentification devra être prêt à gérer plusieurs adresses pour la même personne (car, pendant un certain temps, plusieurs utilisateurs auront à la fois une adresse en Unicode et une en ASCII pur).

Les changements depuis le RFC 5335 sont résumés dans la section 6 du RFC 6530. Le principal est la suppression de la possibilité de repli (downgrading) automatique vers des adresses en ASCII pur.


Téléchargez le RFC 6532


L'article seul

RFC 6531: SMTP Extension for Internationalized Email

Date de publication du RFC : Février 2012
Auteur(s) du RFC : J. Yao (CNNIC), W. Mao (CNNIC)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF eai
Première rédaction de cet article le 18 février 2012


Dans la grande série des RFC décrivant les adresses de courrier internationalisées, ce document traite des modifications au protocole SMTP. Il succède au RFC 5336, qui avait créé ces modifications mais qui n'avait que le statut « Expérimental ». Désormais, ces extensions internationales sont sur le Chemin des Normes de l'IETF.

Plusieurs RFC composent la nouvelle norme EAI ou « Email Addresses Internationalized » (cf. RFC 6530). Les deux principaux concernent le format des messages (RFC 6532) et le dialogue entre deux serveurs de messagerie, suivant le protocole SMTP. Ce dernier cas est couvert dans notre RFC 6531.

Les adresses de courrier en Unicode ne sont pas en effet compatibles avec le SMTP « brut ». Ainsi, la commande RCPT TO qui permet d'indiquer le destinataire, ne prend en paramètre que de l'ASCII. Et les en-têtes du courrier peuvent désormais être en UTF-8 (RFC 6532). Il faut donc étendre SMTP (actuellement normalisé en RFC 5321) pour permettre de l'UTF-8 en paramètre de commandes comme MAIL FROM et RCPT TO. Cette extension se signale avec l'option SMTPUTF8 (l'ancien RFC, le RFC 5336, utilisait UTF8SMTP), dont l'usage permet de vérifier que le MTA situé en face comprend bien la nouvelle norme (sections 1 et 2 du RFC).

La section 3 forme le gros du RFC en spécifiant rigoureusement le nouveau protocole. Voyons d'abord un exemple de dialogue SMTP avec la nouvelle extension (C est le client - l'appelant - et S le serveur - l'appelé). Notre RFC 6531 ne modifie pas SMTP (RFC 5321), il l'étend :


S: 220 mail.example.org ESMTP Foobar (Debian/GNU)
C: EHLO mail.iloveunicode.example 
S: 250-mail.example.org
 250-ENHANCEDSTATUSCODES
 250-8BITMIME
 250-SMTPUTF8
 250 DSN
C: MAIL FROM:<stéphane@internet-en-coopération.fr> SMTPUTF8
S: 250 2.1.0 Ok
C: RCPT TO: <françoise@comptabilité.example.org> 
S: 250 2.1.5 Ok

Notez les deux adresses, chacune comprenant des caractères non-ASCII, à gauche et à droite du @.

Les serveurs qui mettent en œuvre l'extension SMTPUTF8 doivent également accepter la très ancienne extension 8BITMIME (RFC 6152) qui permet, depuis belle lurette, de ne pas se limiter à l'ASCII dans le contenu des messages, sans pour autant nécessiter des encodages comme Quoted-Printable (en dépit de ce que prétend une légende tenace).

Les sections 3.1 et 3.2 présentent la nouvelle extension, SMTPUTF8 (enregistrée à l'IANA, cf. section 4.1). Les extensions SMTP sont définies par le RFC 5321, section 2.2. Un MTA peut annoncer qu'il accepte SMTPUTF8, permettant à son pair, s'il l'accepte également, d'utiliser des adresses UTF-8. C'est également cette section qui définit ce que doit faire un MTA lorsqu'il tente de transmettre un message internationalisé à un ancien MTA qui ne gère pas cette extension. Trois solutions sont possibles, dont le rejet complet du message (retour à l'expéditeur) et un effort pour trouver une route alternative, passant par des serveurs plus modernes (le RFC 5336 avait un quatrième mécanisme, le repli - downgrade - qui a été abandonné après usage, car trop complexe et trop imprédictible).

La section 3.3 décrit la nouvelle syntaxe pour les adresses. L'ancienne était limitée à ASCII mais très permissive (bien qu'on trouve, notamment derrière les formulaires Web, énormément de logiciels de « vérification » bogués). En gros, la syntaxe est qu'une adresse est formée de deux parties, la partie locale et le nom de domaine, tous les deux séparés par l'arobase. La nouveauté est que les deux parties peuvent désormais être en Unicode, avec peu de restrictions sur la partie locale (le nom de domaine étant soumis aux restrictions du RFC 5890).

Il y a plein d'autres détails dans cette section 3, comme celui (section 3.7.1) que le paramètre de la commande EHLO (un nom de machine) doit être encodé en Punycode puisque, à ce stade, on ne sait pas encore si SMTPUTF8 est accepté ou pas.

Les changements depuis le RFC 5336 sont résumés dans la section 6 du RFC 6530. Le principal est la suppression de la possibilité de repli (downgrading) automatique vers des adresses en ASCII pur. Le paramètre ALT-ADDRESS disparait donc.

Cette extension de SMTP ne semble pas mise en œuvre dans les grands logiciels libres classiques comme sendmail ou exim. Pour Postfix, l'auteur a clairement exprimé son manque d'enthousiasme. Il existe des patches non-officiels développés en Chine, pour Postfix http://www.cdnc.org/gb/news/src-EAI.tar.gz (l'archive comprend également d'autres logiciels, d'où sa taille) et pour sendmail http://www.cdnc.org/gb/news/twnic.zip. La société chinoise Coremail est en train de travailler à un produit commercial basé sur ces patches.


Téléchargez le RFC 6531


L'article seul

RFC 6530: Overview and Framework for Internationalized Email

Date de publication du RFC : Février 2012
Auteur(s) du RFC : J. Klensin, Y. Ko (ICU)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF eai
Première rédaction de cet article le 18 février 2012


Parmi les protocoles utilisés sur Internet, presque tous sont internationalisés depuis longtemps. Le dernier gros manque concernait les adresses de courrier électronique, obligées de s'en tenir à stephane@internet-en-cooperation.fr alors qu'on voudrait pouvoir écrire à stéphane@internet-en-coopération.fr. Désormais, nous avons une solution standard, Internationalized Email Addresses.

Bien sûr, pour l'exemple ci-dessus, le gain n'est pas évident. Mais il l'est beaucoup plus si vous voulez écrire votre adresse avec l'écriture arabe ou chinoise. (Cf. section 3 pour la description du problème, section qui exprime clairement le fait qu'un Chinois a le droit d'avoir une adresse en sinogrammes, comme un Occidental jouit des avantages d'une adresse en caractères latins.)

Le contenu des courriers était internationalisé depuis longtemps, au moins depuis MIME (RFC 1341 à l'origine, en juin 1992). De même, certains en-têtes comme le sujet ou même comme le nom de l'expéditeur dans le champ From: - mais pas son adresse - pouvaient être internationalisés via MIME (RFC 2047). Mais les adresses ne l'étaient pas encore et ce manque de cohérence (possibilité d'utiliser des écritures non-latines à certains endroits mais pas à d'autres) rendait le courrier peu attirant pour M. Ali ou M. Wu. Notre RFC, qui remplace le RFC 4952 qui n'était qu'expérimental, décrit le cadre général de l'internationalisation des adresses de courrier. Il y avait depuis longtemps des messages internationaux, il y a désormais également des adresses internationales.

Il y a deux parties à l'adresse (décrites dans le RFC 5322) : la partie locale, à gauche du @ et le nom de domaine à droite. Si ce nom de domaine, depuis la sortie du RFC 3490, en mars 2003, peut s'écrire en Unicode (norme IDN), le courrier exigeait toujours un nom de domaine en ASCII donc un message de non-délivrance, par exemple, allait affichait la forme Punycode du nom. Ce n'était pas une vraie internationalisation.

Le cadre d'internationalisation du courrier couvre plusieurs aspects, couverts chacun par un RFC. Ce RFC expose l'architecture générale. La section 5 décrit le fonctionnement du nouveau système.

SMTP est modifié pour permettre une nouvelle extension, SMTPUTF8, indiquant le support du courrier internationalisé (RFC 6531).

Le format des messages (RFC 5322) est modifié pour permettre d'inclure de l'Unicode, encodé en UTF-8, directement dans les en-têtes, comme le champ To: (RFC 6532). Les autres charsets (comme UTF-32) ne sont pas prévus.

Le format des accusés de réception est modifié pour permettre des rapports de remise ou de non-remise lorsque l'expéditeur ou le destinataire avaient des adresses Unicode (RFC 6533).

Plusieurs autres protocoles « auxiliaires » seront également modifiés, par exemple pour les listes de diffusion (RFC 6783) ou pour IMAP et POP. Même chose pour des formats comme les IRI de plan mailto: (section 11.1 de notre RFC, RFC 3987 et RFC 6068).

Notons (section 11.2 du RFC) que les adresses de courrier sont utilisés en de nombreux endroits, par exemple comme identificateurs sur certains sites Web de commerce électronique, comme Amazon et que ces utilisateurs vont également devoir s'adapter. Quant on voit le nombre de sites, supposés professionnels, qui continuent à interdire des adresses de courrier légales, on mesure l'ampleur du travail. La section 10, elle aussi, décrit des questions liées à l'interface utilisateur. Par exemple, elle rappelle qu'il y a toujours eu des cas délicats dans la syntaxe, dont il est plus prudent de se tenir à l'écart. Ainsi, la partie gauche d'une adresse est sensible à la casse donc, en théorie, on pourrait avoir une adresse Stephane@bortzmeyer.fr et que le courrier bêtement envoyé à stephane@bortzmeyer.fr n'atteindrait pas. Inutile de dire que peu de MTA mettent en œuvre une telle distinction... Dans le cas des adresses internationalisées, il faut donc prendre garde à la canonicalisation Unicode. Au minimum, il faudrait accepter la canonicalisation en NFC de toute adresse, car cette canonicalisation aura peut-être lieu quelque part dans le chemin, qu'on le veuille ou pas.

Les changements par rapport à l'ancien cadre (RFC 4952 et ses copains) sont décrits dans les sections 6 et 12. La section 6 fait en outre le bilan de la phase expérimentale. Désormais, les adresses de courrier internationalisées ont le statut de norme et non plus de simple expérience. Le principal changement technique, de loin, est la suppression du repli. Le repli (downgrading, cf. RFC 5504 et RFC 5825) était prévu pour le cas où un émetteur internationalisé rencontrerait un récepteur qui ne l'est pas, nécessitant une modification des adresses en ASCII. En effet, contrairement à HTTP, le courrier ne fonctionne pas de bout en bout et le message est relayé par plusieurs serveurs, qu'on ne connaît pas forcément a priori.

Le repli était certainement la partie la plus complexe : modifier un message est toujours une opération délicate, notamment en présence de signatures cryptographiques (section 11.3), que le repli ne doit pas invalider ! Tellement complexe que sa mise en œuvre s'est avérée très délicate et que les différentes implémentations avaient du mal à interagir. En outre, l'expérience a montré que le fait de devoir gérer deux adresses (celle en Unicode et une en ASCII pour le repli), sans lien sécurisé entre les deux, était une belle source de problèmes. Résultat, par rapport aux RFC de la phase expérimentale, le repli a été abandonné. Désormais, un courrier internationalisé ne pourra tout simplement pas être transmis à travers les vieux serveurs, ce sera au MUA ou à l'utilisateur de trouver une solution de rechange (cf. section 8, qui détaille les solutions). On note que la phase expérimentale, dont beaucoup de RFC ne sortent jamais, a été ici utile, permettant, par la pratique, d'atteindre un très large consensus sur un point qui était précédemment fortement discuté.

Un deuxième changement technique important par rapport aux premiers RFC sur ce sujet est que, en SMTP, le client aussi bien que le serveur doit signaler sa volonté d'utiliser les nouvelles adresses.

La section 8 décrit plus en détail la marche à suivre si le serveur suivant ne gère pas les adresses Unicode (par exemple, on peut prévoir que certains administrateurs activeront les adresses Unicode sur le serveur de courrier principal du domaine et oublieront le MX secondaire). Elle n'est pas normative puisque c'est largement une question d'interface utilisateur, quelque chose que l'IETF ne fait pas normalement. Comme le note cette section, le meilleur repli est celui fait manuellement par l'utilisateur, car celui-ci est intelligent et motivé. Néanmoins, si on tient à faire du repli automatique, il peut être fait par le MUA, ou bien par une future extension au protocole de soumission (RFC 4409). Ça, c'était pour le cas où le serveur ancien était le premier de la chaîne. Et si le problème d'un serveur non-Unicode survient en cours de route, lorsqu'un MTA se rend compte que le MTA suivant ne convient pas ? La section 9 rappelle qu'il est désormais strictement interdit aux MTA de tripoter le message et il n'y a donc rien d'autre à faire que d'indiquer une erreur, qui sera remontée à l'utilisateur.

Et si le problème survient une fois le message délivré, parce que le protocole de récupération n'a pas été adapté aux adresses Unicode ? Le problème est là encore formellement en dehors du cadre, le RFC notant juste que le MDA peut faire un repli automatique s'il le juge utile.

Cette extension du courrier ne semble pas encore implémentée officiellement dans les logiciels classiques de courrier, malgré la longue période des RFC expérimentaux.


Téléchargez le RFC 6530


L'article seul

RFC 6528: Defending Against Sequence Number Attacks

Date de publication du RFC : Février 2012
Auteur(s) du RFC : F. Gont (SI6 Networks / UTN-FRH), S. Bellovin (Columbia University)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF tcpm
Première rédaction de cet article le 2 février 2012


Ce court RFC spécifie les précautions que doit prendre une mise en œuvre de TCP pour éviter qu'un attaquant ne puisse deviner le numéro de séquence initial. Rien de nouveau, les précautions en question étant programmées dans TCP depuis de nombreuses années, juste un rappel et une mise à jour du précédent RFC sur ce sujet, le RFC 1948. Il a depuis été intégré dans le RFC 9293.

Pour comprendre le problème de sécurité des numéros de séquence, et les solutions présentées dans ce RFC, il vaut mieux revenir à l'attaque qui exploitait les anciennes vulnérabilités. C'est fait dans l'annexe A du RFC, que je reprends ici.

Le but de l'attaquant est de s'en prendre à un serveur qui autorise par adresse IP. À l'époque du RFC 1948, cela concernait rsh mais, de nos jours, SSH a complètement remplacé cet archaïque protocole. Aujourd'hui, ce serait plutôt un serveur DNS qui authentifie le transfert de zones ainsi, ou bien un serveur SMTP qui autorise seulement certaines adresses IP à passer par lui - même s'il ferait mieux de se servir du RFC 4954, ou encore un serveur HTTP qui ne permet l'invocation de certaines actions qu'aux utilisateurs de certaines adresses. En deux mots, dès que l'autorisation se fait par adresse IP uniquement, il faut s'assurer que vous utilisez un TCP qui mette en œuvre les recommandations de ce RFC 6528.

On le sait, il est trivial pour un attaquant d'envoyer des paquets avec une fausse adresse IP source (le RFC 2827, censé l'empêcher, n'étant quasiment pas déployé). Mais, dans ce cas, l'attaquant ne reçoit pas les réponses. Or, si on veut maintenir une connexion TCP avec sa victime, il faut lui envoyer des paquets avec les données qu'elle attend, notamment le numéro de port et les numéros de séquence. Sinon, la victime va jeter ces paquets TCP qui lui sembleront anormaux. Pour les numéros de port, le RFC 6056 s'en occupe. Pour les numéros de séquence, voyons ce qui se passe. Tout paquet TCP doit inclure ces numéros, un pour chaque sens de la conversation (RFC 793, section 3.3). Ce numéro identifie l'octet suivant à envoyer. Une ouverture de connexion TCP normale ressemble donc, pour le cas où Alice veut parler à Bob, à :

  • Alice->Bob: [SYN] ISNa, null (Alice envoie un paquet TCP où le bit SYN est mis, avec un numéro de séquence initial ISNa - ISN = Initial Sequence Number.)
  • Bob->Alice: [SYN] ISNb, ACK(ISNa+1) (Bob répond qu'il est d'accord, envoie son propre ISN - rappelez-vous qu'il y a deux séquences d'octets, une dans chaque direction - et accuse réception de l'ISN d'Alice.)
  • Alice->Bob: [] ISNa, ACK(ISNb+1) (Alice est d'accord et cela termine la «  triple poignée de mains » qui ouvre une connexion TCP.)

Voici d'ailleurs, vu par tcpdump, un exemple d'ouverture de connexion (vers le dépôt git de Linux) :

% tcpdump -S -n -r tmp/3wayhandshake.pcap
reading from file tmp/3wayhandshake.pcap, link-type EN10MB (Ethernet)
09:47:53.086347 IP 192.134.6.69.39859 > 149.20.4.72.9418: Flags [S], seq 3366079112, ...
09:47:53.242880 IP 149.20.4.72.9418 > 192.134.6.69.39859: Flags [S.], seq 3075029842, ack 3366079113, ...
09:47:53.242910 IP 192.134.6.69.39859 > 149.20.4.72.9418: Flags [.], ack 3075029843, ...

Le S entre crochets indique un paquet SYN. L'option -S est là pour indiquer à tcpdump d'afficher les numéros de séquence absolus, tels qu'ils sont envoyés sur le câble (par défaut, il montre des numéros relatifs, sauf pour les paquets SYN). On note aussi que tcpdump n'affiche pas le premier numéro de séquence s'il n'y a pas de données, et n'affiche pas le second si le bit ACK n'est pas mis.

Le deuxième paquet n'a été accepté par Alice que parce qu'il contenait un numéro de séquence attendu. Même chose pour le troisième. Un attaquant qui procéderait au hasard, envoyant des numéros de séquence quelconques, n'aurait aucune chance que ses paquets soient acceptés. Imaginons maintenant que l'attaquant puisse connaître les numéros de séquence utilisés. Bob fait confiance à Alice mais Mallory, l'attaquant, va se faire passer pour Alice. Mallory n'est pas situé sur le chemin entre Alice et Bob (sinon, cela serait trivial, il lui suffirait d'écouter le réseau) :

  • AliceM->Bob: [SYN] ISNa, null (Mallory, utilisant l'adresse source d'Alice, envoie un paquet TCP où le bit SYN est mis, avec un numéro de séquence initial ISNa.)
  • Bob->Alice: [SYN] ISNb, ACK(ISNa+1) (Bob répond qu'il est d'accord, envoie son propre ISN et accuse réception de l'ISN qu'il croit venir d'Alice. Mallory ne recevra pas ce paquet, qui ira à la vraie Alice. Mallory ne sait donc pas ce que vaut ISNb, et doit deviner. En cas de divination juste, son paquet suivant est accepté.)
  • AliceM->Bob: [] ISNa, ACK(ISNb+1) (Mallory, utilisant l'adresse source d'Alice, termine la triple poignée de mains. Bob croit qu'il est connecté à Alice alors qu'il va accepter les paquets de Mallory.)

Et comment Mallory a-t-il trouvé le numéro de séquence que va utiliser Bob ? Le RFC originel, le RFC 793 ne mettait pas du tout en garde contre cette attaque, inconnue à l'époque (1981). Il ne se préoccupait que du risque de collision accidentel entre deux connexions et suggérait donc un algorithme où l'ISN était simplement incrémenté toutes les quatre micro-secondes, ce qui le rendait très prévisible (l'attaquant ouvre une connexion, regarde l'ISN, et sait quel va être celui de la prochaine connexion). Le premier article décrivant une faiblesse dans les mises en œuvre de TCP, faiblesse permettant de trouver le prochain numéro de séquence, a été publié en 1985 (Morris, R., A Weakness in the 4.2BSD UNIX TCP/IP Software, CSTR 117, AT&T Bell Laboratories). À l'époque, elle était suffisante pour établir des sessions rsh avec la victime.

À noter qu'Alice, elle, reçoit l'accusé de réception de Bob, auquel elle ne s'attend pas. Elle va donc émettre un paquet RST qui va fermer la connexion. Diverses techniques permettent à l'attaquant de réussir quand même (par exemple en montant au même moment une attaque DoS contre Alice pour ralentir ses paquets, donnant à l'attaque le temps de réussir).

C'est pour répondre à cette attaque que le RFC 1948 avait été écrit en 1996, documentant la pratique qui était devenue courante, de générer des numéros de séquence, sinon aléatoires, en tout cas imprévisibles. (Un article plus récent et plus détaillé sur la vulnérabilité initiale était celui de Shimomura, T., Technical details of the attack described by Markoff in NYT, envoyé sur Usenet, en comp.security.misc, Message-ID: <3g5gkl$5j1@ariel.sdsc.edu>, en 1995.) Notre RFC 6528 met à jour ce RFC 1948. La section 2 expose les principes d'un bon algorithme de génération d'ISN (Initial Sequence Number), la section 3 décrit l'algorithme proposé. Commençons par celui-ci. Il tient en une formule :

ISN = M + F(localip, localport, remoteip, remoteport)

où M est un compteur qui s'incrémente toutes les quatre micro-secondes, et F une fonction pseudo-aléatoire, qui va prendre comme paramètre le tuple qui identifie une connexion TCP (adresse IP locale, port local, adresse IP distante, port distant). F ne doit pas être prévisible de l'extérieur et le RFC suggère une fonction de hachage cryptographique, comme MD5 (RFC 1321), hachant le tuple ci-dessus après l'avoir concaténé à une clé secrète. La sécurité reposera sur cette clé, l'algorithme de hachage utilisé étant sans doute connu. On peut envisager qu'elle soit générée aléatoirement (vraiment aléatoirement, en suivant le RFC 4086), ou configurée à la main (en espérant que l'ingénieur système ne choisira pas « toto »). Il est recommandé de la changer de temps en temps.

Notez que, bien que MD5 ait de nombreuses faiblesses cryptographiques pour d'autres utilisations, il est parfaitement sûr pour celle-ci (et bien plus rapide que ses concurrents).

La section 2, elle, définissait le cahier des charges : qu'attend t-on d'un algorithme de sélection de l'ISN ? D'abord, il n'est pas forcé d'empêcher des vieux paquets IP qui traînent dans le réseau d'être acceptés. Pour cela, il vaut mieux compter sur l'état TIME_WAIT de TCP (après la fin d'une connexion, garder l'état pendant deux MSL - Maximum Segment Life, cf. RFC 7323). Ça ne marche pas forcément si les connexions sont créées à un rythme très rapide mais c'est la seule solution sûre (mais consommant de la mémoire). On peut lire à ce sujet deux articles sur les générateurs d'ISN, leurs avantages et inconvénients, « Strange Attractors and TCP/IP Sequence Number Analysis » et « Strange Attractors and TCP/IP Sequence Number Analysis - One Year Later ».

Compte-tenu de ces risques, une génération aléatoire de l'ISN suffirait. Mais elle aurait l'inconvénient de de ne pas permettre de deviner si un nouveau paquet TCP appartient à une ancienne connexion ou pas. L'idée de base de ce RFC est donc de créer un espace de numéros de séquence par identificateur TCP (le tuple {adresse IP locale, port local, adresse IP distante, port distant}) et, dans chacun de ces espaces, de suivre les règles d'incrémentation progressive de l'ISN du RFC 793.

Pour ceux qui veulent pousser l'analyse de sécurité, la section 4 prend de la hauteur et rappelle quelques points importants. D'abord que la vraie solution serait évidemment de protéger les paquets IP par de la cryptographie comme le fait IPsec, ou au niveau TCP comme le fait le TCP-AO du RFC 5925 (TLS ou SSH ne suffisent pas, ils n'empêchent pas une attaque par déni de service avec des faux paquets TCP RST).

La section 4 fait aussi remarquer que rien n'est parfait et que l'algorithme proposé dans notre RFC a des effets de bord, comme de permettre le comptage du nombre de machines qui se trouvent derrière un routeur NAT, ce qui peut être une information qu'on souhaiterait garder privée.

Et, surtout, elle rappelle que toutes les précautions de notre RFC 6528 ne s'appliquent que si l'attaquant est en dehors du chemin entre les deux pairs TCP. S'il est sur le chemin et qu'il peut écouter le réseau, elles ne servent à rien.

Quels sont les changements depuis le RFC 1948 ? Il n'y a pas de changement sur le fond (l'algorithme est le même donc un TCP compatible avec le RFC 1948 l'est également avec le RFC 6528). Les changements sont résumés dans l'annexe B. Le statut du RFC a changé (désormais sur le chemin des normes), les exemples maintenant dépassés par l'évolution des techniques ont été mis à jour ou supprimés,

On l'a dit, les précautions décrites dans ce RFC sont présentes dans les implémentations depuis longtemps. Pour un exemple de mise en œuvre de cet algorithme, on peut regarder le code source de NetBSD. Il se trouve en sys/netinet/tcp_subr.c. Son comportement est contrôlé par la variable sysctl iss_hash. Mise à 1, elle indique qu'il faut utiliser l'algorithme ci-dessus. À 0, qu'il faut utiliser une valeur aléatoire. Prenons le premier cas, celui de notre RFC. On voit la génération du secret (un nombre aléatoire, issu de cprng_strong()) puis le hachage MD5 de l'identifiant de connexion avec le secret :


	/*
	 * If we haven't been here before, initialize our cryptographic
	 * hash secret.
	 */
	if (tcp_iss_gotten_secret == false) {
		cprng_strong(kern_cprng,
			     tcp_iss_secret, sizeof(tcp_iss_secret), 0);
		tcp_iss_gotten_secret = true;
	}

        /*
	 * Compute the base value of the ISS.  It is a hash
	 * of (saddr, sport, daddr, dport, secret).
	 */
	MD5Init(&ctx);
	MD5Update(&ctx, (u_char *) laddr, addrsz);
	MD5Update(&ctx, (u_char *) &lport, sizeof(lport));
	MD5Update(&ctx, (u_char *) faddr, addrsz);
	MD5Update(&ctx, (u_char *) &fport, sizeof(fport));
	MD5Update(&ctx, tcp_iss_secret, sizeof(tcp_iss_secret));
	MD5Final(hash, &ctx);
	memcpy(&tcp_iss, hash, sizeof(tcp_iss));

        return (tcp_iss);

Pour Linux (remerciements au passage à @ackrst), il faut regarder le net/core/secure_seq.c qui contient à peu près la même chose (la variable net_secret est initialisée au tout début de ce fichier) :


__u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
				 __be16 sport, __be16 dport)
{
	u32 hash[MD5_DIGEST_WORDS];

	hash[0] = (__force u32)saddr;
	hash[1] = (__force u32)daddr;
	hash[2] = ((__force u16)sport << 16) + (__force u16)dport;
	hash[3] = net_secret[15];

	md5_transform(hash, net_secret);


Téléchargez le RFC 6528


L'article seul

RFC 6522: The Multipart/Report Media Type for the Reporting of Mail System Administrative Messages

Date de publication du RFC : Janvier 2012
Auteur(s) du RFC : M. Kucherawy (Cloudmark)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF appsawg
Première rédaction de cet article le 17 janvier 2012


Un court RFC pour un format simple : le type MIME multipart/report permet d'envoyer des rapports structurés au sujet d'un message. Ce RFC est la dernière version de la norme sur multipart/report, marquée par un léger allègement des règles d'utilisation.

Pas de grands changements, sinon. L'idée de base de multipart/report est de pouvoir faire des messages à propos des messages. Par exemple, un avis de non-remise (RFC 3461) est un message disant qu'un message n'a pu être remis, et intégrant le message originel. Un rapport ARF (RFC 5965) est un message disant qu'un message est abusif (spam, par exemple) et intégrant également le message originel. D'où l'idée d'avoir un type commun pour tous ces « messages sur les messages », et c'est multipart/report, normalisé dans notre RFC 6522, qui succède au RFC 3462 (qui succédait lui-même au RFC 1892). Ce type multipart/report est très largement utilisé depuis longtemps, et par de nombreux logiciels.

La présentation détaillée du type « rapport » figure en section 3. Voici d'abord un exemple d'un tel message, ici pour indiquer une non-délivrance, généré par un MTA Postfix :

Date: Wed, 11 Jan 2012 13:45:44 +0000 (UTC)
From: MAILER-DAEMON@bortzmeyer.org (Mail Delivery System)
Subject: Undelivered Mail Returned to Sender
To: bortzmeyer@nic.fr
Auto-Submitted: auto-replied
MIME-Version: 1.0
Content-Type: multipart/report; report-type=delivery-status;
        boundary="154CD3AC2C.1326289544/mail.bortzmeyer.org"
Content-Transfer-Encoding: 8bit

This is a MIME-encapsulated message.

--154CD3AC2C.1326289544/mail.bortzmeyer.org
Content-Description: Notification
Content-Type: text/plain; charset=us-ascii

[La première partie du rapport, lisible par un humain.]

This is the mail system at host mail.bortzmeyer.org.

I'm sorry to have to inform you that your message could not
be delivered to one or more recipients. It's attached below.

--154CD3AC2C.1326289544/mail.bortzmeyer.org
Content-Description: Delivery report
Content-Type: message/delivery-status

[La deuxième partie du rapport, conçue pour être analysée par des
programmes.]

Reporting-MTA: dns; mail.bortzmeyer.org
X-Postfix-Queue-ID: 154CD3AC2C
X-Postfix-Sender: rfc822; bortzmeyer@nic.fr
Arrival-Date: Wed, 11 Jan 2012 12:24:50 +0000 (UTC)

Final-Recipient: rfc822; nothere@nowhere.example
Action: failed
Status: 5.4.4
Diagnostic-Code: X-Postfix; Host or domain name not found. Name service error
    for name=nowhere.example type=AAAA: Host not found

--154CD3AC2C.1326289544/mail.bortzmeyer.org
Content-Description: Undelivered Message
Content-Type: message/rfc822
Content-Transfer-Encoding: 8bit

[Puis le message originel, dans la troisième partie du rapport.]

Notez le paramètre report-type, qui a ici la valeur delivery-status. (Cela serait feedback-report pour du ARF.)

Notez surtout le découpage en trois parties (la dernière est optionnelle) :

  • Une partie qui contient un message en format libre et en langue naturelle.
  • Une partie structurée (dans l'exemple ci-dessus, avec la syntaxe message/delivery-status du RFC 3464).
  • Le message originel.

Si on trouve le message originel trop gros, la troisième partie peut se composer uniquement des en-têtes du message. Elle aura alors le type message/rfc822-headers (section 4 de notre RFC).

Naturellement, les messages multipart/report ne sont pas plus authentifiés que les autres messages : il faut donc éviter d'agir automatiquement lors de leur réception (section 7).

Le seul changement de fond depuis le RFC 3462 concerne une ancienne restriction : multipart/report ne pouvait apparaître qu'au plus haut niveau du message (rappelez-vous que MIME est récursif, un message MIME peut contenir d'autres messages MIME). Cela interdisait, par exemple, de faire un multipart/report au sujet d'un multipart/report. Il semble bien que personne ne mettait en œuvre cette restriction et ce nouveau RFC 6522 l'a donc supprimé. (Voir section 1.)


Téléchargez le RFC 6522


L'article seul

RFC 6520: Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS) Heartbeat Extension

Date de publication du RFC : Février 2012
Auteur(s) du RFC : R. Seggelmann, M. Tuexen (Muenster Univ. of Appl. Sciences), M. Williams
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF tls
Première rédaction de cet article le 8 février 2012
Dernière mise à jour le 8 avril 2014


Le protocole de cryptographie TLS ne disposait pas en standard de mécanisme de « battement de cœur », permettant de tester qu'une connexion est toujours vivante. C'est désormais chose faite. Grâce à la nouvelle extension de TLS, normalisée dans ce RFC, deux pairs TLS peuvent s'assurer, par un mécanisme standard, que l'autre pair est bien là, et répond.

Savoir si l'autre partie de la connexion est toujours là est souvent utile en matière de réseau. Les sessions qui utilisaient TLS (RFC 5246) ou DTLS (RFC 6347) ne disposaient pas d'un moyen générique de tester si le cœur du pair battait toujours. Les applications devaient donc envoyer des données inutiles et attendre une réponse. Une autre solution était de faire une renégociation (RFC 5246, section 7.4.1) mais cette opération est coûteuse en calculs cryptographiques. C'était encore pire avec DTLS, qui est parfois utilisé dans des applications unidirectionnelles, où aucune réponse applicative n'est prévue.

Désormais, les mises en œuvre de TLS qui gèrent la nouvelle extension, Heartbeat, pourront envoyer des messages HeartbeatRequest, auxquels le pair devra répondre avec un HeartbeatResponse. Cette extension est spécifiée au moment de la négociation (section 2), dans les messages Hello (RFC 5246, section 7.4.1). Dans la syntaxe vaguement analogue à ASN.1 de TLS, la nouvelle extension est décrite par :

   enum {
      peer_allowed_to_send(1),
      peer_not_allowed_to_send(2),
      (255)
   } HeartbeatMode;

   struct {
      HeartbeatMode mode;
   } HeartbeatExtension;

Le mode peer_not_allowed_to_send est là pour indiquer qu'une machine veut utiliser l'extension pour tester son pair mais qu'elle-même ne répondra pas aux requêtes HeartbeatRequest. La nouvelle extension est enregistrée à l'IANA (numéro 15).

Une fois que les deux parties se sont mises d'accord, quel est le protocole pour l'utilisation de cette extension (section 3) ? Le test des battements de cœur fonctionne au-dessus du Record Protocol de TLS, auquel il ajoute deux messages :

 enum {
      heartbeat_request(1),
      heartbeat_response(2),
      (255)
   } HeartbeatMessageType;

Un message HeartbeatRequest peut arriver à tout moment pendant une session, le pair doit alors répondre par un HeartbeatResponse. D'autres types que Requête et Réponse seront peut-être un jour créés, et enregistrés dans le nouveau registre IANA.

Lorsque la session protégée par TLS fonctionne au dessus d'un protocole fiable, comme TCP, c'est tout. La couche de transport se chargera des éventuelles retransmissions. Si la session TLS utilise un protocole non-fiable comme UDP, l'émetteur du HeartbeatRequest doit se préparer, en l'absence de réponse, à réémettre le message (RFC 6347, section 4.2.4).

Et le contenu des messages (section 4) ? Une charge utile est autorisée :

 struct {
      HeartbeatMessageType type;
      uint16 payload_length;
      opaque payload[HeartbeatMessage.payload_length];
      opaque padding[padding_length];
   } HeartbeatMessage;

Le contenu du champ payload est quelconque. La réponse doit inclure le même contenu (elle doit être un écho de la requête).

La section 5 du RFC décrit ensuite deux cas d'utilisation pratique de cette extension. Le premier est celui de la découverte de la MTU du chemin, pour laquelle DTLS n'avait pas de mécanisme (RFC 6347, section 4.1.1.1). La méthode, inspirée du RFC 4821, est simplement d'utiliser des HeartbeatRequest de plus en plus gros, jusqu'à ce qu'on n'obtienne plus de réponse, auquel cas on sait qu'on a trouvé la MTU maximale.

L'autre usage de cette extension est le test de bonne santé du pair, comme expliqué au début de cet article. Le RFC recommande de ne pas en abuser, et de n'émettre les HeartbeatRequest qu'à des intervalles de plusieurs fois le RTT.

Il existe déjà au moins une mise en œuvre de ce mécanisme de battement de cœur. OpenSSL l'aura à partir de la 1.0.1 (le code est déjà dans les versions de développement, l'extension - option heartbeats - est apparemment compilée par défaut). Pour GnuTLS, ce n'est encore qu'un projet. Comme souvent en informatique, quand on ajoute du code, on ajoute des bogues. C'est ainsi que la mise en œuvre de cette extension dans OpenSSL a été à l'origine de la faille CVE-2014-0160, dite « HeartBleed ».


Téléchargez le RFC 6520


L'article seul

RFC 6518: Keying and Authentication for Routing Protocols (KARP) Design Guidelines

Date de publication du RFC : Février 2012
Auteur(s) du RFC : G. Lebovitz, M. Bhatia (Alcatel-Lucent)
Pour information
Réalisé dans le cadre du groupe de travail IETF karp
Première rédaction de cet article le 2 février 2012


Dans l'ensemble du travail engagé pour améliorer la sécurité du routage sur l'Internet, un sous-problème important est celui de la gestion des clés. En cryptographie, c'est souvent par une faiblesse dans cette gestion que les systèmes de sécurité sont compromis. Le groupe de travail KARP de l'IETF est occupé à améliorer les protocoles de gestion de clés et son premier RFC, ce RFC 6518, expose les propriétés attendues des futurs protocoles de gestion des clés des routeurs.

Prenons par exemple N routeurs OSPF qui veulent s'authentifier les uns les autres. La technique du RFC 2328 est d'avoir un secret partagé par tous les routeurs du même réseau local. Les messages OSPF sont concaténés avec ce secret, le résultat de la concaténation est ensuite condensé cryptographiquement, ce qui permettra au destinataire de s'assurer que l'émetteur connaissait bien le secret. Ce secret partagé est une clé cryptographique. Qui va la générer ? Comment la distribuer de façon sûre ? Comment la changer facilement et rapidement si le secret est compromis (ou, tout simplement, si un employé quitte l'entreprise) ? Ce genre de questions est la problématique de gestion de clés. Dans le cas d'OSPF, actuellement, la quasi-totalité des opérateurs de routeurs fait cela à la main (on se logue sur chaque routeur et on change le secret...) ou, à la rigueur, via un protocole général de configuration des routeurs. Peut-on faire mieux ? C'est en tout cas ce que va essayer de faire le groupe KARP (les deux RFC suivants de KARP ont été le RFC 6862, sur l'analyse des menaces, et le RFC 6863, sur l'analyse spécifique du protocole OSPF).

C'est que les mécanismes actuels ne sont pas satisfaisants. Comme le rappelle la section 1 du RFC, lors d'un colloque en 2006 (cf. RFC 4948), les participants avaient dénoncé la vulnérabilité des routeurs aux tentatives de prise de contrôle et appelé à durcir leur sécurité. Quatre axes d'amélioration avaient été identifiés, améliorer la gestion des routeurs (groupe de travail OPSEC), améliorer les IRR, valider les annonces de route (groupe de travail SIDR), et enfin sécuriser les communications entre routeurs (groupe de travail KARP), ce qui fait l'objet de ce RFC. Les informations de routage sont échangées via un protocole et la protection de ce protocole se fait par la cryptographie. Qui dit cryptographie dit clés. Lorsqu'un routeur cherche une clé pour protéger un message, où demande-t-il ? Pour l'instant, il n'y a pas de mécanisme standard et KARP va essayer d'en développer un. Le plus courant aujourd'hui est la gestion manuelle des clés (l'opérateur configure les clés, les change à la main - lorsqu'il y pense, les communique via PGP, SCP voire sans aucune sécurité) mais le RFC estime que le futur est dans des mécanismes automatisés de gestion de clés, les KMP (pour Key Management Protocol). Un KMP, par exemple, change automatiquement les clés au bout d'une période pré-définie.

Compte-tenu de la variété des protocoles de routage, et du transport qu'ils utilisent, ce sera un mécanisme abstrait, pas un protocole précis (ce RFC 6518 n'a donc pas d'implémentation, il définit juste un cadre). Plus précisement, KARP va concevoir les interfaces abstraites entre le système de gestion de clés et le protocole de routage, puis, pour chaque protocole de routage, la correspondance entre cette interface abstraite et le protocole réel. Un projet ambitieux.

Maintenant, au boulot. Qu'est-ce qui est déjà fait dans ce RFC ? La section 2 classe les protocoles de routage selon leurs propriétés. L'idée est que les protocoles de routage qui partagent les mêmes propriétés pourront, avec un peu de chance, utiliser les mêmes mécanismes de gestion de clés. Première propriété, le type de message. Certains protocoles sont de type un-vers-un : les messages d'un routeur sont envoyés à un autre routeur. Les UPDATE BGP (RFC 4271) fonctionnent ainsi. Mais c'est aussi le cas de LDP (RFC 5036), de BFD (RFC 5880) et même d'OSPF (RFC 2328) dans certaines conditions (liens point -à-point). D'autres protocoles fonctionnent en un-vers-plusieurs. Un routeur diffuse sur le réseau local l'information de routage. C'est le mode de fonctionnement le plus courant d'OSPF et c'est aussi celui de RIP (RFC 2453). Enfin, il y a les protocoles utilisés pour le multicast.

Deuxième propriété pour classer les protocoles de routage, proche de la précédente mais pas identique, le fait que la clé soit par groupe ou par pair. Dans BGP ou LDP, les clés sont individuelles, on a une clé différente par pair. Dans OSPF, la clé est la même pour tous les pairs d'un groupe.

La section 3 liste ensuite les points auxquels il faut penser lorsqu'on envisage un protocole de gestion de clés, un KMP. Le RFC 4107 fournit les bases générales et notre RFC l'adapte aux protocoles de routage. Entre autres, il faudra penser aux paramètres à passer avec le système de gestion de clés, comme la durée de vie pour les clés, l'identificateur de l'association de sécurité (SPI dans IPsec, KeyID dans TCP-AO, etc), l'algorithme de chiffrement et plusieurs autres.

Deux points sont soulignés par le RFC, les questions particulières des clés asymétriques (section 3.1) et le cycle de vie des clés (section 3.2). Les clés asymétriques sont souvent une bonne solution aux problèmes de sécurité : déjà utilisées par les routeurs (lorsqu'ils sont administrés via SSH), générées sur le routeur, elles peuvent n'avoir jamais besoin de le quitter (le RFC ne le dit pas clairement mais on peut même imaginer un petit HSM dans le routeur). Générées aléatoirement, elles ne peuvent pas être devinées comme le sont tant de mots de passe choisis par des humains. Il faut juste faire attention à leur taille, pour limiter les risques des attaques par force brute (RFC 3766). L'algorithme classique pour ces clés est RSA mais les algorithmes à base de courbes elliptiques commencent à se répandre, et permettent d'utiliser des clés plus courtes.

Quant au cycle de vie des clés, notre RFC insiste surtout sur la nécessité d'avoir des remplacements (rollover) de clés qui soient discrets : un remplacement de clés ne devrait pas casser les sessions de routage existantes, car cela imposerait des recalculs lourds des tables de routage, se propageant dans tout le réseau, et entraînant parfois des perturbations dans la connectivité. (Le RFC ne le cite pas mais la traditionnelle authentification MD5 de BGP - RFC 2385 - n'a pas cette propriété. Changer la clé impose de relancer les sessions BGP. C'est sans doute une des raisons pour lesquelles ces clés ne sont jamais changées, même quand tout le monde les connait.)

Pourquoi, d'ailleurs, faut-il changer les clés de temps en temps ? Il peut y avoir des raisons cryptographiques (progrès de la cryptanalyse, mais le RFC note qu'en pratique, ce sont les cas les plus rares, des problèmes moins prestigieux scientifiquement sont bien plus communs), des raisons liées au personnel (départ d'un ingénieur qui connaissait les clés), des raisons plus urgentes (compromission d'une machine où étaient stockées des clés). Même s'il n'y a aucune raison immédiate de changer, un remplacement des clés de temps en temps peut être nécessaire pour s'assurer qu'un attaquant qui a obtenu une clé et l'utilise discrètement (de manière purement passive), ne puisse pas profiter de son butin éternellement.

Lorsque les procédures de changement de clés sont manuelles, les changements peuvent être en eux-mêmes une source de vulnérabilité (l'erreur est humaine...).

Après ces préliminaires, la section 4 dessine le travail futur. Il y a deux chantiers génériques (indépendants du protocole de routage) importants, le premier étant un pré-requis du second :

  • Doter tous les protocoles de routage de mécanismes leur permettant l'agilité des algorithmes (changer d'algorithme facilement, contrairement au RFC 2385, qui ne permettait que MD5) et celle des clés (changer de clés sans casser les sessions entre routeurs). À l'heure actuelle, c'est très loin d'être le cas.
  • Une fois ces mécanismes en place, développer un KMP, un Key Management Protocol permettant la gestion et le remplacement automatique des clés. Ce dernier protocole devrait être aussi indépendant du protocole de routage que possible.

Pour que les mécanismes nouveaux aient des chances de succès, ils doivent pouvoir être déployés sans ajouter de complexité par rapport à ce que font déjà les opérateurs (qui connaissent SSH, TCP-MD5, HTTPS et les certificats, etc). Le but n'est pas de faire un système qui empêche l'opérateur de faire une erreur (comme d'utiliser « foobar » comme mot de passe pour tous les systèmes) mais de faire un système qui soit utilisé dans le monde réel, et pour cela, la simplicité et la déployabilité sont des critères essentiels (mais très souvent oubliés par les experts en sécurité, qui se soucient davantage de faire des systèmes parfaits que des systèmes déployables, cf. section 6).

Avec une gestion manuelle des clés, on ne peut gérer de manière raisonnablement sûre que des petits réseaux. La deuxième étape sera donc de déployer le mécanisme de gestion automatique.

Le travail d'amélioration de chaque protocole de routage est décrit en section 4.2 sous forme d'une liste de tâches :

  • Analyser le protocole actuel pour déterminer de façon précise quels sont ses mécanismes de sécurité présents,
  • Déterminer ce qui lui manque pour atteindre le premier état de sécurité souhaité (agilité des algorithmes et possibilité de changer de clés en vol),
  • Analyse des étapes nécessaires pour aller du premier point au deuxième sans tout casser, en faisant particulièrement attention aux questions de déployabilité dans le monde existant,
  • Analyser le futur KMP (protocole de gestion de clés) pour ce protocole de routage particulier : a-t-il des demandes spécifiques ?
  • Déterminer ce qui manque pour atteindre le deuxième état de sécurité (gestion automatique des clés),
  • Normaliser l'adaptation du KMP à ce protocole et déployer le résultat.

On l'a vu en section 2, KARP classe les protocoles de routage en catégories selon leurs propriétés. La section 5 examine les points qui sont spécifiques à chaque catégorie. BGP, LDP et quelques autres sont dans la catégorie « messages un-vers-un et clés par pair ». BGP fonctionne toujours sur TCP, LDP parfois sur TCP et parfois sur UDP. Pour le cas de TCP, une bonne partie du travail a déjà été faite dans le groupe TCPM, avec la technique d'authentification AO (RFC 5925) qui a les propriétés voulues pour la première phase du travail de KARP (agilité des algorithmes et changement de clé facile). Il ne reste donc que le cas de LDP sur UDP.

Pour la catégorie « un-vers-plusieurs avec clés par groupe », qui comprend OSPF, IS-IS et RIP, rien de générique n'est fait. Le problème est ici bien plus difficile, d'autant plus que ces protocoles n'utilisent pas en général de protocole de transport standard, et ne peuvent donc pas réutiliser un mécanisme fourni par la couche 4 (comme peut le faire BGP avec AO). Ceci dit, le RFC 7166 fournit une méthode d'authentification pour OSPF qui, grâce à une indirection, fournit l'agilité de l'algorithme de chiffrement, qu'on peut changer en vol.

BFD est un cas à part et qui nécessitera sa propre équipe. Par exemple, il est beaucoup plus sensible aux délais que les autres. Pour lui, une milliseconde est très longue.

On l'a vu, ce RFC répète régulièrement qu'il est essentiel de prévoir un déploiement incrémental des nouveaux mécanismes de sécurité. Pas question d'ignorer l'existant. La section 6 insiste sur ce point. Contrairement à une attitude fréquente chez les experts en sécurité, qui est de chercher une solution parfaite, KARP va essayer de trouver des solutions qui puissent être déployées par étapes, sans casser le routage actuel, même si ces solutions ne sont pas les meilleures, question sécurité. Par exemple, les routeurs configurés avec les nouveaux mécanismes doivent pouvoir interagir sans ennuis avec les vieux routeurs non sécurisés.

Un des problèmes de sécurité les plus difficiles dans l'Internet est celui des attaques par déni de service (section 7). Ces attaques touchent aussi les routeurs et les protocoles de routage. Il ne faut donc pas que les nouvelles techniques conçues dans le cadre du groupe KARP aggravent le problème. Par exemple, les calculs cryptographiques peuvent être coûteux, surtout pour les ressources matérielles souvent limitées des routeurs, et les protocoles ne doivent donc pas permettre à un attaquant de faire faire au routeur une énorme quantité de ces calculs. Pour éviter cela, il faut permettre au routeur de faire des vérifications non-cryptographiques, donc bien plus légères, avant de se lancer dans les calculs compliqués. Par exemple, le RFC 5082 utilise le TTL du paquet entrant (quelque chose de trivial à vérifier) pour empêcher certaines attaques. Il est important, dans le cadre de KARP, de développer et de documenter de telles alternatives. D'autre part, le protocole doit être conçu de manière à ce que ce soit l'initiateur de la connexion (un attaquant potentiel) qui ait le plus de travail cryptographique à faire, et qui doive maintenir un état pendant ce temps.

La section 9 du RFC, la traditionnelle section sur la sécurité, détaille quelques points précis qui n'avaient pas trouvé leur place dans le reste du RFC. Par exemple, il est important de considérer aussi si le protocole de routage qu'on veut protéger est un IGP ou un EGP (certains protocoles peuvent être utilisés pour les deux, comme BGP avec son mode iBGP). Les deux sont sans doute aussi importants mais les menaces et les solutions ne seront pas forcément les mêmes. Un routeur purement interne et qui n'a aucun accès à l'Internet est ainsi sans doute moins menacé qu'un routeur BGP posé sur un point d'échange avec des dizaines d'autres routeurs inconnus.

Autre question transversale, celle des clés partagées ou uniques. Faut-il utiliser la même clé à plusieurs endroits ? Le débat est simple : c'est la sécurité (clés uniques !) contre la commodité (clés partagées). Actuellement, dans la grande majorité des environnements, les opérateurs ont choisi la commodité, réutilisant la même clé à plusieurs endroits. Les clés des routeurs sont stables dans l'espace (utilisées dans plusieurs routeurs) et dans le temps (on les change rarement, voire jamais et certains routeurs gardent la même clé toute leur vie). L'un des buts de KARP est de casser ce dilemne « sécurité ou commodité » en fournissant des mécanismes de gestion de clés qui soient sûrs (clés uniques) tout en étant faciles à déployer.

Enfin, la section 9.4 discute du dernier problème transversal, la distribution des clés. La méthode la plus courante aujourd'hui est un mécanisme « hors-bande », par exemple l'administrateur qui se connecte en SSH au routeur et entre manuellement les clés dans la configuration. Ça ne passe pas tellement à l'échelle (il faudrait automatiser les connexions SSH, par exemple avec Capistrano, pour faire l'opération sur N routeurs). Et changer toutes les clés en cas, par exemple de départ d'un administrateur (ou, pire, en cas de compromission de la clé) est trop lent. L'approche d'un KMP, protocole de gestion de clés, est donc préférée par KARP, comme nous l'avons déjà vu. Mais le RFC ne cache pas que le KMP a ses propres problèmes : lenteur au début (davantage de calculs cryptographiques) et surtout risques liés au manque de maturité des programmes, les KMP étant encore chose récente.

Une des possibilités envisagées est de réutiliser un KMP existant comme IKE, adapté au monde du routage, mais tournant en dehors du protocole de routage. L'autre possibilité est un nouveau KMP, embarqué dans le protocole de routage. Mais la décision n'est pas encore prise.


Téléchargez le RFC 6518


L'article seul

RFC 6506: Supporting Authentication Trailer for OSPFv3

Date de publication du RFC : Février 2012
Auteur(s) du RFC : M. Bhatia (Alcatel-Lucent), V. Manral (Hewlett Packard), A. Lindem (Ericsson)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF ospf
Première rédaction de cet article le 14 février 2012


La version 2 du protocole de routage OSPF avait un mécanisme d'authentification (annexe D du RFC 2328). Lors de la conception de la version 3 (qui permettait notamment d'ajouter IPv6), ce mécanisme avait été abandonné, l'idée étant que l'IETF avait déjà un mécanisme d'authentification plus général, IPsec, et qu'il « suffisait » de l'utiliser. Selon cette analyse, il n'y avait plus besoin de doter chaque protocole de son propre mécanisme d'authentification. C'était très bien sur le papier. Mais, en pratique, le déploiement d'IPsec est très limité, à la fois en raison de sa complexité et du caractère imparfait de ses implémentations. Résultat, les utilisateurs d'OPSFv3 n'ont, la plupart du temps, pas déployé de mécanisme de sécurité du tout. En voulant faire trop propre, on a donc diminué la sécurité du routage. Ce RFC (depuis remplacé par le RFC 7166) corrige le tir en dotant enfin OSPFv3 d'un mécanisme d'authentification léger et réaliste.

OSPFv3 est normalisé dans le RFC 5340, dont le titre (« OSPF pour IPv6 ») est trompeur car, depuis le RFC 5838, OSPFv3 peut gérer plusieurs familles d'adresses et peut donc, en théorie, remplacer complètement OSPFv2. En pratique, toutefois, ce n'est pas encore le cas, notamment pour le problème de sécurité qui fait l'objet de ce RFC : contrairement aux autres protocoles de routage internes, OSPFv3 ne disposait d'aucun mécanisme d'authentification. N'importe quel méchant sur le réseau local pouvait se proclamer routeur et envoyer de fausses informations de routage. L'argument répété était « pas besoin de mécanisme spécifique à OSPFv3, utilisez les mécanismes IPsec, comme expliqué dans le RFC 4552 ». Mais on constate que cette possibilité a été très peu utilisée. Le RFC se contente de noter que c'est parce que IPsec est mal adapté à certains environnements comme les MANET mais il ne parle pas des autres environnements, où IPsec est simplement rejeté en raison de la difficulté à trouver une implémentation qui marche, et qu'un administrateur système normal arrive à configurer.

IPsec a également des faiblesses plus fondamentales pour des protocoles de routage comme OSPF. Ainsi, les protocoles d'échange de clés comme IKE ne sont pas utilisables tant que le routage ne fonctionne pas. Pour résoudre le problème d'œuf et de poule, et parce que les communications OSPF sont de type un-vers-plusieurs (et pas un-vers-un comme le suppose IKE), le RFC 4552 prône des clés gérées manuellement, ce qui n'est pas toujours pratique.

Enfin, l'absence de protection contre le rejeu affaiblit la sécurité d'IPsec dans ce contexte, comme le note le RFC 6039.

La solution proposée figure en section 2. L'idée est d'ajouter à la fin du packet OSPF un champ qui contienne un condensat cryptographique du paquet et d'une clé secrète, comme pour OSPFv2 (RFC 5709) (D'autres types d'authentification pourront être utilisés dans le futur, un registre IANA des types a été créé.) Les options binaires du paquet, au début de celui-ci (RFC 5340, section A.2), ont un nouveau bit, en position 13, AT (pour Authentication Trailer, désormais dans le registre IANA), qui indique la présence ou l'absence du champ final d'authentification (tous les paquets n'ont pas ce champ Options, donc le routeur devra se souvenir des valeurs de ce champ pour chaque voisin).

Pour chaque couple de routeurs ainsi protégés, il y aura un certain nombre de paramètres, qui forment ce qu'on nomme un accord de sécurité (security association, section 3) :

  • Un identifiant sur 16 bits, manuellement défini, le Security Association ID. L'émetteur le choisit et le récepteur le lit dans le paquet. Cette indirection va permettre de modifier des paramètres comme les clés cryptographiques (ou même l'algorithme cryptographique), tout en continuant le routage.
  • L'algorithme utilisé, par exemple HMAC-SHA1 ou HMAC-SHA512,
  • La clé,
  • Des paramètres temporels indiquant, par exemple, à partir de quand la clé sera valide.

Une fois qu'on a toutes ces informations, qu'est-ce qu'on met dans le paquet OSPF envoyé sur le câble ? La section 4 décrit le mécanisme. Le champ final d'authentification (Authentication Trailer) est composé notamment de l'identifiant d'un accord de sécurité (SA ID, décrit au paragraphe précédent, et qui permet au récepteur de trouver dans sa mémoire les paramètres cryptographiques liés à une conversation particulière), d'un numéro de séquence (qui sert de protection contre le rejeu ; il est augmenté à chaque paquet émis ; il comprend 64 bits, après une très longue discussion dans le groupe de travail, certains auraient préféré 32 bits) et du condensat cryptographique du paquet concaténé avec la clé (la section 4.5 décrit l'algorithme en détail et notamment quels champs du paquet sont inclus dans les données condensées).

Le routeur qui reçoit un paquet utilisant l'authentification (il le sait grâce au bit AT qui était notamment présent dans les paquets OSPF Hello) va accéder au champ d'authentification (le champ Longueur du paquet OSPF lui permet de savoir où commence le champ d'authentification, éventuellement en tenant compte du bloc Link-Local Signaling du RFC 5613, un routeur doit donc gérer au moins en partie ce dernier RFC s'il veut authentifier). Le récepteur refait alors le calcul cryptographique et vérifie si le champ final d'authentification est correct. Le calcul est très proche de celui du RFC 5709 à part l'inclusion de l'adresse IPv6 source.

Supposons que nous soyons administrateur réseaux et que nos routeurs gèrent tous ce nouveau RFC. Comment déployer l'authentification sans tout casser ? La section 5 recommande de migrer tous les routeurs connectés au même lien simultanément. Autrement, les routeurs qui n'utilisent pas l'authentification ne pourront pas former d'adjacences OSPF avec ceux qui l'utilisent. Le RFC prévoit un mode de transition, où le routeur envoie le champ final d'authentification mais ne le vérifie pas en entrée mais l'implémentation de ce mode n'est pas obligatoire.

La section 6 contient l'analyse de sécurité de cette nouvelle extension d'OSPF. Elle rappelle qu'elle ne fournit pas de confidentialité (les informations de routage seront donc accessibles à tout espion). Son seul but est de permettre l'authentification des routeurs, résolvant les problèmes notés par le RFC 6039. À noter que cette extension ne permet pas d'authentifier un routeur particulier mais simplement de s'assurer que l'émetteur est autorisé à participer au routage sur ce lien (tous les routeurs ont la même clé). La clé, rappelle cette section 6, devrait être choisie aléatoirement, pour ne pas être trop facile à deviner (cf. RFC 4552).

À ma connaissance, il n'existe pas encore d'implémentation de cette option dans le logiciel d'un routeur.


Téléchargez le RFC 6506


L'article seul

RFC 6497: BCP 47 Extension T - Transformed Content

Date de publication du RFC : Février 2012
Auteur(s) du RFC : M. Davis (Google), A. Phillips (Lab126), Y. Umaoka (IBM), C. Falk (Infinite Automata)
Pour information
Première rédaction de cet article le 23 février 2012


Le RFC 5646, qui normalise les étiquettes de langue, prévoit un mécanisme d'extension pour ajouter à ces étiquettes des informations maintenues dans des registres extérieurs. Ces extensions sont identifiées par une lettre unique et une nouvelle extension est ajoutée par notre RFC 6497, « T » (pour transformation), qui permet d'indiquer les transformations qu'a subies un texte (par exemple une traduction), en se référant au registre CLDR.

Le RFC 5646 est également connu sous l'identificateur « BCP 47 » (BCP pour Best Common Practice), ce qui explique le titre de notre RFC 6497. Les transformations qu'on pourra noter dans une étiquette de langue sont notamment la translittération, la transcription et la traduction. Sans cette extension « T », on ne peut étiqueter que l'état actuel du document. Par exemple, pes-Latn désignerait un texte en persan dans l'alphabet latin (ce qui est inhabituel) ; l'extension « T » permettra d'écrire pes-Latn-t-pes-arab, indiquant que le texte persan a été translittéré ou transcrit depuis l'alphabet arabe. Autre exemple, donné dans le RFC, une carte d'Italie pour des japonais où les noms des villes ont été translittérés en Katakana. N'indiquer que ja (langue japonaise) pour ce texte serait insuffisant. Cette information sur la source, donnée par l'extension « T » est souvent importante, pour aider à comprendre certaines particularités du texte (comme des fautes lors de la traduction). Le mécanisme des variantes du RFC 5646 ne suffisait pas pour cela, d'où la nouvelle extension. C'est la deuxième enregistrée, après la « U » du RFC 6067. Le mécanisme d'extension est normalisé dans le RFC 5646, sections 2.2.6 et 3.7. Les extensions sont enregistrées dans le registre IANA.

Parfois, il existe des méthodes standard de translittération ou de transcription. C'est par exemple le cas de celles spécifiées par l'UNGEGN. La nouvelle extension « T » permet également d'indiquer comment et par quelle méthode standard un texte a été translittéré ou transcrit.

Maintenant, les détails techniques : l'extension est notée par un t suivi d'une étiquette de langue légale (section 2, notamment 2.2). Ainsi, es-t-pid signifie que le texte est en espagnol, traduit du piaroa. Mais, comme le texte après t peut être une étiquette de langue complète, on peut noter bien plus de détails, comme l'écriture utilisée (comme dans l'exemple du perse plus haut). Comme l'étiquette de langue doit comporter obligatoirement une langue en première position, si celle-ci n'est pas connue ou tout simplement pas pertinente (rappelez-vous que la différence principale entre translittération et transcription est que la première ne dépend pas de la langue, c'est une opération purement mécanique sur les caractères), on la note par und, ce qui veut dire « inconnue ». Ainsi, und-Latn-t-und-cyrl signifie que le texte a été translittéré de l'alphabet cyrillique vers le latin (par exemple par l'algorithme ISO 9), sans tenir compte des langues en jeu.

Enfin, il est possible d'indiquer le mécanisme de transformation, en utilisant le séparateur m0, puis l'organisme qui spécifie ces mécanismes, puis un identificateur d'un mécanisme particulier. Ainsi, und-Cyrl-t-und-latn-m0-ungegn-2007 est du texte en alphabet latin, transformé en cyrillique, suivant la spécification UNGEGN de 2007. D'autres séparateurs que m0 seront peut-être créés dans le futur.

Quels termes peut-on mettre après m0 ? Ce qui vous passe par la tête ? Non. Il faut suivre la section 3 du document Unicode UTR #35. C'est d'ailleurs le consortium Unicode qui est l'autorité gérant l'extension « T » (section 2.4). Cela a suscité de vigoureuses discussions (pourquoi pas l'IETF ?). La conséquence en a été la définition d'un mécanisme plus ouvert pour soumettre des propositions de changement. Si on veut enregistrer de nouvelles possibilités (section 2.6), cela se fait en créant un ticket en http://cldr.unicode.org/index/bug-reports/.

La liste complète des possibilités de mécanismes de transformation figure dans un fichier structuré (section 2.9), librement accessible en http://cldr.unicode.org/index/downloads. Ce point a suscité beaucoup de débats sur la liste de diffusion de l'ancien groupe de travail LTRU. En effet, le fichier officiel est un gros .zip rempli de tas de choses qui n'ont rien à voir. Il faut donc tout télécharger puis trier (les transformations sont dans le répertoire common/transforms).


Téléchargez le RFC 6497


L'article seul

RFC 6493: The RPKI Ghostbusters Record

Date de publication du RFC : Février 2012
Auteur(s) du RFC : R. Bush (Internet Initiative Japan)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF sidr
Première rédaction de cet article le 4 février 2012


Les certificats de la RPKI, qui permettent de sécuriser le routage sur l'Internet en prouvant un droit à utiliser telle ou telle adresse IP, ne portent pas en clair de nom de titulaire. Cela peut être un problème dans certains cas opérationnels. Par exemple, une route reçue en BGP est refusée par le routeur, l'administrateur réseaux enquête, découvre un certificat qui a expiré, et voudrait prévenir le responsable qu'il a fait une boulette. Mais comment trouver le responsable ? Ou, selon la phrase culte du film Ghostbusters, « Who you gonna call? ». Ce RFC résout le problème en permettant de mettre une vCard dans le certificat, indiquant qui contacter en cas de problème.

Il n'y a guère de doute que ce genre de problèmes sera fréquent. La RPKI permet de distribuer des certificats numériques disant « le titulaire de la clé privée de ce certificat est responsable du préfixe IP 2001:db8:137::/48 ». Ce certificat est ensuite utilisé pour signer les ROA (Route Origin Authorization) qui indiquent quel AS peut annoncer ce préfixe. Si on se fie à l'expérience du déploiement d'autres technologies à base de cryptographie dans l'Internet (par exemple DNSSEC), il y aura des problèmes : préfixes trop génériques, interdisant des annonces plus spécifiques, certificats expirés, oubli de créer un nouvel ROA lorsqu'on contracte avec un nouveau transitaire BGP, etc. Ceux et celles qui détecteront les problèmes auront donc besoin de contacter les responsables, dans l'espoir qu'ils agissent.

Or, les métadonnées dans les certificats de la RPKI ne contiennent pas d'identificateurs utilisables par les humains (cf. RFC 6484). D'où l'idée de ce RFC, de mettre une vCard (plus exactement un profil restrictif des vCards du RFC 6350) dans un objet RPKI signé (la description de la syntaxe générique de ces objets est dans le RFC 6488).

Arrivé à ce stade, vous vous demandez peut-être « pourquoi un nouveau format au lieu d'utiliser les données des RIR, telles que publiées via whois ? ». La réponse est que l'enregistrement Ghostbusters identifie le responsable du certificat, qui n'est pas forcément le même que celui de la ressource (adresse IP ou numéro d'AS). Et puis, en pratique, les bases des RIR ne sont pas toujours correctes. Comme le chemin de mise à jour de l'enregistrement Ghostbuster est différent, peut-être sera-t-il parfois correct lorsque la base du RIR ne le sera pas ?

De toute façon, l'enregistrement Ghostbuster est facultatif. Un certificat peut en avoir zéro, un ou davantage. La section 3 du RFC fournit un exemple :

     BEGIN:VCARD
     VERSION:4.0
     FN:Human's Name
     ORG:Organizational Entity
     ADR;TYPE=WORK:;;42 Twisty Passage;Deep Cavern;WA;98666;U.S.A.
     TEL;TYPE=VOICE,TEXT,WORK;VALUE=uri:tel:+1-666-555-1212
     TEL;TYPE=FAX,WORK;VALUE=uri:tel:+1-666-555-1213
     EMAIL:human@example.com
     END:VCARD

En fait, cette vCard est embarquée dans un objet de la RPKI, qu'on peut lire avec des outils comme openssl. Voici un exemple sur un objet réel :

%  openssl asn1parse -inform DER \
          -in b-hiK-PPLhH4jThJ700WoJ3z0Q8.gbr
...
   60:d=5  hl=3 l= 139 prim: OCTET STRING      :BEGIN:VCARD
VERSION:3.0
EMAIL:michael.elkins@cobham.com
FN:Michael Elkins
N:Elkins;Michael;;;
ORG:Cobham Analytic Solutions
END:VCARD
...

Le sous-ensemble de vCard qui est accepté dans les chasseurs de fantômes est décrit en section 4. La définition est très restrictive : ne sont acceptées que les propriétés VERSION (qui doit valoir au moins 4, vous noterez que les enregistrements réels cités plus haut sont donc illégaux), FN, ORG, ADR, TEL et EMAIL (un enregistrement qui inclus N, comme ci-dessus, est donc illégal).

Ensuite (section 5), la vCard est embarquée dans un objet CMS signé (RFC 6488 ; la validation de ces enregistrements se fait de la même façon que pour les autres objets de la RPKI). Le type (OID) est 1.2.840.113549.1.9.16.1.35, ce qu'on voit dans la sortie d'openssl :

% openssl asn1parse -inform DER \
     -in owCgRbSAAkKS9W-MFbSAd7Bru2c.gbr 
...
   44:d=4  hl=2 l=  11 prim: OBJECT            :1.2.840.113549.1.9.16.1.35
   57:d=4  hl=3 l= 195 cons: cont [ 0 ]        
   60:d=5  hl=3 l= 192 prim: OCTET STRING      :BEGIN:VCARD
VERSION:3.0
ADR:;;5147 Crystal Springs;Bainbridge Island;Washington;98110;US
EMAIL:randy@psg.com
FN:Randy Bush
N:Bush;Randy;;;
ORG:RGnet\, LLC
TEL:+1 206 356 8341
END:VCARD

L'objet CMS est enfin mis dans un fichier d'extension .gbr. Fin 2011, on n'en trouvait que très peu dans les dépôts de la RPKI.

Attention, toutes ces données sont publiques. Comme le rappelle la section 8, sur la sécurité, publier ses informations dans un enregistrement Ghostbuster et vous risquez d'être harcelé par des commerciaux au téléphone ou bien spammé.

D'autre part, l'entité qui signe l'objet ne garantit nullement que les informations sont correctes. Elle garantit juste que ces informations ont bien été mises par le titulaire de la ressource (préfixe IP ou AS) correspondante. Celui-ci a pu mettre un numéro de téléphone ou une adresse de courrier bidon...


Téléchargez le RFC 6493


L'article seul

RFC 6492: A Protocol for Provisioning Resource Certificates

Date de publication du RFC : Février 2012
Auteur(s) du RFC : G. Huston, R. Loomans, B. Ellacott (APNIC), R. Austein (ISC)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF sidr
Première rédaction de cet article le 4 février 2012


La RPKI est l'infrastructure de création et de distribution de certificats pour les titulaires de ressources Internet (essentiellement les adresses IP), afin de sécuriser le routage sur l'Internet. Ce RFC normalise un protocole de communication pour réclamer ces certificats (avitaillement, ou provisioning). Il sera typiquement utilisé entre les RIR et les LIR.

Les termes exacts utilisés par le RFC sont Émetteur (Issuer), en général un RIR, qui va donc être une AC, et Destinataire (Subject), qui sera un FAI ou autre opérateur réseau. Le RIR distribue des INR (Internet Number Resource, ce sont les adresses IP et les numéros d'AS, collectivement nommés Ressources) et les certificats prouvant le droit du Destinataire à utiliser ces INR. Notez qu'un Destinataire peut être Émetteur pour des ressources qu'il redistribuera, par exemple à des opérateurs plus petits.

Le trafic attendu rend nécessaire d'automatiser l'avitaillement des certificats. Cela se fait avec un simple protocole (section 3), qui est une extension de HTTP. Le client HTTP fait une requête POST (RFC 7231, section 4.3.4), de type MIME application/rpki-updown. Le protocole est strictement requête/réponse (synchrone). Aussi bien le corps de la requête, que celui de la réponse du serveur, sont au format CMS (RFC 5652), encodé en DER. Le profil CMS est défini en section 3.1. CMS permet de transporter les signatures des différents objets (et les métadonnées associées comme la date de signature) mais le gros du contenu est un élément XML stocké dans le CMS sous le nom de RPKIXMLProtocolObject.

Cet élément XML est forcément <message>. Il forme l'essentiel de la requête ou de la réponse. Sa grammaire est décrite en Relax NG en section 3.7.

Quelles sont les opérations possibles ? Elles sont indiquées par l'attribut type de la requête. Par exemple, le client peut demander une liste des ressources que lui a alloué le serveur, avec type="list". La réponse arrivera sous forme d'une séquence d'éléments <class>. Ou bien il peut demander un certificat pour une nouvelle ressources avec type="issue".

Naturellement, vu que tout le but de l'exercice est d'augmenter la sécurité du routage dans l'Internet, les implémenteurs et les utilisateurs de ce RFC devraient bien faire attention à la section 4, qui couvre la sécurité de ce protocole d'avitaillement. Le RFC précise que l'Émetteur et le Destinataire doivent s'authentifier (par les siognatures contenues dans les messages CMS), en utilisant des lettres de créance qu'ils ont échangé précédemment (par un moyen non spécifié). On note que TLS n'est pas utilisé par ce protocole (ce fut une chaude discussion au sein du groupe de travail), CMS fournissant tous les services de sécurité nécessaires.

Je ne connais pas encore de mise en œuvre publique de ce protocole mais plusieurs RIR ont annoncé qu'ils auraient des serveurs prêts pour la sortie du RFC.


Téléchargez le RFC 6492


L'article seul

RFC 6491: RPKI Objects issued by IANA

Date de publication du RFC : Février 2012
Auteur(s) du RFC : T. Manderson, L. Vegoda (ICANN), S. Kent (BBN)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF sidr
Première rédaction de cet article le 4 février 2012


La RPKI est le système de distribution de certificats et d'objets signés avec les clés de ces certificats, qui permet de poser les bases d'une sécurisation du routage dans l'Internet, en permettant aux titulaires des ressources (préfixes d'adresses IP, notamment), d'autoriser tel ou tel opérateur et uniquement ceux-ci, à utiliser ces ressources. Certains préfixes ne sont pas alloués à un utilisateur, ils dépendent directement de l'IANA et ce RFC 6491 est donc consacré à lister les tâches de l'IANA pour ces préfixes. Par exemple, l'IANA devra émettre et signer un objet disant « Personne ne peut annoncer de route vers 198.51.100.0/24 (ce préfixe étant réservé, par le RFC 5737, à la documentation) ».

Rappelons que les responsabilités de l'IANA vis-à-vis de l'IETF sont fixées par le RFC 2860. Pour le cas particulier de la RPKI (RFC 6480), l'IANA va devoir verrouiller l'usage des préfixes IP qu'elle gère (section 1). Ces préfixes sont utilisées pour la documentation ou réservés pour d'autres usages. Comme personne ne doit les router, l'IANA va émettre des ROA (RFC 6482) négatifs, c'est-à-dire prouvant que ces adresses ne sont pas routables. Un routeur BGP validant (RFC 6483) va alors pouvoir les rejeter, si jamais ils apparaissent dans des annonces de routes. Ces ROA négatifs sont officiellement appelés « AS0 ROA », le numéro d'AS zéro étant invalide (il ne doit jamais être dans un chemin d'AS). La section 4 du RFC 6483 détaille ce concept de désaveu de route.

Ce désaveu s'applique aux préfixes qui sont prévus pour ne jamais apparaître dans la table de routage globale (section 5), ainsi qu'à ceux qui ne sont pas actuellement alloués et donc toujours à l'IANA (aujourd'hui, cela ne concerne plus qu'IPv6, cf. section 6). Les adresses « spéciales » (section 7, voir aussi le RFC 6890) se divisent, elles, en deux : celles prévues pour être routées globalement, pour lesquelles l'IANA ne doit rien faire, et celles non prévues pour être routées, et pour lesquelles il y aura donc un AS0 ROA.

La liste des préfixes figure en annexe A du RFC. On y trouve les suspects habituels, le préfixe 169.254.0.0/16 ou fe80::/10 des adresses locales au lien, les préfixes privés des RFC 1918 et RFC 4193, les préfixes réservés à la documentation... Tous ceux-ci ne seront jamais routés sur l'Internet.

Avant de commencer à émettre ces ROA, l'IANA devra évidemment établir une CA (section 10). Cette CA devra utiliser les extensions à X.509 du RFC 3779. Elle devra aussi publier la liste de ses objets (j'avoue n'avoir pas trouvé où c'était documenté sur le site de l'IANA...).


Téléchargez le RFC 6491


L'article seul

RFC 6488: Signed Object Template for the Resource Public Key Infrastructure

Date de publication du RFC : Février 2012
Auteur(s) du RFC : M. Lepinski, A. Chi, S. Kent (BBN)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF sidr
Première rédaction de cet article le 4 février 2012


Le système de sécurisation de BGP et du routage sur l'Internet, qui tourne autour de la RPKI, utilise des objets numériques signés cryptographiquement pour représenter les autorisations d'annoncer telle ou telle route. Ces objets sont définis avec la syntaxe CMS et le profil que normalise ce RFC.

Le contenu typique de ces objets est une autorisation du genre « L'AS 64641 est autorisé à annoncer le préfixe 192.0.2.0/24 ». Ils sont ensuite signés avec les clés contenues dans les certificats qui identifient le titulaire de ces ressources (ici, seul le titulaire de 192.0.2.0/24 peut émettre l'autorisation ci-dessus). Ces certificats suivent le format du RFC 6487.

Les objets d'autorisation utilisent la syntaxe de CMS (RFC 5652), celle-ci permettant de réutiliser les nombreux outils CMS existants (dont plusieurs en logiciel libre, voir mon article sur les outils de la RPKI). Sur cette syntaxe CMS est bâti le gabarit présenté par ce RFC 6488, qui s'applique à tous les objets de la RPKI. Enfin, sur ce gabarit, est bâti la syntaxe précise de chaque type d'objet. Par exemple, les ROA (Route Origination Authorization), une classe particulière d'objets, sont normalisés dans le RFC 6482.

La syntaxe est décrit dans la section 2 du RFC. CMS utilisant ASN.1, le profil de notre RFC 6488 est décrit en ASN.1. On part de la définition SignedData du RFC 5652 :

      SignedData ::= SEQUENCE {
        version CMSVersion,
        digestAlgorithms DigestAlgorithmIdentifiers,
        encapContentInfo EncapsulatedContentInfo,
        certificates [0] IMPLICIT CertificateSet OPTIONAL,
        crls [1] IMPLICIT RevocationInfoChoices OPTIONAL,
        signerInfos SignerInfos }

et on y ajoute quelques restrictions ou précisions. Par exemple, le digestAlgorithm doit être un de ceux spécifiés dans le RFC 6485. Même méthode pour les métadonnées de signature :

         SignerInfo ::= SEQUENCE {
           version CMSVersion,
           sid SignerIdentifier,
           digestAlgorithm DigestAlgorithmIdentifier,
           signedAttrs [0] IMPLICIT SignedAttributes OPTIONAL,
           signatureAlgorithm SignatureAlgorithmIdentifier,
           signature SignatureValue,
           unsignedAttrs [1] IMPLICIT UnsignedAttributes OPTIONAL }

Les objets de la RPKI doivent être encodés en DER. La liste des règles sémantiques à respecter figure dans la section 3.

Je le rappelle, ce profil, bien que spécialisé par rapport à CMS, est encore très générique. Chaque classe d'objets signés va donc nécessiter son propre RFC, remplissant les blancs indiqués par la section 4 :

  • Indiquer un OID pour la classe en question (1.2.840.113549.1.9.16.1.24 pour les ROA ou 1.2.840.113549.1.9.16.1.26 pour les manifestes du RFC 6486),
  • Définir la syntaxe du champ encapContentInfo (qui contient les données effectivement signées),
  • Indiquer les règles spécifiques de validation (pour un ROA : que le certificat signeur ait été émis pour le préfixe indiqué dans le ROA), s'ajoutant aux règles génériques de CMS (validité de la signature).

Ces classes d'objets sont ensuite enregistrés à l'IANA (section 6).

Notez bien que la sécurité que fournissent ces objets signés est d'authentification et d'intégrité. Les données ne sont pas chiffrées et donc pas confidentielles (section 5). C'est logique, les tables BGP et les informations dans les IRR sont publiques.


Téléchargez le RFC 6488


L'article seul

RFC 6487: A Profile for X.509 PKIX Resource Certificates

Date de publication du RFC : Février 2012
Auteur(s) du RFC : G. Huston, G. Michaelson, R. Loomans (APNIC)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF sidr
Première rédaction de cet article le 4 février 2012


La norme de certificats numériques X.509 est d'une telle complexité (comme beaucoup de productions des comités de l'UIT) qu'il est à peu près impossible de la mettre en œuvre complètement et correctement. La plupart de ses utilisations se font sur un profil de la norme, c'est-à-dire une restriction des usages possibles. De tels profils ont permis l'utilisation pratique de X.509, notamment sur l'Internet. Le profil décrit dans ce RFC a été conçu pour les certificats décrivant le « droit d'utilisation » des ressources Internet, ce qui veut dire, dans le monde du routage, les adresses IP et numéros d'AS (collectivement : les INR pour Internet Number Resources). Ces certificats ainsi profilés seront ensuite ceux utilisés pour la RPKI, afin de sécuriser le routage sur l'Internet.

Rappelons le principe : des certificats sont émis par une autorité, l'AC. Ces certificats suivent le profil décrit ici, qui est lui-même dérivé du profil PKIX du RFC 5280, de loin le plus répandu sur l'Internet. Ces certificats permettent à l'autorité de dire « le titulaire de ce certificat a le droit d'utiliser les adresses 2001:db8:f33::/48, par exemple de les annoncer en BGP », en utilisant les extensions INR du RFC 3779. L'engin qui va valider les routes (c'est typiquement une machine spécialisée, agissant pour le compte d'un routeur) fera une validation X.509 de la chaîne des certificats, plus quelques vérifications spécifiques aux INR (par exemple, dans certains cas, le certificat peut autoriser une route plus spécifique) et dira ensuite si la route est valide, ou bien si elle est émise par un attaquant (ou un maladroit qui a mal configuré BGP).

Donc, un certificat de la RPKI est un certificat PKIX. Les principaux points de notre nouveau profil (section 4) sont le fait que le sujet est un nom choisi par l'AC, la présence obligatoire des extensions INR (Internet Number Resources) du RFC 3779 (le certificat prouve le droit d'usage des préfixes IP indiqués dans ces extensions), et l'indication d'un dépôt accessible en rsync où se trouvent les CRL. Les sections 2 à 6 donnent tous les détails sur ces points.

Quant à la validation des certificats, elle fait l'objet de la section 7, qui précise les points généraux de la section 6 du RFC 5280. Notamment, un certificat peut être accepté même si le préfixe d'adresses présenté est plus spécifique (davantage de bits dans le masque).

La section 8 explique ensuite (et justifie) les principaux choix qui ont été faits lors de la conception de ce profil. Par exemple, notre profil ne permet pas d'utiliser des extensions X.509 autres que celles décrites dans ce RFC. Le but est d'utiliser les certificats dans un environnement bien défini, pour un usage limité, et il s'agit donc de limiter au maximum les risques de non-interopérabilité (un problème fréquent avec X.509, norme conçue par un comité et d'une très grande complexité ; bien des parties de la norme n'ont jamais été testées sur le terrain et nul ne sait comment réagiraient les implémentations). En outre, la RPKI est conçu pour être utilisée dans un contexte opérationnel (le routage sur l'Internet) et il était donc raisonnable de sacrifier l'extensibilité.

Quant au choix du nom du sujet, la RPKI n'étant pas centralisée, et n'ayant pas de système d'allocation arborescente des noms, on ne peut pas espérer avoir des noms uniques. Le RFC conseille donc aux AC (les RIR et les opérateurs réseau) d'adopter un schéma de nommage qui garantisse l'unicité au sein d'une même AC (rappelez-vous que, contrairement à l'utilisation de X.509 dans le cas de TLS, le nom du sujet n'est pas utilisé par la RPKI et n'est donc pas vérifié). Cela peut même être une valeur aléatoire comme un UUID.

L'annexe A du RFC fournit un exemple d'un certificat à ce profil. Mais on peut aussi l'obtenir en regardant un vrai certificat de la RPKI avec openssl (attention, il faut s'assurer qu'il ait été compilé avec l'option enable-rfc3779, ce qui n'est pas le cas chez Debian) :

% openssl x509 -inform DER -text -in \
    ./RPKI-repository/33/36711f-25e1-4b5c-9748-e6c58bef82a5/1/wdWccNZAgvBWFvBZNDJDWLtf-KQ.cer
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 78697736 (0x4b0d508)
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN=u75at9r0D4JbJ3_SFkZXD7C5dmg
        Validity
            Not Before: May 13 07:43:52 2011 GMT
            Not After : Jul  1 00:00:00 2012 GMT
        Subject: CN=wdWccNZAgvBWFvBZNDJDWLtf-KQ
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:99:d8:66:8b:26:15:22:fd:8e:45:c2:32:79:eb:
                    a4:36:d0:6d:47:18:34:d4:ad:17:bf:6f:82:d7:a3:
                    85:d9:80:ea:9f:59:31:6d:da:9f:b5:e0:36:67:e0:
                    f0:00:1b:96:2d:71:3e:5f:35:e0:f9:98:ee:fa:9f:
                    3e:6b:ab:9e:18:a6:ad:3c:fd:7a:50:6d:a5:42:4c:
                    bd:2d:02:f0:2a:7a:e6:66:bf:d5:b1:83:f1:19:02:
                    fe:90:21:d2:e3:b3:cc:91:a4:a6:6f:70:be:65:62:
                    7f:97:c1:43:2e:2c:a5:b2:14:79:e0:f5:5e:4b:c2:
                    aa:ed:13:d0:f2:4d:47:ac:53:fd:82:78:ef:c9:cd:
                    94:ea:52:10:56:88:80:bc:ca:ad:92:46:ef:4c:ae:
                    aa:ae:ae:02:d6:af:ae:2a:4e:dc:8b:c9:43:57:27:
                    84:1f:5a:82:ff:d7:24:ac:25:67:66:5f:70:d1:d6:
                    45:4b:a5:1d:c2:6f:bf:ae:14:3d:e4:2b:50:35:72:
                    ea:52:1c:b2:7d:15:12:15:07:d1:86:bb:2b:4b:ba:
                    47:1c:3e:37:b7:2c:ab:a6:4e:d3:16:54:84:96:92:
                    37:b6:6c:5c:3b:61:f1:73:9e:9c:9b:b8:ad:33:f8:
                    e0:19:9e:6a:dc:30:a6:45:90:f7:90:bb:d2:f9:65:
                    5b:53
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Key Identifier: 
                C1:D5:9C:70:D6:40:82:F0:56:16:F0:59:34:32:43:58:BB:5F:F8:A4
            X509v3 Authority Key Identifier: 
                keyid:BB:BE:5A:B7:DA:F4:0F:82:5B:27:7F:D2:16:46:57:0F:B0:B9:76:68

            X509v3 Basic Constraints: critical
                CA:TRUE
            X509v3 Key Usage: critical
                Certificate Sign, CRL Sign
            Authority Information Access: 
                CA Issuers - URI:rsync://rpki.ripe.net/ta/u75at9r0D4JbJ3_SFkZXD7C5dmg.cer

            Subject Information Access: 
                CA Repository - URI:rsync://rpki.ripe.net/repository/72/f82cc3-00a3-4229-92ff-e5992b4b3fad/1/
                1.3.6.1.5.5.7.48.10 - URI:rsync://rpki.ripe.net/repository/72/f82cc3-00a3-4229-92ff-e5992b4b3fad/1/wdWccNZAgvBWFvBZNDJDWLtf-KQ.mft

            X509v3 CRL Distribution Points: 

                Full Name:
                  URI:rsync://rpki.ripe.net/repository/33/36711f-25e1-4b5c-9748-e6c58bef82a5/1/u75at9r0D4JbJ3_SFkZXD7C5dmg.crl

            X509v3 Certificate Policies: critical
                Policy: 1.3.6.1.5.5.7.14.2

            sbgp-ipAddrBlock: critical
                IPv4:
                  81.27.128.0/20
                IPv6:
                  2a00:8980::/32

    Signature Algorithm: sha256WithRSAEncryption
        8f:03:51:23:44:85:92:42:54:37:a2:22:53:66:0a:ab:be:a7:
        ...
        2e:31:d5:0d
-----BEGIN CERTIFICATE-----
MIIFLDCCBBSgAwIBAgIEBLDVCDANBgkqhkiG9w0BAQsFADAmMSQwIgYDVQQDDBt1
...
-----END CERTIFICATE-----

Voyez notamment :

  • Le sujet (nom du titulaire du certificat) unique, ici CN=wdWccNZAgvBWFvBZNDJDWLtf-KQ généré à partir d'un condensat cryptographique,
  • L'indication de l'endroit où on peut récupérer les CRL (rsync://rpki.ripe.net/repository/33/36711f-25e1-4b5c-9748-e6c58bef82a5/1/u75at9r0D4JbJ3_SFkZXD7C5dmg.crl),
  • Le certificat de l'AC (rsync://rpki.ripe.net/ta/u75at9r0D4JbJ3_SFkZXD7C5dmg.cer),
  • Les extensions du RFC 3779, ici le bloc mal nommé sbgp-ipAddrBlock, qui contient un préfixe IPv4 et un IPv6 (attention, pour les voir, il faut un openssl compilé avec la bonne option).

Téléchargez le RFC 6487


L'article seul

RFC 6483: Validation of Route Origination using the Resource Certificate PKI and ROAs

Date de publication du RFC : Février 2012
Auteur(s) du RFC : G. Huston (APNIC), G. Michaelson (APNIC)
Pour information
Réalisé dans le cadre du groupe de travail IETF sidr
Première rédaction de cet article le 4 février 2012


Ce document s'inscrit dans la longue liste des RFC sur la sécurisation du routage BGP. Il décrit la sémantique des ROA (Route Origin Authorization), ces objets qui expriment l'autorisation du titulaire d'un préfixe IP à ce que ce préfixe soit annoncé initialement par un AS donné. La syntaxe des ROA, elle, figure dans le RFC 6482.

Les ROA (Route Origin Authorization) sont issus de la RPKI, l'IGC du routage (RFC 6480). Ce sont des objets signés qu'un routeur BGP peut vérifier lorsqu'il reçoit une annonce. Ainsi, si un routeur BGP voit son pair lui dire « je connais un chemin vers 192.0.2.0/24 et son chemin d'AS est 64498 65551 65540 », le routeur peut vérifier que l'AS 65540 a bien été autorisé, par le titulaire du préfixe 192.0.2.0/24, à annoncer cette route (l'origine, le premier AS, est le plus à droite ; ce RFC ne permet de valider que l'origine, pas le chemin complet, donc on ne peut rien dire au sujet de la présence des AS 64498 et 65551). Les clés utilisées pour les signatures sont contenues dans des certificats X.509 suivant le format Internet standard (RFC 5280) avec des extensions pour stocker des informations comme les adresses IP (RFC 3779). Ces certificats permettent de vérifier que le signataire était bien titulaire de la ressource (ici, le préfixe 192.0.2.0/24). Quant au format des ROA, on l'a dit, il figure dans le RFC 6482.

Tout d'abord (section 2 du RFC), que se passe-t-il pendant la validation d'une annonce de route et quels sont les résultats possibles ? Une route est composée d'un ensemble de préfixes IP, d'un chemin d'AS et de quelques attributs. L'origine, la seule chose vérifiée par les ROA, est le premier AS du chemin (donc le plus à droite). S'il y a eu agrégation, et que le premier élément du chemin est un ensemble d'AS, l'origine est inconnue.

L'engin qui fait la validation (nommé RP, pour Relying Party, c'est le routeur BGP, ou bien une machine spécialisée à laquelle il a sous-traité ce travail) est supposé avoir accès à tous les ROA valides (ce RFC ne décrit pas comment, a priori, ce sera le protocole standard de récupération des préfixes validés, protocole nommé RTR, normalisé dans le RFC 6810). Il cherche les ROA s'appliquant à l'annonce qu'il veut valider. Si un ROA correspond, l'annonce est valide. Un ROA pour un préfixe donné s'applique à tous les préfixes plus spécifiques (ceux où le masque est plus long). Ainsi, si un ROA dit « l'AS 65540 a le droit d'annoncer 192.0.2.0/24 », alors une annonce de 192.0.2.128/25 (plus spécifique) est invalide (même si l'origine est la même, cf. le tableau Route's validity state). Toutefois, l'utilisation du champ maxLength dans le ROA permet d'accepter des préfixes plus spécifiques (jusqu'à maxLength). Si une annonce ne correspond à aucun ROA, elle est dans l'état « inconnu » (également appelé « non trouvé »). Au début du déploiement, évidemment, la plupart des annonces seront dans l'état inconnu, puisque peu de ROA seront émis. Mais dès qu'un opérateur crée un ROA pour un de ses préfixes, tous les sous-préfixes non signés deviennent invalides (la RPKI suit le modèle hiérarchique des adresses IP). L'algorithme exact est décrit à la fin de la section 2. (Ceux qui ont suivi toute l'histoire de ce RFC avant sa publication noteront que l'algorithme initial était bien plus complexe.)

Maintenant, que faire de ce résultat ? La section 3 explique comment utiliser cet état (valide, invalide, inconnu) pour sélectionner une route (rappelez-vous qu'un routeur BGP typique reçoit plusieurs routes possibles pour chaque préfixe et qu'il doit choisir). En gros, le routeur doit préférer les routes valides, puis les inconnues. Mais la décision est locale : le RFC n'impose rien, notamment il ne dit pas si le routeur doit ignorer complètement les annonces invalides ou, a fortiori, les inconnues (la très grande majorité, au début du déploiement de ce système). Autre piège : la vitesse de propagation des ROA ne sera pas forcément celle des routes, et une annonce peut arriver avant le ROA correspondant.

Le problème est similaire à celui que connaissent les résolveurs DNS avec DNSSEC. Rejeter les réponses DNS non signées, aujourd'hui, reviendrait à rejeter la majorité des réponses. (Une autre expérience de DNSSEC est que les réponses invalides sont beaucoup plus souvent dues à des erreurs du gentil administrateur systèmes qu'à des attaques par les méchants.) Pour BGP, le problème est plus complexe car il est normal de recevoir plusieurs routes vers la même destination. Sans rejeter les annonces inconnues, le routeur peut donc décider de les faire passer après les valides. Et, s'il n'y a qu'une seule route pour une destination donnée, et que l'annonce est invalide, il vaut peut-être mieux l'accepter que de couper la communication avec le réseau concerné (la résilience de l'Internet le recommande).

Donc, pour résumer la section 3 : chaque administrateur réseaux configure son routeur comme il veut, pour décider du sort des annonces inconnues, et même pour celui des annonces invalides. Un exemple en syntaxe IOS serait :

route-map rpki permit 10
 match rpki invalid
 set local-preference 50

route-map rpki permit 20
 match rpki unknown
 set local-preference 100

route-map rpki permit 30
 match rpki valid
 set local-preference 200

Dans cet exemple, tous les états sont acceptés, mais avec des préférences différentes.

Il est également possible à un titulaire de préfixe d'interdire complètement l'utilisation de ce préfixe, en créant un ROA où le numéro d'AS est mis à zéro (section 4). L'AS 0 est réservé dans le registre IANA et ne doit jamais apparaître dans une annonce réelle.

Une fois une route validée, pendant combien de temps garde-t-elle son état ? Question facile à laquelle la section 5 répond : la durée de validité est celle du certificat qui a signé le ROA (rappelez-vous que les ROA indiquent l'AS d'origine, et que c'est une information relativement stable). Si on veut annuler un ROA avant, il faut révoquer le certificat qui l'a signé.

La section 6 rassemble les considérations de sécurité des ROA : d'abord, elle rappelle qu'il y a un risque réel de se tirer dans le pied. Si on publie un ROA pour un préfixe, les préfixes plus spécifiques deviennent aussitôt invalides. Si on a de ces préfixes plus spécifiques, il faut donc penser à leur créer un ROA avant de publier le ROA le plus général.

Voilà, si vous voulez mettre tout cela en pratique, lisez mon article sur les logiciels de la RPKI.


Téléchargez le RFC 6483


L'article seul

RFC 6482: A Profile for Route Origin Authorizations (ROAs)

Date de publication du RFC : Février 2012
Auteur(s) du RFC : M. Lepinski, S. Kent, D. Kong (BBN Technologies)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF sidr
Première rédaction de cet article le 4 février 2012


Un nouveau sigle va devoir être appris par les administrateurs réseaux et sera sans doute souvent prononcé dans les discussions sur les listes de diffusion d'opérateurs : ROA, pour Route Origin Authorizations, ces objets signés cryptographiquement qui permettent à un routeur BGP de valider l'origine d'une route. Dans la très longue liste des RFC décrivant ce système de sécurité, notre court RFC 6482 décrit le format des ROA. Il a depuis été remplacé par le RFC 9582.

Ces ROA (Route Origin Authorizations) sont, à bien des égards, le cœur du système de sécurisation du routage de l'Internet (dont l'architecture générale est décrite dans le RFC 6480). Ils expriment des autorisations d'annonce, par exemple « L'AS 64641 est autorisé à annoncer le préfixe 192.0.2.0/24 » et sont signés par le titulaire de la ressource (ici, le titulaire du préfixe 192.0.2.0/24).

Le format des ROA est tiré de la norme CMS (RFC 5652), précisée par le profil générique des objets de la RPKI, dans le RFC 6488. Ce dernier RFC précise, dans sa section 4, les points spécifiques à normaliser pour chaque classe d'objets de la RPKI. Dans le cas des ROA, ces blancs sont remplis ainsi :

  • L'OID de la classe « ROA » est 1.2.840.113549.1.9.16.1.24 (section 2),
  • Le contenu du ROA est composé (section 3) d'un numéro d'AS (celui qui est autorisé à être à l'origine de la route) et d'un ou plusieurs préfixes IP (un seul dans l'exemple plus haut), qui sont les préfixes où cet AS peut être à l'origine,
  • Des règles de validation spécifiques au ROA sont indiquées (section 4).

Le contenu précis, tel qu'indiqué dans la section 3, est, en ASN.1 :

      RouteOriginAttestation ::= SEQUENCE { 
         version [0] INTEGER DEFAULT 0, 
         asID  ASID, 
         ipAddrBlocks SEQUENCE (SIZE(1..MAX)) OF ROAIPAddressFamily } 

asID est le numéro d'AS, et ipAddrBlocks la liste des préfixes. Les ROAIPAddressFamily sont composées de ROAIPAddress et celles-ci ont un attribut intéressant, maxLength, qui indique la longueur maximale des sous-préfixes que peut annoncer cet AS. Par exemple, en IPv6, un maxLength de 56 indiquera qu'on peut annoncer un /56 mais pas un /60. L'autre attribut d'une ROAIPAddress est le préfixe, représenté selon les règles du RFC 3779.

La section 4 décrit quant à elle les règles de validation spécifiques aux ROA : aux règles génériques des objets de la RPKI, elle ajoute l'obligation de vérifier que les adresses indiquées dans le ROA figurent bien dans le certificat signataire (c'est-à-dire que c'est bien le titulaire des adresses qui a émis le ROA). Mais il vaut mieux consulter le RFC 6483 pour avoir tous les détails.

À noter qu'on ne peut mettre qu'une seule signature par ROA. Une des vives discussions du groupe de travail SIDR avait porté sur la possibilité de signatures multiples, afin de gérer certaines relations complexes entre clients et opérateurs, mais cela avait finalement été rejeté.

On peut récupérer tous les ROA des préfixes RIPE en https://certification.ripe.net/certification/public/all-roas. Si on en télécharge un, on peut afficher ce contenu avec l'outil du même RIPE-NCC :

% certification-validator  --print -f  roa-5574190.roa
Content type: 1.2.840.113549.1.9.16.1.24                        
Signing time: 2011-01-11T19:04:18.000Z
ASN: AS559
Prefixes:
    193.5.26.0/23 [24]
    193.5.152.0/22 [24]
    193.5.168.0/22 [24]
    193.5.22.0/24
    193.5.54.0/23 [24]
    193.5.58.0/24
    193.5.60.0/24
    193.5.80.0/21 [24]

ou bien avec l'outil de l'ARIN, rcynic :

% print_roa /home/bortzmeyer/tmp/roa-5574190.roa
Certificates:   1
CRLs:           0
SignerId[0]:    b6:6f:5a:10:d5:7f:ed:6d:b1:62:96:2c:cb:92:35:bb:5d:f8:c3:ca [Matches certificate 0] [signingTime(U) 110111190418Z]
eContentType:   1.2.840.113549.1.9.16.1.24
version:        0 [Defaulted]
asID:           559
 addressFamily: 1
     IPaddress: 193.5.26.0/23-24
     IPaddress: 193.5.152.0/22-24
     IPaddress: 193.5.168.0/22-24
     IPaddress: 193.5.22.0/24
     IPaddress: 193.5.54.0/23-24
     IPaddress: 193.5.58.0/24
     IPaddress: 193.5.60.0/24
     IPaddress: 193.5.80.0/21-24

Comme les ROA sont en CMS, on peut aussi tenter sa chance avec des logiciels qui traitent du CMS générique. Ils ne comprendront pas tout mais pourront au moins afficher une partie de la structure :

% openssl asn1parse -inform DER -in RFZr0zO7xjc1bNCEVboVjI8JZlw.roa
    0:d=0  hl=2 l=inf  cons: SEQUENCE          
    2:d=1  hl=2 l=   9 prim: OBJECT            :pkcs7-signedData
...
 1340:d=7  hl=2 l=   9 prim: OBJECT            :contentType
 1351:d=7  hl=2 l=  13 cons: SET               
 1353:d=8  hl=2 l=  11 prim: OBJECT            :1.2.840.113549.1.9.16.1.24
 1366:d=6  hl=2 l=  28 cons: SEQUENCE          
 1368:d=7  hl=2 l=   9 prim: OBJECT            :signingTime
 1379:d=7  hl=2 l=  15 cons: SET               
 1381:d=8  hl=2 l=  13 prim: UTCTIME           :110406122632Z
 1396:d=6  hl=2 l=  47 cons: SEQUENCE          
...

De même, les outils génériques ASN/1 comme dumpasn1 peuvent permettre de récupérer une partie de l'information dans le ROA. D'autres outils pour jouer avec les ROA sont présentés dans mon article sur les logiciels de la RPKI.

Un exposé d'Arnaud Fenioux à l'assemblée générale du France-IX en septembre 2017 montrait l'utilisation de ces ROA au France-IX.


Téléchargez le RFC 6482


L'article seul

RFC 6481: A Profile for Resource Certificate Repository Structure

Date de publication du RFC : Février 2012
Auteur(s) du RFC : G. Huston (APNIC), R. Loomans (APNIC), G. Michaelson (APNIC)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF sidr
Première rédaction de cet article le 4 février 2012


La RPKI, cette infrastructure de certificats utilisée pour sécuriser le routage sur l'Internet, repose sur un certain nombre d'objets (certificats mais aussi révocations et surtout les objets signés qui expriment les autorisations, les ROA). Ce RFC décrit comment ils sont stockés dans les points de publication à partir desquels ils sont distribués au monde entier. Cela permet de consolider facilement les données obtenues auprès de plusieurs points de publication. (Il n'est pas obligatoire qu'une copie de la RPKI soit complète.)

Rappelez-vous en effet que les routeurs n'accèdent pas aux informations de la RPKI lorsqu'ils en ont besoin (ce qui ferait dépendre le routeur de serveurs extérieurs) mais à l'avance en chargeant dans un validateur la totalité des informations, que le validateur va ensuite vérifier avant de passer au routeur. Comment se présentent ces informations ? Chacun fait comme il veut mais il existe une forme recommandée, celle de notre RFC 6481.

Dans ce format recommandé, chaque objet va être un fichier. Ces fichiers vont être placés dans une arborescence de répertoires, référencée par un URI (typiquement de type rsync:).

Dans les exemples ci-dessous, j'utiliserai une copie locale de la RPKI obtenue au RIPE-NCC, avec les outils logiciels de ce même RIPE-NCC (voir mon article sur ces outils).

À chaque point de publication (typiquement, chaque AC, c'est-à-dire en pratique chaque opérateur réseau), on trouve un manifeste qui liste les objets publiés. Le fichier a l'extension .mft, le type MIME application/rpki-manifest (cf. section 7.1 du RFC) et son nom est un condensat cryptographique de la clé publique de l'AC (en suivant par exemple la section 2.1 du RFC 4387). Voici le contenu d'un tel manifeste, à un petit point de publication (seulement quatre ROA) :

% certification-validator -print -file Sxe2vn2-fqZLB5Q578V0Vzf_RfQ.mft
Serial: 39571085
Subject: CN=779caa1de4e5938149c831b097a86ee561bf12f3
Not valid before: 2011-10-31T03:42:07.000Z
Not valid after:  2011-11-01T03:42:07.000Z
...
Filenames and hashes:
    1c_GrZeKKzG5b9BI9Iu4fEEG-QU.roa 20aade4dd3e303103b7facb0d462d89e0cc74753c99bf35a8ff28d16e48f7e6a
    1sOqx9K6uCNTcCTMIe7f5P1bZX0.roa 7e9c4c0be54d180b05743abbd6163f0a812c43d4db59fe0550eb2446ceedbb7e
    4nKGhPF4_7JKjwwBrTCXgE_4YYg.roa f1f55d72eb6e66c36b6312c4c6484a83156d32b7e01067a6a3449327095e409f
    Sxe2vn2-fqZLB5Q578V0Vzf_RfQ.crl 39ec393db6b9a8ec6289304a5c1982ab17ef3bfc5feaffaf4a30174af9054966
    TZw7cXuBc5b9BOlBHqCtAEgTZ-w.roa bd7aa3efae357a8591a7b5d708ccb509ad30f791063ea6fe9aa53730d95cb680

On trouve également des révocations, dans des fichiers ayant l'extension .crl (et le type MIME application/pkix-crl qui vient du RFC 2585) :

% certification-validator -print -file Sxe2vn2-fqZLB5Q578V0Vzf_RfQ.crl
CRL type: X.509
CRL version: 2
Issuer: CN=Sxe2vn2-fqZLB5Q578V0Vzf_RfQ
Authority key identifier: Sxe2vn2-fqZLB5Q578V0Vzf_RfQ=
Number: 790
This update time: 2011-10-31T03:42:07.000Z
Next update time: 2011-11-01T03:42:07.000Z
Revoked certificates serial numbers and revocation time:
    32399600 2011-09-10T05:40:48.000Z

On trouve bien sûr les certificats, encodés au format DER et stockés dans des fichiers ayant l'extension .cer et le type MIME application/pkix-cert :

% certification-validator -print -file Fx2dYP3STZSiTUjLGrM8oDkK4Ys.cer
Serial: 18282008
Subject: CN=Fx2dYP3STZSiTUjLGrM8oDkK4Ys
Not valid before: 2011-01-12T02:39:31.000Z
Not valid after:  2012-07-01T00:00:00.000Z
Resources: 46.254.48.0/21

Notez qu'il s'agit d'un format standard donc OpenSSL peut l'afficher aussi (pour voir les ressources gérées, ici 46.254.48.0/21, il faut un OpenSSL compilé avec l'option RFC 3779) :

% openssl x509 -inform DER -text -in Fx2dYP3STZSiTUjLGrM8oDkK4Ys.cer
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 18282008 (0x116f618)
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN=u75at9r0D4JbJ3_SFkZXD7C5dmg
        Validity
            Not Before: Jan 12 02:39:31 2011 GMT
            Not After : Jul  1 00:00:00 2012 GMT
        Subject: CN=Fx2dYP3STZSiTUjLGrM8oDkK4Ys
...
            sbgp-ipAddrBlock: critical
                IPv4:
                  46.254.48.0/21

Et, bien sûr, le dépôt contient des autorisations d'annonces de route, les ROA (Route Origination Authorization), normalisés dans le RFC 6482. Elles sont contenues dans des fichiers d'extension .roa et ont le type MIME application/rpki-roa :

% certification-validator -print -file FiUGfSV6BgZqFlJnQ7SSq_700w8.roa 
Content type: 1.2.840.113549.1.9.16.1.24
Signing time: 2011-04-11T15:07:23.000Z
ASN: AS56595
Prefixes:
    46.226.0.0/21
    2a00:a600::/32

Le ROA ci-dessus autorise l'AS 56595 à annoncer des routes pour 46.226.0.0/21 et 2a00:a600::/32. À noter que la suite logicielle rcynic permet également l'affichage de ROA :

% print_roa FiUGfSV6BgZqFlJnQ7SSq_700w8.roa
Certificates:   1
CRLs:           0
SignerId[0]:    16:25:06:7d:25:7a:06:06:6a:16:52:67:43:b4:92:ab:fe:f4:d3:0f [Matches certificate 0] [signingTime(U) 110411150723Z]
eContentType:   1.2.840.113549.1.9.16.1.24
version:        0 [Defaulted]
asID:           56595
 addressFamily: 1
     IPaddress: 46.226.0.0/21
 addressFamily: 2
     IPaddress: 2a00:a600::/32

La section 3 décrit ensuite les caractéristiques souhaitées du serveur qui va publier toutes ces informations. Il doit notamment être très fiable : même si le serveur n'est évidemment pas accédé de manière synchrone, à chaque mise à jour BGP, il doit néanmoins être accessible la grande majorité du temps, puisque toute panne empêchera les mises à jour de la base et aura potentiellement des conséquencees opérationnelles sur le routage. C'est une tâche nouvelle, par exemple pour les RIR, qui n'avaient pas de rôle opérationnel avant.

Ce serveur doit utiliser rsync (cf. RFC 5781) et peut aussi utiliser d'autres protocoles en prime. Grâce à rsync, la commande :

% rsync -av rsync://rpki.ripe.net/repository /var/RPKI

va vous récupérer tous les objets décrits ici, tels qu'ils sont distribués par le RIPE-NCC, et les mettre dans le répertoire /var/RPKI. rsync travaillant de manière incrémentale, seules les nouveautés seront chargées, pas la totalité de la base (sauf la première fois).

Cette commande peut donc être placée dans le crontab de la machine qui fera la validation. Toutefois, la section 3 recommande des techniques plus subtiles, à base de copie dans un dépôt temporaire puis de renommage (ce que font automatiquement les outils de rcynic), avant d'éviter une incohérence si le rsync est interrompu et qu'on n'a récupéré qu'une partie de la base.

Cette copie locale de la RPKI dans le validateur (machine qui sera proche des routeurs qui l'interrogeront) permettra de fonctionner même en cas de panne des serveurs de distribution (cf. section 5).

Attention à la sécurité, nous avertit la section 6. Les informations de la RPKI sont publiques, il n'y a donc pas besoin de confidentialité, mais il est essentiel que leur intégrité soit préservée. Le protocole rsync utilisé plus haut ne fournit aucune garantie en ce sens. En fait, la protection des données est complètement assurée par les signatures faites avec les clés contenues dans les certificats. Il ne faut donc pas utiliser les informations RPKI récupérées avant d'avoir validé (vérifié les signatures). C'est ce que fait automatiquement rcynic en déplaçant les données validées dans un répertoire nommé authenticated :

% pwd   
/var/rcynic/data

% ls -lt
total 12
lrwxrwxrwx  1 rcynic rcynic   34 Oct 31 15:42 authenticated -> authenticated.2011-10-31T13:36:08Z
lrwxrwxrwx  1 rcynic rcynic   34 Oct 31 15:42 authenticated.old -> authenticated.2011-10-31T11:36:11Z
drwxr-xr-x 15 rcynic rcynic 4096 Oct 31 15:42 authenticated.2011-10-31T13:36:08Z
drwxr-xr-x 15 rcynic rcynic 4096 Oct 31 14:31 authenticated.2011-10-31T11:36:11Z
drwxr-xr-x 17 rcynic rcynic 4096 Oct 31 11:31 unauthenticated

Les extensions des différents fichiers stockés figurent dans un registre IANA.


Téléchargez le RFC 6481


L'article seul

RFC 6480: An Infrastructure to Support Secure Internet Routing

Date de publication du RFC : Février 2012
Auteur(s) du RFC : M. Lepinski, S. Kent (BBN Technologies)
Pour information
Réalisé dans le cadre du groupe de travail IETF sidr
Première rédaction de cet article le 4 février 2012


Les techniques de sécurisation de BGP du groupe de travail SIDR viennent d'être publiées. Elles reposent sur une infrastructure de clés publiques cryptographiques, la RPKI (Resource Public Key Infrastructure). Ce RFC décrit cette RPKI, fondation de tous les systèmes de sécurisation du routage dans l'Internet, ainsi que l'architecture générale du système.

Le principe est le suivant : le titulaire d'un préfixe IP a un certificat lui permettant de signer des objets, par lesquels il autorise tel ou tel AS à annoncer ce préfixe. Ces signatures peuvent être ensuite vérifiées par les routeurs, qui rejetteront les erreurs et les tentatives de piratage.

La section 1 résume les trois composants essentiels de la solution, qui permettra de protéger le routage BGP (RFC 4271) :

  • La RPKI, l'infrastructure de gestion de clés, dont la hiérarchie est plaquée sur l'actuelle hiérarchie d'allocation des adresses (IANA -> RIR -> LIR, etc),
  • Des objets numériques signés (par les clés contenues dans les certificats de la RPKI), les routing objects, qui expriment les autorisations de routage,
  • Le mécanisme de distribution de ces objets, pour que les routeurs y aient accès afin de valider les annonces BGP.

Dans un premier temps, cette solution permettra de valider l'origine des annonces BGP (le premier AS, cf. RFC 6483). Plus tard, elle pourra servir de base à des solutions plus globales, encore en cours de développement, comme soBGP ou Secure Border Gateway Protocol (Secure-BGP).

La correspondance entre le graphe des certificats et celui existant pour allouer des ressources comme les adresses IP évite de réinventer une nouvelle classe d'acteurs. Cela ne veut pas dire que les rapports de force ne vont pas être modifiés. Ainsi, à l'heure actuelle, un RIR peut toujours, techniquement, retirer un préfixe à un LIR, mais cela n'aura pas de conséquence pratique, le RIR n'ayant aucun rôle dans le routage. Demain, avec la RPKI, le RIR enverra une révocation et les routeurs considéreront la route comme invalide... Il y a donc bien renforcement des pouvoirs de la hiérarchie, comme l'analysait un article de l'IGP.

Techniquement, peu de protocoles ou de formats nouveaux sont développés. Ainsi, les certificats de la RPKI sont du X.509, avec les extensions déjà existantes de l'IETF, RFC 5280, plus celles permettant de représenter des ressources (adresses IP et numéros d'AS), normalisées dans le RFC 3779 et suivant le profil du RFC 6487. Les objets signés (cf. RFC 6488) utilisent quant à eux le format CMS (RFC 5652).

Le premier des trois composants, la RPKI (Resource Public Key Infrastructure), est décrit en section 2. L'idée est que c'est le titulaire d'une plage d'adresses IP qui décide comment elle peut être routée et par qui. Les certificats permettent donc d'attester que telle entité est bien le titulaire (ce qui se fait actuellement en consultant la base du RIR, par exemple via whois). L'IANA va donc signer les plages qu'elle alloue aux RIR (cette étape est optionelle, voir plus loin), les RIR signent les plages qu'ils allouent aux LIR et ainsi de suite si nécessaire (il y a des cas plus complexes, pour les NIR, ou bien pour les adresses PI, ou encore lorsqu'un titulaire sous-alloue une partie de ses adresses). Lorsqu'un certificat affirmera « je suis titulaire du 192.0.2.0/24 », il sera ainsi possible de remonter la chaîne, jusqu'à une référence de confiance (l'IANA ou bien l'ensemble des RIR) pour vérifier cette assertion. Donc, bien que le routage dans l'Internet ne soit pas hiérarchique, l'allocation l'est, et la RPKI s'appuie là-dessus.

Les exemples ci-dessus portent sur des adresses IP mais le raisonnement est le même pour les numéros d'AS, d'où ce nom collectif de ressources (adresses IP et numéros d'AS).

Il faut bien noter que ces certificats, s'ils sont techniquement des certificats X.509 comme les autres, ont une sémantique différente; Le fait qu'une CA signe un certificat ne dit pas qu'elle certifie l'identité contenu dans le certificat mais qu'elle certifie le lien entre une ressource et un titulaire. Ces certificats sont davantage d'autorisation que d'authentification. Le RFC recommande simplement de mettre comme nom (X.509 appelle cela le subject) un identificateur spécifique à la CA, par exemple un numéro de client.

Comme cette sémantique est différente, et qu'il n'y a pas les risques juridiques associés aux certificats d'authentification classiques, il n'y a donc pas de nécessiter d'utiliser les CA existantes, ni de raison d'hésiter, pour un opérateur, à devenir CA. Les certificats fournis aux entités intermédiaires (typiquement les LIR) doivent être des certificats CA, autorisant le titulaire à émettre lui-même des certificats (la signature de chaque objet nécessite la création d'un certificat pour cet objet, cf. section 2.2). Les sites terminaux, en général, n'auront pas besoin de certificats du tout (sauf s'ils sont multi-homés avec des adresses PI, cf. section 7.3.2).

Les certificats finaux (section 2.3), ceux qui n'auront pas besoin d'avoir le bit CA à un, servent pour signer les objets (l'intérêt de créer un certificat juste pour signer un objet est de permettre une révocation, en réutilisant les mécanismes existants de X.509).

Pour vérifier, les validateurs (les routeurs BGP, ou bien les machines à qui ces routeurs sous-traiteront le travail), auront besoin de certificats « racine ». Comme en général pour X.509, le choix de ces certificats est une question politique locale et n'est pas spécifiée par la norme. Le RFC évite ainsi (section 2.4) l'épineuse question politique de savoir s'il faut configurer le validateur avec le certificat de l'IANA (donnant à celle-ci un grand pouvoir) ou bien avec les certificats des cinq RIR (court-circuitant ainsi l'IANA).

La section 3, elle, décrit les objets qu'on va signer, les ROA (Route Origination Authorization). La RPKI va dire « il est le titulaire de 192.0.2.0/24 » et le ROA va ajouter « l'AS 64641 est autorisé à annoncer 192.0.2.0/24 » (le ROA n'autorise que l'origine, pas les AS ultérieurs qui relaieront l'annonce). Le ROA est donc tout au bout du graphe des autorisations. On pourrait donc avoir une chaîne comme :

  • IANA : « ARIN gère 192.0.0.0/8 »,
  • ARIN : « le FAI Example est titulaire de 192.0.2.0/24 »,
  • Example : « l'AS 64641 est autorisé à être l'origine d'une annonce de 192.0.2.0/24 » (cette dernière assertion étant un ROA).

Le format des ROA est décrit en RFC 6482 et leur utilisation dans la validation des annonces BGP en RFC 6483. Le format est une spécialisation du format générique des objets de la RPKI, décrit dans le RFC 6488, lui-même issu de CMS. Chaque ROA contient un numéro d'AS, un ou plusieurs préfixes que cet AS a l'autorisation d'« originer » et (facultativement) une longueur maximale des sous-préfixes. Notez bien qu'il n'y a qu'un AS. Si plusieurs AS ont le droit d'être à l'origine des annonces de ces préfixes, il faut créer plusieurs ROA. Il n'y a pas de durée de validité dans le ROA, la validité est celle du certificat.

La distribution des ROA se fait essentiellement par le système de dépôts décrit dans la section 4 mais pourrait se faire dans le futur par d'autres moyens, comme les messages BGP UPDATE. On l'a vu, la validation des routes suppose que les validateurs (les routeurs BGP eux-même, ou bien des machines spécialisées à qui les routeurs sous-traitent l'opération) aient accès à tous les ROA. (Ce n'est pas un nombre énorme, typiquement un seul par route visible mondialement.) Un mécanisme est proposé pour créer un dépôt distribué de ROA, accessible à la demande (les mécanismes où les ROA seraient poussés vers les validateurs, par exemple par BGP, ne sont pas encore définis). Le dépôt est décrit en détail dans le RFC 6481.

Le dépôt n'est pas spécialement « de confiance ». Ce sont les signatures sur les ROA qui comptent, pas l'endroit où ils ont été récupérés. C'est d'autant plus vrai que le RFC encourage à recopier le dépôt, pour faciliter l'accès.

Le dépôt pourra offrir un choix de protocoles d'accès (section 4.3). Notre RFC décrit juste les fonctions de ces protocoles :

  • Téléchargement en bloc de toutes les données (rappelez-vous que le validateur est supposé avoir une vue complète). Les données sont donc réellement publiques.
  • Ajout d'une donnée, ou modification d'une donnée existante.

Des tas de protocoles offrent ces fonctions (par exemple HTTP/REST, même s'il n'est pas cité). Pour éviter que chaque acteur du routage ne déploie un protocole d'accès différent, rendant la vie des clients infernale, notre RFC impose que chaque copie soit accessible en lecture avec rsync, garantissant ainsi un mécanisme toujours disponible. On désigne donc la copie avec un URI rsync (RFC 5781) et on y accède par :

% rsync -av rsync://rpki.ripe.net/repository /where/i/want/RPKI-repository

Les experts en sécurité ont peut-être noté un peu de hand waving dans les paragraphes précédents. J'ai dit que la sécurité du dépôt était peu importante puisque ce sont les signatures des ROA qui font foi et que l'endroit où on les a trouvé ne compte donc pas. Mais si un méchant arrive à modifier un dépôt et supprime un ROA ? La signature ne protège pas contre ce genre de problèmes. La RPKI a donc un système de manifestes, des listes d'objets signés, listes elle-même signées et mises dans le dépôt (section 5 et RFC 6486).

Le dépôt sera donc massivement distribué, et les validateurs encouragés à garder des copies locales. La section 6 décrit ce processus, où le validateur obtient la copie de tous les objets (ROA, certificats, manifestes, etc), valide la signature des manifestes, puis vérifie leur contenu, et vérifie la signature des objets indiqués dans le manifeste.

Comme avec tous les caches, cette copie pose le problème de la fraîcheur des informations. Le cache ne contient-il pas des informations dépassées ? La section 6 n'est pas très bavarde sur ce point. À l'heure actuelle, ces informations de routage sont assez stables (on ne change pas d'AS d'origine tous les mois) donc le problème n'est pas trop aigü.

La section 7 décrit la vie du dépôt, et les opérations courantes. Les acteurs du routage devront donc désormais penser à la mise à jour de ce dépôt. Dans le futur, l'émission de ces certificats se fera peut-être automatiquement, en même temps que l'allocation des ressources. Aujourd'hui, ce n'est pas encore le cas.

La section 7.3 décrit en détail les aspects pratiques de cette gestion des ROA. Il va falloir acquérrir de nouveaux réflexes, notamment celui de créer et signer des ROA lors de tout changement de la politique de routage. Comme l'absence d'un ROA pour une annonce donnée pourra être interprété comme un détournement, et mener à un refus de l'annonce BGP par les routeurs validants, il y aura plein de possibilité de « se tirer une balle dans le pied ». Les opérateurs devront donc appliquer le principe « make before break », c'est-à-dire créer le ROA signé bien avant d'annoncer la route (pour permettre à tous les dépôts et tous les caches d'être à jour) et, en sens inverse, arrêter l'annonce longtemps avant de signer la révocation du ROA correspondant (et s'assurer qu'il existe un autre ROA, pour la nouvelle annonce).

Cela ne s'applique qu'aux opérateurs, pas au client final. Le site qui a des adresses PA et est connecté à un seul opérateur, n'a rien à faire, les ROA seront émis par l'opérateur. Ce site ne participe donc pas à la RPKI. En revanche, un site multi-homé peut, dans certains cas, avoir à émettre des ROA. Par exemple, s'il a un préfixe PA qu'il fait relayer par deux opérateurs, il doit créer un ROA pour cela (et donc obtenir un certificat depuis l'opérateur qui lui a affecté le préfixe PA) ou demander à l'opérateur de le faire pour lui. Si les adresses sont PI, le site doit émettre un ROA avec son propre AS en origine, en utilisant le certificat reçu avec le préfixe PI.

Si vous souhaitez appronfondir la question, une liste d'articles à lire se trouve dans mon article général. Si vous voulez pratiquer et voir la RPKI en action, regardez mon article sur les logiciels.


Téléchargez le RFC 6480


L'article seul

RFC 6474: vCard Format Extensions : place of birth, place and date of death

Date de publication du RFC : Décembre 2011
Auteur(s) du RFC : K. Li, B. Leiba (Huawei Technologies)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF vcarddav
Première rédaction de cet article le 24 décembre 2011


Le format de carte de visite numérique vCard, normalisé dans le RFC 6350, est un des grands succès de l'Internet. On trouve ces cartes partout. Le format de base définit un jeu de données limité mais permet des extensions. Ce RFC est donc la première extension à vCard version 4 (ex-aequo avec celle du RFC 6473), et normalise des champs pour indiquer un lieu de naissance, un lieu de mort et une date de mort (la date de naissance, BDAY, est dans le format de base).

La section 2 décrit ces trois propriétés, toutes facultatives :

  • BIRTHPLACE indique le lieu de naissance. Il peut être indiqué en texte libre ou bien sous forme d'une URI, comme par exemple les URI de plan geo: du RFC 5870. Ainsi, Jésus-Christ pourrait avoir BIRTHPLACE: Dans une grange, Bethléem (Palestine) ou bien BIRTHPLACE;VALUE=uri:geo:31.7031,35.196.
  • DEATHPLACE indique le lieu de mort, par exemple DEATHPLACE: Colline du Golgotha, Jérusalem (le RFC fournit un exemple où la longitude et latitude indiqués sont celles du point où a coulé le Titanic).
  • DEATHDATE indique la date de la mort. Il avait longtemps été envisagé de la garder dans le format de base, comme BDAY mais elle avait finalement été retirée, suite à la réunion IETF de Pékin en 2010. Comme son homologue BDAY, le format préféré de DEATHDATE est celui d'ISO 8601 (cf. RFC 6350, section 4.3), par exemple DEATHDATE:00300501 (date mise un peu au hasard, vu le manque de sources fiables...). Mais on peut aussi utiliser du texte libre pour le cas où on doit utiliser des formules vagues comme « au début du treizième siècle ».

Un exemple complet d'une vCard avec ces trois propriétés est :

BEGIN:VCARD
VERSION:4.0
FN:Jeanne d'Arc
N:d'Arc;Jeanne;;;
UID:urn:uuid:4f660936-28d5-46bf-86c6-9720411ac02a
GENDER:F
KIND:individual
TITLE:Bergère
TITLE:Pucelle
TITLE:Sauveuse de la France
PHOTO:http://commons.wikimedia.org/wiki/File:Lenepveu,_Jeanne_d%27Arc_au_si%C3%A8ge_d%27Orl%C3%A9ans.jpg
LANG:fr
URL:http://fr.wikipedia.org/wiki/Jeanne_d%27arc
BDAY:14120106
BIRTHPLACE:Domrémy (Lorraine)
DEATHDATE:14310530
DEATHPLACE:Rouen (Normandie)
END:VCARD

Ces trois nouvelles propriétés sont désormais enregistrées dans le registre IANA.


Téléchargez le RFC 6474


L'article seul

RFC 6471: Overview of Email DNS-Based List (DNSBL) Best Practice

Date de publication du RFC : Janvier 2011
Auteur(s) du RFC : C. Lewis (Nortel Networks), M. Sergeant (Symantec Corporation), J. Levine (Taughannock Networks)
Pour information
Première rédaction de cet article le 19 janvier 2012


En raison de l'importance du problème du spam (et d'autres comportements tout aussi nuisibles), un grand nombre de sites utilisent des listes noires des gens avec qui on ne veut pas communiquer (DNSBL pour DNS-based Black List). Ces listes sont souvent distribuées via le DNS, et gérées par des organismes très divers, dont le niveau de sérieux et d'honnêteté est très variable. La question étant très polémique, documenter le comportement attendu de ces organismes n'a pas été une mince affaire. Ce RFC 6471 décrit donc ce qu'on espère d'un gérant de DNSBL.

Rien ne dit qu'il sera suivi, bien sûr. Mais l'espoir est que ce document serve à faire évoluer les choses dans le bon sens. À noter que le groupe en charge de ce RFC, l'Anti-Spam Research Group de l'IRTF, n'a pas toujours réussi à se mettre d'accord sur le comportement idéal de la DNSBL. Dans ces cas, ce RFC 6471 se contente d'indiquer des recommandations sur la forme (« le gérant de DNSBL devrait documenter ce qu'il fait » si le RFC ne peut pas dire ce qui devrait être fait). La section 1.4 rappelle d'ailleurs que les règles de l'IRTF n'imposent pas de consensus au sein du groupe avant publication. À noter que ce RFC ne parle pas de protocole, les questions purement techniques étant traitées dans le RFC 5782.

Le sujet est tellement polémique que je ne vais pas forcément me contenter d'un compte-rendu neutre, objectif et ennuyeux de ce RFC et que je risque de glisser quelques opinions personnelles, pour lesquelles je demande l'indulgence de mes lecteurs. C'est que les DNSBL sont un marécage de gens bizarres, de racketteurs (« pour être retiré de notre liste, il faut payer »), d'éradicateurs (« nous avons mis les trois-quarts de l'Afrique en liste noire ») et de quelques personnes sérieuses. Le groupe ASRG représente plutôt le point de vue des éradicateurs (« dans le doute, on filtre »).

La section 1 du RFC rappelle ce qu'est une DNSBL et comment elle fonctionne. Les détails techniques du fonctionnement de ce service sont exposés dans le RFC 5782. L'idée est de publier dans le DNS les noms de domaine des méchants, ou bien les adresses IP de leurs serveurs de messagerie. Le serveur qui reçoit du courrier peut alors, en consultant le DNS (ce qui est simple et rapide), prendre connaissance de la « note » attribuée au domaine ou à l'adresse IP par le gérant de la DNSBL. Sur la base de cette note, il peut alors décider de filtrer, de contrôler plus étroitement, etc. Rappelons-bien que c'est le destinataire qui décide quoi faire du courrier, pas le gérant de la DNSBL, qui se contente de publier une information. Au bout du compte, c'est le gérant du serveur de messagerie de destination qui est responsable de l'usage qu'il fait de cette information. Beaucoup sont irresponsables, et filtrent aveuglément sur la base de listes noires sur lesquelles ils n'ont même pas pris la peine de se renseigner.

Comme le DNS est une technique éprouvée, très fiable et rapide, cet usage original des DNSBL s'est étendu. On voit aujourd'hui des DNSWL (listes blanches, désignant ceux qui ont droit à un traitement de faveur), listes d'URI dont la présence dans un courrier indique un spam, etc. On voit aussi des changements dans l'usage de ces listes. Très binaire autrefois (l'adresse IP est présente dans la liste noire => on rejette le message), il est devenu plus souple, les résultats d'une recherche dans la liste noire étant souvent un facteur de décision parmi d'autres (SpamAssassin fonctionne ainsi). Poursuivant cette idée d'utiliser le DNS pour récupérer de l'information, on voit aussi des services de géolocalisation utilisant le DNS et d'autres encore plus techniques (je me sers beaucoup du domaine aspath.routeviews.org de Route Views, qui permet de récupérer les informations de routage d'une adresse). Enfin, les listes distribuées par le DNS sont désormais utilisées pour bien d'autres choses que le courrier, par exemple pour du contrôle d'accès à des serveurs IRC ou des formulaires Web. Bref, on peut tout faire avec le DNS, qui a cessé il y bien longtemps d'être uniquement un service qui « traduit des noms de domaine en adresses IP ».

Quelles sont les DNSBL aujourd'hui ? Il y a de tout, certaines sont privées, gérées par une organisation pour son besoin propre, d'autres publiques et gratuites, d'autres payantes (beaucoup de DNSBL sont gratuites en dessous d'un certain seuil d'utilisation et payantes ensuite). On estime qu'il existe plus de 700 listes publiques, la plus ancienne ayant été créée en 1997. À cette époque, les spammeurs utilisaient leurs propres machines et c'est en grande partie en raison des DNSBL, qui distribuaient rapidement les adresses de ces machines, que les spammeurs sont passés à d'autres tactiques (comme les relais de courrier ouverts), tactiques à lesquelles les DNSBL ont dû s'adapter.

Il n'y a pas que le statut juridique et administratif qui différencient les DNSBL actuelles. Elles se différencient également par leurs politiques (comment une entrée est-elle ajoutée à la base et, plus important, comment elle est retirée) et, comme le note pudiquement le RFC, les DNSBL se différencient aussi par le niveau d'honnêteté de leurs responsables.

Justement, cette politique (qui va être mis dans la liste noire, sur quels critères ?) est un point de controverse permanent. Des cow-boys qui vous blacklistent un /20 entier parce qu'une adresse a envoyé un spam, aux gens sérieux qui prennent beaucoup de temps et d'effort avant d'ajouter une adresse à la base, il y a un large spectre d'opinions. Ce RFC 6471 n'essaie pas de trancher entre ces opinions. Il ne dit pas quelle est la bonne politique, simplement que le gérant de la DNSBL doit documenter ses critères d'inclusion et d'exclusion, et faire ensuite réellement ce qu'il annonce (ce qui est très loin d'être le cas). C'est ensuite à l'utilisateur de la DNSBL (l'administrateur d'un serveur de messagerie qui décide d'interroger cette base avant d'accepter un message) de s'informer et de s'assurer que la politique de la DNSBL lui convient.

La section 1.2 fournit une bonne check-list pour ledit utilisateur, sous forme d'une série de questions à se poser avant d'utiliser une DNSBL. Par exemple (entre parenthèses, une étude de l'application de cette check-list à Spamhaus, pour sa liste SBL) :

  • Est-ce que les politiques d'inclusion et d'exclusion suivies par la liste sont nettement marquées sur son site Web ? Sont-elles claires ? (Pour la SBL, la réponse est oui, pour l'inclusion et l'exclusion.)
  • Existe-t-il une évaluation indépendante de cette liste, permettant de comparer la théorie et la pratique ? (Je n'en sais rien, pour la SBL.)
  • Qu'en pensent vos pairs, les collègues qui travaillent dans des conditions analogues aux vôtres ? Comme le note justement le RFC, les DNSBL baignent souvent dans un climat de rude controverse. Il faut bien vérifier que les opinions sur une liste sont formulées par des gens qui s'y connaissent, et pas par Jean-Kevin Boulet qui crie bien fort « Ouais, cette liste est super, marche trop bien ». (La SBL est une des listes les plus utilisées et Spamhaus une organisation ancienne et appréciée.)

Il faut en outre réviser ces questions de temps en temps, les listes évoluent et plus d'une a cessé tout fonctionnement.

Le RFC enfonce le clou à plusieurs reprises : c'est l'utilisateur qui est responsable, au final, pas la DNSBL. Certes, c'est un plaidoyer pour les gérants de DNSBL (« ce n'est pas nous qui filtrons », remarque courante des DNSBL face aux contestations) mais cela reflète la réalité. Filtrer avec une DNSBL, c'est sous-traiter une partie de sa sécurité, c'est confier les décisions à d'autres (la section 4 revient sur ce point et rappelle que des DNSBL ont déjà listé 0/0 c'est-à-dire tout l'Internet). Il est donc crucial d'évaluer les sous-traitants. Le postmaster responsable comprend ce point : la DNSBL exprime une opinion, mais c'est lui qui décide d'agir sur la base de cette opinion.

Bref, quels sont les conseils effectifs de ce RFC 6471 ? Ils commencent en section 2. D'abord, la transparence de l'offre. La DNSBL doit écrire noir sur blanc quels sont les critères pour être mis dans la liste noire et quels sont ceux pour être enlevés. Par exemple, une liste qui s'appuie sur un pot de miel peut avoir comme critère d'ajout « On ajoute toute adresse IP qui a envoyé au moins trois messages dans une semaine aux adresses du pot de miel » et comme critère de retrait « On retire toute adresse qui n'a rien écrit au pot de miel depuis deux mois ». Cette politique doit ensuite être suivie rigoureusement et honnêtement. Dans la jungle des DNSBL, on a déjà vu des gérants de liste qui ajoutaient à la liste noire les adresses IP des gens qui les critiquaient (spite listing)... Il y a des tas de politiques raisonnables, l'important est de se tenir à celle publiée. Si on prétend gérer une liste de relais de courrier ouverts, on ne doit pas y mettre des adresses IP pour une autre raison, même en rapport avec le spam.

La transparence n'empêche pas des politiques dingues, mais ouvertement assumées par le gérant de la liste. Un bel exemple est chez UCEprotect, qui menace directement les critiques « Should you want to contact us, you should keep this in mind and behave rationally and calmly in order not to aggravate your situation. [...] Applying legal action or other pressure against us will result in your IP address and/or your network range being listed in our database. ».

À noter que cette règle de transparence n'impose pas de donner tous les détails. Par exemple, l'opérateur de la liste ne va évidemment pas publier les adresses du pot de miel, cela détruirait complètement son efficacité.

Ensuite, la traçabilité. La DNSBL devrait maintenir un historique des ajouts et retraits, avec les raisons, et publier cet historique. Là encore, l'historique publié peut être expurgé mais il doit contenir suffisamment d'informations pour qu'un utilisateur (ou l'administrateur d'une machine listée dans la liste noire) puisse comprendre pourquoi. Si on prend (un peu au hasard), la liste CBL, on trouve juste : « IP Address X.Y.Z.170 is listed in the CBL. It appears to be infected with a spam sending trojan or proxy. It was last detected at 2011-12-17 12:00 GMT (+/- 30 minutes), approximately 4 hours ago. », ce qui est un peu court.

Beaucoup de gérants de DNSBL sont du genre « éradicateur » et n'hésitent pas devant les dommages collatéraux. Le RFC dit d'ailleurs franchement qu'on ne fait pas d'omelette sans casser d'œufs. Ainsi, il arrive que des listes répondent pour des adresses qui n'ont pas eu de comportement malveillant mais font partie du même préfixe (mettre dans la liste tout un /28 lorsqu'une seule adresse IPv4 de ce /28 a mal agi, par exemple). Le RFC recommande que cette pratique d'élargissement soit clairement documentée.

L'entrée dans la liste est une chose. Mais, avec la plupart des DNSBL, les problèmes sont encore pires pour sortir de la liste. Même quand l'entrée est correctement faite, et à juste titre, on peut avoir des difficultés incroyables pour se faire rayer de la liste. Par exemple, une machine Windows devient un zombie, crache du spam à tout va, et se retrouve « noirlistée », ce qui est normal. Ensuite, l'administrateur système prend les choses en main, reformate le disque, installe NetBSD à la place, et va tenter de « délister » la machine, désormais propre. Avec la plupart des DNSBL, il aura un mal fou. Être enregistré dans une liste est facile, la quitter est très très dur. C'est le même problème lorsqu'une organisation disparait et que ses adresses IP sont récupérées par une autre, qui va s'apercevoir, mais trop tard, que le RIR lui a passé des adresses plombées par une mauvaise réputation.

Le RFC demande donc que les gérants de liste changent de perspective. Au lieu de considérer le retrait comme une opération en soi, toute la liste devrait être considérée comme temporaire et la sortie devrait être automatique au bout d'un moment.

Quelle durée avant cette expiration automatique ? Cela dépend de comment est constituée la liste. Si elle est faite manuellement, sur la base d'informations relativement statiques, comme les allocations de préfixes IP, alors les durées de vie peuvent être longues. Si la détection est automatique (par exemple une liste noire de relais HTTP ouverts), alors une durée de vie très courte est plus raisonnable. Ainsi, la machine dont la configuration a été corrigée disparaîtra vite de la liste et la machine qui rechute sera vite réadmise dans la liste. Dans tous les cas, le RFC demande que la politique d'expiration soit elle aussi publiée. Des informations comme « dernière vérification le tant » sont très précieuses pour évaluer la qualité d'une entrée de la base.

Autre bonne pratique, la fourniture d'un canal privé pour demander le retrait d'une entrée dans la base. Il est nécessaire qu'un tel canal soit disponible. Cela peut être aussi simple qu'une adresse de courrier ou qu'un formulaire Web. Mais, en tout cas, une DNSBL ne devrait pas exiger de discussion publique de la demande de retrait. (Oui, certaines le font, comme forme de punition des administrateurs systèmes qui ont fait preuve de négligence, et laissé leur machine être utilisée pour le spam.)

Et, bien sûr, la DNSBL doit fournir un canal de communication qui ne soit pas lui-même bloqué par la DNSBL... Si l'administrateur de 192.0.2.25 veut demander le retrait de cette adresse de la liste, et que le canal des demandes de retrait est une adresse de courrier, sur un serveur qui utilise la DNSBL, on se retrouverait dans une situation très kafkaïenne. Bien sûr, ces adresses de demande de retrait reçoivent beaucoup de spam mais le filtrage qui les protège devrait être très prudent, pour ne pas rejeter des demandes légitimes.

Les réponses à ces demandes de retrait devraient être raisonnablement rapides. Le RFC suggère deux jours (et sept au grand maximum).

Certaines DNSBL n'acceptent de demandes de retrait de la liste noire que lorsqu'il y a eu une forme d'authentification que le demandeur est bien en charge de l'adresse en question (vérification de l'adresse de courrier dans les bases des RIR, par exemple). Cette pratique est déconseillée car une telle authentification est souvent très difficile à fournir dans l'Internet d'aujourd'hui.

Le RFC recommande même de sérieusement envisager la possibilité de retirer automatiquement les adresses incriminées, sur simple requête (politique dite « pas de question » car on ne demande rien au demandeur). Si l'inscription dans la liste est le résultat d'un test automatique, l'adresse IP « coupable » sera très vite remise, de toute façon. Si on craint une guerre d'ajout/retrait dans la base, il suffit de mettre une limitation au rythme des requêtes (par exemple, deux retraits maximum en vingt-quatre heures) ou de détecter ces guerres et de verrouiller alors l'adresse dans la base. Une telle politique « pas de question » permet de corriger très vite les erreurs dans la base, et ne diminue pas sensiblement l'efficacité globale de la DNSBL (qui ne dépend pas de quelques adresses). Enfin, cette politique permet de désamorcer les (nombreux) conflits entre les gérants de la DNSBL et les responsables des adresses noirlistées.

On l'a vu, ce RFC ne veut pas trancher la question de savoir si une politique d'ajout dans la liste est correcte ou pas. Par contre, la liste des bonnes pratiques demande qu'il y ait symétrie entre la politique d'ajout et celle de retrait. Normalement, si une adresse est ajoutée pour une raison X, et que X cesse d'être vrai, l'adresse devrait être retirée. Par exemple, si une DNSBL stocke les adresses IP des relais de courrier ouverts, elle devrait retirer les adresses qui ne sont plus de tels relais (parce que l'administrateur a réparé la configuration). Cette recommandation du RFC va à l'encontre de la pratique de certaines DNSBL de punir les gérants des machines en question, en demandant une autocritique publique, voire carrément de l'argent, pour être délisté.

Enfin, dernière bonne pratique dans la section 2, cette question du paiement. Le RFC explique qu'il est normal qu'une DNSBL fasse payer ses clients pour y accéder (la définition d'une DNSBL commerciale, après tout). Mais faire payer les administrateurs système, responsables des adresses listées, est, comme le dit le RFC avec euphémisme « proche du racket ». Pour convaincre les administrateurs de listes noires que cette pratique devrait être abandonnée, le RFC note que, même lorsqu'elle est faite avec les meilleures intentions du monde, elle est susceptible de déclencher des réactions négatives, et de mettre en péril le principe même des DNSBL.

Les points traités dans la section 2 étaients de nature plutôt politique. La section 3 touche plutôt aux questions techniques. Quelles sont les bonnes pratiques opérationnelles ? Il y en a plusieurs, par exemple l'importance de disposer d'un ensemble de serveurs de noms suffisant pour faire face à la charge. Il s'agit non seulement de la charge normale, mais également de celle, bien plus élevée, qui surviendra lors d'une dDoS (les spammeurs n'ont pas le sens de l'humour et les attaques par déni de service contre les listes noires ne sont pas rares). Pour être sûr que le nom de domaine « principal » de l'opérateur (mettons spamhaus.org) soit à l'écart des problèmes, le RFC conseille que la DNSBL soit dans un sous-domaine délégué, avec ses propres serveurs de noms :


% dig NS sbl-xbl.spamhaus.org

; <<>> DiG 9.7.3 <<>> NS sbl-xbl.spamhaus.org
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 16914
;; flags: qr rd ra; QUERY: 1, ANSWER: 21, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;sbl-xbl.spamhaus.org.		IN	NS

;; ANSWER SECTION:
sbl-xbl.spamhaus.org.	86400	IN	NS	b.ns.spamhaus.org.
sbl-xbl.spamhaus.org.	86400	IN	NS	5.ns.spamhaus.org.
sbl-xbl.spamhaus.org.	86400	IN	NS	0.ns.spamhaus.org.
sbl-xbl.spamhaus.org.	86400	IN	NS	k.ns.spamhaus.org.
sbl-xbl.spamhaus.org.	86400	IN	NS	d.ns.spamhaus.org.
sbl-xbl.spamhaus.org.	86400	IN	NS	o.ns.spamhaus.org.
sbl-xbl.spamhaus.org.	86400	IN	NS	x.ns.spamhaus.org.
sbl-xbl.spamhaus.org.	86400	IN	NS	h.ns.spamhaus.org.
sbl-xbl.spamhaus.org.	86400	IN	NS	l.ns.spamhaus.org.
sbl-xbl.spamhaus.org.	86400	IN	NS	2.ns.spamhaus.org.
sbl-xbl.spamhaus.org.	86400	IN	NS	4.ns.spamhaus.org.
sbl-xbl.spamhaus.org.	86400	IN	NS	i.ns.spamhaus.org.
sbl-xbl.spamhaus.org.	86400	IN	NS	3.ns.spamhaus.org.
sbl-xbl.spamhaus.org.	86400	IN	NS	r.ns.spamhaus.org.
sbl-xbl.spamhaus.org.	86400	IN	NS	f.ns.spamhaus.org.
sbl-xbl.spamhaus.org.	86400	IN	NS	g.ns.spamhaus.org.
sbl-xbl.spamhaus.org.	86400	IN	NS	t.ns.spamhaus.org.
sbl-xbl.spamhaus.org.	86400	IN	NS	8.ns.spamhaus.org.
sbl-xbl.spamhaus.org.	86400	IN	NS	q.ns.spamhaus.org.
sbl-xbl.spamhaus.org.	86400	IN	NS	1.ns.spamhaus.org.
sbl-xbl.spamhaus.org.	86400	IN	NS	c.ns.spamhaus.org.

;; Query time: 341 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Sat Dec 17 17:40:40 2011
;; MSG SIZE  rcvd: 388

Un des problèmes récurrents avec les DNSBL est que la plupart des administrateurs système ne testent jamais si leur configuration est toujours bonne, et lorsqu'une DNSBL cesse son activité, elle continue à être interrogée. Pour éviter cela, certaines DNSBL en fin de vie ont choisi la solution radicale de lister la totalité de l'Internet. À chaque adresse, elles répondaient qu'elle était listée. Pour détecter rapidement ce genre de problèmes, le RFC rappelle qu'on peut tester 127.0.0.1. Cette adresse ne devrait jamais apparaître dans une DNSBL. Si elle le fait, c'est que la liste a un gros problème et ne devrait plus être utilisée. Si la liste comprend des noms de domaines et pas des adresses IP, c'est le domaine invalid qui joue ce rôle. (Le RFC 5782 donne des détails sur ces conventions. D'autres domaines réservés par le RFC 2606 peuvent être utiles comme test.)

Néanmoins, la première responsabilité est celle du gérant de la liste : s'il arrête le service, il doit le faire proprement (prévenir sur son site Web au moins un mois à l'avance, etc) et surtout pas en se mettant soudain à lister tout l'Internet dans sa base. Il est important de garder le nom de domaine actif : si celui-ci était libéré, un méchant pourrait l'enregistrer et monter une fausse liste noire, qui serait utilisée par tous les clients distraits qui ont oublié de changer leur configuration.

Du point de vue technique, la méthode recommandée est de changer les serveurs de noms de la zone où se trouve la liste pour des adresses IP qui ne peuvent pas exister, par exemple celles réservées pour la documentation (RFC 5735). Ainsi, on est sûr que le domaine ne marchera pas et qu'aucun enregistrement ne sera retourné, montrant bien aux clients que la liste n'est plus en service. Par exemple, avec la syntaxe standard des fichiers de zone DNS :

dnsbl.example.com.  604800  IN  NS  u1.example.com.
                    604800  IN  NS  u2.example.com.
   
u1.example.com.     604800  IN  A   192.0.2.1
u2.example.com.     604800  IN  A   192.0.2.2

Le RFC a aussi des recommandations opérationnelles à faire pour le cas spécifiques des DNSBL qui listent les adresses IP de machines présentant une certaine vulnérabilité (relais SMTP ou HTTP ouverts, par exemple), détectée par un programme. D'abord, le programme ne devrait pas tester des machines préventivement (la question est controversée : certains défendent la légitimité de balayages systématiques de tout l'Internet, d'autres ne sont pas d'accord). Il ne devrait le faire que si quelque chose (un rapport d'envoi de spam, par exemple) attire l'attention sur des machines spécifiques.

Ensuite, une fois une adresse listée, les tests périodiques qui visent à évaluer si la machine est toujours vulnérable devraient être relativement espacés (pas plus d'une fois par jour). Et, bien sûr, le test ne doit pas avoir d'effet négatif (pas d'envoi de grandes quantités de données, par exemple).

Les logiciels qui sont derrière la DNSBL, comme tous les logiciels, ont des bogues. Et les utilisateurs d'une DNSBL peuvent faire des erreurs de configuration. Il est donc important que tout soit vérifié et testé et que des procédures soient en place pour faire face aux problèmes (par exemple, le gérant de la DNSBL doit être prêt à vider manuellement la base ou une partie de celle-ci, si une erreur entraîne le listage erronée d'adresses IP).

À noter que le Wikipédia anglophone a un intéressant tableau de comparaison des DNSBL.

Pour résumer, on a vu que ce RFC résultait d'un compromis entre ceux qui voulaient des listes noires opérant comme elles le voulaient et ceux qui souhaitaient les rendre un peu plus responsables. Le compromis a été de donner peu de recommandations concrètes excepté de documenter les choix effectués. À l'heure actuelle, le moins qu'on puisse dire est que la plupart des listes noires ne font même pas ce minimum...


Téléchargez le RFC 6471


L'article seul

RFC 6468: Sieve Notification Mechanism: SIP MESSAGE

Date de publication du RFC : Février 2012
Auteur(s) du RFC : A. Melnikov (Isode), B. Leiba (Huawei), K. Li (Huawei)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF sieve
Première rédaction de cet article le 3 mars 2012


Je vais peut-être décevoir certains lecteurs mais, dans cet article, je ne parlerai pas du contenu du RFC mais uniquement du scandale de brevets qui l'a accompagné. En violation des règles de l'IETF, Huawei avait dissimulé l'existence d'un brevet que cette compagnie détenait sur le sujet de ce RFC.

Techniquement, ce RFC est simple : c'est une extension au langage de filtrage de courrier Sieve (RFC 5228) pour notifier des destinataires de l'arrivée d'un message, en utilisant le protocole SIP (RFC 3261). Comme les organismes de dépôt des brevets acceptent tout et n'importe quoi, on peut breveter une idée aussi simple... (Le brevet ne semble pas avoir encore été publié mais nul doute qu'il ne le sera : je n'ai pas trouvé de serveur permettant de lire les brevets chinois comme ce CN 200710076523.4 mais une version états-unienne existe aussi, le US Patent 20090204681.)

Le problème n'est pas que la technologie soit brevetée. Les règles de l'IETF ne l'interdisent pas. Le problème est que Huawei a dissimulé ce brevet, pour être sûr que le RFC soit adopté malgré cette menace (c'est ce qu'on nomme un brevet sous-marin). Et cette dissimulation, elle, est interdite par l'IETF (RFC 8179). Mais les entreprises capitalistes n'ont manifestement pas peur des règles de l'IETF, celle-ci n'ayant pas de dents pour mordre les contrevenants...

Laissons Adam Roach résumer ce qui s'est passé (message envoyé à la liste de diffusion générale de l'IETF) : Just to make sure I understand the sequence of events:

  • 1. August 21, 2007: Huawei files a patent (CN 200710076523.4) on using SIP for SIEVE notifications. The inventor is listed as a single Huawei employee.
  • 2. August 30, 2007: That same Huawei employee and two additional authors publish an IETF draft ( draft-melnikov-sieve-notify-sip-message-00) on using SIP for SIEVE notifications.
  • 3. September 2007 - September 2011: The SIEVE working group discusses and improves the IETF draft.
  • 4. October 6, 2011: The IESG approves the IETF draft for publication as an RFC.
  • 5. December 14th, 2011: Huawei files an IPR disclosure with the IETF informing it of patent CN 200710076523.4

La publication du 14 décembre 2011 à laquelle il fait allusion est la #1658. Une version plus récente est la #1681.

Le 25 janvier 2012, l'IESG a relancé l'IETF (Second Last Call, un terme bien orwellien) pour demander un avis sur la publication du RFC, malgré la divulgation du brevet sous-marin. Suite à cela, le RFC a été publié. L'IETF n'avait aucun moyen de représailles, à part refuser le RFC (qui ne posait aucun problème technique).

Aucune sanction n'a été prise, l'IETF n'avait pas de mécanisme évident pour cela. Une discussion a commencé, qui a mené à la publication de deux RFC, un répressif, le RFC 6701 (qui liste des sanctions, de l'annonce publique de la tricherie, méthode du name and shame, jusqu'au retrait des Internet-Drafts des mains des tricheurs, en passant par la suspension de leur droit d'écriture dans les listes IETF, selon les principes du RFC 2418 et surtout du RFC 3683), et un préventif, le RFC 6702.

À noter que Huawei n'est pas la première société à agir ainsi, RIM en avait fait autant.


Téléchargez le RFC 6468


L'article seul

RFC 6462: Report from the Internet Privacy Workshop

Date de publication du RFC : Janvier 2012
Auteur(s) du RFC : A. Cooper (Center for Democracy and Technology)
Pour information
Première rédaction de cet article le 17 janvier 2012


Après une très longue période d'ignorance quasi-complète des problèmes de protection de la vie privée, l'IETF a évolué et on n'entend plus gère ses participants écarter d'un revers de main ces questions, en disant « Nous, on fait juste de la technique, tout ça, c'est de la politique, ça ne nous concerne pas. » De nos jours, au contraire, la prise de conscience est nette et l'IETF a désormais une activité structurée autour de la notion de vie privée, activité qui se traduit par un programme dédié et une liste de diffusion. Faut-il aller plus loin ? C'était une des questions posées lors de l'Atelier « Internet Privacy Workshop 2010 », atelier qui s'est tenu du 8 au 9 décembre 2010 à Cambridge et dont ce RFC est le compte-rendu. (L'auteure travaille pour une ONG qui lutte pour les libertés sur l'Internet.)

Pas de décisions à attendre tout de suite, donc. On en est à un stade d'exploration. L'atelier de Cambridge était coorganisé par l'IETF, le MIT et le W3C pour voir ce que les SDO pouvaient faire en terme de protection de la vie privée. On est loin d'un accord unanime (et le résumé du RFC dit bien qu'aucun des organismes présents n'a de position officielle sur ces questions) mais au moins quelques pistes de travail émergent. L'IETF étant chargé de produire des spécifications concrètes, une bonne partie de l'atelier a porté, non pas sur des discours généraux sur la vie privée, mais sur les tâches envisageables.

La question de la protection de la vie privée sur l'Internet est immense et couvre beaucoup de domaines très différents. Certains problèmes apparaissent de manière récurrente, le fingerprinting (la détermination d'une identité à partir de traces numériques qui n'étaient a priori pas conçues pour cela), la fuite d'informations, la difficulté à distinguer les partenaires primaires (à qui on a donné directement de l'information) des tiers (qui ont eu de l'information sans qu'on interagisse explicitement avec eux), le manque d'informations des utilisateurs sur les avantages et inconvénients d'une meilleure protection, etc. (Notons que le RFC mentionne les faiblesses des utilisateurs, mais pas l'aggressivité avec laquelle les capitalistes collectent et revendent de l'information privée.) Le RFC note que la vie privée n'est pas un absolu et que, par exemple, la protéger peut influer négativement sur l'utilisabilité d'un service. Bref, il y a pour l'instant davantage de défis que de solutions (section 1).

Plus précisement, de quoi a-t-on parlé pendant l'atelier (les supports présentés sont disponibles en ligne) ? La section 2 résume tout cela. D'abord, une discussion technique (section 2.1). Commençons par l'adresse IP. Elle donne souvent bien trop d'informations (il est trivial de remonter d'une adresse IP à un utilisateur, ce qui explique pourquoi elle est considérée comme une donnée personnelle). Certains protocoles offrent des risques particuliers comme certaines techniques de mobilité, qui permettent de suivre un utilisateur à la trace.

C'est d'ailleurs dans le cas de l'adresse IP qu'on trouve un des rares exemples d'une technologie IETF spécialement développée pour répondre à des craintes concernant la vie privée : les adresses IP temporaires du RFC 4941, qui sont partiellement aléatoires, et regénérées de temps en temps, pour éviter le suivi de l'utilisateur.

Autre mécanisme bien connu pour empêcher le suivi par l'adresse IP : le routage en oignon, surtout connu grâce à Tor. Ce service route les paquets à travers plusieurs nœuds distincts, chiffrant leur contenu à chaque fois. Seuls les premiers et derniers nœuds voient le message en clair. Observer le trafic ne permet de trouver, au pire, que l'origine (si on espionne au début), ou bien que la destination (si on espionne à la fin).

Mais Tor n'est pas parfait : le contenu des messages peut donner des indications sur l'origine (cookies, par exemple, pour une requête HTTP). Si on veut vraiment être anonyme, utiliser Tor ne suffit pas : il faut aussi couper bien des choses sur son navigateur, à commencer par Flash et JavaScript, et certains peuvent considérer cela comme un problème. Comme souvent en sécurité, rien n'est gratuit. Protéger sa vie privée peut nécessiter des sacrifices.

Les participants à l'atelier ont également planché sur le mode private browsing qu'offrent certains navigateurs. C'est un mode dans lequel le navigateur ne stocke pas localement les identifiants de session (comme les cookies). Son but n'est pas de protéger contre un suivi de l'utilisateur par le serveur mais de protéger contre d'autres utilisateurs du même poste client. L'expérience indique que beaucoup d'utilisateurs ne comprennent pas la différence et croient que le private browsing leur procure une navigation sans flicage. C'est un exemple d'un autre problème courant en sécurité : les utilisateurs ne comprennent pas les risques.

Enfin, dernière discussion technique, sur les propositions Do Not Track, qui permettent à un utilisateur d'indiquer clairement aux sites Web qu'il ne veut pas être suivi à la trace. Pour l'instant, ce ne sont que des propositions, sans accord technique ou politique.

Après ces discussions techniques, l'atelier s'est demandé quel pouvait être le rôle des SDO dans cette histoire. Dans le passé, il n'y a pas eu d'appproche systématique de la vie privée dans les protocoles IETF. Cela ne veut pas dire que rien n'a été fait : certains RFC ont été entièrement conçus pour résoudre un problème de vie privée (comme le RFC 4941 pour IPv6 ou le RFC 3323 pour SIP). Certains services particulièrement sensibles ont bénéficié de davantage d'efforts, par exemple l'indication de présence (RFC 2778) ou bien sûr la géolocalisation (RFC 3693). Un protocole comme ALTO (RFC 5693) a également vu ses problèmes de vie privée étudiés dès le début. Le cas d'ALTO est difficile car le protocole est d'autant plus efficace que l'utilisateur révèle beaucoup de choses sur lui (en demandant à l'oracle « Je veux télécharger le fichier Serge Reggiani - Les Loups Sont Entrés Dans Paris.mp3 de taille 4732679 octets et de MD5 2d79e0d7e25c8c10c9879cefcef4102a et voici la liste complète des pairs BitTorrent qui l'ont » par rapport au plus discret mais moins efficace « je voudrais savoir si le pair 2001:db8:1::1 est plus ou moins rapide que le 2001:db8:67e::34a:1ff3 »).

La protection de la vie privée a pas mal de rapports avec la sécurité (la section 8 discute du rapprochement de ces deux concepts) et la sécurité est un bon exemple d'une préoccupation transverse (elle affecte tous les protocoles) qui était largement ignorée au début de l'IETF et a vu son rôle de plus en plus pris en compte. L'IETF a ainsi bâti une culture de la sécurité. Ainsi, depuis le RFC 1543, tous les RFC doivent inclure une section Security Considerations pour exposer l'analyse sécurité du protocole. Elle peut être vide mais elle doit être présente avec une mention expliquant pourquoi les auteurs du RFC ont consciemment laissé la section vide. Cette obligation bureaucratique n'est évidemment pas suffisante et l'IETF a ajouté une direction de la sécurité, un RFC dédié pour guider les auteurs de RFC (RFC 3552), de nombreux tutoriels pour auteurs de RFC aux réunions physiques, etc. La même méthode peut-elle être appliquée à la vie privée ? (Le RFC 2828, qui rassemble la terminologie IETF sur la sécurité, contient des termes liés à la protection de la vie privée.)

Le W3C a également procédé à un effort semblable. Un de ses premiers grands efforts a été P3P, un mécanisme pour permettre aux sites Web d'exprimer de manière formelle leur politique de gestion des données personnelles. P3P est un langage riche, qui permet d'indiquer des politiques complexes. Mais il a été très peu adopté en pratique. Opinion personnelle : comme pour la neutralité du réseau, tout le monde prétend que l'information du consommateur résout tous les problèmes, qu'il suffit d'annoncer sa politique et que le marché choisira. Mais personne ne veut le faire réellement. P3P permettait d'exprimer les politiques de protection des données personnelles en des termes simples et non ambigus et c'était évidemment intolérable pour les e-commerçants, qui préfèrent infliger à l'utilisateur des privacy policies de vingt pages écrites en langage légal.

Après ce tour d'horizon du travail effectué et des acteurs en place, l'atelier s'est attaqué aux défis (section 3). Quels sont les grands problèmes à résoudre ?

D'abord, la trop grande facilité à identifier un utilisateur donné par les informations que donne le logiciel qu'il utilise : adresse IP, champs de la requête HTTP comme User-Agent: ou Accept-Language:, cookies (RFC 6265), et plein d'autres paramètres font qu'on peut identifier un utilisateur ou une machine bien trop souvent. C'est ce qu'on nomme le fingerprinting et c'est bien démontré par le Panopticlick.

Comme dans toute réunion de geeks, les participants à l'atelier ont évidemment pris plaisir à explorer en détail des techniques de fingerprinting particulièrement rigolotes comme d'envoyer du code JavaScript qui va transmettre au serveur la liste des polices installées dans le navigateur (elle est souvent unique).

Capturés par un simple script WSGI sur le serveur (testez-le en https://www.bortzmeyer.org/apps/env ; les variables d'environnement dont le nom commence par HTTP_ sont les en-têtes de la requête HTTP), voici une partie de ce qu'envoie un Firefox typique, depuis une machine Ubuntu :

HTTP_ACCEPT_CHARSET: ISO-8859-1,utf-8;q=0.7,*;q=0.7
HTTP_USER_AGENT: Mozilla/5.0 (Ubuntu; X11; Linux i686; rv:8.0) Gecko/20100101 Firefox/8.0
HTTP_ACCEPT: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
HTTP_ACCEPT_LANGUAGE: en-us,en;q=0.5
HTTP_ACCEPT_ENCODING: gzip, deflate

Cette combinaison d'options et de numéros de version est probablement unique, ou en tout cas rare sur le Web, et identifie donc assez bien une machine (sans même avoir besoin de cookie). Une telle combinaison a par exemple déjà été utilisée pour confondre un agresseur agissant pour le compte de l'industrie du divertissement.

Ces informations n'étaient pas prévues pour cet usage (par exemple, les adresses IP étaient prévues pour router les paquets, pas pour identifier une machine ou une personne). Mais remplacer ces informations par des mécanismes qui empêchent ou limitent le fingerprinting ne sera pas trivial. D'autant plus que pas mal de gens se sont habitués à les utiliser dans ce but et qu'il sera de plus en plus difficile de revenir en arrière. Ainsi, le fingerprinting est souvent utilisé pour détecter des fraudes, ou pour fournir du contenu adapté (et le RFC, qui est gentil et évite les sujets qui fâchent, ne cite pas les applications répressives du fingerprinting, pour identifier l'auteur d'un délit abominable, comme de partager des œuvres d'art). Il y aura probablement beaucoup de désaccords sur le compromis entre vie privée et service « amélioré » grâce au fingerprinting.

Au minimum, l'IETF et le W3C vont essayer de documenter les points qui, dans les protocoles courants (TCP, HTTP, SIP), facilitent le fingerprinting.

Un problème proche est celui de la fuite d'informations (section 3.2) : des mécanismes conçus pour des motifs tout à fait honorables transmettent néanmoins plus d'information qu'ils ne le devraient. Ainsi, le champ Referer: dans une requête HTTP permet de savoir d'où vient un visiteur Web (ce qui est utile) mais révèle également des choses comme les ID de session (lorsqu'ils sont mis dans l'URL), les termes de recherche utilisés, etc. Voici un exemple vu dans le journal de mon blog (les informations trop sensibles ont été modifiées). On voit les termes de recherche utilisés dans Google :

192.0.2.70 - - [16/Dec/2011:17:08:53 +0000] "GET /1383.html HTTP/1.0" 200 3291 "http://www.google.fr/url?sa=t&rct=j&q=aide+rfc+dns...

Le contrôle sur les données privées repose normalement sur la possibilité de distinguer les récepteurs primaires des données des tiers (section 3.3). Ainsi, si je me connecte sur SeenThis, ce site est récepteur primaire de mes données et je ne suis pas surpris qu'il récolte des informations sur moi. Il s'agissait d'un choix conscient et informé de ma part. Mais l'examen du code source de ce site montre qu'il fait appel au service Google Analytics et donc, sans l'avoir demandé, sans même le savoir, je transmets également des données à Google, un tiers qui peut alors récolter des données sans que je l'ai choisi.

Le cas ci-dessus est relativement simple. Mais dans le Web d'aujourd'hui, on trouve d'autres cas où la distinction entre destinataire primaire et tiers est moins évidente. Un utilisateur qui met un widget amusant sur une page peut le considérer comme primaire alors que le navigateur (par exemple pour retourner les cookies) le traitera comme un tiers, et l'inverse existe également.

Enfin, le dernier grand défi est celui de l'information de l'utilisateur (section 3.4). La plupart du temps, le flicage de ce dernier se fait discrètement, sans qu'il se rende compte de l'immense quantité de données qui est collectée à son insu. La seule information disponible est composée de « policy statements » écrits dans un jargon juridique délibérement confus, conçu pour protéger le patron de l'entreprise et pas pour informer l'utilisateur. Le RFC note que des informations cruciales (comme la durée de conservation des données) en sont souvent absentes. Opinion personnelle : c'est pour cela que les mécanismes du marché - l'entreprise publie sa politique et le consommateur est libre de continuer ou pas - ne fonctionnent pas et qu'il faut des lois comme la loi I&L. Le marché suppose une information parfaite et des acteurs symétriques, ce qui n'est pas du tout le cas ici.

Le problème est d'autant plus sérieux que, si le technicien se doute bien de tout ce que le site Web peut apprendre sur son visiteur, l'utilisateur ordinaire n'a souvent pas pas idée de la quantité de traces numériques qu'il laisse.

Il est donc nécessaire de travailler à une meilleure information. P3P était un bon effort dans ce sens. Mais comme c'était un langage riche, il était difficile de traduire une politique P3P de manière claire pour l'utilisateur. Les efforts actuels portent plutôt sur un nombre limité d'icônes qui pourraient devenir largement connues (un panneau « danger, ici votre vie privée est menacée »...) Un exemple est le projet Common Terms.

La section 4 étudie ensuite les défis liés au déploiement des bonnes pratiques. D'abord (section 4.1), le problème que les mesures techniques sont génériques, alors que les menaces effectives sont souvent spécifiques à un contexte donné. La vie privée n'est pas un concept binaire. Il y a d'autres stades que « complètement privé » et « public ». Mais il est très difficile de traiter cette complexité par des mesures techniques.

Par exemple, les solutions situées en couche 3 comme les adresses IP temporaires du RFC 4941 résolvent certes certains problèmes (le serveur qui reconnaît un visiteur récurrent uniquement sur son adresse) mais ne protège pas du tout contre un FAI ou un État qui essaie d'associer une adresse à un utilisateur. Selon la menace envisagée, ces adresses temporaires sont donc efficaces... ou pas du tout.

Il ne faut donc pas évaluer les solutions techniques en leur demandant de résoudre tous les problèmes possibles. Il ne serait pas raisonnable pour l'IETF d'exiger de ses protocoles qu'ils empêchent complètement toute atteinte à la vie privée. Il faut plutôt dire clairement quels sont les risques et qui (le programmeur, l'utilisateur, la loi) est chargé de les traiter.

Autre problème délicat de déploiement de solutions de protection de la vie privée : la tension entre l'utilisabilité et la protection (section 4.2). Comme souvent en matière de sécurité, il va falloir faire des choix douloureux. Les tenants du Roi Marché ont beau jeu de faire remarquer que les utilisateurs, lorsqu'ils ont le choix, vont vers les services qui violent le plus leur vie privée (Facebook, Google, etc) en échange d'applications sympas et qui brillent. La principale faiblesse de cet argument est qu'il suppose que l'utilisateur est parfaitement conscient des risques, et de ce qui peut lui arriver, ce qui est très optimiste.

Un bon exemple de ce compromis est donné par Tor. Celui-ci fournit une bonne protection mais complique et ralentit (en raison du nombre d'étapes de routage) la navigation. Résultat, il reste peu utilisé, en bonne partie parce que les utilisateurs font un calcul coût/bénéfice (peu informé, d'ailleurs) et décident que leur vie privée n'est pas assez importante pour justifier ce coût.

Avec Tor, le coût de la protection est élevé. Mais même des mesures bien plus légères ont des coûts. Supprimer l'en-tête Referer: des requêtes HTTP améliore certainement la protection. Mais certains sites Web proposent une vue différente selon la valeur de ce champ et, en le supprimant, on se prive de ce service. Reste à savoir qui va décider du compromis, et sur quelles informations : comment exposer ce choix (« Do not send Referer headers ») dans une interface utilisateur, de manière qui permette un choix raisonné ? Alors même que l'effet de ce choix va dépendre des sites (dans la plupart des cas, le Referer: est inutile au client Web.)

Ces problèmes d'utilisabilité sont cruciaux. Le RFC cite l'exemple de SIP, où un mécanisme normalisé de protection des requêtes contre l'écoute existe (RFC 3261, section 23) mais il n'est pas utilisé en pratique car trop contraignant.

Dernier obstacle au déploiement de techniques respectant davantage la vie privée, la difficulté à trouver les bonnes motivations (section 4.3). Les différents acteurs impliqués ne feront pas d'effort s'ils n'ont pas une motivation pour cela. Cela peut être la crainte du gendarme, la conviction que cela leur apportera plus de clients ou simplement le souci d'utiliser les meilleures techniques (ces trois motivations sont rarement présentes en même temps). La crainte du gendarme est discutée en section 4.3.1. Traditionnellement, beaucoup de services proposés sur l'Internet sont gratuits et la possibilité de vendre les données personnelles des utilisateurs est l'une des voies les plus évidentes pour gagner de l'argent. Comme l'illustre un dessin célèbre, « soit l'utilisateur est le client, soit il est la marchandise ». Dans un tel contexte, il n'y a pas de motivation économique à respecter la vie privée, bien au contraire. Les diverses autorités de régulation ont fini par froncer les sourcils, ce qui a mené les fournisseurs de ces services à publier de longues politiques d'utilisation des données sur leur site. Comme le note le RFC, ces politiques, écrites sans effort pédagogique, visent plutôt à protéger le fournisseur du service qu'à informer correctement et complètement l'utilisateur. Le RFC note à juste titre que ces problèmes ne se corrigeront pas tout seuls et qu'une approche régulatrice est nécessaire (cf. le rapport de la FTC de 2010 sur l'importance d'avoir des politiques publiques mieux écrites).

Le RFC soutient que cette tendance doit continuer : sans forte pression des régulateurs, de la loi, le patronat Internet va toujours essayer de concéder le moins de vie privée possible aux utilisateurs. Un exemple d'une telle pression est la directive européenne qui parle des cookies, indiquant qu'ils ne doivent pas être utilisés sans le consentement des utilisateurs.

Le cas de P3P, déjà cité, est un bon exemple de ce problème des motivations (section 4.3.2). L'idée de base était que les logiciels du côté du client allaient pouvoir lire et comprendre les politiques de protection de la vie privée et automatiquement réagir (par exemple en n'envoyant pas de cookies aux sites dont la politique était trop peu protectrice de la vie privée). C'est une idée très états-unienne : les acteurs libres s'informent mutuellement de leurs pratiques et décident ensuite librement, en adultes majeurs, informés et consentants, de poursuivre ou pas la relation. Si on croit qu'il y a égalité (d'information, de moyens de traitement, de pouvoir) entre le patron de Facebook et M. Michu, utilisateur de Facebook, cela peut marcher. Sinon, on préfère l'approche européenne où certaines pratiques sont interdites, qu'il y ait ou pas consentement de la marchandise, pardon, de l'utilisateur.

Donc, P3P permettait d'automatiser ce processus d'information et de décision. Microsoft a pris une décision importante en choisissant, dans Internet Explorer 6, de n'envoyer des cookies aux tiers que si ceux-ci avaient une politique P3P. Comme n'importe quelle politique, même outrageusement prédatrice, était acceptée par Internet Explorer, la plupart des sites Web se sont pliés à cette décision et ont copié/collé la première politique P3P qu'ils trouvaient (souvent l'exemple pris sur le site du W3C). Cette expérience menée grâce à Internet Explorer (les autres auteurs de navigateurs n'ont fait aucun effort et n'ont jamais intégré P3P) a permis de mettre en évidence une limite de P3P : le site qui publie sa politique peut mentir (« Nous ne vendons pas vos données personnelles »). Aucun mécanisme légal ou autre ne l'en empêche. (Voir par exemple l'article « Token Attempt: The Misrepresentation of Website Privacy Policies through the Misuse of P3P Compact Policy Tokens ».)

Le cas illustre bien la question des motivations : pour qu'ils reçoivent des cookies d'Internet Explorer, les sites devaient publier du P3P. Alors, ils l'ont fait (motivation technique). Il n'y avait pas de pression légale ou régulatrice pour dire la vérité dans ces politiques P3P, alors ils ne l'ont pas fait (pas de motivation légale). Les clients (en partie à cause de l'absence de gestion de P3P par les navigateurs) ne donnaient pas la préférence aux sites publiant du bon P3P, alors les sites n'ont pas cherché à l'améliorer (pas de motivation commerciale).

Il sera intéressant de voir si cela marche mieux en sens inverse : pour la géolocalisation, le RFC 4119 et le RFC 6280 fonctionnent de manière opposée à P3P, en permettant aux utilisateurs d'indiquer leurs choix en matière de protection des données personnelles. Ils sont normalement plus motivés que les entreprises capitalistes pour cela.

Bien sûr, on est ici très loin des questions techniques que se posent normalement les SDO. Mais la compréhension de ces enjeux économiques et légaux est nécessaire, si on veut que les futures techniques de protection de la vie privée aient plus de succès que P3P.

Conclusion, en section 5, quel est le plan d'action pour les SDO ? Pour l'IETF, la synthèse est que cela va être compliqué. L'IETF normalise des protocoles dans les couches basses, sans présupposer d'un usage particulier, alors que les menaces pour la vie privée sont très dépendantes du contexte. Il va donc être difficile de trouver des réponses générales, dans les protocoles IETF. Cela ne veut pas dire qu'il ne faut rien faire. Le travail a déjà commencé autour d'une série de recommandations pour les auteurs de RFC (rassemblées dans le Internet-Draft, draft-morris-privacy-considerations, qui a évolué depuis et a été publié en RFC 6973).

Les participants à l'atelier étaient tous d'accord sur la nécessité de poursuivre également le travail technique, par exemple sur les leçons apprises de Tor, ainsi que sur les capacités (plus fortes que prévues) de fingerprinting des protocoles existants.

Et le W3C ? Il est probablement mieux placé pour améliorer la protection de la vie privée, puisque les normes du W3C sont plus proches de l'utilisateur, et utilisées dans un contexte plus spécifique. Contrairement à l'IETF, le W3C peut se restreindre au Web.

L'annexe A résume quels sont les documents bruts disponibles pour ceux qui veulent approfondir leur connaissance des travaux de cet atelier :


Téléchargez le RFC 6462


L'article seul

RFC 6458: Sockets API Extensions for Stream Control Transmission Protocol (SCTP)

Date de publication du RFC : Décembre 2011
Auteur(s) du RFC : R. Stewart (Adara Networks), M. Tuexen (Muenster University of Applied Sciences), K. Poon (Oracle Corporation), P. Lei (Cisco Systems), V. Yasevich (HP)
Pour information
Réalisé dans le cadre du groupe de travail IETF tsvwg
Première rédaction de cet article le 12 décembre 2011


Il n'y a pas de protocole qui réussit sans une API, c'est-à-dire une spécification d'une interface qui permet au programmeur d'utiliser le protocole en question. Le protocole de transport SCTP, normalisé dans le RFC 4960, n'avait pas jusqu'à présent d'API standard et les programmes ne fonctionnaient donc qu'avec une seule bibliothèque. Désormais, avec ce RFC, SCTP a des chances de voir le développement de programmes portables.

SCTP est le principal concurrent de TCP dans la catégorie « protocole de couche 4 fiable » (i.e. qui garantit l'acheminement des données, contrairement à UDP). Mais il est beaucoup moins utilisé que TCP, plus ancien, et qui a une API standard depuis longtemps, interface décrite dans la norme POSIX. Il y a aussi d'autres raisons au moindre déploiement de SCTP. Mais l'absence d'API jouait certainement un rôle : pas moyen de programmer avec SCTP sans devoir se limiter, non seulement à un système donné, mais en prime à une mise en œuvre particulière de SCTP. Les instructions d'installation devenaient donc pénibles à lire. C'est ce problème que résout notre RFC.

L'API décrite dans ce RFC est longue (le RFC fait 113 pages) donc je résume plutôt sauvagement. Elle permet d'écrire des programmes qui font la même chose qu'avec TCP, comme des programmes qui tirent profit des fonctions spécifiques de SCTP. Car la sémantique de SCTP n'est pas exactement la même que celle de TCP, le remplacement de l'un par l'autre n'est pas entièrement invisible aux applications. Les points importants de cette nouvelle API :

  • Elle est basée sur la traditionnelle interface socket,
  • Elle permet le style de programmation un-vers-N (section 3). TCP ne permet que un-vers-un, UDP permet d'utiliser une prise (socket) pour du un-vers-N, et SCTP aussi. En termes SCTP, une prise permet de contrôler plusieurs associations. Par contre, pas de diffusion, que ne permet pas SCTP.
  • Elle permet également le style un-vers-un (section 4), familier aux programmeurs qui utilisent TCP. Avec ce style (une seule association par prise), les applications existantes qui se servent de TCP peuvent être portées en SCTP avec très peu d'efforts.

Ces deux styles ne sont pas compatibles dans le même programme, le programmeur devra choisir.

Notez que les efforts de conception d'une API SCTP sont anciens. Résultat, il traîne dans la nature des tutoriels, des Howto, des exemples de programme utilisant des mécanismes qui ne sont plus les mécanismes recommandés. Plusieurs éléments des API expérimentales qui ont précédé celle-ci sont repris dans ce RFC, en les notant comme dépassés et ne devant plus être utilisés pour de nouveaux programmes.

Un programme serveur typique qui utilise le style un-vers-N ressemble à :

socket(..., SOCK_SEQPACKET, IPPROTO_SCTP): /* Le type SOCK_SEQPACKET indique le
style 1-vers-n. Section 3.1.1 */
bind(...);
listen(...); /* Pas besoin de accept(). Les nouvelles associations
sont gérées automatiquement (si le serveur le veut, il est prévenu
lors des recvmsg(), évenement SCTP_ASSOC_CHANGE). Section 3.1.3 */
recvmsg(...);
sendmsg(...);
close(...); /* close() ferme tout. Pour ne fermer qu'une seule association, on utilise
sendmsg() avec SCTP_EOF. */

pendant que le client fera plutôt :

socket(..., SOCK_SEQPACKET, IPPROTO_SCTP):
sendmsg(...);
recvmsg(...);
close(...):

Toutes les associations du serveur seront représentées par une seule prise et distinguées par leur identificateur d'association, de type sctp_assoc_t. La section 3.3 fournit les détails pour ce cas. Par exemple, si le programme n'utilise qu'un seul tampon par prise réseau, une association qui traîne peut bloquer toutes les autres. Le RFC recommande d'utiliser des prises non-bloquantes.

Quant au style un-vers-un, c'est celui de TCP et il est familier à tous les programmeurs réseau. Il est présenté en section 4. L'idée est qu'une application d'aujourd'hui, qui utilise TCP, sera ainsi portée en très peu de temps.

La séquence de commandes pour le serveur est typiquement :

socket(..., SOCK_STREAM, IPPROTO_SCTP); /* Le protocole IPPROTO_SCTP
est la seule différence avec TCP. */
bind(...);
listen(...);
accept(...);
/* Ensuite, recv() et send() avec la nouvelle prise retournée par
accept(). */
close(...);

Et chez le client :

socket(..., SOCK_STREAM, IPPROTO_SCTP); 
connect(...);
/* Ensuite, recv()/recvmsg() et send()/sendmsg() */
close(...);

Voici pour le code. La section 5 présente ensuite les nouvelles structures de données, celles qui sont spécifiques à SCTP, lorsqu'on utilise recvmsg() et sendmsg() pour des opérations de contrôle (et pas seulement d'envoi et de récupération de données). Ces fonctions prennent un paramètre message de type msghdr (RFC 3542). On peut s'en servir pour définir des paramètres de la connexion (options SCTP_INIT et SCTP_SNDINFO), ou obtenir des informations supplémentaires lors de la réception de données (option SCTP_RCVINFO, par exemple le champ rcv_assoc_id indiquera par quelle association est venue le message).

Pendant la durée de vie d'une connexion SCTP, des tas d'évenements qui n'ont pas d'équivalent dans le monde TCP peuvent se produire : changement d'adresse IP d'un pair (SCTP_PEER_ADDR_CHANGE, section 6.1.2), établissement de nouvelles associations (ou arrêt des anciennes, cf. SCTP_ASSOC_CHANGE, section 6.1.1), etc. La section 6 décrit comment être informé de ces évenements. Quant aux options des prises spécifiques à SCTP, elles sont dans la section 8. Elles s'utilisent avec setsockopt() et getsockopt(). Par exemple, SCTP_ASSOCINFO permet d'obtenir (ou de modifier) les paramètres liés aux associations, SCTP_PRIMARY_ADDR d'obtenir l'adresse IP du pair pour une association donnée, etc.

Le RFC contient en annexe A deux exemples d'utilisation de cette API, un pour un serveur en un-vers-N et un pour un client en un-vers-un. Pour les raisons expliquées plus haut (retard à normaliser l'API et bibliothèque non standards développées en attedant), ces exemples ne compilent pas sur une Debian ou une Ubuntu récente :

% gcc sctp-sample-client.c
sctp-sample-client.c: In function 'main':
sctp-sample-client.c:40:25: error: storage size of 'info' isn't known
sctp-sample-client.c:97:54: error: 'SCTP_SENDV_SNDINFO' undeclared (first use in this function)
sctp-sample-client.c:97:54: note: each undeclared identifier is reported only once for each function it appears in

Je n'ai pas encore trouvé de système où ces exemples compilent. Il existe en effet plusieurs mises en œuvre de SCTP mais pas de cette API. Plus exactement, les implémentations de cette API sont ultra-récentes et ne sont pas encore arrivés chez l'utilisateur. On a :

Le RFC note que des implémentations de l'API standard existent sur Linux, FreeBSD et Solaris mais leur déploiement effectif est inconnu. Elles ont apparemment déjà servi à ajouter SCTP à Firefox et Chrome.

Le livre de référence sur la programmation réseau, celui de Stevens, ne parle pas de SCTP dans les deux premières éditions. C'est à partir de la troisième édition (réalisée par d'autres, après la mort de l'auteur) que SCTP apparaît.

En attendant, la bogue echoping #1676608 risque d'attendre longtemps (d'autant plus que je n'ai plus le temps de m'occuper d'echoping).


Téléchargez le RFC 6458


L'article seul

RFC 6455: The WebSocket protocol

Date de publication du RFC : Décembre 2011
Auteur(s) du RFC : I. Fette (Google), A. Melnikov (Isode)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF hybi
Première rédaction de cet article le 12 décembre 2011


Ce nouveau protocole, WebSocket, vise à résoudre un problème embêtant pour les développeurs d'applications réseau. L'architecture de l'Internet était conçue pour que le seul point commun réellement obligatoire soit le protocole de couche 3, IP. Ce protocole est simple et fournit peu de services. Les développeurs qui voulaient des choses en plus les mettaient dans leurs applications ou, la plupart du temps, comptaient sur les protocoles de transport comme TCP. Si aucun des protocoles de transport existant ne satisfaisaient leurs besoins, ils avaient parfaitement le droit d'en inventer un autre et de le déployer sans rien demander à personne (principe dit « de bout en bout »). Ce modèle ne marche plus guère aujourd'hui. Il est devenu très difficile de faire passer un autre protocole de transport que TCP à travers les innombrables obstacles du réseau (NAT et pare-feux, notamment), et même un protocole applicatif nouveau, tournant sur un port TCP à lui, risque d'avoir le plus grand mal à passer. D'où l'idée de base de WebSocket : faire un protocole de transport au dessus de HTTP, qui va être le seul à passer à peu près partout. WebSocket est donc l'aboutissement d'un processus, qui a mené à ce que le protocole d'unification ne soit plus IP mais HTTP. Bienvenue dans l'Internet d'aujourd'hui « Tout sur le port 80 ».

WebSocket n'est toutefois pas un protocole généraliste, il est conçu pour fonctionner essentiellement dans le cadre du navigateur Web qui charge du code inconnu (typiquement en JavaScript) et qui va ensuite l'exécuter. Ce code pourra utiliser le réseau, dans une certaine limite (vers la même origine, cf. RFC 6454) mais les possibilités de communication offertes précédemment étaient limitées. WebSocket donne à ce code JavaScript (ou écrit dans d'autres langages) les possibilités d'une vraie communication réseau bidirectionnelle.

Avant, les applications s'exécutant sur le navigateur n'avaient pas de moyen simple de faire de telles communications, équivalentes à ce qu'on fait en TCP. Des applications comme la messagerie instantanée, le partage d'un document en cours d'édition ou bien comme des jeux en commun souhaitaient un modèle d'interaction plus riche que le traditionnel GET du client vers le serveur. Bien sûr, elles auraient pu être extérieures au navigateur, ce qui était certainement plus propre du point de vue architectural. Mais elles se heurtent alors au problème de filtrage décrit plus haut. Et, dans le navigateur, elles dépendaient de XMLHttpRequest ou bien de <iframe> et de polling. Par exemple, un code tournant sur le navigateur qui voulait simplement se mettre en attente de donnés émises de manière asynchrone par le serveur n'avait pas d'autres solutions que d'interroger ce dernier de temps en temps. Ce problème est décrit en détail dans le RFC 6202. Il avait plusieurs conséquences fâcheuses comme un surcoût en octets (tout envoi de données nécessitait les en-têtes HTTP complets) ou comme un modèle de programmation peu naturel.

WebSocket vise à résoudre ce problème en transformant HTTP en un protocole de transport. Il réutilise toute l'infrastructure HTTP (par exemple les relais ou bien l'authentification). Passant sur les mêmes ports 80 et 443, on espère qu'il réussira à passer partout. Comme le note un observateur, « WebSocket est un protocole totalement alambiqué pour contourner la stupidité du monde ».

Le résultat n'est donc pas parfait (rappelez-vous que HTTP n'avait pas été conçu pour cela) et le RFC note qu'on verra peut-être un jour les services de WebSocket fonctionner directement sur TCP (personnellement, j'ai des doutes, puisqu'on pourrait aussi bien dans ce cas utiliser des protocoles de transport qui fournissent les mêmes services, comme SCTP - RFC 4960).

Une petite note avant d'attaquer le RFC : si vous avez l'habitude de lire des RFC, vous noterez que celui-ci a des notations originales (section 2.1) comme d'utiliser les tirets bas pour souligner les définitions, les barres verticales pour encadrer les noms d'en-têtes ou de variables et les barres obliques pour les valeurs des variables.

La section 1.2 résume le fonctionnement du protocole (le lecteur pressé du RFC peut d'ailleurs se contenter de la section 1, non normative mais qui contient l'essentiel sur WebSocket). Le principe de base est d'utiliser du HTTP normal (RFC 7230) mais le client ajoute un en-tête Upgrade: à une requête GET, pour indiquer sa volonté de faire du WebSocket :

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13

Le serveur répond alors par un code 101 et en indiquant upgrade dans l'en-tête Connection: et en ajoutant des en-têtes spécifiques à WebSocket :

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat

Bien sûr, d'autres en-têtes HTTP sont possibles comme les petits gâteaux du RFC 6265. Une fois que le client a fait sa demande, et que le serveur l'a acceptée, il existe une connexion bidirectionnelle entre ces deux acteurs et on peut faire passer les données.

Contrairement à TCP (mais comme dans SCTP), la communication n'est pas un flot d'octets sans structure ; c'est une suite de messages, chacun composé d'une ou plusieurs trames. Les trames sont typées et toutes les trames d'un même message ont le même type. Par exemple, il existe un type texte, où les trames contiennent des caractères Unicode encodés en UTF-8. Il existe évidemment un type binaire. Et il existe des trames de contrôle, conçues pour l'usage du protocole lui-même.

La section 1.3 se focalise sur la poignée de main entre client et serveur qui lance le protocole (les détails complets étant en section 4). On l'a vu, le client doit ajouter l'en-tête Upgrade: websocket pour demander au serveur de basculer en WebSocket (RFC 7230, section 6.7 ; la valeur websocket pour cet en-tête est enregistrée à l'IANA, cf. section 11.2, et aussi le RFC 2817, section 7.2). Le client indique également des en-têtes spécifiques à WebSocket comme Sec-WebSocket-Protocol: qui permet d'indiquer un protocole applicatif au dessus de WebSocket (chat dans l'exemple plus haut). Ces protocoles applicatifs (section 1.9) sont normalement enregistrés à l'IANA pour assurer l'unicité de leurs noms. L'en-tête Origin: du RFC 6454 sert à indiquer quelle était l'origine de la page Web qui a chargé le script client. Quand à Sec-WebSocket-Key:, son rôle est de permettre de vérifier que la connexion était bien prévue pour être du WebSocket et pas des jeux faits par un programme malveillant qui enverrait des données ressemblant à du WebSocket sur le port 80, sans être passé par la poignée de main normale. Le serveur doit combiner la valeur de l'en-tête Sec-WebSocket-Key: avec un GUID (RFC 9562) fixe, 258EAFA5-E914-47DA-95CA-C5AB0DC85B11. Il passe le résultat par SHA-1 puis par Base64 et retourne ce résultat au client (dans un en-tête Sec-WebSocket-Accept:), qui peut alors être sûr que c'est bien ce serveur qui a reçu sa poignée de main. (Voir la section 1.6 sur ce point. Les en-têtes commençant par Sec ne peuvent pas être ajoutés via du code XMLHttpRequest normal et, donc, un client JavaScript ordinaire ne peut pas se comporter en client WebSocket.)

À noter que les en-têtes spécifiques de WebSocket ont été ajoutés au registre des en-têtes.

La réponse du serveur utilise le code HTTP 101 (qui avait été prévu de longue date par le RFC 7231, section 6.2.2), qui signifie que le serveur accepte le changement de protocole. Tout autre code indique que le serveur n'accepte pas WebSocket et que le client doit donc continuer en HTTP normal. Ainsi, un serveur HTTP normal refusera l'en-tête Upgrade: :

% telnet www.bortzmeyer.org http
Trying 2605:4500:2:245b::bad:dcaf...
Connected to www.bortzmeyer.org.
Escape character is '^]'.
GET / HTTP/1.1
Host: www.bortzmeyer.org
Upgrade: websocket

HTTP/1.1 400 Bad Request
Date: Tue, 29 Nov 2011 21:15:34 GMT
Server: Apache/2.2.16 (Debian)
Vary: Accept-Encoding
Content-Length: 310
Connection: close
Content-Type: text/html; charset=iso-8859-1

La section 1.4, elle, décrit la fermeture de la connexion (détails en section 7). Elle se fait par l'envoi d'une trame de contrôle ad hoc. Notez que la simple fermeture de la connexion TCP sous-jacente ne suffit pas forcément : en présence d'intermédiaires, par exemple les relais, elle peut être insuffisante.

Un peu de philosophie après ces détails ? La section 1.5 décrit les concepts à la base de WebSocket. Par exemple, l'un des buts était de garder au strict minimum le nombre de bits de tramage. La structure des données que permet WebSocket est donc réduite (séparation des trames, et typage de celles-ci) et toute structuration plus sophistiquée (par exemple pour indiquer des métadonnées) doit être faite par l'application, au dessus de WebSocket.

Dans cette optique « ne pas trop en ajouter », cette section note que WebSocket ajoute à TCP uniquement :

  • Le modèle de sécurité du Web, fondé sur la notion d'origine du RFC 6454,
  • Un mécanisme de nommage permettant de mettre plusieurs applications sur le même port (c'est le chemin donné en argument de la commande GET),
  • Un système de tramage, que n'a pas TCP, qui ne connait que les flots d'octets sans structure,
  • Un mécanisme de fermeture explicite de la connexion (on l'a dit, TCP seul ne suffit pas, dans la jungle qu'est le Web d'aujourd'hui, truffé de middleboxes).

Et c'est tout. Le reste doit être fait par les applications. Compte-tenu des contraintes spécifiques du Web, WebSocket offre donc pratiquement le même service aux applications que TCP. Sans ces contraintes Web (de sécurité, de fonctionnement à travers les middleboxes), du TCP brut suffirait.

Voila, vous connaissez maintenant l'essentiel de WebSocket. Le reste du RFC précise les détails. La section 3 décrit les URI WebSocket. Ils utilisent le plan ws: (non chiffré, port 80 par défaut) ou le wss: (chiffré avec TLS, port 443 par défaut). La section 11 décrit l'enregistrement de ces plans dans le registre IANA. Par exemple ws://example.com/chat est un URI WebSocket (pour la connexion donnée en exemple au début de cet article), comme ws://www.3kbo.com:9090/servers/1/status ou wss://foobar.example/newsfeed.

Comment fonctionne le tramage, le découpage du flot de données en trames bien délimitées ? La section 5 le normalise avec précision. Une trame a un type, une longueur et des données. On trouve également quelques bits comme FIN qui indique la dernière trame d'un message, ou comme RSV1, RSV2 et RSV3, réservés pour de futures extensions du protocole. Une grammaire complète est donnée en section 5.2, en utilisant ABNF (RFC 5234. Les fanas d'ABNF noteront que cette grammaire ne décrit pas des caractères mais des bits, ce qui représente une utilisation originale de la norme.

Le type est nommé opcode et occupe quatre bits. Les valeurs de 0x0 à 0x7 indiquent une trame de données, les autres sont des trames de contrôle. 0x1 indique une trame de texte, 0x2 du binaire, 0x8 est une trame de contrôle signalant la fin de la connexion, 0x9 une demande d'écho (ping), 0xA une réponse (pong), etc. La sémantique des trames de contrôle figure en section 5.5. On y apprend par exemple que des échos non sollicités (pong non précédé d'un ping) sont légaux et peuvent servir à indiquer qu'une machine est toujours en vie.

On le sait, l'insécurité est une des plaies du Web, on trouve tout le temps de nouvelles manières de pirater les utilisateurs. Les problèmes viennent souvent de nouveaux services ou de nouvelles fonctions qui semblent super-cool sur le moment mais dont on découvre après qu'elles offrent plein de pièges. Il n'est donc pas étonnant que la section 10, sur la sécurité, soit longue.

D'abord, le serveur WebSocket doit se rappeler qu'il peut avoir deux sortes de clients (section 10.1) : du code « embarqué » par exemple du JavaScript exécuté par un navigateur et dont l'environnement d'exécution contraint sérieusement les possibilités. Par exemple, l'en-tête Origin: est mis par ce dernier, pas par le code Javascript, qui ne peut donc pas mentir sur sa provenance. Mais un serveur WebSocket peut aussi être appelé par un client plus capable, par exemple un programe autonome. Celui-ci peut alors raconter ce qu'il veut. Le serveur ne doit donc pas faire confiance (par exemple, il ne doit pas supposer que les données sont valides : il serait très imprudent de faire une confiance aveugle au champ Payload length, qu'un client malveillant a pu mettre à une valeur plus élevée que la taille de la trame, pour tenter un débordement de tampon).

WebSocket ayant été conçu pour fonctionner au dessus de l'infrastructure Web existante, y compris les relais, la section 10.3 décrit les risques que courent ceux-ci. Un exemple est l'envoi, par un client malveillant, de données qui seront du WebSocket pour le serveur mais qui sembleront un GET normal pour le relais. Outre le tramage, la principale protection de WebSocket contre ce genre d'attaques est le masquage des données avec une clé contrôlée par l'environnement d'exécution (l'interpréteur JavaScript, par exemple), pas par l'application (section 5.3 pour en savoir plus sur le masquage). Ainsi, un code JavaScript méchant ne pourra pas fabriquer des chaînes de bits de son choix, que WebSocket transmettrait aveuglément.

Un peu d'histoire et de politique, maintenant. WebSocket a une histoire compliquée. L'idée de pousser les informations du serveur vers le client (connue sous le nom de Comet) est ancienne. Le protocole WebSocket (dont l'un des buts est justement cela) a été créé par Ian Hickson (qui a aussi écrit les premiers projets de RFC mais n'apparait plus comme auteur). Le groupe de travail WHATWG a ensuite beaucoup participé. La plupart des mises en œuvre de WebSocket citent ce groupe ou bien les anciens Internet-Drafts, écrits avant la création du groupe de travail IETF HyBi en janvier 2010.

Le principe même de WebSocket a souvent été contesté. Pourquoi passer tant d'efforts à contourner les problèmes de l'Internet aujourd'hui (notamment les middleboxes abusives) plutôt qu'à les résoudre ? Un intéressant texte de justification a été écrit à ce sujet. Notez qu'il inclut des exemples de code. Le groupe HyBi a connu de vives discussions, avec menaces de scission (« À WHATWG, c'était mieux, on va quitter l'IETF si ça n'avance pas »). Un des points d'affrontement était par exemple les problèmes de sécurité (résolus par la solution du masquage). Cela s'est ensuite arrangé, début 2011.

Si vous voulez vous lancer dans la programmation d'applications WebSocket tournant dans le navigateur, regardez l'API. Aujourd'hui, on trouve des implémentations de WebSocket pour les différents serveurs (GlassFish, Jetty, Apache). Dans les environnements de développement, on trouve du WebSocket chez Django et bien d'autres. Chez les clients, Firefox l'a en théorie depuis la version 6, Chrome et Internet Explorer l'ont annoncé pour une version prochaine. Bon, en pratique, c'est compliqué, et la démo ne donne pas toujours les résultats attendus (elle me refuse mon Firefox 7 mais accepte un Chrome).

Attention si vous lisez les sources, pas mal d'implémentations ont été faites en suivant des vieilles versions de la spécification de WebSocket, antérieures à sa normalisation à l'IETF. Cela se sent par exemple dans les noms des variables utilisés. (Un terme comme « opcode » pour le type est dans le RFC mais pas toujours dans les programmes.)

En dehors du monde des navigateurs, si vous voulez programmer du WebSocket, vous avez, entre autres :

Si vous voulez jouer plutôt avec un programme client comme curl, vous avez un bon article qui explique comment faire du WebSocket avec curl.

Si vous cherchez des fichiers pcap de Websocket, on en trouve sur pcapr mais attention, la plupart concernent des mises en œuvres de versions antérieures du protocole. Mais Wireshark n'a pas l'air encore capable de décoder le framing Websocket. (Une mise en œuvre existe.)

Un exemple de service publiquement accessible et utilisant WebSocket est le service RIS Live.

Enfin, si vous voulez d'autres articles sur WebSocket, j'ai beaucoup apprécié celui de Brian Raymor.


Téléchargez le RFC 6455


L'article seul

RFC 6454: The Web Origin Concept

Date de publication du RFC : Décembre 2011
Auteur(s) du RFC : A. Barth (Google)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF websec
Première rédaction de cet article le 12 décembre 2011


Chaque jour, plusieurs failles de sécurité sont annoncées frappant un site Web, ou, plus rarement, un navigateur. Ces failles proviennent souvent de l'exécution de code, par exemple Java ou JavaScript, téléchargé depuis un serveur qui n'était pas digne de confiance, et exécuté avec davantage de privilèges qu'il n'aurait fallu. Une des armes principales utilisées par la sécurité du Web, pour essayer d'endiguer la marée de ces attaques, est le concept d'origine. L'idée est que toute ressource téléchargée (notamment le code) a une origine, et que cette ressource peut ensuite accéder uniquement à ce qui a la même origine qu'elle. Ainsi, un code JavaScript téléchargé depuis www.example.com aura le droit d'accéder à l'arbre DOM de www.example.com, ou à ses cookies, mais pas à ceux de manager.example.net. Ce concept d'origine semble simple mais il y a plein de subtileries qui le rendent en fait très complexe et, surtout, il n'avait jamais été défini précisément. Ce que tente de faire ce RFC.

Pour comprendre l'importance de l'origine, revoyons un navigateur Web en action. Imaginons qu'il n'impose aucune limite au code (Java, JavaScript, Silverlight, etc) qu'il exécute. Un méchant pourrait alors mettre du code malveillant JavaScript sur son serveur, faire de la publicité (par exemple via le spam) pour http://www.evil.example/scarlet-johansson-pictures/, et attendre les visites. Le navigateur récupérerait l'HTML, puis le JavaScript inclus, et celui-ci pourrait faire des choses comme lancer une DoS par connexions HTTP répétées vers http://www.victim.example/. C'est pour éviter ce genre d'attaques que tous les navigateurs ont la notion d'origine. Le code récupéré sur le site du méchant va avoir l'origine www.evil.example, et le navigateur l'empêchera de faire des requêtes HTTP vers un autre serveur que www.evil.example. En gros, le principe traditionnel de sécurité est « Le contenu récupéré depuis l'origine X peut interagir librement avec les ressources ayant cette même origine. Le reste est interdit. » (section 1 du RFC, pour un résumé).

Mais ce principe très simple à énoncer et à comprendre dissimule pas mal de pièges. Ce RFC va donc essayer de les mettre en évidence. À noter qu'il ne fait que fournir un cadre, ce n'est pas un protocole, et il n'y a donc pas besoin de modifier les navigateurs pour obéir à ce texte. Les détails concrets du principe d'origine vont en effet dépendre du protocole utilisé et chacun (HTML, WebSockets du RFC 6455, etc) va donc devoir décliner ce principe selon ses caractéristiques propres. Par exemple, pour le futur HTML5, voici la définition.

Donc, on attaque avec la section 3, qui expose ce qu'est ce « principe de même origine » (Same Origin Policy). D'abord, la confiance (section 3.1) est exprimée sous forme d'un URI. Lorsque le serveur www.niceguy.example sert une page HTML https://www.niceguy.example/foo/bar.html qui contient :


   <script src="https://example.com/library.js"/>

Il annonce sa confiance envers l'URI https://example.com/library.js. Le code JavaScript téléchargé via cet URI sera exécuté avec les privilèges de https://www.niceguy.example/foo/bar.html, qui a choisi de lui faire confiance.

Cette idée de « confiance par URI » peut poser des problèmes dans certains cas. Par exemple, si on utilise le STARTTLS du RFC 2817, le fait d'utiliser TLS ou pas n'apparait pas dans l'URI et la page HTML ne peut donc pas exiger TLS. Les URI de plan https: n'ont pas ce défaut, l'exigence de TLS y est explicite.

Mais il y a une question plus sérieuse : dans https://www.niceguy.example/foo/bar.html, quelle est l'origine, celle dont vont dépendre les autorisations ultérieures (section 3.2) ? Est-ce tout l'URI ? Ou bien seulement le FQDN www.niceguy.example ? Réponse : aucune des deux.

Utiliser tout l'URL comme origine manquerait de souplesse. Un code venu de http://www.niceguy.example/foo ne pourrait pas interagir avec du contenu récupéré en http://www.niceguy.example/bar. Mais n'utiliser que le nom de domaine n'est pas génial non plus. Car cela permettrait à du code JavaScript récupéré par http://www.niceguy.example:8080/ de modifier un arbre DOM de https://www.niceguy.example/ (notez que la seconde est sécurisée avec HTTPS ; ne se servir que du nom de domaine comme origine permettrait à du contenu non sûr de manipuler du contenu sûr).

Et faut-il utiliser tout le FQDN ? Cela empêche http://portal.niceguy.example/ de jouer avec http://manager.niceguy.example/ alors que les deux sites sont sous la même autorité, celle de niceguy.example. Mais le problème est que la détermination de cette autorité est difficile. Contrairement à ce que croient les débutants, elle n'est pas forcément dans les deux derniers composants du nom de domaine. Par exemple, jones.co.uk et smith.co.uk ne sont pas sous la même autorité. Et, même lorsque c'est le cas, une Université ne souhaite pas forcément que http://students.example.edu/ (consacré aux pages personnelles des étudiants) aient des droits sur http://admin.example.edu/. Bien sûr, aucun système n'est parfait. Avec le FQDN, http://example.edu/students/~mark aura des droits sur http://example.edu/grades/admin. Mais ce modèle fondé sur le FQDN est maintenant trop ancien pour le changer (rappelez-vous qu'il a évolué informellement, notre RFC 6454 ne fait que le documenter a posteriori).

Donc, pour résumer le point important de la section 3.2 : une origine est un tuple {FQDN, plan, port}. Par exemple, http://example.com/, http://example.com:80 et http://example.com/toto.html ont tous les trois la même origine, le tuple {example.com, http, 80}. En revanche, http://example.com:81/ a une autre origine (port différent), de même que ftp://example.com (plan différent), ou http://www.example.com/ (nom différent).

Ce principe de même origine ne répond pas à tous les risques de sécurité. Il faut également intégrer la notion d'autorité (tel que ce terme est utilisé en sécurité, notez que le RFC 3986 utilise ce mot dans un autre sens). L'autorité est que le navigateur donne des droits différents selon le type de document. Une image n'a aucun droit, c'est du contenu passif (du moins pour les formats traditionnels : avec des formats comme SVG, l'analyse de sécurité est bien plus complexe). En revanche, un document HTML a le droit de déclencher le chargement d'autres ressources (styles CSS mais surtout code actif, par exemple JavaScript). Normalement, l'autorité dépend du type MIME indiqué (image/png pour une image, text/html pour l'HTML). Si ce type est déterminé par un utilisateur, de nouvelles vulnérabilités peuvent survenir (et certains navigateurs sont assez imprudents pour deviner le type MIME en examinant le contenu, une mauvaise pratique, connue sous le nom de content sniffing). Pire, si l'utilisateur peut insérer du contenu qu'il choisit dans des documents ayant une forte autorité (pages HTML), de nouveaux risques peuvent survenir. Par exemple, une attaque XSS débute par l'insertion de contenu dans une page HTML, contenu qui sera ensuite interprété par le navigateur, et exécuté avec l'origine de la page Web (cf. section 8.3). Or, ce cas est très fréquent (pensez à un moteur de recherche qui affiche la requête originale sans précaution, alorss qu'elle était choisie par un utilisateur extérieur). La protection contre les XSS est complexe mais le conseil de base est : modifiez tout contenu venu de l'extérieur avant de l'inclure dans un document ayant de l'autorité (comme une page HTML), de façon à ce qu'il ne puisse pas être interprété par le navigateur. Le plus simple pour cela est d'utiliser exclusivement un système de gabarit pour fabriquer les pages. Il se chargera alors des précautions comme de transformer les < en &lt;.

Une fois déterminée l'origine, il reste à décider des privilèges donnés aux objets de la même origine (section 3.4). Pour les objets récupérés, on l'a vu, la politique est typiquement de ne donner accès qu'aux objets de même origine que le code. Mais pour les accès à d'autres objets, tout est bien plus complexe et la sécurité rentre ici en conflit avec l'utilisabilité. Par exemple, une application stricte du principe de même origine aux accès aux ressources interdirait à une page Web de mener à une autre page, d'origine différente, alors que c'est évidemment une fonction essentielle du Web. Moins caricatural, le cas d'images ou autres contenus embarqués dans une page Web. Bien que cela pose des problèmes de sécurité (pensez aux Web bugs), aucun navigateur n'impose que les images aient la même origine que la page qui les charge... De même, aucun navigateur n'interdit complètement d'envoyer des données à une autre origine, même si c'est la base de nombreuses CSRF.

Voilà, l'essentiel des principes du RFC tient dans cette section 3. Le reste, ce sont les détails pratiques. La section 4 formalise la notion d'origine en en donnant une définition rigoureuse. Elle couvre des cas rigolos comme les URI de plan file: (autrefois, les navigateurs considéraient tous les fichiers locaux comme ayant la même origine, aujourd'hui, les plus paranoïaques font de chaque fichier une origine différente), ou bien explicite le cas des ports par défaut de certains plans (vous avez remarqué l'équivalence entre les URI http://example.com/, http://example.com:80, plus haut ?). La section 5 décrit d'autres pièges comme le cas des plans où n'apparaissent pas de noms de machine comme par exemple les data: du RFC 2397 (un cas amusant car deux URI data: complètement identiques, bit par bit, sont quand même d'origine différente). Et la section 6 explique la sérialisation d'un URI, à des fins de comparaison simples avec d'autres URI, pour déterminer s'ils ont la même origine. Par exemple, http://www.example.com:80/ et http://www.example.com/toto se sérialisent tous les deux en http://www.example.com. Pour les URI de type {scheme, host, port} (les plus fréquents), une simple comparaison de chaînes de caractères nous dira ensuite s'ils ont la même origine (ici, oui).

Si on revient au premier exemple JavaScript que j'ai donné, celui où https://www.niceguy.example/foo/bar.html charge https://example.com/library.js, on voit que l'origine n'est pas l'URI du script mais celle de la page qui le charge. Or, on peut imaginer que le serveur example.com voudrait bien connaître cette origine, par exemple pour appliquer des règles différentes. ou tout simplement pour informer le script du contexte dans lequel il va s'exécuter. C'est le rôle de l'en-tête HTTP Origin:, normalisé dans la section 7, et qui peut être ajouté aux requêtes. Ainsi, dans l'exemple ci-dessus, la requête HTTP ressemblerait à :

[Connexion à exemple.com...]
GET /library.js HTTP/1.1
Host: example.com
Origin: https://www.niceguy.example
...

On voit que l'origine indiquée est la forme sérialisée comme indiqué plus haut. Ce n'est donc pas l'équivalent de Referer: qui indique un URI complet.

Cet en-tête est désormais dans le registre des en-têtes (cf. section 9).

Comme tout ce RFC décrit un mécanisme de sécurité, il est prudent de bien lire la section 8, Security Considerations, qui prend de la hauteur et rappelle les limites de ce mécanisme. Historiquement, d'autres modèles que le « principe de même origine » ont été utilisés (à noter que le RFC ne fournit pas de référence), comme le taint tracking ou l'exfiltration prevention mais pas avec le même succès.

D'abord, la notion d'origine est une notion unique qui s'applique à des problèmes très différents et peut donc ne pas être optimisée pour tous les cas.

Ensuite, elle dépend du DNS (section 8.1) puisque la plupart des plans d'URI utilisent la notion d'host et que la politique de même origine considère que deux serveurs sont les mêmes s'ils ont le même nom. Si l'attaquant contrôle le DNS, plus aucune sécurité n'est possible (on croit parler au vrai www.example.com et on parle en fait à une autre machine).

À noter que le RFC prend bien soin de ne pas parler de la principale vulnérabilité de ce concept d'host : l'absence de notion générale d'identité d'une machine dans l'Internet (cette notion n'existe que pour certains protocoles spécifiques comme SSH). En l'absence d'une telle notion, des attaques sont possibles sans que l'attaquant ait eu à compromettre le DNS, comme par exemple le changement d'adresse IP.

Autre piège, le fait que le principe de même origine, ne soit pas apparu tout de suite et que certaines techniques de sécurité du Web utilisent une autre unité d'isolation que l'origine (section 8.2). Le Web n'a pas en effet de sécurité cohérente. C'est le cas des cookies (RFC 6265), qui se servent d'un autre concept, le « domaine enregistré ». Le navigateur essaie de trouver, lorsqu'il récupère un cookie, à quel « domaine enregistré » il appartient (l'idée étant que sales.example.com et it.example.com appartiennent au même domaine enregistré, alors qu'ils n'ont pas la même origine). Il enverra ensuite le cookie lors des connexions au même domaine enregistré. Pour déterminer ce domaine, notez que les cookies ne font pas de différence entre HTTP et HTTPS (sauf utilisation de l'attribut Secure) et qu'un cookie acquis de manière sûre peut donc être envoyé par un canal non sûr.

Notre RFC note que cette pratique d'utiliser le « domaine enregistré » est mauvaise et la déconseille. En effet :

  • Rien n'indique dans le nom lui-même où est le domaine enregistré. Sans connaître les règles d'enregistrement de JPRS, vous ne pouvez pas dire que a.co.jp et b.co.jp sont deux domaines enregistrés différents. Il existe des listes publiques de politiques d'enregistrement comme http://publicsuffix.org/ mais aucune n'est officielle et aucune n'est à jour.
  • Cette pratique dépend fortement du plan d'URI utilisé, certains n'ayant pas de domaine (donc pas de domaine enregistré).

Autre faiblesse du principe de même origine, l'autorité diffuse (section 8.3). L'autorité va dépendre de l'URI, pas du contenu. Or, un URI de confiance peut inclure du contenu qui ne l'est pas (pour le cas, fréquent, où une page Web inclut du contenu généré par l'utiisateur) et c'est alors un risque de XSS.

Résultat, le principe de même origine ne suffit pas à lui seul à protéger l'utilisateur (plusieurs attaques ont déjà été documentées.) Il faut donc ajouter d'autres pratiques de sécurité.

Notez que la question des mises en œuvre de ce RFC ne se pose pas, il a été réalisé après le déploiement du concept de même origine et tous les navigateurs Web utilisent aujourd'hui ce système. Toutefois, certains ne le font peut-être pas encore absolument comme décrit ici, par exemple en accordant au plan ou au port moins de poids qu'au host (il semble que cela ait été le cas de certaines versions d'Internet Explorer).

Une autre bonne lecture sur ce concept d'origine est l'article de Google pour les développeurs.


Téléchargez le RFC 6454


L'article seul

RFC 6452: The Unicode code points and IDNA - Unicode 6.0

Date de publication du RFC : Novembre 2011
Auteur(s) du RFC : P. Faltstrom (Cisco), P. Hoffman (VPN Consortium)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF appsawg
Première rédaction de cet article le 13 novembre 2011


Une des exigences de la norme sur les IDN (RFC 5890) est la stabilité : si un caractère est autorisé dans les noms de domaine à un moment donné, il devrait l'être pour toujours, sous peine qu'une épée de Damoclès pèse sur les titulaires de noms, la crainte qu'un nom qu'ils utilisent devienne subitement invalide. Mais le mécanisme par lequel sont déterminés les caractères autorisés ou interdits rend inévitable de tels problèmes, heureusement dans des cas rares et marginaux. C'est ce qui vient de se produire avec la sortie de la norme Unicode version 6 : le caractère ᧚ (U+19DA), autrefois autorisé, est désormais interdit. S'il y avait eu des noms de domaine l'utilisant (ce n'était apparemment pas le cas), ils deviendraient subitement illégaux.

Vu que ce caractère est très rare, toute cette discussion n'est-elle pas une tempête dans un verre d'eau ? Pas complètement, parce que c'est la première fois que le problème se pose depuis la sortie de la version 2 de la norme IDN, et que la façon dont ce cas a été traité va servir de modèle pour des futurs problèmes qui pourraient être plus délicats.

Reprenons dès le début : dans la norme actuelle sur les IDN, dite « IDNAbis » (RFC 5890), les caractères Unicode peuvent être valides ou invalides dans un nom de domaine. Cette validité (qui était déterminée manuellement dans la première version d'IDN) découle d'un algorithme, normalisé dans le RFC 5892, qui prend en compte les propriétés que la norme Unicode attache à un caractère. Par exemple, si le caractère a la propriété « Est une lettre », il est valide. Ce système a l'avantage de remédier au principal inconvénient d'IDN version 1, le fait que le premier IDN était lié à une version particulière d'Unicode. Avec IDNAbis, au contraire, lorsque le consortium Unicode sort une nouvelle version de sa norme, il suffit de faire tourner à nouveau l'algorithme, et on a la liste des caractères valides dans cette nouvelle version.

Le problème que cela pose est que les propriétés d'un caractère Unicode peuvent changer d'une version à l'autre. Elles ne sont pas forcément couvertes par les engagements de stabilité du consortium Unicode. C'est ce qui s'est produit en octobre 2010, lors de la sortie de la version 6 d'Unicode. Trois caractères ont vu leur validité changer car leur GeneralCategory Unicode a changé. Pour les deux premiers, rien de très grave. ೱ (U+0CF1) et ೲ (U+0CF2), classés à tort comme des symboles, ont été reclassés comme lettres et sont donc devenus valides, alors qu'ils étaient invalides. Personne n'avait donc pu les utiliser et le changement ne va donc pas affecter les titulaires de noms de domaine.

Mais le troisième pose un problème épineux. Pas quantitativement. Ce caractère ᧚ (U+19DA), de l'écriture Tai Lue n'a apparemment jamais été utilisé dans un nom de domaine, en partie par ce que l'écriture dont il fait partie est peu répandue (et ses utilisateurs sont peu connectés à l'Internet). Mais, qualitativement, c'est ennuyeux car U+19DA (un chiffre) fait le chemin inverse. D'autorisé, il devient interdit. Potentiellement, il peut donc remettre en cause la stabilité des noms de domaine. Si on applique aveuglément l'algorithme du RFC 5892, U+19DA va devenir interdit. Alors, que faire ? Le RFC 5892 (section 2.7) prévoyait une table des exceptions, où on pouvait mettre les caractères à qui on désirait épargner le sort commun. Fallait-il y mettre le chiffre 1 du Tai Lue ?

La décision finalement prise, et documentée par ce RFC (décision pompeusement baptisée « IETF consensus », bien que la section 5 rappelle qu'elle a été vigoureusement discutée) a finalement été de laisser s'accomplir le destin. Aucune exception n'a été ajoutée pour ces trois caractères, l'algorithme normal s'applique et U+19DA ne peut donc plus être utilisé. L'argument principal est que ce caractère n'était quasiment pas utilisé. Les cas suivants mèneront donc peut-être à des décisions différentes (la section 2 rappelle bien que, dans le futur, les choses seront peut-être différentes).

Ce RFC 6452 documente donc cette décision. Bien qu'elle se résume à « ne touchons à rien », il était préférable de la noter, car un changement qui casse la compatibilité ascendante n'est pas à prendre à la légère.

Les deux autres caractères, utilisés en Kannada, ೱ (U+0CF1) et ೲ (U+0CF2) ne créent pas le même problème car ils ont changé en sens inverse (interdits autrefois, ils sont désormais autorisés).


Téléchargez le RFC 6452


L'article seul

RFC 6441: Time to Remove Filters for Previously Unallocated IPv4 /8s

Date de publication du RFC : Novembre 2011
Auteur(s) du RFC : L. Vegoda (ICANN)
Réalisé dans le cadre du groupe de travail IETF grow
Première rédaction de cet article le 29 novembre 2011
Dernière mise à jour le 5 janvier 2012


Pour limiter certains risques de sécurité, des opérateurs réseaux filtraient en entrée de leur réseau les adresses IP non encore allouées (dites bogons). Les adresses IPv4 étant désormais totalement épuisées, cette pratique n'a plus lieu d'être et ce RFC demande donc que ces filtres soient démantelés.

L'idée était d'empêcher l'usage de ces préfixes IP non alloués. Ils représentaient des cibles tentantes, par exemple pour un spammeur qui voulait des adresses jetables et non traçables : on trouve un bloc non alloué, on l'annonce en BGP (puisqu'il n'est pas alloué, il n'y a pas de risque de collision), on envoie son spam et on arrête l'annonce BGP (voir les articles cités à la fin). Pour éviter cela, et d'autres attaques analogues, l'habitude s'est prise de filtrer les bogons, ces préfixes non alloués. Certains opérateurs rejetaient les annonces BGP pour ces bogons, d'autres bloquaient sur le pare-feu les paquets ayant une adresse source dans ces préfixes non alloués. Ces pratiques étaient largement documentées par exemple sur le site de référence sur les bogons.

Cette pratique a toujours posé des problèmes, notamment celui de la « débogonisation ». Lorsqu'un préfixe qui n'était pas alloué le devient, il faut toute une gymnastique pour le retirer des filtres existants, sachant que beaucoup de ces filtres ne sont que rarement mis à jour. On voit ainsi des messages sur les listes de diffusion d'opérateurs réseaux avertissant de l'arrivée prochaine d'un nouveau préfixe et demandant qu'il soit supprimé des filtres. Voici deux exemples de ces annonces en 2004 et en 2005. Pour permettre aux opérateurs de tester que tout va bien après cette suppression, les RIR mettent souvent un beacon, un amer, dans le préfixe, une adresse IP qu'on peut pinguer pour tester, comme le recommande le RFC 5943. Tout ce travail faisait donc que la chasse aux bogons était contestée depuis longtemps.

À noter (section 2) que le terme de bogon a été défini dans le RFC 3871, qui recommande leur blocage. Ce même RFC 3871 décrit en détail le problème que posent les bogons et la raison de leur éradication. Le terme de martien, plus flou (il vient du RFC 1208), est appliqué à toutes sortes de paquets dont l'adresse source est anormale (dans le DNS, il a un autre sens, celui de paquet de réponse à une question qui n'a pas été posée).

La section 3 représente le cœur du RFC : elle formule la nouvelle règle. Celle-ci, tenant compte de l'épuisement des adresses IPv4 est simple : tous les préfixes IPv4 sont désormais alloués ou réservés. Il ne faut donc filtrer que les réservés. Les autres peuvent désormais tous être une source légitime de trafic IP. La chasse aux bogons et les difficultés de la débogonisation faisant partie du folklore de l'Internet depuis très longtemps, c'est donc une page d'histoire qui se tourne. (Les adresses IPv6 sont, elles, loin d'être toutes allouées et ne sont donc pas concernées.)

La section 4 rappelle que l'autorité pour cette liste de préfixes réservés est le RFC 6890. On y trouve par exemple les adresses privées du RFC 1918 ou bien les adresses réservées à la documentation du RFC 5737. Les listes de bogons qu'on trouve sur le réseau, comme celle de TeamCymru sont désormais réduites à ce groupe.

À noter que l'assertion « Tous les préfixes sont désormais alloués » ne vaut que pour les préfixes de longueur 8 (les « /8 ») distribués aux RIR. Certains peuvent filtrer à un niveau plus fin, en distinguant dans ces /8 les adresses que les RIR ont affectés de celles qui ne le sont pas encore. Comme le rappelle la section 3.2, cette pratique est risquée, les affectations par les RIR changeant vite. Le RFC demande donc que, si on a de tels filtres, ils soient changés au moins une fois par jour.

Pour en apprendre plus sur les bogons, on peut regarder la bonne analyse faite par BGPmon. On voit finalement peu d'annonces BGP de bogons (6 seulement en 2011), la plupart pour le préfixe 198.18.0.0/15 des mesures de performance (RFC 5735). Un bon résumé des bogons et de la débogonisation avait été fait par Dave Deitrich en 2005.

Quelques articles sur les trucs utilisés par des méchants (spammeurs, par exemple), en connexion avec les bogons :


Téléchargez le RFC 6441


L'article seul

RFC 6434: IPv6 Node Requirements

Date de publication du RFC : Décembre 2011
Auteur(s) du RFC : E. Jankiewicz (SRI International), J. Loughney (Nokia), T. Narten (IBM Corporation)
Pour information
Réalisé dans le cadre du groupe de travail IETF 6man
Première rédaction de cet article le 22 décembre 2011


Il existe des tas de RFC qui concernent IPv6 et le programmeur qui met en œuvre ce protocole dans une machine risque fort d'en rater certains, ou bien d'implémenter certains qu'il aurait pu éviter. Ce RFC était donc un méta-RFC, chargé de dresser la liste de ce qui est indispensable dans une machine IPv6. Il a été remplacé depuis par le RFC 8504. Les deux points les plus chauds concernaient la configuration (par DHCP ou par RA - Router Advertisment ?) et la gestion d'IPsec, désormais officiellement facultative.

Ce document remplace son prédécesseur, le RFC 4294 (et est lui-même remplacé par le RFC 8504. Il vise le même but, servir de carte au développeur qui veut doter un système de capacités IPv6 et qui se demande s'il doit vraiment tout faire (réponse : non). Ce RFC explique clairement quels sont les points d'IPv6 qu'on ne peut pas négliger, sous peine de ne pas pouvoir interagir avec les autres machines IPv6. Le reste est laissé à l'appréciation du développeur. La section 2 résume ce but.

Les deux gros changements par rapport au RFC 4294 sont :

  • DHCP monte en grade, bien que restant derrière les RA pour la configuration des machines IPv6,
  • IPsec n'est plus obligatoire.

Ce RFC s'applique à tous les nœuds IPv6, aussi bien les routeurs (ceux qui transmettent des paquets IPv6 reçus qui ne leur étaient pas destinés) que les machines terminales (toutes les autres).

Bien, maintenant, les obligations d'une machine IPv6, dans l'ordre. D'abord, la couche 2 (section 4 du RFC). Comme IPv4, IPv6 peut tourner sur des tas de couches de liaison différentes et d'autres apparaîtront certainement dans le futur. En attendant, on en a déjà beaucoup, Ethernet (RFC 2464), 802.16 (RFC 5121), PPP (RFC 5072) et bien d'autres, sans compter les tunnels.

Ensuite, la couche 3 (section 5 du RFC) qui est évidemment le gros morceau puisque c'est la couche d'IP. Le cœur d'IPv6 est normalisé dans le RFC 2460 et ce dernier RFC doit donc être intégralement implémenté, à l'exception de l'en-tête de routage de type 0, qui a été abandonné par le RFC 5095.

Comme IPv6, contrairement à IPv4, ne permet pas aux routeurs intermédiaires de fragmenter les paquets, la découverte de la MTU du chemin est particulièrement cruciale. La mise en œuvre du RFC 1981 est donc recommandée. Seules les machines ayant des ressources très limitées (genre où tout doit tenir dans la ROM de démarrage) sont dispensées. Mais le RFC se doit de rappeler que la détection de la MTU du chemin est malheuresement peu fiable dans l'Internet actuel, en raison du grand nombre de pare-feux configurés avec les pieds et qui bloquent tout l'ICMP. Il peut être donc nécessaire de se rabattre sur les techniques du RFC 4821).

Le RFC 2460 décrit le format des paquets et leur traitement. Les adresses y sont simplement mentionnées comme des champs de 128 bits de long. Leur architecture est normalisée dans le RFC 4291, qui est obligatoire.

Également indispensable à toute machine IPv6, l'autoconfiguration sans état du RFC 4862, ainsi que ses protocoles auxiliaires comme la détection d'une adresse déjà utilisée.

ICMP (RFC 4443) est évidemment obligatoire, c'est le protocole de signalisation d'IP (une des erreurs les plus courantes des administrateurs réseaux incompétents est de bloquer ICMP sur les pare-feux).

Dernier protocole obligatoire, la sélection de l'adresse source selon les règles du RFC 3484 (depuis remplacé par le RFC 6724), pour le cas où la machine aurait le choix entre plusieurs adresses (ce qui est plus fréquent en IPv6 qu'en IPv4).

Le reste n'est en général pas absolument obligatoire mais recommandé (le terme a un sens précis dans les RFC, définie dans le RFC 2119 : ce qui est marqué d'un SHOULD doit être mis œuvre, sauf si on a une bonne raison explicite et qu'on sait exactement ce qu'on fait). Par exemple, la découverte des voisins (NDP, RFC 4861) est recommandée. Toutes les machines IPv6 en ont besoin, sauf si elles utilisent les liens ne permettant pas la diffusion.

Moins générale, la sélection d'une route par défaut s'il en existe plusieurs, telle que la normalise le RFC 4191. Elle est particulièrement importante pour les environnements SOHO (RFC 7084).

On a vu que l'autoconfiguration sans état (sans qu'un serveur doive se souvenir de qui a quelle adresse) était obligatoire. DHCP (RFC 8415), lui, n'est que recommandé.

Une extension utile (mais pas obligatoire) d'IP est celle des adresses IP temporaires du RFC 8981, permettant de résoudre certains problèmes de protection de la vie privée. Évidemment, elle n'a pas de sens pour toutes les machines (par exemple, un serveur dans son rack n'en a typiquement pas besoin). Elle est par contre recommandée pour les autres.

Encore moins d'usage général, la sécurisation des annonces de route (et des résolutions d'adresses des voisins) avec le protocole SEND (RFC 3971). Le déploiement effectif de SEND est très faible et le RFC ne peut donc pas recommander cette technique pour laquelle on n'a pas d'expérience, et qui reste simplement optionnelle.

L'une des grandes questions que se pose l'administrateur réseaux avec IPv6 a toujours été « autoconfiguration RA - Router Advertisment - ou bien DHCP ? » C'est l'un des gros points de ce RFC et la section 6 le discute en détail. Au début d'IPv6, DHCP n'existait pas encore pour IPv6 et les RA ne permettaient pas encore de transmettre des informations pourtant indispensables comme les adresses des résolveurs DNS (le RFC 6106 a résolu cela). Aujourd'hui, les deux protocoles ont à peu près des capacités équivalentes. RA a l'avantage d'être sans état, DHCP a l'avantage de permettre des options de configuration différentes par machine. Alors, quel protocole choisir ? Le problème de l'IETF est que si on en normalise deux, en laissant les administrateurs du réseau choisir, on court le risque de se trouver dans des situations où le réseau a choisi DHCP alors que la machine attend du RA ou bien le contraire. Bref, on n'aurait pas d'interopérabilité, ce qui est le but premier des normes Internet. Lorsque l'environnement est très fermé (un seul fournisseur, machines toutes choisies par l'administrateur réseaux), ce n'est pas un gros problème. Mais dans un environnement ouvert, par exemple un campus universitaire ou un hotspot Wifi, que faire ? Comme l'indiquent les sections 5.9.2 et 5.9.5, seul RA est obligatoire, DHCP ne l'est pas. RA est donc toujours la méthode recommandée si on doit n'en choisir qu'une, c'est la seule qui garantit l'interopérabilité. (Voir aussi la section 7.2 sur DHCP.)

Continuons à grimper vers les couches hautes. La section 7 est consacrée aux questions DNS. Une machine IPv6 devrait pouvoir suivre le RFC 3596 et donc avoir la possibilité de gérer des enregistrements DNS de type AAAA (les adresses IPv6) et la résolution d'adresses en noms grâce à des enregistrements PTR dans ip6.arpa. Les anciens enregistrements A6 (RFC 3363) ont été abandonnés mais on constate que ces enregistrements sont toujours très demandés lors des requêtes à des serveurs DNS faisant autorité, comme ceux de .fr (dans les 0,5 % des requêtes, soit davantage que SRV ou DS).

À noter qu'une machine IPv6, aujourd'hui, a de fortes chances de se retrouver dans un environnement où il y aura une majorité du trafic en IPv4 (c'est certainement le cas si cet environnement est l'Internet). La section 8 rappelle donc qu'une machine IPv6 peut avoir intérêt à avoir également IPv4 et à déployer des techniques de transition comme la double-pile du RFC 4213.

Encore juste une étape et nous en sommes à la couche 7, à laquelle la section 9 est consacrée. Si elle parle de certains détails de présentation des adresses (RFC 5952), elle est surtout consacrée à la question des API. En 2011, on peut dire que la grande majorité des machines a IPv6, côté couche 3 (ce qui ne veut pas dire que c'est activé, ni que le réseau le route). Mais les applications sont souvent en retard et beaucoup ne peuvent tout simplement pas communiquer avec une autre machine en IPv6. L'IETF ne normalise pas traditionnellement les API donc il n'y a pas d'API recommandée ou officielle dans ce RFC, juste de l'insistance sur le fait qu'il faut fournir une API IPv6 aux applications, si on veut qu'elles utilisent cette version d'IP, et qu'il en existe déjà, dans les RFC 3493 (fonctions de base) et RFC 3542 (fonctions avancées).

La sécurité d'IPv6 a fait bouger beaucoup d'électrons, longtemps avant que le protocole ne soit suffisamment déployé pour qu'on puisse avoir des retours d'expérience. Certains ont survendu IPv6 en prétendant que, contrairement à IPv4, il avait la sécurité intégrée dès le début et était donc plus sûr. Cette légende vient du fait qu'en théorie, IPsec était obligatoire pour toute mise en œuvre d'IPv6. Ce point n'a jamais été respecté par les implémentations (et puis, de toute façon, avoir IPsec est une chose, l'activer, avec sa complexe configuration, en est une autre). Désormais, depuis la sortie de notre RFC 6434, ce point n'est même plus vrai en théorie, IPsec (RFC 4301) est officiellement simplement recommandé.

Le RFC note donc bien que la sécurité est un processus complexe, qui ne dépend certainement pas que d'une technique magique (« IPsec est intégré donc il n'y a pas de problème de sécurité ») et qu'aucun clair gagnant n'émerge de la liste des solutions de sécurité (IPsec, TLS, SSH, etc). D'autant plus qu'IPv6 vise à être déployé dans des contextes comme « l'Internet des Trucs » où beaucoup de machines n'auront pas forcément les ressources nécessaires pour faire de l'IPsec.

Toutes les règles et recommandations précédentes étaient pour tous les nœuds IPv6. La section 12 expose les règles spécifiques aux routeurs. Ils doivent être capables d'envoyer les Router Advertisment et de répondre aux Router Solicitation du RFC 4861 et on suggère aux routeurs SOHO d'envisager sérieusement d'inclure un serveur DHCP (RFC 7084) et aux routeurs de réseaux locaux de permettre le relayage des requêtes DHCP.

Enfin, la section 13 se penche sur la gestion des réseaux IPv6 en notant que deux MIB sont obligatoires, celle du RFC 4292 sur la table de routage, et celle du RFC 4293 sur IP en général.

Les changements par rapport au RFC 4294 sont résumés dans l'annexe 16. Les deux plus importants, comme déjà noté, sont IPsec et DHCP, un qui descend, l'autre qui monte. Mais on y trouve aussi l'arrivée de SEND (mais en option), celle des options DNS du RFC 6106, et beaucoup de détails et de clarifications. Depuis, le RFC 8504 a aussi apporté ses changements.


Téléchargez le RFC 6434


L'article seul

RFC 6430: Email Feedback Report Type Value : not-spam

Date de publication du RFC : Novembre 2011
Auteur(s) du RFC : K. Li (Huawei), B. Leiba (Huawei)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF marf
Première rédaction de cet article le 11 novembre 2011


Il existe un format standard pour la transmission de rapports d'abus entre acteurs de l'Internet qui permet, par exemple, à des opérateurs de serveurs de messagerie de signaler un spam, et de traiter automatiquement ces rapports. Ce format se nomme ARF et est normalisé dans le RFC 5965. Chaque rapport ARF indique un type d'abus et ce nouveau RFC 6430 ajoute le type not spam, qui permet d'attirer l'attention sur un message classé à tort.

Le format ARF est conçu pour de gros opérateurs, traitant des millions de messages et d'innombrables rapports d'abus (spam mais aussi hameçonnage, distribution de logiciel malveillant, etc). Avec de tels volumes à traiter, l'automatisation est nécessaire et c'est ce que permet ARF. Le type abuse, documenté en section 7.3 du RFC 5965, permet de signaler un message comme n'étant pas désiré. Mais on a parfois besoin de l'inverse, signaler qu'un message n'est pas du spam, pour que le destinataire du rapport ajuste ses filtres. C'est ce qu'introduit notre RFC, suite à une demande de l'OMAMobile Spam Reporting Requirements », OMA-RD-SpamRep-V1_0 20101123-C).

Bien sûr, le destinataire du rapport est libre de l'action à entreprendre. Il peut par exemple attendre d'avoir plusieurs rapports équivalents, Si l'opérateur accepte des rapports envoyés directement par les utilisateurs (ceux-ci ne vont pas taper du ARF à la main mais ils peuvent avoir un MUA muni d'un bouton Report as non-spam qui le fait pour eux), il doit tenir compte du fait que les utilisateurs peuvent se tromper (cliquer trop vite) ou même tenter d'influencer le système (mais non, cette publicité n'est pas du spam, laissez-la passer...). La section 4 rappelle donc de traiter avec prudence ces rapports.

Les détails de syntaxe figurent en section 3 du RFC. Voici un exemple de rapport avec le Feedback-Type: à not-spam. abusedesk@example.com signale à abuse@example.net que le message de someone@example.net n'est pas, en dépit des apparences, du spam (mettons qu'il ait été envoyé en réponse à une sollicitation d'un médecin) :


From: <abusedesk@example.com>
Date: Thu, 8 Mar 2005 17:40:36 EDT
Subject: FW: Discount on pharmaceuticals
To: <abuse@example.net>
Message-ID: <20030712040037.46341.5F8J@example.com>
MIME-Version: 1.0
Content-Type: multipart/report; report-type=feedback-report;
     boundary="part1_13d.2e68ed54_boundary"

--part1_13d.2e68ed54_boundary
Content-Type: text/plain; charset="US-ASCII"
Content-Transfer-Encoding: 7bit

This is an email abuse report for an email message received
from IP 192.0.2.1 on Thu, 8 Mar 2005 14:00:00 EDT.
For more information about this format please see
http://tools.ietf.org/html/rfc5965
Comment: I sell pharmaceuticals, so this is not spam for me.

--part1_13d.2e68ed54_boundary
Content-Type: message/feedback-report

Feedback-Type: not-spam
User-Agent: SomeGenerator/1.0
Version: 1

--part1_13d.2e68ed54_boundary
Content-Type: message/rfc822
Content-Disposition: inline

Received: from mailserver.example.net
     (mailserver.example.net [192.0.2.1])
     by example.com with ESMTP id M63d4137594e46;
     Thu, 08 Mar 2005 14:00:00 -0400
From: <someone@example.net>
To: <Undisclosed Recipients>
Subject: Discount on pharmaceuticals
MIME-Version: 1.0
Content-type: text/plain
Message-ID: 8787KJKJ3K4J3K4J3K4J3.mail@example.net
Date: Thu, 02 Sep 2004 12:31:03 -0500

Hi, Joe.  I got a lead on a source for discounts on
pharmaceuticals, and I thought you might be interested.
[...etc...]
--part1_13d.2e68ed54_boundary--

Le type not-spam fait donc désormais partie du registre des types de rapport ARF.


Téléchargez le RFC 6430


L'article seul

RFC 6419: Current Practices for Multiple Interface Hosts

Date de publication du RFC : Novembre 2011
Auteur(s) du RFC : M. Wasserman (Painless Security, LLC), P. Seite (France Telecom - Orange)
Pour information
Réalisé dans le cadre du groupe de travail IETF mif
Première rédaction de cet article le 22 novembre 2011


Il fut une époque où la machine terminale connectée à l'Internet n'avait typiquement qu'une seule interface réseau. Seuls les routeurs avaient plusieurs interfaces et donc des décisions difficiles à prendre comme « quelle adresse source choisir pour le paquet que je génère ? » Aujourd'hui, les machines les plus ordinaires ont souvent, à leur tour, plusieurs interfaces réseau. Mon smartphone a une interface WiFi et une 3G. Mon ordinateur portable a une interface filaire, une 3G, une Wifi et une Bluetooth. Qui dit plusieurs interfaces dit décisions à prendre. Quel serveur DNS utiliser ? Celui appris via l'interface filaire ou bien celui appris en Wifi ? Par quelle interface envoyer un paquet qui sort de la machine ? La question est d'autant plus difficile que les différentes interfaces fournissent en général des services très différents, en terme de qualité et de prix. Le groupe de travail MIF de l'IETF travaille à normaliser le comportement des machines sur ce point. Son premier RFC (un autre, le RFC 6418, concerne l'exposé du problème) commence par examiner l'état de l'art : que font aujourd'hui les divers systèmes d'exploitation confrontés à cette question ?

Le RFC ne prétend pas couvrir tous les systèmes. Il se contente de ceux que les membres du groupe de travail connaissaient, ceux sur lesquels ils avaient de la documentation et des informations : Nokia S60, Windows Mobile, Blackberry, Android, Windows, et des systèmes à base de Linux.

Comment ces systèmes gèrent cette multiplicité des interfaces réseaux, se demande la section 2. Une première approche est de centraliser la gestion des connexions : ce n'est pas l'application qui choisit l'interface à utiliser, elle passe par un gestionnaire de connexions (en lui transmettant parfois quelques souhaits) qui choisit pour elle. Le gestionnaire peut choisir en fonction de la table de routages (si l'application veut écrire à 172.23.1.35 et qu'une seule interface a une route vers cette adresse, le choix est vite fait) mais elle ne suffit pas toujours (que faire si deux interfaces sont connectées à un réseau privé 172.23.0.0/16 ?). Le gestionnaire doit aussi tenir compte d'autres facteurs. Le coût est souvent le plus important (prix élevés de la 3G, surtout en itinérance, par rapport au Wifi ou au filaire, par exemple).

Une autre solution est que l'application choisisse elle-même, en fonction des informations qu'elle reçoit du système. Certaines applications ont des idées bien précises sur la connexion qu'elles veulent utiliser. Par exemple, sur Android, la plupart des clients SIP refusent par défaut d'utiliser les connexions 3G, les opérateurs y interdisant en général le trafix voix (en violation de la neutralité du réseau). Les deux méthodes (gestionnaire de connexions centralisé et choix par l'application) ne sont pas complètement exclusives. Comme indiqué, on peut aussi avoir un gestionnaire centralisé, mais qui permet aux applications d'indiquer des préférences (« essaie d'éviter la 3G »).

Certains choix sont par contre typiquement réglés par une troisième approche : le faire entièrement dans le système, sans demander à l'utilisateur ou aux applications (section 2.3). Le système rassemble des informations de sources diverses (DHCP, RA (Router Advertisment), configuration manuelle par l'administrateur système) et fait ensuite des choix qui sont globaux au système, ou bien spécifiques à chaque interface. Il n'y a aucune règle commune entre les différents systèmes d'exploitation sur ce plan, et aucun ne semble fournir une solution parfaite.

Par exemple, la configuration DNS voit certains systèmes permettre un jeu de résolveurs DNS différent par interface, avec des règles indiquant quel jeu est choisi. D'autres ont au contraire un seul jeu de résolveurs.

La sélection de l'adresse source est plus « standard ». L'application fournit l'adresse de destination et, lorsqu'elle n'a pas choisi une adresse source explicité (option -b de OpenSSH, par exemple), le système en sélectionne automatiquement une. Pour IPv6, il existe même une norme pour cela, le RFC 6724 (et son prédécesseur, le RFC 3484, qui est encore la référence). Un grand nombre de systèmes d'exploitation ont adapté cette norme à IPv4 et l'utilisent donc pour toutes les familles d'adresses. En revanche, tous ne fournissent pas forcément un mécanisme permettant à l'administrateur système d'influencer cette sélection (le /etc/gai.conf sur Linux). Autre point où les systèmes diffèrent, certains choisissent l'interface de sortie avant l'adresse source, d'autres après.

La section 3 est ensuite l'exposé des pratiques des différents systèmes, à l'heure actuelle (une version future pourra changer leur comportement). Ainsi, le système S60 (qui tourne sur Symbian) introduit le concept d'IAP (Internet Access Point) ; un IAP rassemble toutes les informations sur une interface (physique ou virtuelle, dans le cas des tunnels). La machine a en général plusieurs IAP et l'application choisit une IAP au moment où elle a besoin du réseau. Ce choix est motivé par le fait que toutes les IAP ne fournissent pas forcément le service attendu par l'application. Par exemple, l'envoi d'un MMS nécessite l'usage d'un IAP qui donne accès à la passerelle MMS de l'opérateur, qui n'est en général pas joignable depuis l'Internet public. De même, une application qui accède aux serveurs privés d'une entreprise va choisir l'IAP qui correspond au VPN vers l'entreprise.

Ce concept d'IAP permet d'éviter bien des questions. Ainsi, le serveur DNS est indiqué dans l'IAP et, une fois celle-ci choisie, il n'y a pas à se demander quel serveur utiliser. (Reprenez l'exemple du VPN : cela garantira que l'application corporate utilisera un serveur DNS sûr et pas celui du hotspot où le téléphone est actuellement connecté.) De même, il existe une route par défaut par IAP et ce n'est donc pas un problème si deux interfaces de la même machine ont des plages d'adresses RFC 1918 qui se recouvrent (ou même si les deux interfaces ont la même adresse IP).

Comment l'application choisit-elle l'IAP ? Cela peut être fixé en dur dans le programme (cas de l'application MMS, en général), choisi par l'utilisateur au moment de la connexion, ou bien déterminé automatiquement par le système. La documentation de ce système figure en ligne.

Pour Windows Mobile et Windows Phone 7, tout dépend du Connection Manager. Celui-ci gère les connexions pour le compte des applications, en tenant compte de critères comme le coût ou comme la capacité du lien. Les applications peuvent l'influencer en demandant des caractéristiques particulières (par exemple une capacité minimale). Windows met en œuvre le RFC 3484 et l'administrateur système peut configurer des règles qui remplacent celles par défaut. Ce système est documenté en ligne.

Le Blackberry laisse les applications choisir la connexion qu'elles veulent, même s'il fournit un relais pour celles qui le désirent. Cela dépend toutefois de la configuration du réseau (l'utilisation obligatoire du Enterprise Server peut être choisie, par exemple). Les réglages comme le DNS sont par interface et non pas globaux au système. Plus de détails sont fournis dans la documentation.

Et Google Android ? Utilisant un noyau Linux, il partage certaines caractéristiques avec les autres systèmes Linux. Par défaut, il se comporte selon le modèle « machine terminale ouverte » (weak host model, cf. RFC 1122, section 3.3.4.2), mais peut aussi utiliser le modèle « machine strictement terminale » (strong host model). Dans le premier cas, les différentes interfaces réseaux ne sont pas strictement séparées, un paquet reçu sur une interface est accepté même si l'adresse IP de destination n'est pas celle de cette interface. Dans le second, la machine est stricte et refuse les paquets entrants si l'adresse IP de destination ne correspond pas à l'interface d'entrée du paquet.

La configuration DNS est globale (attention, Android ne la note pas dans /etc/resolv.conf, dont le contenu est ignoré). Cela veut dire que, dès qu'une réponse DHCP est reçue sur une interface, la configuration DNS de cette interface remplace la précédente.

Depuis Android 2.2, le RFC 3484 est géré. (Notez que, à l'heure actuelle, Android ne peut pas faire d'IPv6 sur l'interface 3G.)

La documentation figure dans le paquetage android.net. Les applications peuvent utiliser la classe ConnectivityManager si elles veulent influencer la sélection de l'interface. Pour cela, le système met à leur disposition la liste des interfaces et leurs caractéristiques. (Pour étudier un programme qui l'utilise, vous pouvez par exemple regarder les occurrences de ConnectivityManager dans le source Java de CSIPsimple.)

Le RFC se penche aussi sur un système moins connu, Arena, qui utilise également Linux et fournit un gestionnaire de connexions pour choisir les interfaces, avec indication des préférences par les applications. Il sera décrit dans un futur RFC.

Et sur les systèmes d'exploitation utilisés sur le bureau ? Windows est présenté mais sera décrit plus en détail dans un autre RFC. Les systèmes utilisant Linux (comme Ubuntu ou Fedora) partagent plusieurs caractéristiques :

  • Les informations comme l'adresse IP utilisée sont stockées par interface et sont obtenues par DHCP (ou RA).
  • Un certain nombre d'informations, notamment la route par défaut, les serveurs DNS ou les serveurs NTP sont globales au système. Bien que les clients DHCP utilisés, comme celui de l'ISC, permettent une configuration différente par interface, des paramètres comme la liste des résolveurs DNS, quelle que soit l'interface d'où ils viennent, effacent et remplacent globalement les paramètres précédemment obtenus.
  • La dernière interface configurée est donc forcément l'interface principale.

Les systèmes à base de BSD ont en gros les mêmes caractéristiques. Dans les deux cas, Linux ou BSD, certaines options permettent de passer outre les informations obtenues par DHCP. Par exemple, des option modifiers dans le client DHCP OpenBSD offrent la possibilité d'indiquer des valeurs à utiliser avant, ou bien à la place de, celles fournies par le serveur DHCP. Même chose pour des options comme -R du client DHCP Phystech (qui indique de ne pas modifier resolv.conf) ou comme nodns et nogateway dans les options de Pump, pour ignorer les résolveurs DNS et la route par défaut de certaines interfaces. D'autres systèmes disposent d'options similaires.

Enfin, même si le RFC ne le mentionne que très rapidement, il existe des systèmes de plus haut niveau (comme Network Manager, très pratique pour les machines qui se déplacent fréquemment) dont la tâche est d'orchestrer tout cela, de surveiller la disponibilité des interfaces, de lancer le client DHCP lorsque c'est nécessaire, d'accepter ou de passer outre ses choix, etc.

Voilà en gros la situation actuelle. Prochains efforts du groupe MIF : l'améliorer... Le RFC 6418 donne le cahier des charges de cet effort. Le RFC 6731 normalise les nouvelles règles de sélection pour les serveurs DNS.


Téléchargez le RFC 6419


L'article seul

RFC 6417: How to Contribute Research Results to Internet Standardization

Date de publication du RFC : Novembre 2011
Auteur(s) du RFC : P. Eardley (BT), L. Eggert (Nokia), M. Bagnulo (UC3M), R. Winter (NEC Europe)
Pour information
Première rédaction de cet article le 2 novembre 2011


Nourri de la vaste expérience de ses auteurs (tous chercheurs et tous ayant écrit des RFC), ce document essaie de combler une partie du fossé entre la communauté des chercheurs et la normalisation, en encourageant ces chercheurs à participer à l'IETF, et en leur expliquant ce à quoi ils doivent s'attendre.

L'Internet est bien issu d'un projet de recherche, ARPANET, et a ensuite intégré un bon nombre de résultats de recherche. Normalement, le monde académique devrait se sentir à l'aise dans celui de la normalisation Internet. Mais ce n'est pas toujours le cas. Le chercheur isolé peut même trouver que l'IETF est une organisation mystérieuse et que le processus de normalisation y est très frustrant. C'est pour guider ces chercheurs que ce RFC leur explique ce nouveau (pour eux) monde.

Optimisme scientiste ou simplement désir de plaire aux lecteurs issus de la recherche ? En tout cas, le RFC commence par prétendre que le développement de nouvelles techniques est dû à la recherche scientifique. Après ce remontage de moral, la section 1 explique pourtant aux chercheurs candidats à un travail de normalisation à l'IETF qu'ils ne doivent pas s'attendre à un chemin de roses. Une SDO a d'autres motivations qu'une université. Dans la recherche, le plus important est qu'une solution soit correcte. Dans la normalisation, les problèmes à résoudre sont ceux du monde réel et le caractère pratique et réaliste de la solution a autant, voire plus d'importance, que sa parfaite correction.

Ainsi, l'IETF adopte souvent des solutions dont les limites, voire les défauts, sont connus, simplement parce que des alternatives « meilleures » ne semblent pas déployable sur le terrain. De même, une bonne solution à un problème intéressant peut être écartée, si ce problème ne se pose tout simplement pas dans l'Internet. Enfin, la normalisation progresse souvent par étapes incrémentales, nécessaires pour un déploiement effectif, et cela peut être jugé peu apétissant par des chercheurs qui veulent s'attaquer aux Grands Problèmes.

On voit ainsi régulièrement des malentendus, où des chercheurs arrivent à l'IETF avec des idées trop éloignées du domaine de l'IETF, ou bien trop générales pour qu'un travail concret (l'IETF normalise des bits qui passent sur le câble...) puisse commencer, des idées qui ne peuvent pas être déployées dans l'Internet d'aujourd'hui, ou encore des idées qui résolvent des problèmes qui ne sont pas, ou pas encore, d'actualité. Sans compter des problèmes moins techniques comme l'hésitation à passer leur bébé à l'IETF (perdant ainsi le contrôle de son évolution), la constatation que la normalisation est très chronophage, ou simplement l'impression qu'on ne les écoute pas réellement.

Cela ne veut pas dire que les chercheurs ne doivent même pas essayer. Bien au contraire, ce RFC doit leur permettre de mieux déterminer si et comment ils peuvent présenter leur travail à l'IETF. Il vient en complément de documents plus généraux sur l'IETF, notamment le fameux Tao (RFC 4677)).

Donc, première question à se poser (en section 2) : est-ce que l'IETF est le bon endroit pour ce travail ? Le RFC suggère deux questions simples aux candidats. Si votre travail était pris en compte :

  • Est-ce que l'Internet serait meilleur ?
  • Quelles machines devraient être mise à jour ?

La première question est une variante du classique « Quel problème essayez-vous de résoudre ? » Après tout, il y a déjà eu des tas de travaux (dont certains normalisés à l'IETF) qui n'ont jamais été déployés. Il est donc raisonnable de se demander si ce travail apportera un bénéfice. Un travail de recherche, même remarquable, n'est pas forcément dans ce cas.

La seconde question, sur les machines à mettre à jour en cas d'adoption de la technique, a pour but de pointer du doigt les problèmes de déploiement. Les chercheurs ont facilement tendance à les ignorer, préférant partir d'une table rase. Dans l'Internet d'aujourd'hui, utilisé par des milliards de personnes et pour qui des investissements colossaux ont été faits, cette approche n'est pas réaliste. Il est donc crucial de se demander « Est-ce que cette nouvelle technique pourra être déployée, et à quel coût ? » Par exemple, est-ce que la nouvelle technique nécessitera de mettre à jour seulement les routeurs, seulement les machines terminales, ou les deux ? Cette analyse est d'autant plus complexe qu'il faudra prendre en compte, non seulement les protocoles, mais également les pratiques opérationnelles et peut-être même certains modèles de business, qui pourraient être remis en cause.

Une fois cette analyse faite, si la conclusion est que le travail semble à sa place à l'IETF, comment convaincre celle-ci de s'y mettre (section 3) ? Il faut trouver le bon endroit dans l'IETF. Celle-ci n'est plus le petit groupe de travail du début, où tout le monde était impliqué dans tous les protocoles. C'est désormais un gros machin, avec des dizaines de groupes de travail différents (eux-même regroupés en zones - areas) et il faut trouver le bon. S'il existe, il faut le rejoindre (l'IETF n'a pas d'adhésion explicite, rejoindre un groupe, c'est simplement s'abonner à sa liste de diffusion). Et s'il n'existe pas ?

Alors, il va falloir construire une communauté d'intérêts autour de la nouvelle proposition. Après tout, la normalisation, contrairement à la recherche, nécessite un accord large et il va donc falloir se lancer dans le travail de persuasion. Le RFC note que cet effort aura des bénéfices, notamment celui d'améliorer la proposition technique, grâce aux remarques et commentaire des participants à l'IETF. Cela oblige également à documenter le protocole d'une manière compréhensible pour les autres (on peut s'inspirer du RFC 4101). C'est à ce stade qu'on peut tenir des réunions informelles (les Bar BoF) pendant les réunions physiques de l'IETF.

Si on n'a pas trouvé de groupe de travail qui convenait, que faut-il faire ? « En créer un ! », vont crier beaucoup de gens. Bonne idée, mais il faut d'abord lire la section 3.4, qui explique les étapes préalables, celles citées dans le paragraphe précédent, et la tenue recommandée d'une BoF (cf. RFC 5434).

Une fois que tout ceci est fait, la situation semble idyllique. L'IETF a accepté de travailler sur la nouvelle technique, un groupe de travail a été créé, il suffit d'attendre tranquillement son résultat ? Mais non. Comme le rappelle la section 4, il faut continuer à suivre le projet. Il faut prévoir pour cela des efforts importants, du temps et de la patience. Les gens qui n'ont jamais travaillé avec une SDO sont presque tous étonnés de la longueur et de la lourdeur du processus. Tout groupe de travail ne produit pas forcément de RFC et le succès va dépendre d'un travail continuel. Bien qu'en théorie, tout puisse se faire à distance, le RFC rappelle qu'une présence physique aux réunions va, en pratique, augmenter les chances de réussite (c'est comme pour les élections, il faut serrer des mains).

Pire, on a parfois l'impression que le processus s'enlise. L'IETF n'a pas de votes et encore moins de chefs qui décideraient tout. Un consensus relatif est nécessaire pour à peu près tout, et l'IETF n'est pas connue pour sa capacité à prendre des décisions... Bref, notre RFC prévient les candidats : deux ans au moins, depuis la création du groupe de travail. Si le projet de recherche qui a donné naissance à la nouvelle technique dure trois ans, cela veut dire qu'il faut commencer le travail de lobbying à l'IETF dès la première semaine du projet, si on veut que la nouvelle technique soit normalisée avant la fin du projet ! Il vaut donc mieux se préparer d'avance à ce que le projet ne soit pas complété par l'auteur lui-même, et soit terminé par d'autres.

Et c'est si tout se passe bien. Mais il y a parfois des chocs de cultures qui ralentissent le projet. Par exemple, le monde de la recherche privilégié la paternité (« l'algorithme X, décrit par Dupont et Durand dans leur article de 2008 ») alors que l'IETF privilégie le travail collectif. Une norme n'appartient pas à son auteur mais à toute la communauté. Il est donc préférable d'avoir une mentalité très ouverte avant de commencer.

Autre point sur lequel le choc des cultures est fréquent : la mise en œuvre de l'idée dans du vrai logiciel qui tourne. L'IETF accorde une grande importance à ce logiciel (le running code), qui montre que l'idée est viable, et que quelqu'un y a cru suffisamment pour dédier une partie de son précieux temps à sa programmation. C'est encore mieux si le programme connait un début de déploiement (le RFC suggère, pour un protocole réseau, d'essayer de le faire adopter dans le noyau Linux, par exemple). Si ces règles semblent contraignantes, il faut se rappeler qu'elles sont dues à de nombreuses expériences douloureuses, de protocoles déployés uniquement sur le papier, et qui avaient donc fait perdre du temps à tout le monde.

Pour rendre ces conseils plus concrets, le RFC contient une section d'exemples, la 5. On y trouve des résumés de l'incorporation dans le processus IETF de deux protocoles issus de la recherche « académique » :

  • Multipath TCP, issu du projet Trilogy, présenté à l'IETF pour la première fois en 2008, a donné naissance à un groupe de travail, MPTCP en 2009, dont les RFC ont été publiés en 2011.
  • Autre enfant de Trilogy, Congestion exposure a été présenté en 2009, mais le groupe de travail CONEX n'a été créé qu'en 2010, et avec une charte aux ambitions réduites.

Téléchargez le RFC 6417


L'article seul

RFC 6415: Web Host Metadata

Date de publication du RFC : Octobre 2011
Auteur(s) du RFC : E. Hammer-Lahav, B. Cook
Chemin des normes
Première rédaction de cet article le 1 novembre 2011


Ce court RFC spécifie une convention qui permet à un client Web de récupérer sur un serveur une description formelle de métadonnées sur le site servi (par exemple l'auteur du site Web, ou bien la licence du contenu servi). Cela se fait en mettant ces métadonnées au format XRD dans une ressource nommée /.well-known/host-meta.

Vous pouvez voir le résultat dans le /.well-known/host-meta de mon site, très inspiré de l'exemple de la section 1.1 du RFC. Il est vraiment minimal et n'inclut que des métadonnées globales (le format XRD permet également de s'en servir pour des métadonnées locales à une ressource, cf. section 4.2).

Notez que le vocabulaire peut être trompeur. Le RFC 3986 parle de host pour le example.com de http://example.com/truc/machin mais ce terme ne désigne pas du tout une machine. Finalement, le terme marketing flou de « site » est encore le moins mauvais.

Ce nouveau nom de host-meta a donc été le premier à être enregistré (cf. section 6.1) dans le registre des ressources bien connues qui avait été créé par le RFC 5785. (Deux ou trois autres sont venus juste après, et le RFC 5785 a été depuis remplacé par le RFC 8615.)

Pour le client, par exemple un navigateur Web, récupérer les métadonnées consiste juste donc à faire une requête GET sur le nom /.well-known/host-meta (section 2). Il obtient en échange un fichier XML au format XRD, servi avec le type application/xrd+xml.

Le contenu du document est détaillé dans la section 3. Ce vocabulaire XRD a été normalisé par OASIS et sert à beaucoup de choses très compliquées. Mais l'accent est mis ici sur son utilisation pour fournir des métadonnées. Tout en gardant le modèle de données de XRD, le serveur peut envoyer du XML (la syntaxe habituelle) ou du JSON. Cette dernière syntaxe est normalisée dans l'annexe A, sous le nom de JRD. On peut l'obtenir (n'essayez pas sur mon site, il n'est pas configuré pour cela) en utilisant la négociation de contenu HTTP (champ Accept: application/json dans la requête) ou en demandant /.well-known/host-meta.json au lieu de simplement /.well-known/host-meta.

Qui utilise ou va utiliser ces métadonnées ? Pour l'instant, les moteurs de recherche ne semblent pas y accéder mais cela viendra peut-être bientôt (Yahoo et Google ont annoncé travailler sur le sujet). La communauté WebFinger (RFC 7033) est également très impliquée dans ce projet.

Sinon, ce choix d'utiliser une ressource avec un nom spécial (le préfixe /.well-known est normalisé dans le RFC 8615) est dû au fait qu'un serveur n'a pas d'URI qui le désigne globalement et on ne peut donc pas utiliser les techniques qui attachent les métadonnées à une ressource (par exemple les en-têtes HTTP comme l'en-tête Link: du RFC 8288), sauf à utiliser des trucs contestables comme de considérer que /, la racine du site, désigne tout le site.


Téléchargez le RFC 6415


L'article seul

RFC 6410: Reducing the Standards Track to Two Maturity Levels

Date de publication du RFC : Octobre 2011
Auteur(s) du RFC : R. Housley (Vigil Security), D. Crocker (Brandenburg InternetWorking), E. Burger (Georgetown University)
Première rédaction de cet article le 12 octobre 2011


Ce très court RFC met fin (provisoirement ?) à un très long et très agité débat au sein de l'IETF. Après de longs efforts, il réussit à réformer une vache sacrée du processus de normalisation des protocoles TCP/IP. Les RFC spécifiant ces protocoles avaient trois étapes sur le chemin des normes. Il n'y en a désormais plus que deux.

D'innombrables documents, cours et articles ont expliqué le cheminement d'un RFC sur le chemin des normes, tel que le décrit le RFC 2026. Un premier point essentiel du RFC 2026 est que tous les RFC ne sont pas sur le chemin des normes. Ils peuvent être simplement « expérimentaux » ou bien « pour information ». Un deuxième point essentiel était que le chemin des normes comprenait trois étapes, chacune marquant une progression vers le statut de norme complète et achevée. L'étape atteinte par chaque RFC (pas encore adaptée à ce nouveau RFC) est visible en http://www.rfc-editor.org/category.html.

Ce schéma était simple et bien décrit. Mais il a été peu appliqué en pratique. D'abord, même parmi les participants à l'IETF, peu ont vraiment compris les subtiles nuances entre les trois étapes. A fortiori, à l'extérieur, peu de gens prenaient leurs décisions techniques en fonction des niveaux atteints sur le chemin des normes ! (Je me souviens de réunions d'un groupe de travail anti-spam où la lobbyiste d'AOL pouvait ergoter sans fin sur les niveaux de maturité de normes comme SMTP, uniquement pour donner un habillage pseudo-juridique aux décisions déjà prises par AOL.) Enfin, on constate qu'avancer sur ce chemin était trop pénible. Certaines normes l'ont fait, car elles étaient poussées par un acteur décidé qui avait intérêt à un statut le plus élevé possible mais, dans d'autres cas, personne ne s'en est occupé et des tas de normes très stables et très déployées sont restées à une étape intermédiaire. C'est ainsi que EPP, bien que récent, a atteint l'étape suprême avec le RFC 5730, simplement parce que VeriSign a poussé très fort, alors que HTTP (RFC 2616) est coincé en étape Projet-de-norme, parce que personne n'a le courage de lobbyer pour qu'il avance. Même chose pour SMTP (RFC 5321) qui, comme HTTP, est indubitablement largement déployé et avec succès ! Bref, l'état actuel de ses RFC sur le chemin des normes ne reflète que très peu la qualité, la stabilité, la popularité et la maturité d'un protocole.

L'IETF a donc, non sans douleur, réfléchi depuis plusieurs années à une simplification du processus, en réduisant le nombre d'étapes à deux. Il y a eu de nombreuses discussions à ce sujet, certains voulant en profiter pour faire une refonte complète du système de normalisation à cette occasion. C'est finalement un choix plus conservateur qui a été fait : le changement reste limité. C'est déjà bien qu'il ait lieu, certains commençaient même à être sceptiques quant aux capacités de l'IETF à réformer ses processus.

Le RFC 2026 réclamait, pour bouger de la première étape (proposition de norme), un rapport explicite sur l'interopérabilité des mises en œuvre de la norme. Et pour atteindre la troisième (norme tout court), un déploiement massif était nécessaire. Ces deux critères sont désormais fusionnés en un seul, qui permettra le passage de la nouvelle première étape, à la nouvelle deuxième (et dernière) étape. Il faudrait plutôt dire la seconde étape, d'ailleurs, si on suit les règles du français soutenu, où « deuxième » implique qu'il y a d'autres étapes ensuite.

Les règles précises figurent en section 2. Il n'y a désormais que deux niveaux sur l'échelle :

  • Proposition de norme (proposed standard). Il ne change pas de nom par rapport au premier niveau de l'ancien RFC 2026 car sa définition est exactement la même. Les critères pour atteindre ce niveau n'ont pas changé.
  • Norme Internet (Internet standard). C'est la fusion des deux anciens niveaux Projet de norme (Draft standard, on notera que ce nom mal choisi avait entraîné de nombreuses confusions avec les Internet-Drafts) et Norme tout court (Standard ou Full standard).

Lors de son passage de la première à la seconde étape, une norme peut être révisée de façon mineure (c'est bien l'un des buts de ce chemin des normes que de permettre l'amélioration des normes, à la lumière de l'expérience). Mais, si l'utilisation réelle montre des problèmes sérieux, qui nécessitent une révision plus fondamentale du protocole, il faudra repartir de la première étape.

Donc, désormais, pour avancer de la première à la seconde étape, il faudra :

  • Deux mises en œuvre indépendantes du protocole, qui interopèrent et sont effectivement déployées,
  • Pas d'errata enregistrés sur la norme, si les erreurs ainsi notées peuvent gêner l'interopérabilité,
  • Pas de fonctions inutilisées dans la norme, dans la mesure où cette mauvaise graisse accroît la complexité d'un protocole,
  • Si la technologie normalisée requiert l'usage de brevets (ce qui n'est pas interdit par les règles de l'IETF, cf. RFC 8179), alors il faut également démontrer qu'au moins deux implémenteurs ont réussi à obtenir une licence pour l'usage des parties brevetées (en pratique, indépendamment des coûts, l'obtention d'une licence est en effet souvent un cauchemar bureaucratique).

Et pour les RFC actuels, on fait quoi ? La section 2.3 traite de la transition et précise que les RFC à l'étape Norme-tout-court passent automatiquement à l'état Norme-Internet. Ceux à l'étape Proposition-de-norme y restent (rappelez-vous que cette étape n'a pas changé). Et ceux à l'étape (supprimée) Projet-de-norme y restent provisoirement, en attendant une reclassification par l'IESG (qui aura le droit, dans deux ans, de les passer tous, d'autorité, à l'état de Norme-Internet).

Ce RFC supprime également certaines obligations, bonnes sur le principe mais qui, en pratique, bloquaient certains RFC sur le chemin des normes, sans bonne raison (section 3). C'est ainsi qu'il n'est plus nécessaire :

  • De faire une revue annuelle des documents sur le chemin des normes pour voir s'ils peuvent avancer (cette revue n'a jamais eu lieu).
  • De publier un rapport d'interopérabilité formel pour montrer qu'il y a plusieurs implémentations qui peuvent agir ensemble. Dommage, c'était une institution sympathique et utile. De tels rapports restent possibles, quoique facultatifs, et le RFC 5657 contient plein d'informations concrètes à ce sujet.

Téléchargez le RFC 6410


L'article seul

RFC 6409: Message Submission for Mail

Date de publication du RFC : Novembre 2011
Auteur(s) du RFC : R. Gellens (Qualcomm), J. Klensin
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF yam
Première rédaction de cet article le 16 novembre 2011


Pendant longtemps, le système de courrier électronique de l'Internet ne faisait aucune différence entre le serveur de messagerie et le simple PC de l'utilisateur. Tous utilisaient le même protocole SMTP, spécifié dans le RFC 2821. Depuis le RFC 2476 et plus encore depuis le RFC 4409, précurseurs de notre RFC 6409, ce n'est plus vrai. Le simple PC doit désormais utiliser une autre solution, la soumission de message.

L'ancienne architecture était raisonnable à l'époque où toutes les machines connectées à l'Internet étaient de gros serveurs gérés par des professionnels. Ceux-ci pouvaient faire en sorte que tout soit correctement configuré. Et, donc les autres serveurs, les MTA pouvaient ériger en principe le "Pas touche" et ne jamais modifier ou contester un message reçu (section 1 du RFC ; en pratique, pas mal de MTA modifiaient quand même le contenu des messages, avec des conséquences négatives).

Aujourd'hui, avec le nombre de micro-ordinateurs non gérés qui sont connectés à Internet, cela n'est plus possible. Le RFC 2476 avait donc séparé les clients SMTP en deux catégories : les MTA qui se connectent au port traditionnel, le numéro 25 et les MUA qui, s'ils veulent envoyer en SMTP, doivent utiliser un autre service, nommé MSA, tournant en général sur le port 587 (section 3.1), et soumis à d'autres règles :

  • Le serveur est autorisé à modifier le message (par exemple en ajoutant des en-têtes comme Date ou Message-ID s'ils sont absents ou incorrects, sections 5, 6 et 8),
  • Une authentification est souvent requise, surtout si le port de soumission est accessible de tout l'Internet (sections 4.3 et 9).

Attention toutefois, la section 8 rappelle que les modifications du message soumis ne sont pas toujours inoffensives et qu'elles peuvent, par exemple, invalider les signatures existantes.

Notre RFC, qui remplace le RFC 4409, qui lui-même remplaçait le RFC 2476, pose en principe que, désormais, les machines des simples utilisateurs devraient désormais utiliser ce service.

La soumission de messages, telle que normalisée dans ce RFC est ses prédécesseurs, a été un grand succès depuis dix ans, notamment depuis trois ans. Le port 25 est de plus en plus souvent bloqué en sortie des FAI (pour limiter l'envoi de spam par les zombies), et la seule solution pour écrire sans passer par le serveur de son FAI est désormais le port 587. La norme technique est sortie il y a désormais treize ans et est particulièrement stable et mûre.

Si vous utilisez Postfix, vous pouvez lire un exemple de configuration de Postfix conforme (partiellement) à ce RFC.

Notre RFC a été développé par le groupe de travail YAM de l'IETF. Ce groupe est chargé de prendre toutes les normes IETF liées au courrier électronique et de les faire avancer sur le chemin des normes, si possible. La soumission de courrier est ainsi devenue « norme tout court » (Full Standard) avec ce RFC 6409. Les changements depuis le RFC 4409 sont décrits dans l'annexe A. Les principaux sont l'importance plus grande de l'internationalisation (section 6.5, qui précise que le MSA peut changer l'encodage), et une mise en garde plus nette contre les risques encourus en cas de modification de messages par le MSA.


Téléchargez le RFC 6409


L'article seul

RFC 6394: Use Cases and Requirements for DNS-based Authentication of Named Entities (DANE)

Date de publication du RFC : Octobre 2011
Auteur(s) du RFC : R. Barnes (BBN Technologies)
Pour information
Réalisé dans le cadre du groupe de travail IETF dane
Première rédaction de cet article le 28 octobre 2011


Le projet DANE (DNS-based Authentication of Named Entities, anciennement KIDNS - Keys In DNS), vise à améliorer et/ou remplacer les certificats X.509 utilisés dans des protocoles comme TLS (RFC 5246). Ces certificats souffrent de plusieurs problèmes, le principal étant qu'une Autorité de Certification (AC) malhonnête ou piratée peut créer des certificats pour n'importe quelle entité, même si celle-ci n'est pas cliente de l'AC tricheuse. C'est ce qui s'est produit dans les affaires Comodo et DigiNotar et ces deux affaires ont sérieusement poussé aux progrès de DANE. Ce premier RFC du groupe de travail DANE établit les scénarios d'usage : quels problèmes veut résoudre DANE et selon quels principes ?

Revenons d'abord sur le fond du problème (section 1 du RFC) : lors de l'établissement d'une session TLS (par exemple en HTTPS), le client se connecte à un serveur dont il connait le nom (par exemple impots.gouv.fr, cf. RFC 6125), le serveur (et, plus rarement, le client) présente un certificat numérique à la norme X.509 (bien qu'un certificat PGP soit aussi possible, cf. RFC 6091). Ce certificat suit le profil PKIX, normalisé dans le RFC 5280, un sous-ensemble de X.509. Comme ce certificat peut avoir été présenté par un homme du milieu qui a intercepté la session (par exemple en jouant avec BGP ou OSPF), il faut l'authentifier, sinon TLS ne protégerait plus que contre les attaques passives, laissant ses utilisateurs à la merci des attaques actives. Cette authentification se fait typiquement aujourd'hui en vérifiant que le certificat a été signé par une des plusieurs centaines d'AC qui se trouvent dans le magasin de certificats de n'importe quel navigateur Web. Le point important, et qui est l'une des deux principales faiblesses de X.509 (l'autre étant son extrême complexité), est que n'importe laquelle de ces centaines d'AC peut signer un certificat. Ainsi, dans l'affaire DigiNotar, une AC néerlandaise était piratée, le pirate lui faisait générer des certificats pour *.google.com ou *.gmail.com (alors que Google n'est pas du tout client de DigiNotar) et ces certificats sont acceptés par tous les navigateurs. Le pirate a vendu ou donné les clés privées de ces certificats au gouvernement iranien, qui n'a plus eu qu'à monter une attaque de l'homme du milieu (facile lorsqu'on est un état policier et qu'on contrôle tous les FAI du pays) pour détourner les utilisateurs vers un faux Gmail, qui présentait un certificat acceptable. La dictature intégriste pouvait alors lire les messages et emprisonner ou tuer les opposants. (Le fait que l'attaque venait d'Iran est établi par les requêtes OCSP des victimes. Cf. le rapport sur l'opération Tulipe Noire.)

Identifiée depuis longtemps (mais niée par le lobby des AC ou par l'UIT, à l'origine de la norme X.509), cette vulnérabilité a mené au projet DANE. L'idée de base est qu'introduire un intermédiaire (l'AC) est en général une mauvaise idée pour la sécurité. Pour reprendre l'exemple ci-dessus, il vaudrait mieux permettre à Google de prouver sa propre identité. Comme quasiment toutes les transactions sur l'Internet commençent par une requête DNS, pourquoi ne pas utiliser la zone DNS google.com pour y mettre le certificat ? L'idée est ancienne, mais elle ne suscitait guère d'intérêt tant que le DNS lui-même n'était pas un tant soit peu sécurisé. Le déploiement rapide de DNSSEC, à partir de 2009, a changé la donne : mettre des clés cryptographiques ou des certificats dans le DNS devient réaliste. D'où la création, en février 2011, du groupe de travail DANE de l'IETF, chargé de trouver une technique de sécurité qui marche.

Ce RFC ne donne pas encore de solution (au moment de sa parution, celle-ci est très avancée et a des chances sérieuses d'être publiée en 2012). Il explique les scénarios d'usage, pour aider à évaluer la future solution. Pour décrire ces scénarios, on recourt évidemment aux personae traditionnels :

  • Alice gère le serveur alice.example.com,
  • Bob, le client, se connecte à ce serveur,
  • Charlie est l'AC,
  • Trent est un émetteur de certificats mais qui n'est pas dans les magasins de certificats d'AC typiques.

Trois scénarios sont ensuite décrits dans la section 3, le œur de ce RFC :

  • « Contrainte sur l'AC » (dit aussi « type 0 »),
  • « Contrainte sur les certificats » (« type 1 »),
  • « Certificats locaux » (« type 2 »),

Dans les deux premiers cas, DANE ne fait qu'ajouter de la sécurité à X.509 et on a toujours besoin de l'IGC actuelle. Le troisième est le plus novateur, permettant de remplacer complètement l'IGC, et ne gardant de X.509 que son format de certificats. (Notez que ces trois scénarios ne se retrouvent pas exactement dans le RFC 6698 sur le protocole qui a quatre types et non pas trois.)

Voyons d'abord le premier scénario (section 3.1) , les contraintes sur l'AC. Dans un cas comme celui des piratages de Comodo ou de DigiNotar, Alice, qui est cliente d'une autre AC, Charlie, est inquiète du risque d'un faux certificat pour alice.example.com, émis par l'AC voyoute. Elle voudrait dire aux visiteurs de https://alice.example.com/ que les seuls certificats légitimes sont ceux émis par Charlie. En d'autres termes, elle voudrait que la vérification du certificat de son serveur parte du certificat de Charlie, pas de n'importe quel certificat d'AC du magasin.

Notez que, si Alice dispose d'un tel système, elle peut aussi s'en servir vis-à-vis de Charlie. Lorsqu'elle demande un certificat à ce dernier, il pourrait vérifier qu'Alice l'a bien listé comme AC.

Donc, Alice va mettre dans le DNS un enregistrement qui dit « je suis cliente de Charlie ». Cet enregistrement doit-il être sécurisé par DNSSEC ? La question est toujours très discutée au sein du groupe DANE. A priori, DNSSEC n'est pas impératif puisque cet enregistrement DNS n'est qu'une sécurité supplémentaire : le X.509 traditionnel fonctionne toujours en dessous. D'un autre côté, cette sécurité supplémentaire est très faible si on ne met pas DNSSEC : un attaquant qui peut monter une attaque de l'Homme du Milieu pour détourner vers son propre serveur peut probablement aussi supprimer les enregistrements DANE au passage. Notons aussi que le fait d'exiger la validation X.50 comme avant limite les possibilités d'attaque par un registre DNS. Avec le type 0 (contrainte sur l'AC), un attaquant devrait contrôler à la fois l'enregistrement DNS et l'Autorité de Cértification.

Second scénario, la contrainte sur le certificat (section 3.2), alias type 1. Alice est cliente de Charlie mais se demande si Charlie ne va pas émettre d'autres certificats pour alice.example.com, par exemple parce que les machines de Charlie ont été piratées. Elle voudrait donc indiquer aux visiteurs de https://alice.example.com/> que seul tel certificat est valable. Alice va donc mettre le certificat (ou un condensat cryptographique de celui-ci) dans le DNS. Comme avec le type 0, toute la validation classique de X.509 est ensuite appliquée. Dans ce mode, DANE ne fait qu'ajouter une vérification supplémentaire.

Bien plus « disruptive » est la possibilité de se passer complètement des AC et de dire dans le DNS « voici le certificat à utiliser », sans qu'il doit validé par d'autres mécanismes que DNSSEC. Cette possibilité (section 3.3), dite type 2, est l'équivalent des certificats auto-signés actuels, mais avec possibilité de les vérifier (grâce à DNSSEC). Alice se passe alors complètement de Charlie. (Notez que le cas où Alice est cliente de Trent est équivalent, le certificat de Trent n'étant quasiment dans aucun magasin. Alice va alors publier dans le DNS le certificat de Trent et non le sien.)

Notez que ce mécanisme n'empêche pas Bob d'avoir sa propre politique de validation. On pourrait imaginer un Bob suspicieux vis-à-vis de DNSSEC qui n'accepterait que les enregistrements DANE de type 0 ou 1. Ou un Bob qui aurait une liste noire des certificats à qui il ne fait pas confiance, DANE ou pas DANE.

Cette fois, avec le type 2, DNSSEC est absolument indispensable. Sans lui, il n'y a plus aucune validation du certificat. Ne publiez donc pas d'enregistrements de type 2 avant d'avoir vérifié que DNSSEC était correctement déployé et que vous le maîtrisez parfaitement. Pour la même raison, le type 2 est celui qui met le plus de responsabilités chez les opérateurs DNS. Si ceux-ci trahissent ou sont piratés, tout le système est en danger. Mais rappelez-vous que, contrairement à ce qui se passe pour X.509, le risque est uniquement dans les prestataires que vous choisissez. Si vous choisissez d'utiliser un nom de domaine en .org, vous savez qu'Afilias peut tout faire rater, mais que ni l'AFNIC, ni CNNIC n'ont ce pouvoir. Alors qu'avec X.509, même en choisissant soigneusement son AC, on peut être victime de n'importe quelle autre AC, qu'on n'a pas choisi. Donc, conseil pratique, choisissez bien vos prestataires (registre DNS, bureau d'enregistrement, hébergeur DNS, etc).

Mais il est clair que DANE donne plus de responsabilité (on peut même dire de pouvoir) aux acteurs du DNS. Ce point est souvent à la base de la plupart des critiques de DANE.

Autre point à garder en tête lorsqu'on évalue la sécurité de DANE : aujourd'hui, avec X.509, le contrôle de la zone DNS donne déjà souvent accès à des certificats (bien des AC ne font pas d'autres vérifications que l'envoi d'un courrier avec un cookie, ou la publication d'un certain enregistrement).

Voilà, vous connaissez l'essentiel sur DANE. la section 4 couvre toutefois d'autres points, moins centraux, sous forme d'une liste de souhaits pour le futur protocole :

  • Capacité à gérer des certificats différents pour une même machine, pour des services tournant sur des ports différents (par exemple un serveur HTTP et un serveur IMAP).
  • Pas de possibilité d'attaque par repli.
  • Possibilité de combiner plusieurs assertions (par exemple de type 1 et 2, la première servant pour les clients qui refusent de croire au type 2 et qui tiennent à faire une validation X.509 classique).
  • Le moins de dépendances possibles, à part bien sûr celle sur DNSSEC.
  • Le moins d'options possibles, pour faciliter l'analyse de sécurité (IPsec avait été beaucoup critiqué pour le trop grand nombre de choix qu'il offrait).

Le protocole qui met en œuvre ce cahier des charges a été normalisé en août 2012 dans le RFC 6698.

Pour ceux qui souhaitent approfondir le sujet, j'ai fait un exposé sur la question (avec article détaillé) en novembre 2011 aux JRES à Toulouse.


Téléchargez le RFC 6394


L'article seul

RFC 6393: Moving RFC 4693 to Historic

Date de publication du RFC : Septembre 2011
Auteur(s) du RFC : M. Yevstifeyev
Pour information
Première rédaction de cet article le 19 septembre 2011


L'expérimentation des ION (IETF Operational Notes, une série de documents IETF plus légers que les RFC) ayant été abandonnée, ce RFC reclassifie officiellement le RFC 4693, qui créait les ION, comme n'ayant qu'un intérêt historique.

Ce nouveau RFC, de même que la décision d'abandon, ne s'étend guère sur les raisons de l'échec et ne tire pas de bilan.


Téléchargez le RFC 6393


L'article seul

RFC 6392: A Survey of In-network Storage Systems

Date de publication du RFC : Octobre 2011
Auteur(s) du RFC : R. Alimi (Google), A. Rahman (InterDigital Communications), Y. Yang (Yale University)
Pour information
Réalisé dans le cadre du groupe de travail IETF decade
Première rédaction de cet article le 26 octobre 2011


Cette intéressante étude des systèmes de stockage de données en ligne (le RFC n'utilise pas le terme de cloud, pourtant bien plus vendeur) fait le tour des principales solutions d'aujourd'hui. Son but est de préparer le travail ultérieur du groupe de travail IETF DECADE, dont le rôle est de normaliser une architecture pour l'accès au stockage en ligne, notamment pour le pair à pair. Ce RFC, le premier produit par DECADE, étudie l'offre existante, afin de voir dans quelle mesure elle est réutilisable pour DECADE.

Notons que tous les systèmes existants n'y sont pas : l'accent a été mis sur une sélection de systèmes typiques couvrant à peu près toutes les variantes possibles d'un tel service. C'est ainsi que, par exemple, Swift/OpenStack n'y figure pas. Par contre, le plus célèbre, le S3 d'Amazon est présent. Certains de ceux qui y figurent sont très expérimentaux, peu déployés, mais ont été ajoutés parce qu'ils illustrent un point important.

Il existe des tas de raisons pour stocker ses données dans le nuage. Cela peut être pour y accéder de partout, depuis n'importe quelle machine. Ou bien cela peut être pour rapprocher les données des utilisateurs. Si on distribue du contenu en pair à pair, il vaut mieux qu'il soit déjà dans le nuage, plus près des téléchargeurs, que sur une machine à la maison, connectée en ADSL, où le coût du dernier kilomètre à franchir est élevé.

La section 2 brosse un panorama historique du stockage en ligne. Par exemple, le goulet d'étranglement que représente le gros site Web, lorsqu'il a de très nombreux utilisateurs, a été partiellement levé avec l'introduction des CDN. Ceux-ci dupliquent le contenu statique des sites Web, et le rapprochent des utilisateurs, en plaçant des copies chez les principaux FAI. Mais les CDN ne sont pas accessibles à l'utilisateur normal. Si je voulais accélérer le temps de chargement des pages de http://www.bortzmeyer.org/, je ne pourrais certainement pas monter un CDN moi-même, un tel travail nécessite des moyens financiers et administratifs hors de ma portée.

Le pair à pair a ensuite fourni d'autres possibilités. Si on utilise les machines de tout le monde pour distribuer du contenu, pourquoi ne pas également s'en servir pour améliorer l'accès au contenu par une réplication et une copie proche des autres pairs ? Plusieurs systèmes de « caches P2P » ont ainsi été développés pour accélérer le pair à pair (cf. section 4.12). Malheureusement, tous sont spécifiques à une application particulière et ne peuvent donc pas servir aux nouvelles applications. Le monde du pair à pair évoluant vite, il ne peut donc pas bénéficier d'une infrastructure de stockage existante. Le but de DECADE est justement de permettre la création de cette infrastructure.

Pour pouvoir étudier de manière systématique les techniques existantes, la section 3 du RFC liste les composants d'une solution de stockage en ligne. Chaque technique sera alors décrite pour chacun de ces composants :

  • Une interface d'accès aux données, permettant les opérations de base, notamment lire et écrire,
  • Une interface de gestion des données, permettant des choses comme la suppression d'un bloc de données,
  • Une interface de recherche permettant de s'y retrouver dans ses données,
  • Un mécanisme de contrôle d'accès, permettant d'avoir des données publiques, des données restreintes à certains utilisateurs (par exemple seulement depuis certains pays), des données privées (accessibles uniquement à des clients identifiés, par exemple après paiement). L'accès peut dépendre de l'opération (lecture pour tous mais écriture seulement pour certains).
  • Un mécanisme de découverte des mécanismes d'accès (le mode d'emploi du service),
  • Un mode de stockage : les données sont-elles des fichiers (organisés en répertoires hiérarchiques), des objets (contrairement aux fichiers, ils ne sont pas organisés), ou simplement des blocs d'octets, comme le propose le disque dur local ?

Sur la base de ce découpage en composants, on peut décrire les systèmes existants (section 4, mais rappelez-vous que le RFC ne prétend pas les présenter tous et que je n'ai pas repris ici tous ceux listés dans le RFC). Notez que l'ordre de la présentation est celui du RFC, même s'il peut sembler incohérent. D'autre part, un bon nombre des descriptions ressemblent à du copier-coller depuis les descriptions officielles (y compris dans leur côté marketing).

Commençons par le plus connu, Amazon S3. Les utilisateurs créent des containers, les seaux (buckets) puis y déposent des objets. Les accès se font en REST.

Pour montrer les capacités de S3, testons un peu avec un client Unix en ligne de commande, s3cmd. On lui indique les clés avec s3cmd --configure puis on peut créer un seau (le nom est hiérarchique car un nom de seau doit être unique entre tous les utilisateurs ; on peut aussi préfixer avec l'ID Amazon) :

% s3cmd  mb s3://org-bortzmeyer-essais

(où mb signifie make bucket, créer un seau.) Puis on peut mettre un fichier dans ce seau :

% s3cmd  put tartiflette1.jpg s3://org-bortzmeyer-essais
/home/stephane/Downloads/tartiflette1.jpg -> s3://org-bortzmeyer-essais/tartiflette1.jpg  [1 of 1]
...
 35267 of 35267   100% in    0s    37.21 kB/s  done

Il est ensuite possible de récupérer cet objet, par exemple depuis une autre machine :

% s3cmd  get s3://org-bortzmeyer-essais/tartiflette1.jpg
...
s3://org-bortzmeyer-essais/tartiflette1.jpg -> ./tartiflette1.jpg  [1 of 1]
 35267 of 35267   100% in    0s    74.04 kB/s  done

On a donc vu les deux commandes les plus importantes, put et get (lire et écrire des objets).

S3 est devenu très populaire, entre autres en raison de sa simplicité. Pas d'espace de nommage hiérarchique, pas de possibilité de modifier les données existantes, accès en REST... L'interface d'accès permet de lire et d'écrire (les deux opérations illustrées plus haut), on peut détruire les objets, on peut lire le contenu d'un seau (c'est la seule possibilité de recherche), S3 fournit des mécanismes de contrôle d'accès riches, il n'y a pas de vraie découverte (l'utilisateur doit connaître l'URL où envoyer les requêtes, dans l'exemple ci-dessus, on utilise celle par défaut), et enfin, on l'a vu, S3 stocke des objets (aucun mécanisme de dossiers ou répertoires).

Il existe d'autres systèmes analogues à S3 comme Dropbox.

Un exemple d'un service très différent est le BranchCache de Windows, assez répandu en raison de la diffusion de ce système d'exploitation. Les accès ne sont pas explicites comme avec S3, BranchCache vise à stocker et récupérer les données automatiquement dans un cache. Il y arrive en se mettant sur le trajet des requêtes HTTP et SMB. Il intercepte la requête normale, et accède au fichier depuis le cache, si c'était une opération de lecture et que le fichier était déjà disponible.

Autre exemple très différent de S3, le CNF (Cache-and-Forward), une architecture de recherche visant à doter les réseaux d'un mécanisme efficace d'accès aux données. Dans CNF, les routeurs ne sont plus simplement des routeurs qui opèrent au niveau 3 mais des moteurs d'accès des données (store and forward) qui font suivre les requêtes d'accès et gardent le résultat localement, pour les accès ultérieurs. Le contenu très populaire est ainsi petit à petit copié dans les routeurs les plus proches. Un mélange de Usenet et de cache opportuniste (tout le contenu n'est pas copié, contrairement à Usenet ou aux CDN, seulement celui qui est demandé).

Plus dans l'idée d'un accès explicite aux données, le standard CDMI vise à résoudre un problème récurrent du cloud : l'absence de normes pour l'accès aux données, qui font qu'une fois choisi un fournisseur, on en est prisonniers. Si vous bâtissez votre service autour d'un accès à S3, vous ne pouvez plus quitter Amazon. Certes, l'interface de S3 est tellement populaire qu'il existe désormais des offres compatibles (hébergées, ou bien à construire soi-même comme celle d'Eucalyptus) mais ces offres sont à la merci d'un changement unilatéral de l'interface S3 par Amazon. CDMI est donc une tentative pour concevoir et populariser, au sein d'un consortium industriel, la SNIA, une interface standard. Elle ressemble dans ses principes à S3 et repose sur les modes actuelles (REST et JSON).

Comme CDMI est indépendant d'un vendeur particulier, et repose sur des protocoles simples et bien connus comme HTTP, elle est une approche tentante pour le groupe DECADE.

J'ai déjà parlé des CDN. Ils représentent aujourd'hui une des approches les plus populaires, d'accès aux données en ligne. Un bon tour d'horison complet des CDN figure dans « A Taxonomy and Survey of Content Delivery Networks » de Pathan, A.K. et Buyya, R. Le principe est de copier à l'avance le contenu vers des serveurs situés chez les FAI et d'utiliser divers trucs (par exemple fondés sur le DNS) pour que les utilisateurs soient redirigés vers ces serveurs. Le plus connu des CDN est Akamai mais il en existe bien d'autres comme Limelight ou CloudFront. Pour DECADE, l'intérêt des CDN est que c'est une technique très répandue et éprouvée. Mais elle nécessite une relation d'affaires existante entre l'opérateur du CDN et le fournisseur de contenu (contrairement aux caches classiques).

Le CDN ne fournit typiquement d'accès qu'en lecture (l'écriture est réservée au fournisseur de contenu, via le mécanisme que lui offre l'opérateur du CDN).

Plus proche du CNF, le système DTN vise à créer un environnement adapté aux cas difficiles, notamment aux missions spatiales. Dans ces cas où la connectivité est très intermittente (une seule tempête solaire peut tout interrompre pendant des semaines), et où les délais sont énormes, les protocoles TCP/IP classiques ne conviennent plus. D'où le DTN, normalisé dans le RFC 4838, une architecture store and forward qui ressemble davantage à UUCP.

Le DTN repose sur le protocole Bundle (RFC 9171), qui permet de stocker les données en attendant que le destinataire soit à nouveau disponible. Bien sûr, IP est lui aussi store and forward dans la mesure où le routeur garde le paquet en mémoire avant de le passer au routeur suivant. Mais le temps de rétention des données dans IP est typiquement de quelques milli-secondes au maximum, alors qu'il atteint couramment plusieurs jours dans Bundle, imposant le recours à un stockage persistant (au cas où le routeur redémarre). Contrairement à IP, où le routeur a le droit de jeter des paquets, Bundle est plus proche du courrier électronique : le routeur doit prendre soin des données jusqu'à ce qu'il ait pu les transmettre. Il n'est donc pas exagéré de l'inclure dans cette liste des services de stockage en ligne.

Dans la catégorie futuriste, une autre famille de candidats intéressants est celle qu'on va appeler, pour simplifier. les « réseaux fondés sur les objets nommés » (c'est le nom de la première conférence scientifique sur le sujet). C'est une vaste famille, comprenant uniquement des projets de recherche fondamentale, qui ont en commun le fait que toute l'architecture du réseau repose sur des objets de données, ayant un nom, et que le réseau est conçu pour accéder rapidement et de manière sûre à ces objets. Cette famille privilégie donc l'accès au contenu. On y trouve des systèmes comme CCN, ou comme NDN (Named Data Networking) et NetInf (Network of Information), traités plus en détail dans ce RFC.

NDN est un tel système. Le réseau gère des objets nommés et signés cryptographiquement. Les routeurs qui transmettent ces objets ont la possibilité de les garder en cache. Les objets les plus demandés vont donc avoir plus de chance de se retrouver dans un cache proche, réalisant ainsi automatiquement ce que les CDN font manuellement. Comme les autres propositions de la famille Name-oriented networking, tout repose sur l'idée que « data delivery has become the primary use of the network ».

NetInf reprend les mêmes affirmations minitéliennes et y ajoute des fausses explications sur ce que représente un URL (le deuxième champ d'un URL, après le plan, n'identifie pas une machine).

Plus sérieux, OceanStore est une architecture où un ensemble de machines coopèrent en mettant en commun des espaces de stockage. OceanStore met l'accent sur la résilience et l'auto-organisation. Son intérêt pour DECADE est surtout cette capacité à résister aux pannes, et même à une certaine proportion de participants malhonnêtes (qui modifieraient les données, ou bien les effaceraient). OceanStore fournit une interface permettant lecture et écriture des objets mais reste encore très expérimental.

Un des domaines où il y a eu le plus d'utilisations du stockage en ligne est évidemment le partage de photos. Une section est donc consacrée à ce cas particulier, où on voit apparaître des noms connus comme Flickr ou ImageShack, sans compter des services qui, sans être spécialisés dans les photos, sont néanmoins largement utilisés pour cela, comme Tumblr. Une particularité de ces services est l'accent mis sur les fonctions de recherche (qui sont absentes de beaucoup de services de stockage), notamment par le biais d'étiquettes attachées aux photos. On peut ainsi retrouver, parmi des myriades de photos, celles qui concernaient saint-quentin-en-yvelines ou lascaux. Ces services ont en général également des moyens d'organisation des photos (en « albums » ou « galeries », analogues à ce que fournit un système de fichiers).

Ces services fournissent la plupart du temps des moyens de désigner les photos comme privées (personnelles) ou publiques et, dans certains cas, comme limitées à un ensemble de personnes. À noter que le RFC n'évoque pas un problème sérieux du stockage en ligne : le fait que rien n'est privé pour l'opérateur du service. On peut toujours marquer ses données comme privé, l'opérateur y a quand même accès (ainsi que la police et la justice de son pays).

Le RFC n'hésite pas à mélanger technologies très nouvelles (et souvent très expérimentales) et très anciennes. Usenet a ainsi sa section. C'est un système de distribution de messages, rangés hiérarchiquement par sujet (cf. RFC 5537). Ces messages sont automatiquement recopiés entre tous les serveurs Usenet qui participent à ce réseau. L'utilisateur final peut alors y accéder via un protocole comme NNTP. Usenet était donc du P2P longtemps avant que ce terme ne soit à la mode. Si Usenet semble nettement sur le déclin aujourd'hui, il reste un des plus importants exemples de distribution efficace de contenu sur le réseau.

En tant que système de stockage en ligne, Usenet permet de lire et d'écrire (on dit to post), et, dans une mesure très limitée, de détruire des messages (avec l'opération cancel).

S'il y a les caches pair à pair, un autre type de cache largement déployé est le cache Web, qui fait l'objet d'une analyse dans ce RFC. L'idée est surtout d'économiser de la capacité réseau (et de gagner en latence), et le cache Web est donc en général mis en œuvre par le FAI ou par les administrateurs du réseau local. Le protocole HTTP dispose de tout un tas d'options pour contrôler finement le niveau de « cachage ». Le logiciel libre le plus répandu pour cette tâche est Squid.

Ce service ne donne accès aux utilisateurs qu'en lecture, l'écriture est faite automatiquement, comme conséquence de la lecture.

Après ce long catalogue de systèmes très variés, la section 4.15 fait le point : est-ce que DECADE a trouvé ce qu'il cherchait ? La plupart de ces services sont nettement plus client-serveur que pair à pair. Et beaucoup sont spécifiques au « cachage », pas au stockage à long terme (un cache peut toujours perdre des données, par exemple, elles seront récupérées sur le site originel). Pour ces raisons et pour d'autres, il est probable que DECADE devra développer son propre service.

Après l'examen des services, la seection 5 du RFC porte sur un examen des protocoles. Quels protocoles existants pourraient être utiles pour DECADE ? Le premier examiné est bien sûr HTTP (RFC 7230). S'il est surtout connu pour ses fonctions de lecture (téléchargement de ressources Web), HTTP peut servir à bien d'autres choses, à développer des applications REST ou à écrire du contenu nouveau sur le serveur. Un des gros avantages de HTTP est évidemment que les logiciels clients sont déjà disponibles, du navigateur Web au programme en ligne de commande comme cURL, en passant par des bibliothèques pour tous les langages de programmation.

HTTP permet donc les fonctions d'accès aux données (opérations GET, PUT, etc), de gestion des données (le RFC fait une erreur en disant qu'il n'y en a pas, ce qui oublie DELETE, section 4.3.5 du RFC 7231) et de contrôle d'accès (accès public, ou accès restreint après authentification). Les données sont nommées « ressources » et sont souvent des fichiers. HTTP étant client-serveur, il ne convient pas parfaitement à DECADE, qui met plutôt l'accent sur le pair à pair.

HTTP a servi de base à d'autres protocoles. Pour l'accès aux données en ligne, on pense évidemment à WebDAV (RFC 4918). C'est une extension de HTTP qui lui ajoute des fonctions comme le verrouillage ou comme le regroupement des ressources en collections, qu'on peut gérer collectivement. Ces collections font que le modèle de données de WebDAV devient très proche de celui d'un modèle « système de fichiers ».

WebDAV a également une extension pour avoir des ACL, le RFC 3744. Par contre, il n'est pas évident que ce mécanisme de gestion des droits passe à l'échelle, dans le contexte de l'Internet entier.

Autre protocole d'accès à du stockage en ligne, iSCSI, normalisé dans le RFC 7143. En gros, il s'agit d'un protocole permettant l'envoi de commandes SCSI au dessus de TCP, vers des périphériques de stockage comme des disques durs. iSCSI est typiquement un outil pour réaliser des SAN, bien qu'il puisse aussi servir au dessus de l'Internet (par exemple avec les services de nommage du RFC 4171).

iSCSI fournit des opérations de lecture et d'écriture sur des blocs de données (qui correspondent en général aux blocs du disque dur). iSCSI est de très bas niveau et aucun développeur d'applications n'aurait envie de travailler directement avec ce protocole. En réseau local, on utilise plutôt NFS, dont les dernières versions (RFC 8881) disposent de ce qu'il faut pour travailler sur l'Internet.

NFS fournit des opérations de lecture, d'écriture, de gestion (destruction, renommage) de fichiers. Il a des mécanismes de contrôle d'accès qui se sont particulièrement perfectionnés avec sa version 4, qui a amené les ACL.

Par contre, il n'est pas du tout évident qu'il puisse servir dans un service pair à pair de grande taille, notamment vue la rigidité de certains de ses mécanismes de sécurité (même problème qu'avec WebDAV).

Le dernier protocole envisagé, OAuth (RFC 5849) n'est pas vraiment un protocole d'accès à du stockage en ligne. S'il est mentionné ici, c'est parce qu'il fournit un modèle intéressant pour le contrôle d'accès à ces services de stockage. Les modèles traditionnels n'avaient que deux acteurs, le client et le serveur. Le serveur autorisait (ou pas) le client à accéder aux données. OAuth introduit un troisième acteur, le titulaire des données. Celui-ci peut donner une autorisation d'accès à un client tiers, sans lui fournir pour autant toutes ses lettres de créance (mots de passe, clés privées, etc). OAuth permet donc de déléguer l'accès.

Que peut-on synthétiser de l'examen de ces protocoles ? Ils sont surtout conçus pour du client-serveur (bien que certains puissent être adaptés au pair à pair). Et HTTP est tellement répandu et bien connu qu'il peut fournir un bon point de départ à DECADE. Par contre, aucun de ces protocoles ne prend en compte la nécessité d'accès avec faible latence, qui est nécessaire pour la diffusion de vidéo en streaming.

Enfin, si presque tous les protocoles fournissent les mécanismes de base, comme lire et écrire, la grande majorité n'a aucun mécanisme de contrôle de l'allocation des ressources, un des objectifs de DECADE (il s'agit de permettre un accès à ses ressources, sans que les pairs ne puissent tout consommer).

Bref, résume la section 6, conclusion de ce RFC, s'il existe de nombreux systèmes de stockage en ligne, ils ont été conçus avec un cahier des charges très différent de celui de DECADE (l'exemple le plus net étant leur conception client-serveur et pas pair à pair). Aucun ne peut donc être choisi tel quel pour le projet.


Téléchargez le RFC 6392


L'article seul

RFC 6390: Guidelines for Considering New Performance Metric Development

Date de publication du RFC : Octobre 2011
Auteur(s) du RFC : A. Clark (Telchemy Incorporated), B. Claise (Cisco Systems)
Réalisé dans le cadre du groupe de travail IETF pmol
Première rédaction de cet article le 6 octobre 2011


Le groupe de travail IETF PMOL était chargé de travailler à la définition de métriques de haut niveau, proche de l'utilisateur (le groupe IPPM s'occupant, lui, des couches plus basses). Désormais fermé, il condense son expérience dans ce RFC, qui explique comment définir de nouvelles métriques, comme PMOL l'avait fait dans les RFC 5814 sur MPLS et RFC 6076 sur SIP. La section 3 résume ce but de ce RFC, définir un cadre utile.

La section 1 rappelle l'importance de la mesure, pour pouvoir améliorer les performances d'un système. Pour que ces mesures soient vraiment efficaces, il faut qu'elles s'appuient sur des métriques normalisées, une métrique étant une définition rigoureuse de la grandeur qu'on veut mesurer. Il faut aussi définir une méthode concrète pour faire la mesure et un format pour publier cette mesure. Pour les métriques « applicatives » de PMOL, ces mesures concernent des choses comme le temps de transfert d'un fichier, le temps de réponse d'un serveur DNS à une requête, etc (section 2.3).

Comme la plupart des RFC, on commence avec un peu de terminologie (section 2). D'abord, l'IETF aura désormais une Direction des Performances (Performance Metrics Directorate). C'est quoi ? Comme les autres Directions, c'est un organe transversal, composé d'experts du domaine, qui doit garder un œil sur tout travail IETF lié à la définition de métriques de performance. Ensuite, le RFC définit la qualité de service (QoS pour Quality of service) et la qualité du vécu (QoE pour Quality of Experience). J'ai déjà écrit sur la différence entre QoS et QoE et je trouve les définitions du RFC très embrouillées, et ne permettant pas de saisir la différence entre les deux concepts (la QoE vient d'une norme UIT, la E.800). Heureusement, la section 4 clarifie cette question. En gros, la QoS est une mesure scientifique de paramètres qui influencent le service rendu (par exemple, la latence ou la gigue), la QoE est la vision de l'utilisateur, qui peut être influencée par divers facteurs, y compris psychologiques. Bien sûr, la QoE va dépendre en partie de la QoS (par exemple, un taux de perte de paquets élevé va sérieusement baisser le débit TCP atteignable) mais le lien n'est pas évident (la norme UIT P.800 donne un exemple de reconstruction de QoE à partir de la QoS). Il y a aussi des facteurs techniques à la différence entre QoS et QoE, comme l'application utilisée : elle peut, indépendamment du bon ou mauvais comportement du réseau, influencer la QoE. Il y a enfin le contexte : tel problème de VoIP passera inaperçu pendant une communication de bavardage mais sera intolérable s'il s'agit d'un appel d'urgence.

La section 5 est le cœur du RFC, les conseils concrets sur la définition de nouvelles métriques. Premier point, déterminer le public visé (section 5.1). Qui va utiliser la métrique et pourquoi ? Est-elle destinée au laboratoire ou bien aux mesures sur des réseaux de production ? Quelle degré d'approxmation peut être accepté ? Et autres questions fondamentales.

Ensuite, la métrique elle-même (section 5.2). Pour qu'elle soit utile, il faut étudier si son absence causerait une sérieuse perte d'information, et si elle est corrélée au vécu de l'utilisateur (par exemple, un taux de pertes élevé - cf. RFC 7680 - entraine une baisse très nette de la capacité du « tuyau » TCP, attristant ainsi l'utilisateur). Mais certaines applications peuvent tolérer des pertes isolées tout en étant intolérantes à des moments de pertes massives. Dans ce cas, une meilleure métrique incluerait non seulement le taux de pertes moyen, mais sa distribution dans le temps (voir par exemple le RFC 3611).

Les grandeurs ne sont pas toujours mesurées, elles peuvent aussi être calculées à partir d'autres grandeurs (section 5.3). On trouve ainsi des compositions spatiales de métriques (RFC 5835, RFC 6049), comme lorsqu'on déduit le taux de pertes sur un chemin en faisant le produit du pourcentage de paquets qui passent, sur toutes les composantes du chemin. Il y a aussi des compositions temporelles (RFC 5835), par exemple le calcul d'un minimum en prenant le plus petit résultat d'une série de mesures.

Une fois qu'un a bien défini ce qu'on voulait, on peut écrire la spécification de la métrique (section 5.4). Il faut un nom (mais voir le RFC 6248 qui explique pourquoi il n'y a plus de registre de ces noms), une description (qui inclus les critères d'utilité présentés plus haut), une méthode de mesure, les unités de mesure, et des indications sur le choix des points de mesure (le temps de réponse à une requête SIP n'est pas le même sur l'UAC (logiciel client, le softphone) et l'UAS (logiciel serveur du fournisseur SI de l'abonné). La méthode de mesure doit permettre de répondre aux questions-pièges. Par exemple, la métrique « taux de perte de paquets » semble triviale à définir. On retire de 1 le résultat de la division du nombre de paquets arrivés par le nombre de paquets envoyés. Mais cette définition sommaire est insuffisante. Si des paquets sont dupliqués (c'est possible avec IP), comment les traite-t-on ? Et, pour compter le nombre de paquets arrivés, on les attend combien de temps ? Un retardataire est-il une perte (voir aussi la section 5.5.2) ? Un autre exemple est que la méthode de mesure peut décider délibérement d'éliminer les outliers, ces valeurs très éloignées de la moyenne, qui sont fréquentes sur les réseaux informatiques. C'est ainsi que les opérateurs Internet font en général payer leurs clients en « 95 percentile » (on élimine 5 % de valeurs qui sortent trop du rang, les outliers).

Outre ces points essentiels de la spécification, la définition d'une métrique peut aussi inclure une mise en œuvre (par exemple sous forme de code), des valeurs attendues pour certains cas (pour évaluer la qualité du résultat), etc. Plus délicat, la définition peut inclure des indications sur l'usage de la métrique, par exemple sur les valeurs « raisonnables ». Un utilisateur typique à qui on dit qu'il y a « 1 % de pertes » sur le réseau ne sait pas forcément quoi en faire. Lui dire que les performances de TCP commencent à baisser sérieusement dès 0,5 % de pertes, serait plus utile. De même, annoncer dans un système de transport de la voix un niveau sonore de -7 dBm0 n'est guère utile à l'utilisateur non expert en téléphonie si on n'ajoute pas que les valeurs normales sont entre -18 et -28 dBm0 et que le son est donc ici bien trop fort.

Notre RFC 6390 fournit un exemple complet de définition d'une métrique, en prenant le taux de perte du RFC 3611 comme exemple. Notez que cette définition est un peu floue quant au sort des paquets arrivant tardivement.

Dans le monde réel, aucune mesure n'est parfaite : divers problèmes limitent la qualité des mesures effectuées. La section 5.5 décrit ces problèmes : précision de l'horloge, présence ou non d'une middlebox (RFC 3303) qui fausse les résultats, etc.

Et enfin, la métrique ainsi normalisée doit préciser les différents paramètres utilisés, pour que les utilisateurs puissent comparer deux mesures différentes.

La section 6 est plutôt orientée vers le processus social de développement d'une nouvelle métrique : si on a une idée d'une métrique à normaliser, comment agir dans l'IETF pour augmenter les chances de succès ? Elle insiste par exemple sur la check-list des caractéristiques à vérifier (la métrique est-elle bien définie, par exemple) et sur la rôle de la Direction des Performances, qui va évaluer le futur RFC.

Un peu d'histoire (section 1.1): l'IETF avait déjà travaillé, dans des temps anciens, sur des métriques pour les applications. Ce furent le RFC 4710, centré sur les terminaux mobiles, ou les RFC 3611 ou RFC 6035 sur la téléphonie. Mais, pendant longtemps, les principales métriques développées étaient uniquement pour les couches 3 et 4. Notre RFC 6390 vise donc à élargir le bestiaire des métriques.


Téléchargez le RFC 6390


L'article seul

RFC 6386: VP8 Data Format and Decoding Guide

Date de publication du RFC : Novembre 2011
Auteur(s) du RFC : J. Bankoski, J. Koleszar, L. Quillio, J. Salonen, P. Wilkins, Y. Xu (Google)
Pour information
Première rédaction de cet article le 11 novembre 2011


Le monde des formats vidéo est très hostile pour ceux qui apprécient la liberté et l'ouverture : formats privés, non documentés, contrôlés par une seule compagnie, plombé de brevets tous plus futiles les uns que les autres... Aujourd'hui, il est à peu près impossible de regarder une vidéo, quelle qu'elle soit, avec du logiciel entièrement libre, et sans enfreindre une centaine de brevets. Ce RFC documente un des très rares codecs vidéos ouverts, qui puisse être mis en œuvre dans du logiciel libre sans trop de crainte juridique. Il a été produit par Google, documenté pour l'IETF et se nomme VP8.

Lorsqu'on configure une machine utilisant du logiciel libre aujourd'hui, si on s'en tient strictement à ses principes, et qu'on refuse d'intégrer les sources de logiciel que Debian ou Ubuntu marquent comme non-libres, on n'arrivera pas à voir beaucoup de films... Même si le format du container vidéo est relativement ouvert, les techniques de compression ne le sont pas et on constate vite que son MPlayer ou son vlc n'arrivent pas à lire grand'chose. (C'est particulièrement vrai pour les films achetés légalement, pour lesquels l'usage de formats fermés sert de DRM. Les films partagés gratuitement sur le réseau réservent en général moins de mauvaises surprises.) Le problème de la personne qui produit le film est le manque de formats ouverts dans ce domaine. Le principal est Ogg (avec le codec vidéo Theora) mais les experts lui reprochent des performances en compression et décompression qui ne sont pas extraordinaires. Google prétend avoir une solution, son format VP8 (avec le format de container WebM), supposé bien meilleur (il a été développé à l'origine par On2). Mais utiliser un format spécifique à Google n'est pas mieux qu'utiliser un format spécifique à Adobe. Alors, Google a produit un RFC, soumis à l'IETF (en termes IETF, c'est une « soumission indépendante », pas le résutat d'un groupe de travail IETF) et qui devient donc un format ouvert, libre de la compagnie qui lui a donné naissance. Ce RFC inclut également une mise en œuvre de référence du décodeur, distribuée sous une licence libre (la BSD, cf. section 20.26).

La question des brevets est traditionnellement une de celles qui plombent le plus les projets de codecs ouverts. La section 20.27 décrit en détail la situation pour VP8. Google promet une licence gratuite d'exploitation de ses brevets pour toute implémentation de VP8. Mais il n'est pas clair, pour un non-juriste, si cela couvre la possibilité de versions ultérieures de VP8, qui ne seraient pas approuvées par Google. En attendant, pas mal de requins pourraient attaquer VP8. (Un bon article de synthèse est « Video codecs: The ugly business behind pretty pictures ».)

Ce RFC 6386 est essentiellement composé de code. VP8 est en effet défini par son implémentation de référence (la libvpx), le texte n'étant là que pour expliquer. Le RFC note bien (section 1) que, s'il y a une contradiction entre le code et le texte, c'est le code qui a raison (choix inhabituel à l'IETF). Avec ses 310 pages, c'est un des plus longs RFC existants. Je ne vais donc pas le traiter dans sa totalité, d'autant plus que les codecs vidéos ne sont pas ma spécialité.

Donc, en simplifiant à l'extrême, VP8 décompose chaque image d'un flux vidéo en une série de sous-blocs, chacun des sous-blocs étant composé de pixels. La compression d'un sous-bloc dépend des sous-blocs précédents, pour bénéficier de la redondance temporelle de la vidéo (sauf dans les films avec Bruce Willis, il y a relativement peu de changements d'une image à la suivante, et en général sur une partie de l'image seulement). Il y a aussi une redondance spatiale (des parties de l'image qui sont répétées, par exemple un grand ciel noir pour les scènes de nuit). La technique de compression se nomme transformée en cosinus discrète, mais VP8 utilise également à certains endroits une autre technique, la transformée de Walsh-Hadamard. VP8 ne permet pas de reconstituer exactement les pixels originaux, il compte sur la tolérance de l'œil humain (qui peut accepter certains changements sans tiquer).

Contrairement à son concurrent MPEG, VP8 encode et décode uniquement avec des nombres entiers et ne perd donc pas de précision dans les calculs en virgule flottante. Ces pertes peuvent parfois provoquer des effets surprenants, visibles à l'écran (rappelez-vous que, dans l'arithmétique en virgule flottante, il y a moins d'assertions vérifiables. Par exemple, 1 - x + x n'est pas forcément égal à 1).

La section 2 du RFC expose les grandes lignes du format : utilisation de l'espace YUV en 4:2:0 8bits, c'est-à-dire que chaque pixel dans les deux plans chromatiques (U et V) fait huit bits et correspond à un bloc de quatre pixels dans le plan de lumière Y. Les pixels sont ensuite transmis en lignes, de haut en bas, chaque ligne étant transmise de gauche à droite. Les informations permettant le décodage ne sont pas au niveau du pixel mais à celui de blocs de pixels. Dans l'implémentation de référence, la description du format se trouve dans le fichier d'en-tête vpx_image.h.

Une fois comprimées, il y a deux types de trames dans un flux VP8 (section 3) : les intratrames (ou trames clés, ce que MPEG appelle les trames-I) sont complètes et n'ont pas besoin d'autres trames pour être décodées. La première trame envoyée est évidemment une intratrame. Et le deuxième type sont les intertrame (trames-P chez MPEG), qui codent une différence par rapport à la précédente intratrame, et aux autres intertrames arrivées entre temps. La perte d'une intertrame empêche donc de décoder les suivantes, jusqu'à l'arrivée de la prochaine intratrame, qui permettra au décodeur de repartir d'un état connu.

À noter que, contrairement à MPEG, il n'y a pas de trame-B, trame permettant d'indiquer le futur. En revanche, VP8 a des « trames en or » et des « trames de référence de secours » qui sont des intertrames contenant suffisamment d'informations pour permettre de reconstituer les quelques trames suivantes. Elles permettent à VP8 d'être plus tolérant aux pertes de trame (normalement, lorsqu'un perd une intratrame, il n'y a rien d'autre à faire qu'à attendre la suivante).

Le format des trames compressées est décrit en section 4. Un en-tête (plus grand dans le cas des intratrames), et les données. Bon, en fait, c'est un peu plus compliqué que cela car, au sein des données, les macroblocs ont aussi leur en-tête. Pour décoder (section 5), le programme doit garder quatre tampons YUV : la trame actuellement en cours de reconstruction, la trame précédente (rappelez-vous que les intertrames sont uniquement des différences par rapport à la trame précédente, qu'il faut donc garder en mémoire), et les plus récentes trames en or et de référence de secours. Le principe est simple (on réapplique les différences à la trame de référence, obtenant ainsi la trame originale), mais il y plein de pièges, dus par exemple à l'abondance du contexte à maintenir (puisque le décodage dépend du contexte en cours). Le code se trouve dans dixie.c dans le RFC (l'implémentation de référence a été réorganisée et ce fichier n'y figure plus). Une façon de simplifier l'écriture d'un décodeur est de commencer par ne programmer que le décodage des intratrames, avant d'ajouter celui des trames intermdiaires. C'est d'ailleurs le plan que choisit le RFC.

Le langage de l'implémentation de référence est le C. Comme le note la section 6, c'est en raison de sa disponibilité universelle et de sa capacité à décrire exactement la précision des calculs qu'il a été choisi. Notez que le code C dans le RFC n'est pas exactement celui de l'implémentation de référence (qui est, elle, disponible en http://www.webmproject.org/code/). Plusieurs raisons à cela, notamment le fait que l'implémentation de référence a été optimisée pour la performance, le code dans le RFC pour la lisibilité, Mais les deux codes produisent le même résultat. Rappelons enfin que VP8 n'utilise pas de flottants, seulement des entiers.

Le code commence en section 7, avec le décodeur booléen. L'idée est que l'encodage est fait en produisant une série de booléens, avec pour chacun une probabilité d'être à zéro ou à un. Si la probabilité était de 0,5, aucune compression ne serait possible (il faudrait indiquer explicitement tous les booléens) mais ici, les probabilités sont souvent très éloignées de 0,5 (en raison des cohérences spatiales et temporelles du flux vidéo) et VP8 consomme donc moins d'un bit par booléen. Travailler sur bits étant typiquement peu efficace sur la plupart des processeurs, le code en section 7.3 les regroupe en octets.

Le reste du RFC est essentiellement composé de code C avec commentaires. Je saute directement à la section 19 / annexe A qui donne la liste complète des données encodées, Tous les objets manipulés par VP8 sont là.

Notez que le projet parent, WebM, utilise actuellement Vorbis pour l'audio (VP8 ne faisant que la vidéo). L'IETF a un projet de développement d'un codec audio, les détails figurent dans le RFC 6366.

Pour plus d'information, on peut consulter le site officiel du projet WebM qui contient entre autres une liste des outils disponibles. Pour le déploiement de WebM, on peut voir la page du Wikipédia anglophone. Une analyse (critique) de VP8 a été faite par Jason Garnett-Glaser.

Parmi les autres mises en œuvre de VP8, un cas curieux, un décodeur en JavaScript...


Téléchargez le RFC 6386


L'article seul

RFC 6385: General Area Review Team (Gen-ART) Experiences

Date de publication du RFC : Octobre 2011
Auteur(s) du RFC : M. Barnes (Polycom), A. Doria (Lulea University of Technology), H. Alvestrand (Google), B. Carpenter (University of Auckland)
Pour information
Première rédaction de cet article le 19 octobre 2011


Comme souvent à l'IETF, les expériences les plus réussies ne sont pas documentées, ou alors le sont longtemps après. Les examens des Internet-Drafts par Gen-ART (General Area Review Team) ont commencé en 2004 mais viennent juste d'être formalisées. Gen-ART, dont l'expérience est décrite dans ce nouveau RFC, est un groupe d'experts volontaires qui regardent les Internet-Drafts lorsqu'ils sont prêts de devenir un RFC. Le terme de « Gen-ART » apparait de plus en plus souvent dans les discussions à l'IETF, mais que recouvre-t-il exactement ?

Les procédures de l'IETF sont loin d'être toutes documentées. Il y a la théorie, et la pratique. Par exemple, l'IESG est censée examiner les Internet-Drafts avant leur publication au cours de ses réunions à distance, les telechats. Mais la quantité de documents à examiner est telle que toute aide est la bienvenue. Un groupe de volontaires s'est donc constitué et s'est mis tout seul (rappellons que tout le processus IETF est public, il n'y a pas besoin d'une autorisation spéciale pour créer un groupe, lire des documents et publier les résultats) à lire les documents qui allaient passer à l'IESG, pour débrousailler le tas de papier. Ce RFC est le compte-rendu de l'expérience de ce groupe, qui prend désormais de plus en plus de place, au point que certains croient même qu'il s'agit d'un projet officiel.

La section 1 du RFC résume d'où vient Gen-ART, et insiste sur ce caractère non officiel. Gen-ART fait ce que tout le monde a le droit de faire : lire les Internet-Drafts (ils sont publics) et les commenter publiquement. Son autorité est purement morale, provenant de la qualité de ses examens et du prestige de ses membres.

La section 2 est consacrée à ces membres : un groupe d'experts auto-désignés, en général auteurs de plusieurs RFC, et expérimentés dans la normalisation IETF. La section 12 donne la liste actuelle (qu'on trouve aussi en ligne). Bien que le RFC n'en parle pas, on peut noter que la relecture est parfois faite par un autre membre de l'IETF, sur délégation d'un membre de Gen-ART (évidemment en toute transparence). C'est ainsi que j'ai fait ma première (et unique, pour l'instant) revue Gen-ART, en décembre 2010, comme délégué de Francis Dupont. Il s'agissait du document draft-cheshire-dnsext-dns-sd, très contesté (ma conclusion était peu favorable, et le document est toujours, aujourd'hui, en discussion). L'auteur avait répondu à mon analyse.

La section 3 résume ensuite le but poursuivi par Gen-ART : décharger l'IESG d'une partie du fardeau (parfois vingt Internet-Drafts en un seul telechat), de façon à ce que l'examen de l'IESG puisse se concentrer sur les quelques documents à problème, en ignorant la majorité qui va bien. Bien qu'il existe tout un tas de comités et de groupes à l'IETF, personne ne vise cette tâche à part Gen-ART.

La section 4 décrit comment fonctionne Gen-ART, quels documents sont relus, et qu'est-ce que produit Gen-ART. Le rapport final indique si l'Internet-Draft :

  • est prêt à devenir un RFC, et de quel type (expérimental, pour information, chemin des normes...),
  • ou bien est presque bon mais mérite quelques changements,
  • ou encore s'il va dans le bon sens mais a besoin d'être sérieusement revu,
  • ou, pourquoi pas, s'il est tellement catastrophique qu'il vaut mieux arrêter là.

Les critères pour décider sont ceux classiquement utilisés à l'IETF :

Gen-ART étant issu de la « zone générale » (General Area, celle qui s'occupe de tout ce qui ne rentre pas dans une catégorie particulière), le groupe de relecteurs fait notamment attention à tout ce qui n'est pas sous la responsabilité d'une autre zone. Par exemple, dans un Internet-Draft sur un nouveau protocole de routage, on peut supposer que la zone Routage (Routing Area) s'est occupé de la qualité technique du protocole. Cela laisse donc à vérifier, un tas de choses, certaines de haut niveau et d'autres triviales. Le RFC cite, entre autres :

La section 4 décrit ensuite le processus suivi lors des relectures. Il faut notamment noter que les RFC ne sont pas affectés aux relecteurs en fonction de leur spécialité : le but étant d'avoir un regard général, un expert en sécurité peut se retrouver avec un Internet-Draft sur le routage. Le processus bureaucratique, lui (maintien de la liste des relecteurs, détails très précis sur les conditions d'affectation d'un document à un relecteur), est en section 5.

Quels sont les résultats de Gen-ART ? La section 6 fait le bilan : environ 2 000 relectures ont été faites en sept ans, avec une équipe comportant environ douze relecteurs, chacun recevant plus d'un Internet-Draft par mois. Ces relectures ont permis de faire passer le pourcentage de documents considérés comme « prêts pour publication » au moment du telechat IESG de 25 % à 75 %.

Par delà les chiffres, quel est le ressenti des participants ? La section 7 rassemble tout un tas de témoignages très variés, notant par exemple que la qualité moyenne est bonne mais que Gen-ART a déjà servi à arrêter de très mauvais documents.

Mais le mécanisme des relectures Gen-ART est-il parfait ? La section 8 propose de l'améliorer, notant les points faibles. Le principal est l'absence presque complète d'automatisation. Gen-ART n'a actuellement pas d'outils spécialisés (un des buts de la section 5 était, en décrivant précisement le processus, de faciliter l'écriture d'un cahier des charges pour le développement de ces outils).

Vous pouvez aussi visiter le site Web de Gen-ART et prendre connaissance de sa FAQ.


Téléchargez le RFC 6385


L'article seul

RFC 6382: Unique Per-Node Origin ASNs for Globally Anycasted Services

Date de publication du RFC : Octobre 2011
Auteur(s) du RFC : Danny McPherson, Ryan Donnelly, Frank Scalzo (Verisign)
Réalisé dans le cadre du groupe de travail IETF grow
Première rédaction de cet article le 25 octobre 2011
Dernière mise à jour le 26 octobre 2011


Ce court RFC propose un changement radical dans la gestion des annonces BGP par les services anycastés. Actuellement, ils utilisent presque tous un seul numéro d'AS pour tous les nœuds d'un nuage anycast. Notre RFC 6382, au contraire, suggère d'utiliser un numéro d'AS par nœud.

Comme l'explique la section 2 de notre RFC, l'anycast (RFC 4786) est désormais une technique banale. Elle permet notamment d'augmenter sérieusement la résistance aux dDoS. Dans le monde du DNS, l'anycast est particulièrement répandu (par exemple, .fr n'a plus que deux serveurs unicasts, tous les autres sont anycastés).

L'anycast fonctionnant en injectant la même route, via BGP, depuis des points différents du réseau, on peut se demander s'il faut que tous ces points annonçent le préfixe depuis le même AS, ou bien si chacun doit utiliser un AS différent ? Aujourd'hui, la quasi-totalité des services anycastés utilisent un seul numéro d'AS pour tous leurs points de présence (POP). VeriSign (la boîte des auteurs du RFC) est un des rares acteurs à le faire, pour certains de leurs serveurs. Cela a notamment l'avantage de préserver une ressource rare : les numéros d'AS n'étaient codés que sur seize bits. Cela facilite également la configuraion des routeurs. Et, aujourd'hui, cela évite des ennuis avec les systèmes d'alarme BGP, qui pourraient couiner en voyant le même préfixe avoir plusieurs AS d'origine. Hurricane Electric fournit ainsi une liste des préfixes annoncés par plusieurs AS. Même chose chez Cymru. Comme illustré par un exposé à NANOG en 2001, c'était plutôt considéré comme une erreur.

Mais cette politique a aussi des défauts : lorsqu'un routeur BGP voit arriver une annonce pour un préfixe anycasté, il ne sait pas exactement de quel nœud elle vient. Cela peut compliquer le débogage des problèmes. Certains services ont un mécanisme pour identifier le serveur (RFC 5001 pour le DNS, ou bien le traditionnel quoique non normalisé hostname.bind dans la classe CH). Et, évidemment, on peut toujours utiliser traceroute pour trouver où se trouve telle instance anycast. Essayons avec un serveur DNS anycasté, d.nic.fr, depuis une machine située dans le Missouri :

% dig +nsid @d.nic.fr SOA fr.
...
; NSID: 64 6e 73 2e 6c 79 6e 32 2e 6e 69 63 2e 66 72  (d) (n) (s) (.) (l) (y) (n) (2) (.) (n) (i) (c) (.) (f) (r)
...

C'est donc dns.lyn2.nic.fr qui a répondu. Et on confirme (l'AFNIC utilise les Locodes pour nommer ses machines, donc LYN = Lyon) qu'on touche l'instance de Lyon (cette machine a surtout des instances en métropole et dans les DOM-TOM et aucune aux États-Unis) :

# tcptraceroute d.nic.fr 53
Selected device eth0, address 208.75.84.80, port 43778 for outgoing packets
Tracing the path to d.nic.fr (194.0.9.1) on TCP port 53 (domain), 30 hops max
 1  208.75.84.1  0.000 ms  0.000 ms  0.000 ms
 2  host123.datotel.com (208.75.82.123)  0.000 ms  0.000 ms  0.000 ms
 3  stl-c1-g1-15.datotel.com (208.82.151.29)  10.000 ms  0.000 ms  0.000 ms
 4  stl-e2-g0-2.datotel.com (208.82.151.13)  0.000 ms  0.000 ms  0.000 ms
 5  vlan100.car2.StLouis1.Level3.net (4.53.162.121)  0.000 ms  0.000 ms  0.000 ms
 6  ae-4-4.ebr2.Chicago1.Level3.net (4.69.132.190)  10.000 ms  9.999 ms  10.000 ms
 7  ae-5-5.ebr2.Chicago2.Level3.net (4.69.140.194)  0.000 ms  9.999 ms  9.999 ms
 8  ae-6-6.ebr2.Washington12.Level3.net (4.69.148.145)  10.000 ms  19.999 ms  19.999 ms
 9  ae-5-5.ebr2.Washington1.Level3.net (4.69.143.221)  19.999 ms  19.999 ms  29.998 ms
10  ae-44-44.ebr2.Paris1.Level3.net (4.69.137.61)  89.994 ms  99.994 ms  109.994 ms
11  ae-22-52.car2.Paris1.Level3.net (4.69.139.227)  109.994 ms  99.994 ms  99.994 ms
12  JAGUAR-NETW.car2.Paris1.Level3.net (212.73.207.162)  109.993 ms  99.995 ms  99.994 ms
13  dns.lyn2.afnic.cust.jaguar-network.net (78.153.224.126)  119.993 ms  119.993 ms  139.992 ms
14  d.nic.fr (194.0.9.1) [open]  109.994 ms  119.993 ms  109.993 ms

Les machines de l'AFNIC ayant un enregistrement DNS indiquant leur position physique (RFC 1876), on peut même être plus précis :

% dig LOC dns.lyn2.nic.fr
...
dns.lyn2.nic.fr.	172800	IN	LOC	45 43 20.568 N 4 51 39.816 E 1.00m 1m 10m 10m

et on sait alors où est la machine.

Autre essai, avec un serveur de la racine du DNS, L.root-servers.net, largement anycasté. Depuis un fournisseur en France :

% dig +nsid @l.root-servers.net SOA .
...
; NSID: 6c 79 73 30 31 2e 6c 2e 72 6f 6f 74 2d 73 65 72 76 65 72 73 2e 6f 72 67  (l) (y) (s) (0) (1) (.) (l) (.) (r) (o) (o) (t) (
-) (s) (e) (r) (v) (e) (r) (s) (.) (o) (r) (g)

On touche lys01.l.root-servers.org. Comme son opérateur, l'ICANN, utilise (comme beaucoup), les codes aéroport pour nommer les machines, on voit qu'elle est également à Lyon (LYS est l'aéroport de cette ville). Depuis une machine d'un autre FAI français, la même requête renvoie lux01.l.root-servers.org, ce qui situe le nœud anycast au Luxembourg. Et, en testant depuis la machine missourienne citée plus haut, on atteint lax12.l.root-servers.org soit Los Angeles.

Ces techniques sont toutefois imparfaites. Or, les services anycast ont des vulnérabilités paticulières. Par exemple, l'injection de routes pirates dans BGP par un méchant est plus difficile à détecter (cf. section 5). L'anycast a besoin d'outils de débogage puissants, pour venir à bout des problèmes de routage, volontaires ou involontaires, qui peuvent se manifester. Pire, on peut avoir des cas où les différentes instances d'un même nuage anycast ne répondent pas exactement la même chose, et il est dans ce cas crucial de pouvoir identifier sans aucune ambiguïté celles qui sont différentes.

Avant la recommandation officielle, un petit détour de terminologie (section 1). Parmi les termes importants (lire le RFC 4786 pour plus de détails) :

  • Bassin d'attraction (catchment), terme emprunté à l'hydrographie (la zone dont toutes les eaux finissent dans une rivière donnée), désigne la partie de l'Internet qui envoie ses paquets à un nœud (une instance anycast) donné,
  • Nœud local, instance d'un service anycast qui ne publie son préfixe que dans une partie de l'Internet (typiquement, uniquement les participants à un point d'échange donné, en utilisant la communauté BGP no-export). La recommandation de ce RFC s'applique à tous les nœuds, locaux ou globaux,
  • Nœud global, instance qui annonce son préfixe à l'Internet entier.

Venons-en maintenant à la nouveauté de ce RFC. Il tient en une phrase (section 3), « Il faudrait utiliser un numéro d'AS différent par nœud ». Le but est de fournir un mécanisme discriminant les annonces. Si on a deux nœuds, un en Chine (AS 65536) et un en Europe (AS 65551), et qu'on voit le préfixe anycast 192.0.2.64/26 annoncé depuis l'AS 65536, on sait qu'on s'adressera à l'instance chinoise. On peut même filtrer sur l'AS d'origine pour éviter cela. L'utilisation de numéros d'AS différents permettra de choisir sa politique de routage.

Est-ce sans inconvénient ? Actuellement, le principal problème risque d'être les systèmes d'alarme qui s'inquiéteraient de ces différentes origines. Ainsi, BGPmon, par défaut, considère qu'une annonce depuis un autre AS que celui indiqué comme origine, est une attaque possible (possible hijack) et il alarme. Toutefois, le même BGPmon permet d'indiquer plusieurs AS d'origine supplémentaire, ce qui lui permet de gérer la nouvelle politique. (Une société comme PCH a environ soixante localisations physiques dans le monde, Netnod en a cent : les enregistrer toutes comme origine possible, auprès d'un système d'alarme BGP, pourrait être fastidieux. À noter que la fonction auto-detect de BGPmon simplifie cela : comme l'explique l'auteur « Just click on the prefix to edit it, then click on the little green icon next to the 'Additional Origin AS' section. It will then show a popup with all additional origin ASn's we have in our database. You can then copy paste that line into the 'Additional Origin AS' field. ». Un exemple est donné par un serveur de .com, m.gtld-servers.net.)

Autre inconvénient possible : la consommation excessive de numéros d'AS. Toutefois, depuis le RFC 4893, ceux-ci peuvent désormais être codés sur 32 bits et le risque d'épuisement disparait.

Après cette nouvelle recommandation de consommer un numéro d'AS par site, la section 4 du RFC rassemble divers conseils aux gérants de services anycast :

  • Publier des informations sur la localisation physique de la machine (la méthode n'est pas précisée mais on peut penser aux enregistrements LOC du RFC 1876, peut-être en les attachant au nom obtenu par la requête NSID),
  • Publier dans les IRR les informations sur les AS auxquels le nœud anycast s'interconnecte (par exemple en RPSL, RFC 4012).

Et la section 6 contient l'examen de divers points pratiques liés au déploiement de cette nouvelle politique. Les opérateurs de services anycast critiques ont été largement consultés avant la publication du RFC, ce qui ne veut pas dire qu'ils déploieront cette recommandation tout de suite (aucun n'a annoncé de plan précis et l'ISC a au contraire annoncé qu'ils ne le feraient pas, voir plus loin leur analyse). En gros, la nouvelle politique fera davantage de travail au début (obtenir les numéros d'AS - ce qui nécessitera probablement un changement dans la politique des RIR, ajouter une colonne pour le numéro d'AS dans la base de données des instances anycast, penser à indiquer le bon numéro d'AS lorsqu'on fait une demande de peering, changer les centaines de peerings existants, etc) mais simplifiera la surveillance du service, en permettant de trouver plus facilement l'origine d'une annonce.

Et pour finir, un exemple de ce que donne un excellent outil d'analyse existant, le RIS, avec le serveur de .com déjà cité (annoncé par trois AS) : http://www.ris.ripe.net/dashboard/192.55.83.0/24.

Une autre question n'est pas couverte dans le RFC mais mérite une mention (merci à Olivier Benghozi et Guillaume Barrot pour leurs explications) : pourquoi n'avoir pas utilisé plutôt les communautés BGP (RFC 1997), des étiquettes qu'on peut attacher aux annonces et qui sont transitives ? La raison principale est qu'elles sont fréquemment effacées en entrée des AS (sans compter les systèmes qui, par défaut, ne les transmettent pas du tout comme IOS, cf. un article sur leur utilisation). Même problème avec d'autres attributs facultatifs de BGP comme AGGREGATOR (qu'on aurait pu, en le détournant un peu, utiliser à ce but).

Merci à Jean-Philippe Pick pour sa relecture et pour les informations.


Téléchargez le RFC 6382


L'article seul

RFC 6377: DKIM And Mailing Lists

Date de publication du RFC : Septembre 2011
Auteur(s) du RFC : M. Kucherawy (Cloudmark)
Réalisé dans le cadre du groupe de travail IETF dkim
Première rédaction de cet article le 22 septembre 2011


La sécurité, c'est compliqué. Ce n'est pas tout de définir des normes techniques comme DKIM, pour sécuriser le courrier électronique. Il faut encore étudier leurs conséquences pour tous les cas. Le courrier électronique ayant débuté il y a très longtemps, et n'ayant pas vraiment été spécifié dans tous les détails (son architecture n'a été officiellement décrite qu'en 2009, avec le RFC 5598), il représente un défi particulier pour tous ceux qui essaient de le sécuriser a posteriori. C'est ainsi que ce nouveau RFC s'attaque au cas particulier des listes de diffusion et étudie comment elles réagissent avec le mécanisme d'authentification DKIM.

D'abord, à quoi sert DKIM ? Normalisé dans le RFC 6376, DKIM permet de signer un message électronique. Sans lui, il est trivial de fabriquer un faux message (prétendant venir de votre banque et vous demandant de saisir votre mot de passe sur un formulaire Web) et il n'y a aucun moyen d'acquérir des certitudes sur ce message, où (presque) tout peut être faux. Avec DKIM, un domaine de courrier peut signer le message et ainsi en prendre la responsabilité. Si le message est signé par mabanque.example, vous pouvez être sûr, pas forcément de sa véracité, mais en tout cas d'un lien avec votre banque. Contrairement à PGP, conçu pour authentifier une personne, DKIM permet d'authentifier un domaine qui a une responsabilité dans l'envoi de ce message.

Mais les listes de diffusion posent des problèmes spécifiques (section 1). DKIM avait été conçu avec l'idée que le message n'était pas modifié en cours de route. S'il l'est, c'est considéré comme une attaque qu'il faut détecter. Or, les gestionnaires de listes de diffusion ne respectent pas ce principe. Par exemple, il est fréquent (bien que ce soit une très mauvaise idée, cf. le RFC 4096) que le sujet soit modifié pour y inclure le nom de la liste entre crochets. De même, l'ajout d'instructions de désabonnement à la fin de chaque message est commun. De telles modifications sont peut-être honnêtes (dans l'esprit de celui qui les a décidés, ce ne sont pas des tentatives de fraude) mais, pour un logiciel de vérification, elles suffisent à invalider la signature.

Si les intermédiaires qui relaient un message le laissaient rigoureusement intact, ce serait non seulement une bonne idée pour les utilisateurs, mais cela permettrait à DKIM de continuer à fonctionner. Comme, parmi les intermédiaires, les MLM (Mailing List Managers) sont souvent les plus intrusifs, que peut faire DKIM pour gérer ce problème ?

  • Est-ce une bonne idée de signer avec DKIM un message envoyé à une liste de diffusion ?
  • Est-ce que le MLM devrait vérifier ces signatures en entrée ?
  • Est-ce que le MLM devrait retirer les signatures existantes ?
  • Et/ou mettre la sienne ?

Ce RFC ne normalise pas de réponse officielle à ces questions : il explique le problème et pointe du doigt les compromis à faire. La recommandation générale est « dans le cas typique, le MLM a intérêt à signer les messages qu'il relaie, et les vérificateurs à la destination ont intérêt à tenir compte de cette signature ». Le lecteur attentif aura noté que cette recommandation laisse plein de questions ouvertes...

Avant de détailler les problèmes, la fin de la section 1 rappelle quelques éléments importants sur le courrier électronique et les MLM (voir le RFC 5598 pour une présentation générale de l'architecture du courrier et sa section 5.3 sur les MLM). Les MLM (les gestionnaires de listes de diffusion) n'ayant jamais fait l'objet d'une normalisation officielle (le RFC 5598 a été écrit longtemps après), leur comportement varie énormément. Lorsqu'un MLM fait une opération, il est bien difficile de trouver un RFC qui dit noir sur blanc s'il est en droit de la faire ou non. Une notion aussi simple que celle d'identité (qui est l'auteur du message) n'est pas évidente et DKIM a donc sagement décidé de ne pas lier le domaine signant (celui qui est indiqué par d= dans une signature DKIM) avec une des « identités » présentes dans les en-têtes du message. Ainsi, le domaine signant n'est pas forcément celui présent dans le champ From:. Il peut refléter, par exemple, un domaine qui a relayé le courrier et, en le signant, a affirmé une certaine responsabilité pour ce message. Donc, si un MLM signe avec son domaine un message venu d'un autre domaine, cela ne pose pas de problème : c'est dans l'esprit de DKIM.

C'est l'interprétation qui va poser problème. Si j'écris un message sur la liste smtp-fr@cru.fr avec mon adresse professionnelle (bortzmeyer@nic.fr), qui est responsable ? L'« auteur », mentionné dans le champ From:, ou bien l'ex-CRU, qui gère le MLM, ou encore la personne mentionnée (ce terme est d'ailleurs malheureux) comme « propriétaire » de la liste smtp-fr (aujourd'hui, Christophe Wolfhugel). Selon le cas, un vérificateur sera plus intéressé par l'un ou l'autre des responsables.

Je l'ai dit, la normalisation des fonctions des MLM n'a été faite qu'a posteriori, n'est pas complète, et n'a pas été largement adoptée. C'est ainsi que des normes comme le champ List-ID: (RFC 2929) ou les en-têtes donnant les mécanismes de désabonnement (RFC 2369) ne sont que partiellement déployés.

Bref, que conseille ce RFC ? Avant d'en arriver aux conseils pratiques, en section 4 et 5, il faut encore bien se mettre à jour sur la terminologie (section 2) et les principes de fonctionnement des MLM (section 3). En section 2, il faut d'abord lire les RFC sur DKIM, le RFC 5585, qui sert d'introduction et le RFC 6376 sur la norme elle-même. Ensuite, notre RFC introduit quelques termes nouveaux comme « gentil avec DKIM » (DKIM-friendly), qui désigne un MLM dont les actions n'invalident pas les signatures DKIM. À noter que cela ne dépend pas que du logiciel mais aussi de sa configuration (si on lui fait ajouter un pied de page en bas de chaque message, les signatures portant sur le corps du message sont invalidées), et des options du signeur (si le MLM modifie le sujet mais que le signeur n'a pas signé le sujet, le MLM sera considéré comme gentil avec DKIM).

Alors, comment fonctionnent les MLM ? Le problème, note la section 3, est qu'il y en a plusieurs sortes. Les différents rôles qui décrivent les acteurs du système de messagerie (auteur, signeur, récepteur, etc) sont évidents lorsque le message est un envoi direct d'Alice à Bob. Mais le MLM perturbe ce bel ordonnancement théorique. Déjà, il y a quatre types de MLM :

  • Les alias, qui transmettent le message sans autre changement que l'ajout de quelques en-têtes de trace (comme Received:). La section 3.9.2 du RFC 5321 les mentionne. Ils ne changent que l'enveloppe SMTP, pas le message (en tout cas pas dans les parties signées). Les alias se mettent typiquement en œuvre sur Unix dans les fichiers aliases (directives alias_database et alias_maps de Postfix). Ces MLM sont gentils avec DKIM et n'invalident jamais les signatures (on notera que c'est le contraire avec SPF, RFC 7208, puisque ce dernier authentifie l'enveloppe et pas le message).
  • Les réexpéditeurs (resenders), qui reçoivent un message, lui font parfois subir quelques modifications, et renvoient ce message à la liste des abonnés. Ce sont les MLM typiques comme Mailman ou Sympa.
  • Les auteurs. Ce sont les MLM qui créent le message, plutôt que de renvoyer un message qu'on leur a transmis. Pensez à une newsletter, ou au spam. Ils n'ont guère de problème avec DKIM puisqu'ils contrôlent toute la chaîne, depuis la rédaction initiale.
  • Les synthétiseurs (digesters) qui prennent plusieurs messages reçus et les assemblent en un seul message, de type MIME multipart/digest (certains abonnés préfèrent lire ainsi). Cette synthèse est un nouveau message, mais composé à partir de messages pré-existants.

Dans les deux derniers cas, le MLM crée un nouveau message. Dans le second, le plus difficile, son rôle est moins clair. Si on veut approfondir ces nuances philosophiques, on peut consulter les sections 3.6.4 du RFC 5322 et 3.4.1 du RFC 5598.

Quels sont les effets exacts des MLM sur les messages signés ? La section 3.3 les détaille :

  • Le sujet (Subject:) est parfois modifié, pour ajouter le nom de la liste entre crochets. Cette pratique est très contestée (personnellement, je ne l'aime pas du tout, car elle modifie le message pour rien : si on veut trier le courrier, il est plus simple de le faire automatiquement via Sieve ou un système équivalent) mais, comme le note le RFC, contestée ou pas, elle ne va pas disparaître du jour au lendemain. Comme le sujet est un des éléments les plus importants de l'en-tête (c'est souvent ce que l'utilisateur regarde en premier) et qu'il est donc recommandé de le signer, ce comportement des MLM pose un problème.
  • En revanche, les en-têtes spécifiques aux listes de diffusion, comme le List-ID: du RFC 2929 ne posent a priori pas de problème, car ils sont rarement mis par les MUA et DKIM n'a pas de problème avec l'ajout de nouveaux champs.
  • Mais il peut aussi y avoir des changements dans le corps du message. Ils sont parfois mineurs (par exemple l'ajout de trois lignes d'instructions de désabonnement à la fin de chaque message). Mais cela suffit à rendre la signature DKIM invalide. DKIM permet de limiter la portée de la signature du corps (par exemple, de ne signer que les N premiers octets), ce qui permet l'ajout ultérieur de contenu (au prix d'une sérieuse baisse de sécurité). Si les changements sont plus significatifs (par exemple traduire le message HTML en texte seul), alors la signature sera invalide quoiqu'il arrive.
  • Enfin, certains MLM suppriment les fichiers attachés (présents dans une partie MIME du message), les remplaçant par exemple par l'URL d'un service d'hébergement où le fichier a été déposé. Cela cassera également la signature.

Bref, à l'heure actuelle, les MLM sont souvent méchants avec DKIM. Dans le futur, cela évoluera peut-être mais on ne peut pas en être sûr, notamment parce que DKIM n'est pas assez important pour que les programmeurs de MLM changent leurs pratiques juste pour lui.

Une fois ces pratiques des MLM étudiées, le RFC a deux parties de conseils. L'une est consacrée aux MLM qui ne connaissent pas DKIM. Cette section 4 fournit donc des conseils aux signeurs et aux validateurs pour le cas où le message est passé par un tel MLM. L'autre, la section 5, est composée de conseils aux MLM qui connaissent DKIM et veulent bien faire. Voyons d'abord la section 4. Si un message signé va passer par un MLM non-DKIM, que faire ?

Idéalement, si l'auteur sait qu'un message va passer par un MLM non-DKIM, il devrait décider de signer ou pas, selon le comportement du MLM. La signature est risquée car le MLM peut faire une des modifications citées plus haut, rendant la signature invalide et inquiétant les récepteurs. (En théorie, une signature invalide doit être ignorée - RFC 6376, section 6.1 - sauf si le domaine émetteur publie en ADSP une politique plus stricte.) Le problème de cette approche est que l'émetteur ne connaît pas forcément les détails de tous les MLM et autres logiciels par lesquels son message risque de passer. Les administrateurs système qui activent DKIM sur leur infrastructure vont donc devoir décider sans connaître toute l'information. Les politiques strictes de signature et de vérification n'ont donc de sens qu'en cas de contrôle complet de la chaîne entre l'émetteur et le récepteur (ce qui exclut les MLM). Ne mettez donc pas une politique ADSP discardable si le courrier de ce flux de messages risque de passer par un MLM.

Cette absence d'information sur les MLM et autres logiciels intermédiaires touche également les vérificateurs. Une solution possible est d'exclure de la vérification les courriers passés par les listes. Ce serait évidemment un gros travail, sans compter la maintenance d'un tel système (lorsqu'une nouvelle liste apparait). Les vérificateurs ont donc tout intérêt à respecter l'un des principes de base de DKIM : ne pas jeter un message simplement parce que sa signature est invalide.

Et pour les MLM modernes et qui gèrent DKIM ? Que doivent-ils faire ? La section 5 expose, dans l'ordre du voyage du message, les recommandations qui leur sont destinées. Ajouter des en-têtes (comme List-ID:) ne pose pas de problèmes. C'est un comportement gentil (sauf dans le cas où ces en-têtes étaient déjà présents et signés, ce qui est rare).

Par contre, ajouter un texte à la fin du message, on l'a vu, casse la signature. L'IETF n'a pas de politique officielle à ce sujet et il n'existe pas de RFC qui dise noir sur blanc « Thou SHALL NOT change the text, even by a single byte ». Même si un tel RFC existait, rien ne dit que les MLM suivraient ses consignes d'autant plus qu'il n'existe pas d'en-tête standard pour des informations telles que les conditions d'usage de la liste. DKIM a normalement une technique pour ce cas : l'option l= qui indique la portée de la signature (en nombre d'octets). L'ajout de texte après la valeur indiquée par l= n'invalide pas la signature. Mais cette méthode est déconseillée : un de ses inconvénients est qu'un attaquant peut, lui aussi, ajouter ce qu'il veut au message, sans craindre d'être détecté.

Notre RFC suggère donc, plutôt que d'ajouter à la fin de chaque message un texte comme « Le spam et les remarques désagréables sont prohibées sur cette liste. Les règles d'utilisation complètes sont présentées en http://www.example.com/lists/the-list/terms-of-use », d'envoyer de telles informations de temps en temps via un message automatique. Certes, ce sera ennuyeux (pensez à tous les messages de Mailman le premier du mois) mais cela pourra être filtré facilement.

Le problème d'ADSP (RFC 5617) est encore plus fort. ADSP permet de publier dans le DNS des directives de validation du genre « Je signe tout et correctement, vous pouvez jeter tout ce qui n'est pas bien signé ». Si un domaine publie une politique ADSP discardable, il interdit quasiment tout usage d'un MLM. Les seules solutions sont encore dans le futur. Par exemple, le RFC imagine des MLM qui connaissent ADSP et qui, lors de la réception d'une demande d'abonnement, testent la politique et, si elle est stricte, refusent l'abonnement. Mais la politique ADSP peut changer à tout moment, donc ce n'est pas une solution parfaite. Va-t-il falloir retester régulièrement ?

L'auteur d'un message signé est de toute façon toujours dans une position difficile : il ne sait pas ce qui va arriver à son message et il ne connaît pas les réglages des logiciels intermédiaires. La section 5.5 recommande donc de séparer le courrier en deux : celui qui sera forcément de bout-en-bout devrait être signé avec une identité et une clé différente du courrier général, qui sera peut-être relayé par un MLM. Ainsi, si mabanquecherie.example est le domaine d'une banque, le courrier envoyé directement au client ne devrait pas avoir le même d= que celui utilisé pour le travail quotidien des employés.

Et sur le MLM lui-même, s'il connaît DKIM, quelles sont les bonnes pratiques (section 5) ? La plupart des MLM procèdent à une forme d'authentification, souvent plutôt faible (par exemple, une vérification du From: vis-à-vis de la liste des abonnés). Avec DKIM, on pourrait avoir apparaître de nouvelles politiques, plus sûres (par exemple une exigence que le message soit signé et que le domaine indiqué par d= soit celui du champ From:). Évidemment, aujourd'hui, très peu de messages seront signés, donc le gérant du MLM va devoir décider quoi faire des autres. En tout cas, une vérification positive est bon signe et le RFC demande que le MLM ajoute dans ce cas un en-tête indiquant une authentification réussie (RFC 7001).

Et que faire des signatures DKIM existantes, déjà présentes lorsque le MLM reçoit le message original ? Si le MLM est sûr de ne rien changer au message, il peut laisser ces signatures, qui apportent une information intéressante. Mais s'il modifie le message, il est sans doute plus prudent de les supprimer, pour éviter tout risque qu'un message arrive au destinataire final avec une signature invalide (ce que certains destinataires considéreront, en violation de la norme DKIM, comme une incitation à jeter le message).

Ensuite, il reste une autre décision à prendre pour le MLM : doit-il apposer sa propre signature ? Le RFC le recommande fortement, afin de bien marquer que le gérant du MLM accepte sa responsabilité pour le message qu'il transmet. Le risque est évidemment que certains destinataires interprètent cette signature comme signifiant que le message a été authentifié dès le début. Toutefois, DKIM en lui-même ne peut rien faire dans ce cas : il y aura toujours des gens pour mal interpréter une signature et lui attribuer un poids qu'elle n'a pas.

Continuons le trajet du message : nous approchons de la fin avec les conseils aux vérificateurs. En gros, le RFC demande que ceux-ci traitent les messages des listes comme n'importe quel autre message (dans l'état actuel du déploiement des RFC 2919 et RFC 2369, il n'y a pas de moyen fiable de savoir si un message est passé par un MLM).

Les listes de diffusion de l'IETF signent tous les messages sortants, depuis juillet 2011, avec d=ietf.org (les signatures originelles sont apparemment retirées). Barry Leiba a bien résumé ce que cela apporte : « What it does is allow you to assure yourself that the message was, indeed, from an IETF mailing list (well, from an IETF email server), and that it wasn't that someone tried to spoof that. That, in turn, allows you to confidently increase your trust that the message is not spam in proportion to your confidence in the IETF's spam-filtering capabilities. ». Voici une telle signature :

DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ietf.org; s=ietf1;
        t=1311614276; bh=qLpIZcZ8XeP5xTrgVPRjnXlZjXWiz9DqXpACtarsL0Q=;
        h=Date:From:To:Subject:Message-ID:MIME-Version:List-Id:
        List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe:
        Content-Type:Content-Transfer-Encoding:Sender;
        b=ppseQobrat1rQ+Brsy2LSpMAA79YgaFJ7PK2EG1N4w0zS2IZBqDQiXYHJxG/wv4wl
        GOd42GtThBVxB5BmBhkTn8M1Rqz+ZhW2pLPlcI1zHcmLmJHLMt1wC6R3wiCi4bipVd
        CszNeb58HSYGNDQmvnW9dAxi38pL/kjunJTpmVT4=

Le RFC mentionnait à plusieurs reprises les MLM qui comprennent DKIM. À ma connaissance, aujourd'hui, il n'y a que Sympa dans ce cas. DKIM y a été introduit dans la version 6.1. Quelqu'un connaît d'autres implémentations ?

Un bon article de fond en français sur la coexistence entre DKIM et les listes de diffusion est l'article de Serge Aumont aux JRES, « DKIM et les listes de diffusion ». Sinon, concernant les modifications d'en-tête par les MLM, un article toujours utile, quoique centré sur les modifications du Reply-To:, est « "Reply-To" Munging Considered Harmful ».

Merci à Serge Aumont pour sa relecture.


Téléchargez le RFC 6377


L'article seul

RFC 6376: DomainKeys Identified Mail (DKIM) Signatures

Date de publication du RFC : Septembre 2011
Auteur(s) du RFC : D. Crocker (Brandenburg InternetWorking), T. Hansen (AT&T Laboratories), M. Kucherawy (Cloudmark)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dkim
Première rédaction de cet article le 22 septembre 2011


Le courrier électronique, on le sait, n'offre, en natif, aucun mécanisme d'authentification des utilisateurs. Il est donc assez facile d'envoyer un courrier prétendant venir de Bill.Gates@microsoft.com. DKIM, spécifié dans notre RFC, est la dernière tentative de combler ce manque. (La première version de DKIM était normalisée dans le RFC 4871. Cette nouvelle version n'apporte pas de changements cruciaux.)

Notons d'abord que, si le courrier électronique, tel que décrit dans les RFC 5321 ou RFC 5322, ou bien leurs prédécesseurs, n'offre pas d'authentification des utilisateurs, ce n'est pas parce que leurs concepteurs étaient imprévoyants ou trop confiants dans la nature humaine. C'est tout simplement parce que le problème est très complexe, ne serait-ce que parce qu'il n'existe pas de fournisseur d'identité unique sur Internet, qui pourrait jouer le rôle que joue l'État avec les papiers d'identité.

Mais l'absence d'authentification devient de plus en plus regrettable, d'autant plus qu'elle est activement exploitée par les spammeurs et les phisheurs pour leurs entreprises malhonnêtes. Non seulement il est difficile de retrouver le véritable envoyeur d'un message, mais une personne tout à fait innocente peut voir son identité usurpée. Ces problèmes de sécurité sont documentés dans le RFC 4686.

De nombreuses tentatives ont eu lieu pour tenter de traiter ce problème. Certaines ont connu un déploiement non négligeable comme PGP (normalisé dans le RFC 4880), surtout connu pour ses services de chiffrement mais qui peut aussi servir à l'authentification.

PGP est surtout utilisé dans des environnements à forte composante technique, au sein de groupes d'experts qui se connaissent. D'autres protocoles ont tenté de traiter le problème de l'authentification de la masse d'utilisateurs de Hotmail ou de Wanadoo.

SPF (normalisé dans le RFC 7208) a été condamné par l'hostilité de la plupart des gros acteurs.

DKIM aborde le problème différemment. Comme SPF, il vise surtout à authentifier le domaine dans l'adresse électronique, en d'autres termes à garantir que le courrier vient bien de microsoft.com, laissant à Microsoft le soin de dire si la partie gauche (Bill.Gates) est authentique ou pas. En deux mots, DKIM permet à un domaine de proclamer qu'il a une part de responsabilité dans un message, et donc que ce domaine peut répondre dudit message. On trouve une introduction générale à DKIM dans le RFC 5585 et une réfutation de beaucoup d'erreurs à propos de DKIM en « The truth about: Trust and DKIM ».

Mais, contrairement à SPF, DKIM ne procède pas par énumération des adresses IP des MTA autorisés à émettre du courrier pour le compte d'un domaine mais par signature cryptographique.

Le principe de DKIM est le suivant (les exemples sont tirés de l'excellente annexe A du RFC). Un message émis ressemble à :

   From: Joe SixPack <joe@football.example.com>
   To: Suzie Q <suzie@shopping.example.net>
   Subject: Is dinner ready?
   Date: Fri, 11 Jul 2003 21:00:37 -0700 (PDT)
   Message-ID: <20030712040037.46341.5F8J@football.example.com>

   Hi.

   We lost the game. Are you hungry yet?

   Joe.

DKIM (qui peut être installé dans le MUA mais sera en général plutôt dans le MTA, cf. section 2.1 et annexe B) le signe et ajoute un en-tête DKIM-Signature (section 3.5 pour sa syntaxe) :

   DKIM-Signature: v=1; a=rsa-sha256; s=brisbane; d=example.com;
         c=simple/simple; q=dns/txt; i=joe@football.example.com;
         h=Received : From : To : Subject : Date : Message-ID;
         bh=2jUSOH9NhtVGCQWNr9BrIAPreKQjO6Sn7XIkfJVOzv8=;
         b=AuUoFEfDxTDkHlLXSZEpZj79LICEps6eda7W3deTVFOk4yAUoqOB
           4nujc7YopdG5dWLSdNg6xNAZpOPr+kHxt1IrE+NahM6L/LbvaHut
           KVdkLLkpVaVVQPzeRDI009SO2Il5Lu7rDNH6mZckBdrIx0orEtZV
           4bmp/YzhwvcubU4=;
   Received: from client1.football.example.com  [192.0.2.1]
         by submitserver.example.com with SUBMISSION;
         Fri, 11 Jul 2003 21:01:54 -0700 (PDT)
   From: Joe SixPack <joe@football.example.com>
   To: Suzie Q <suzie@shopping.example.net>
   Subject: Is dinner ready?
   Date: Fri, 11 Jul 2003 21:00:37 -0700 (PDT)
   Message-ID: <20030712040037.46341.5F8J@football.example.com>

   Hi.

   We lost the game. Are you hungry yet?

   Joe.

L'en-tête en question spécifie l'algorithme de chiffrement utilisé (ici SHA-256 et RSA), le domaine signant (ici example.com), un sélecteur (ici brisbane) qui servira à sélectionner la bonne clé (section 3.1), les en-têtes effectivement signés (ici Received : From : To : Subject : Date : Message-ID, cf. la section 5.4 sur le choix des en-têtes à signer), la signature elle-même et l'identité de l'émetteur (ici joe@football.example.com). (La différence entre le domaine, identifié par d= et l'« identité » indiquée par i= est subtile.)

L'identité est indiquée dans la signature pour éviter les longs débats sur l'identité la plus pertinente parmi toutes celles présentes dans un message (cf. le RFC 4407 pour un des exemples d'algorithme qui croit naïvement qu'il existe une et une seule bonne identité). Le signeur n'est donc pas forcément l'émetteur (section 1.2). Notre RFC note que le MUA doit en tenir compte et doit afficher l'adresse qui est authentifiée, pas seulement celle qui se trouve dans le champ From: et qui peut être différente.

Le programme qui veut vérifier la signature (en général un MTA mais cela peut être le MUA) va devoir récupérer la clé de signature. DKIM ne souhaitant pas dépendre des lourdes et chères autorités de certification, la clé est récupérée via le DNS (section 3.6.2 ; d'autres méthodes que le DNS sont en cours de normalisation mais ça n'avance pas). Pour le message ci-dessus, la requête DNS sera brisbane._domainkey.example.com et un enregistrement DNS de type TXT contiendra la clé. Pour voir une clé réelle, vous pouvez taper dig TXT beta._domainkey.gmail.com. ou dig TXT ietf1._domainkey.ietf.org. DKIM n'impose pas d'utiliser DNSSEC et la sécurité de la clé ainsi ramassée peut être faible (cf. section 8.5 : DKIM ne prétend pas être aussi fort que PGP).

Un des problèmes difficiles en cryptographie est que les messages sont souvent modifiés en cours de route. Par exemple, un logiciel imposé par le direction de l'entreprise va ajouter automatiquement un stupide message pseudo-légal comme « Ce message e-mail et les pièces jointes sont transmis à l'intention exclusive de ses destinataires et sont confidentiels et/ou soumis au secret professionnel. Si vous recevez ce message par erreur, merci de le détruire et d'en avertir immédiatement l'expéditeur par téléphone ou par mail. Toute utilisation de ce message non conforme à sa destination, toute diffusion ou toute publication, totale ou partielle, est interdite, sauf autorisation. L'intégrité de ce message n'étant pas assurée sur Internet, nous ne pouvons être tenu responsables de son contenu. » (notons que le dernier point devient faux avec DKIM). Ou bien une liste de diffusion va mettre des instructions de désabonnement (pour ces listes, voir aussi le RFC 6377). DKIM traite ces problèmes avec deux méthodes : une canonicalisation (section 3.4 du RFC) du message (plusieurs algorithmes sont disponibles, plus ou moins violents) pour limiter les risques qu'une modification triviale ne fausse le calcul de la signature et l'option l= qui permet d'indiquer sur quelle distance le message est signé. Si on indique l=1000, seuls les mille premiers octets seront signés et une liste pourra ajouter un message automatiquement à la fin, cela n'invalidera pas la signature. (Cette technique est déconseillée, voir la section 8.2.)

Malheureusement, DKIM encourage également (section 5.3) à remplacer les caractères codés sur 8 bits (comme l'UTF-8 ou le Latin-1) par des horreurs comme le Quoted-Printable, pour limiter les risques qu'une conversion automatique en Quoted-Printable, comme le font certains MTA, n'invalide la signature. Des années d'efforts pour faire passer les caractères 8-bits dans le courrier sont ainsi négligées.

DKIM a nécessité la création de plusieurs registres à l'IANA (section 7) comme le registre des méthodes pour récupérer la clé (aujourd'hui, seulement le DNS).

Parmi les limites de DKIM (qui sont celles de beaucoup de solutions de sécurité, un domaine complexe où il faut faire beaucoup de compromis), il faut aussi se rappeler qu'un attaquant actif peut tout simplement retirer complètement une signature. Tant que les domaines ne publient pas leur politique de sécurité (en suivant le RFC 5617) et donc annoncent « Nous signons toujours », cette attaque passera inaperçue.

Quels sont les changements depuis la première version de DKIM, normalisée dans le RFC 4871 ? L'annexe E les résume. Premier point, les changements sont mineurs : comme le note l'annexe C.2, les anciennes et nouvelles implémentations de DKIM peuvent communiquer sans problèmes. Mais la sortie de ce nouveau RFC ne s'est pas faite sans mal. Il y avait des désaccords sérieux sur l'avis à donner en terme de quels en-têtes devraient être signés, sur le lien entre le domaine signant et les autres domaines de l'en-tête (typiquement celui dans le from:), la façon de traiter les attaques par ajout d'en-têtes (non couverts par la signature originale), etc. Beaucoup d'erreurs ont été détectées dans le RFC 4871 et corrigées ici, la plus grosse étant celle qui avait fait l'objet d'une mise à jour d'urgence dans le RFC 5672, désormais inutile. D'autre part, le nouveau RFC comporte davantage de texte d'introduction et d'architecture. Enfin, l'option de signature g= (qui contrôlait la granularité de la clé) a été abandonnée. Il y a aussi une différence complète entre les deux RFC, en ligne.

Aujourd'hui, tous les messages sortant de Gmail sont signés avec DKIM et des implémentations de DKIM existent pour plusieurs logiciels (comme le DKIM milter de sendmail). Le rapport d'implémentation du RFC 4871 en donne une bonne liste. Mais peu de domaines signent et encore moins de domaines vérifient les signatures aujourd'hui (le RFC 5863 discute les questions de déploiement).

Enfin, notons que DKIM est une technologie d'authentification, pas d'autorisation. Cette distinction est cruciale. DKIM peut prouver que le message vient bien de Nicolas.Sarkozy@elysee.fr (plus exactement, DKIM peut dire que le message a bien été approuvé par elysee.fr), il ne peut pas dire si la personne en question est digne de confiance ou si elle va réellement se préoccuper de « la France qui se lève tôt ».


Téléchargez le RFC 6376


L'article seul

RFC 6369: ForCES Implementation Experience Draft

Date de publication du RFC : Septembre 2011
Auteur(s) du RFC : E. Haleplidis, O. Koufopavlou, S. Denazis (University of Patras)
Pour information
Première rédaction de cet article le 21 septembre 2011


Le protocole ForCES (Forwarding and Control Element Separation) sert à la communication entre les éléments d'un même routeur. Il permet à la « tête » du routeur (le CE Control Element) de donner des instructions aux « jambes » (les FS Forwarding Element), par exemple de dire où envoyer le trafic pour 2001:db8::/32. Le fait que ce protocole soit normalisé pourrait permettre dans le futur d'acheter des routeurs en plusieurs parties, par exemple un PC avec du logiciel libre pour le CE et des ASIC matériels spécialisés pour les FE, le tout communiquant dans la joie. Ce RFC fait le court bilan d'une des équipes qui a le plus travaillé à la programmation de ForCES, à l'Université de Patras.

Le cahier des charges de ce système figure dans le RFC 3654. ForCES est normalisé dans le RFC 5810 et son architecture est décrite dans le RFC 3746. Il a déjà fait l'objet de deux rapports d'interopérabilité (dans le RFC 6053 et le RFC 6984), vérifiant que les trois mises en œuvre de ForCES coopéraient correctement. L'une de ces mises en œuvre était celle de l'Université de Patras. Les auteurs de cette implémentation tirent, dans ce nouveau RFC, les leçons de leur expérience, afin qu'elle puisse profiter à d'autres.

Petit rappel de ForCES (section 1) : le CE (Control Element) est la partie intelligente du routeur, celle qui fait tourner les protocoles compliqués comme OSPF. Le FE (Forwarding Element) peut être réalisé en logiciel mais, sur les routeurs haut de gamme, il s'agit plus souvent d'un circuit matériel, puisqu'il doit faire passer des millions de paquets à la seconde. Le LFB (Logical Function Block) est une fonction dans le FE, que le CE contrôle. Par exemple, la fonction « comptage des paquets » (à des fins de surveillance et de statistique) est un LFB. Un LFB fait partie d'une classe, qui a des instances (un routeur a souvent plusieurs exemplaires d'un LFB de chaque classe). Pour décrire un LFB, on utilise le modèle du RFC 5812 et éventuellement la bibliothèque de fonctions du RFC 6956. Le protocole ForCES gouverne la communication entre CE (le maître, qui donne des ordres) et FE (l'esclave, qui obéit). S'il y a des discussions entre CE ou bien entre FE, elles se font en dehors de ForCES. De même, le mécanisme par lequel sont configurés CE et FE n'est pas normalisé. Le protocole ForCES peut être transporté entre FE et CE de diverses manières, mais celle recommandée est le transport du RFC 5811.

Le RFC suit l'architecture de ForCES (section 3). La configuration initiale du FE et du CE (non spécifié par ForCES) doit permettre de fixer l'identificateur de chaque élément, le transport utilisé et l'adresse IP (si le transport se fait sur IP).

Le transport standard de ForCES, normalisé dans le RFC 5811, utilise SCTP. Lors des tests d'interopérabilité, ce transport avait même été utilisé entre un site en Chine et un en Grèce mais, évidemment, dans un routeur réel, les distances sont moins longues. (Comme ForCES permet de séparer FE et CE, ils ne sont pas forcément dans la même boîte, et il peut même y avoir des choses bizarres, comme un pare-feu entre eux.) Bien moins connu que son concurrent TCP, SCTP pose un problème au programmeur : les bibliothèques existantes ne permettent pas toujours de l'utiliser simplement. La section 4 contient un tableau des disponibilités pour C, C++ et Java. Par exemple, pour Java sur Windows, il n'y a pas grand'chose à attendre. (Les auteurs ont également eu des difficultés avec un autre problème Java, la gestion des types non signés, pour laquelle ils recommandent Java Unsigned Types.)

Le protocole n'est pas trivial à programmer. En effet, la liste des classes de LFB possibles n'est pas figée. De nouveaux LFB peuvent apparaître à tout moment. En outre, un message peut comporter plusieurs opérations, et plusieurs LFB par opération. C'est bien sûr une... force du protocole (il est très puissant et complet) mais cela le rend plus complexe. Il est donc très difficile de créer du code générique, capable de traiter tous les messages. C'est sans doute la principale difficulté que rencontre l'implémenteur de ForCES. La section 3.4 fournit des pistes possibles, ainsi que des algorithmes d'encodage et de décodage des messages. Les informations dans le message pouvant être emboîtées, l'utilisation de la récursion est recommandée.


Téléchargez le RFC 6369


L'article seul

RFC 6366: Requirements for an Internet Audio Codec

Date de publication du RFC : Août 2011
Auteur(s) du RFC : JM. Valin (Mozilla), K. Vos (Skype Technologies)
Pour information
Réalisé dans le cadre du groupe de travail IETF codec
Première rédaction de cet article le 7 septembre 2011


Début 2010, l'IETF avait lancé un travail pour la normalisation d'un codec libre pour l'Internet, c'est-à-dire qui ne serait pas plombé par des brevets ou autres appropriations intellectuelles et pourrait donc être utilisé par n'importe quel protocole Internet. Ce RFC est le premier produit par le groupe de travail, et contient le cahier des charges du futur codec (qui a finalement été publié dans le RFC 6716).

Comme toujours avec ce groupe de travail, cela n'a pas été sans mal. Par exemple, le RFC mentionne des codecs « à battre », c'est-à-dire où le nouveau codec doit être meilleur que ceux-ci, pour être pris en considération. Certains demandaient que les codecs à battre soient uniquement ceux qui sont déjà à peu près libres, d'autres voulaient qu'on compare le nouveau codec avec tous ses concurrents, même plombés. Vue la difficulté de la tâche technique, une telle comparaison aurait sérieusement menacé le projet. Finalement, les codecs libres ont été pris comme référence, mais avec mention des autres, en demandant que, à défaut de les battre, le nouveau codec ne soit pas trop pire qu'eux (section 5.2).

Le but est donc d'avoir un codec libre pour les applications Internet, comme la téléphonie sur IP, la téléconférence, l'exécution de musique en temps réel (concert où les musiciens ne sont pas au même endroit), etc. La section 3 liste, pour chaque application envisagée, ses caractéristiques propres. Car certaines applications sont bien plus exigeantes que les autres. Commençons par l'ordinaire téléphonie à deux. Un codec à large bande (16 kHz) est nécessaire, mais le cahier des charges ajoute la possibilité de fonctionner avec seulement 8 kHz, par exemple pour les vieux téléphones. En large bande, la consommation de capacité réseau attendue va de 12 à 32 kb/s. La latence imposée par le codec doit rester inférieure à 40 ms, mais 25 ms sont souhaitées. (Pour des détails sur les bandes et les latences, voir la section 5.1 du RFC.) Pas besoin d'être haute-fidélité, encore que le RFC note que le codec ne doit pas massacrer les musiques d'attente au point de les rendre désagréables.

Plus exigeantes, la conférence (ou le bavardage en temps réel entre joueurs d'une même partie), où plusieur voix se mêlent. Comme ces applications ont en général davantage de capacité réseau, le codec doit cette fois fonctionner à plus de 24 kHz, pour un débit de 32 à 64 kb/s. Comme les participants à une conférence ont souvent les mains occupées par autre chose et ne tiennent pas le téléphone près de la bouche ou de l'oreille, les problèmes d'écho sont plus sévères qu'en conversation à deux. La latence doit donc être encore plus basse (moins de 30 ms, avec le souhait de descendre à 10), car elle influence la qualité de la suppression d'écho.

Mais, surtout, un système de conférence va mixer les voix de plusieurs participants. Le codec ne doit donc pas gêner le mixage.

Les applications dites de téléprésence sont encore plus demandeuses en terme de qualité, pour arriver à reproduire quelque chose qui ressemble à la présence physique.

Encore plus dur pour un codec, la téléopération (commande d'un robot à distance, par exemple). Si le retour d'information est par la voix (l'opérateur entend ce qui se passe près du robot), une très faible latence est nécessaire.

Et la diffusion de musique en train d'être jouée par plusieurs musiciens ? Des mesures faites avec des musiciens imposent une latence totale de moins de 25 ms (50 si on est prêt à accepter de sérieux problèmes de synchronisation dans l'orchestre). Compte tenu de la latence des autres composants (à commencer par le réseau), cela contraint la latence propre au codec à rester en dessous de 10 ms. Chaque milli-seconde gagnée dans le codec nous donne 200 km de distance en plus, compte-tenu de la vitesse de la lumière dans la silice de la fibre optique. On peut avoir un concert où les musiciens sont dans le même pays, mais pas s'ils sont dispersés aux quatres coins du monde. Et, pour cette application, il faut évidemment une grande qualité, donc un débit soutenu (facilement 128 kb/s).

Il y a bien sûr d'innombrables autres applications où un codec audio est utile mais ce tour d'horizon couvre bien les exigences essentielles.

Le futur codec est conçu avant tout pour être utilisé sur l'Internet. Il s'agit d'un environnement difficile pour un codec audio. La section 4 du RFC liste les contraintes qui découlent de cet environnement. D'abord, les pertes de paquets sont un phénomène normal sur l'Internet et le codec doit y réagir proprement (voir section 5.3). Notamment, lorsque les paquets recommencent à arriver après une ou plusieurs pertes :

  • Il faut que le codec puisse lire les paquets, sans avoir besoin d'informations contenues dans les paquets précédents (qui sont perdus), comme demandé par le RFC 2736,
  • Il faut que le décodeur puisse se resynchroniser rapidement.

Cela implique que la taille d'un paquet soit inférieure à la MTU (pour éviter la fragmentation : la perte d'un des fragments entraîne celle du paquet original tout entier), et qu'il n'y ait pas d'information implicite, car contenue dans un paquet précédent. Par exemple, si on change les paramètres d'encodage, les paquets suivants ne doivent pas considérer que le changement a été reçu : il pouvait être dans le paquet perdu. Les paramètres permettant le décodage doivent donc être dans chaque paquet (ou pouvoir être récupérés rapidement).

Cela n'interdit pas au décodeur de faire des prédictions sur les paquets suivants mais il doit pouvoir les corriger rapidement en cas de pertes. En gros, un codec résistant aux pertes de paquet doit être conçu comme un compromis entre l'efficacité (qui pousse à ne pas répéter les informations et à faire de chaque paquet un delta du précédent) et la robustesse (qui pousse à faire des paquets autonomes, pouvant être interprétés même si on a perdu les précédents).

Autre particularité de l'Internet, c'est un réseau qui fait « au mieux », et qui ne garantit pas la capacité réseau disponible. Le codec doit donc s'ajuster dynamiquement (augmentant et diminuant son débit), sans que cela ne s'entende après le décodage.

Les protocoles de la famille TCP/IP fournissent des mécanismes qui peuvent aider le codec à prendre ses décisions, comme l'ECN du RFC 3168, et il est donc recommandé des les utiliser.

Enfin, le nouveau codec arrivera dans un monde où il existe déjà des protocoles applicatifs qui ont besoin de lui, et il devra donc s'interfacer gentiment avec ces protocoles comme RTP (RFC 3550 et RFC 2736). Si le codec nécessite de négocier des paramètres entre les deux machines qui communiquent, cette négociation devra utiliser les protocoles de signalisation existants comme SDP (RFC 3261 et RFC 4566) dans le cas de SIP, et Jingle (XEP-O167) dans le cas de XMPP.

La section 5 en vient aux exigences détaillées. Le but est que le rapport entre la qualité du son et le débit utilisé soit meilleur qu'avec les codecs existants comme Speex, iLBC (RFC 3951) et G.722.1 (norme UIT du même nom). Ces trois codecs sont a priori implémentables sans payer de royalties mais seul Speex est vraiment libre et c'est donc le seul que le nouveau codec doit battre. En outre, il serait souhaitable que le nouveau codec fasse ex-aequo avec AMR-NB en bande étroite (8 à 16 kb/s) et AMR-WB en bande large (12 à 32 kb/s). Cette qualité doit être mesurée pour plusieurs langues, y compris les langues à tons pour lesquelles une bonne qualité de son est impérative.

À noter que la seule exigence est de faire mieux que ces codecs : le RFC ne demande aucune interopérabilité avec eux (section 6.10).

Concernant la résistance aux pertes de paquets, le codev devra bien se comporter jusqu'à 5 % de pertes et la voix rester compréhensible jusqu'à 15 % de pertes. Comme la qualité ne dépend pas que du pourcentage global de pertes, mais aussi de leur répartition (continue ou au contraire en brusques trous noirs), la qualité devra être évaluée avec des traces réelles, et avec des répartitions de pertes telles qu'on les observe dans un accès ADSL typique.

Les codecs peuvent être gourmands en ressources machines, par exemple exiger un processeur très rapide. Or, il devra être mis en œuvre sur une grande variété de machines (de l'ordinateur généraliste au petit téléphone), qui ne disposeront parfois pas de FPU et dont les éventuels DSP auront des caractéristiques très différentes. Le RFC demande donc que le codec puisse être implémentable en virgule fixe. Du point de vue quantitatif, notre RFC exige une limite à la consommation de processeur. Pour un x86 récent, l'encodage et le décodage d'un signal en mono ne devrait prendre que 40 MHz en bande étroite (soit 2 % du temps d'un cœur à 2 Hz), et 200 MHz en très large bande. Ces chiffres peuvent paraître bas mais il faut se rappeler que le codec va aussi tourner sur des machines dont le processeur est bien plus lent que celui du PC de bureau typique.

Il est facile d'ammonceler dans un cahier des charges des exigences irréalistes, et ensuite de laisser les pauvres implémenteurs se débrouiller. Ce problème est fréquent dans les SDO où les participants à la normalisation sont des bureaucrates et des politiciens qui ne feront pas le travail de mise en œuvre eux-mêmes. L'IETF se méfie traditionnellement de ce risque et une des méthodes utilisées pour s'en préserver est l'implémentation de référence, une mise en œuvre du logiciel réalisée pour s'assurer que c'est possible, et qui est souvent publiée en même temps que le RFC. Notre RFC encadre cette implémentation de référence du futur codec en lui interdisant de tirer profit de fonctions spécifiques de tel ou tel matériel : elle doit être le plus portable possible. Par exemple, le RFC interdit de dépendre de l'arithmétique saturée, pour pouvoir tourner sur les processeurs qui n'ont pas cette fonction comme certains ARM. Par contre, les « vraies » implémentations, elles, auront tout intérêt à exploiter à fond les particularités du matériel sur lesquelles elles tournent.

Outre la consommation de processeur, le nouveau codec ne doit pas être trop encombrant en mémoire (code et données), pour pouvoir être lancé sur des systèmes embarqués. Pour les données (l'état à garder en mémoire pour faire fonctionner le codec), le RFC met une limite à 2*R*C octets, où R est le taux d'échantillonage et C le nombre de canaux.

Et ce n'est qu'une petite partie des problèmes auxquels un codec sur l'Internet fait face. La section 6 charge la barque avec diverses considérations et des souhaits (les exigences précédentes étaient considérées comme impératives). Par exemple, s'il y a mixage (pour une téléconférence, par exemple), il serait bien de limiter le coût de l'opération. L'implémentation naïve du mixage est de décoder tous les flux audios, les mélanger et réencoder le résultat. Une approche où un décodage complet ne soit pas nécessaire est souhaitée. Autre souhait : un bon support de la stéréo, là encore en évitant l'approche naïve, qui consiste à encoder séparement les deux canaux. Comme ceux-ci ont probablement beaucoup de redondances, cette propriété devrait être utilisée pour limiter le débit utilisé. Il serait également très bien de gérer les erreurs dans les paquets (bits dont la valeur a changé). La plupart des applications Internet ne le font pas car le phénomène est rare. En général, un paquet arrive intact ou n'arrive pas. Mais des transformations non désirées se produisent parfois (avec des protocoles comme UDP Lite, il n'y a pas de somme de contrôle, cf. RFC 3828) et le RFC demande que la question soit étudiée, en insistant que, dans tous les cas, c'est la robustesse du codec aux pertes de paquets qui est prioritaire.

Plus rigolo, et pour les amateurs de polars, la section 6.9 demande que le codec n'élimine pas et ne dégrade pas le bruit de fond des appels : ce bruit peut servir à identifier l'origine d'un appel, et, dans le cas d'appels au 112, cela peut être crucial. Un bon exemple figure dans le génial film de Kurosawa, « Entre le ciel et l'enfer », où policiers et employés du tramway arrivent à reconnaître près de quelle ligne de tramway se trouve le criminel qui appelle, juste en écoutant le bruit de fond, et en remarquant un léger bruit, caractéristique d'un endroit où le câble est abîmé par un accident récent. (Les cinéphiles savent qu'il y a un exemple plus léger dans « La double vie de Véronique ».)

Restent les traditionnelles questions de sécurité : la section 7 rappelle l'évidence (le décodeur doit faire attention aux attaques par débordement de tampons) mais aussi l'importance d'avoir une consommation de ressources bornée : quels que soient les paquets entrants, le temps de processeur utilisé et la mémoire consommée ne doivent pas croître sans limites (autrement, une DoS serait possible en envoyant des paquets créés pour cela).

Plus subtil, le problème de la fuite d'informations lorsque la communication est normalement protégée par du chiffrement. Des attaques ont déjà été décrites où des informations importantes sur la conversation pouvaient être extraites d'un flux audio chiffré (« Spot me if you can: Uncovering spoken phrases in encrypted VoIP conversations » et « Phonotactic Reconstruction of Encrypted VoIP Conversations: Hookt on fon-iks »). Le codec peut compliquer certaines de ces attaques, par exemple en ayant un mode où le débit est constant, quelle que soit la conversation.

Le codec choisi, Opus, a finalement été normalisé dans le RFC 6716 en septembre 2012.


Téléchargez le RFC 6366


L'article seul

RFC 6365: Terminology Used in Internationalization in the IETF

Date de publication du RFC : Septembre 2011
Auteur(s) du RFC : P. Hoffman (VPN Consortium), J. Klensin
Réalisé dans le cadre du groupe de travail IETF appsawg
Première rédaction de cet article le 12 septembre 2011


L'internationalisation des protocoles développés par l'IETF est depuis quinze ans un des sujets chauds de cette organisation. Réussir à rendre tous les protocoles Internet adaptés aux différentes langues, écritures et cultures nécessite d'avoir un socle linguistique commun et c'est le rôle de ce RFC, qui décrit la terminologie en usage à l'IETF. Il remplace le RFC 3536 dans le rôle du texte « l'internationalisation pour les débutants ». Le texte est long car le sujet est complexe.

Cette terminologie est d'autant plus importante que les discussions sur le sujet sont souvent victimes d'un vocabulaire flou et mal utilisé. Ainsi, on voit parfois apparaître le terme de « caractère latin » sans que celui-ci soit bien défini. Seulement ASCII ou bien également les caractères composés, utilisés par exemple en français ? Autre exemple, à l'ICANN, les discussions sur les IDN sont souvent rendues incompréhensibles par une confusion fréquente entre des concepts aussi différents que « langue » et « écriture ». Si vous lisez dans un article ou un rapport des termes absurdes comme « noms de domaines multilingues », faites lire ce RFC 6365 à l'auteur de ce texte, il en a besoin...

Ce RFC est en anglais et fixe une terminologie anglophone. Dans mon article, je vais donner le terme anglais défini et la traduction française que j'utilise (sans consulter les normes officielles, qui ne sont pas toujours de grande qualité et souvent faites par des gens qui ignorent le domaine). Mais le lecteur doit bien être conscient du fait qu'il n'existe pas forcément de terminologie standard en français. Même en anglais, le consensus est loin d'exister sur tous ces termes, et le caractère ultra-sensible des questions de langue n'arrange rien.

Petit rappel de l'objectif poursuivi, en section 1 : comme le dit le RFC 2277, document fondateur, l'internationalisation concerne les humains, pas les protocoles. On ne va donc pas traduire le GET de HTTP. Par contre, lorsqu'un protocole manipule des chaînes de caractères qui vont être lues ou écrites par des humains, il faut que cela soit possible quelle que soit la langue ou l'écriture utilisée. Cette politique de l'IETF est donc différente de celle, qu'on entend souvent à l'ICANN, comme quoi tout le monde n'a qu'à parler anglais, langue internationale de toute façon.

Avoir un vocabulaire commun est évidemment essentiel pour les discussions au sein de l'IETF, et pour la qualité et l'homogénéité des documents produits (les RFC). Ce RFC 6365 sert aussi de tutoriel sur l'internationalisation en expliquant les concepts de base aux membres de l'IETF, un public d'ingénieurs qui n'est pas forcément très sensible à cette question. Notre RFC rappelle ainsi que, dans beaucoup de groupes de travail de l'IETF, lorsque quelqu'un soulève la question de l'internationalisation du protocole en cours de développement, les réponses « faut-il vraiment s'en préoccuper ? » sont souvent nombreuses. Il y a donc un certain fossé à combler.

Voyons maintenant les définitions générales (section 2). Le RFC ne pouvait pas tout couvrir et un des plus grands débats dans le groupe avait été l'étendue de la liste des termes à définir. Le choix a été fait de se restreindre, pour augmenter la probabilité que les non-spécialistes de l'internationalisation lisent le texte. Je ne reprends ici qu'une partie des termes, ceux que je trouve indispensables, ou bien dont la définition est mal connue.

Une langue (language) est une façon de communiquer entre humains, notamment par la parole ou l'écriture. Lorsqu'une forme écrite et une forme parlée existent pour une langue, elles sont parfois très proches... et parfois très distantes. Ce terme n'inclus pas les langages de programmation.

Une écriture (script) est un ensemble de caractères graphiques qui sont utilisés pour la forme écrite d'une ou de plusieurs langues. C'est le cas de l'écriture latine, cyrillique, arabe (attention dans ce cas, arabe est également le nom d'une langue) et han. L'IETF s'occupant surtout de l'écrit (la langue parlée peut être transmise par des protocoles comme RTP mais elle n'est typiquement pas interprétée par ces protocoles), presque toujours, les protocoles IETF s'occupent d'écritures, pas de langues. C'est ainsi que les IDN sont des noms de domaines multi-écritures et surtout pas multilingues. (Le RFC note explicitement que « multilingue » est un de ces termes flous et passe-partout, qu'il faut éviter.)

(La définition de l'internationalisation dans notre RFC est d'ailleurs modeste, « permettre ou améliorer l'utilisation de caractères non-ASCII dans les protocoles IETF », par rapport celle du W3C, plus ambitieuse, « permettre l'adaptation facile à n'importe quelle langue, écriture ou culture ».)

La relation entre les langues et les écritures est complexe : il y a beaucoup moins d'écritures que de langues et la plupart des écritures peuvent servir à plusieurs langues. D'autre part, si certaines langues n'ont jamais été écrites qu'avec une seule écriture (le français avec l'écriture latine, le russe avec la cyrillique), d'autres ont changé, comme le turc ou le vietnamien. L'effondrement de l'URSS a eu entre autres pour conséquence l'abandon du cyrillique par plusieurs langues comme le mongol. Autre exemple, le malais est passé récemment (et la transition n'est pas terminée) du jawi à l'alphabet latin.

On voit parfois le terme alphabet pour désigner une écriture mais, comme toutes ne sont pas alphabétiques (cf. section 4.1), ce terme est plutôt à éviter.

Un système d'écriture (writing system) est un ensemble de règles pour utiliser une écriture dans le cas d'un langage donné. Ainsi, le français et l'anglais utilisent la même écriture, mais avec des règles différentes (par exemple pour la ponctuation).

Un caractère (character) est un membre de l'ensemble des éléments qui servent à représenter les données écrites. Le terme est plus flou qu'il n'y parait car il existe des tas de cas qui défient la classification comme le digramme « ll » du catalan. En anglais, les informaticiens disent souvent char au lieu de character, vu que c'est le type de données utilisé dans plusieurs langages de programmation. En tout cas, un caractère n'est pas une représentation graphique, un glyphe. Par exemple, il n'y a qu'un seul caractère A alors qu'il en existe de nombreuses représentations possibles (il y a un excellent article sur ce sujet dans le livre de Hofstadter, « Metamagical Themas »).

En parlant de glyphe, sa définition dans le RFC est « l'image d'un caractère rendue sur une surface ». On aura donc un glyphe différent si on affiche avec une résolution différente. Unicode a une autre définition, basée plutôt sur l'encodage d'une police particulière, et où le glyphe est donc le même quel que soit le périphérique de sortie. Dans la définition d'Unicode, chaque glyphe a un code de glyphe, qui est un index dans une police donnée (et qui n'est pas standard : deux auteurs de polices peuvent utiliser des codes de glyphes différents).

Un jeu de caractères (repertoire) est simplement un ensemble de caractères, rigoureusement défini (c'est par exemple à ce stade qu'on décide si œ est un seul caractère ou deux).

Un jeu de caractères codé (Coded Character Set, CCS) est un ensemble de règles qui définissent un jeu de caractères et une représentation codée (typiquement, par un nombre entier unique par caractère). Unicode ou ISO-8859-6 définissent un CCS.

L'encodage (character encoding scheme) est la représentation en machine des caractères, c'est-à-dire la définition de quelle chaîne de bits représente tel caractère. Si des normes comme ISO 8859 ne définissent qu'un seul encodage possible, Unicode en a plusieurs (le plus connu étant UTF-8, qui est le protocole par défaut dans l'Internet, cf. RFC 2277).

Le transcodage (transcoding) est la traduction d'un encodage dans un autre, comme le font les outils Unix iconv ou recode.

Je laisse en anglais le terme charset car il est purement technique et n'est pas la même chose qu'un jeu de caractères tel que défini plus haut. Ce terme de charset est très utilisé dans les normes IETF (notamment MIME) et les charsets peuvent être enregistrés dans un registre IANA selon les règles du RFC 2978. Un charset est un moyen de passer d'une séquence d'octets à une chaîne de caractères abstraits. C'est donc la combinaison d'un jeu de caractères codé et d'un encodage. charset doit être considéré comme un mot-clé, à utiliser sans regarder de trop près son étymologie, et le RFC déconseille notamment de le remplacer par character set, qui peut avoir d'autres définitions en anglais. On va donc dire que charset est un néologisme spécifique à l'IETF.

La section suivante, la 3, liste les organismes de normalisation qui ont à voir avec l'internationalisation (ou plutôt une partie d'entre eux). Par exemple, l'ISO a une norme de jeu de caractères, ISO 10646, qui fait même partie des rares normes ISO disponibles gratuitement en ligne (dans sa version anglaise, uniquement, et après acceptation d'un long texte juridique menaçant, c'est pour cela que je ne mets pas de lien ici). Cette norme est synchronisée avec Unicode et il n'y a donc pas de raison de la lire, Unicode offre davantage de choses. Le groupe de travail SC2/WG2 qui produit la norme ISO a un site Web qui donne des aperçus du travail en cours.

D'autres normes ISO ont un rapport direct avec l'internationalisation comme ISO 639 qui gère un catalogue de langues, avec des codes alphabétiques (comme fr pour le français) ou ISO 3166 qui gère une liste de pays, avec leurs codes (comme fr pour la France). Ces normes forment la base des étiquettes de langue (cf. RFC 5646), utilisées par exemple dans le Web pour indiquer la langue d'une page.

Le consortium Unicode est un autre organisme de normalisation, qui gère le jeu de caractères du même nom, ainsi qu'un certain nombre de travaux qui lui sont liés, comme la définition d'expressions rationnelles pour Unicode. On l'a vu, Unicode et ISO 10646 sont synchronisées et, techniquement, on peut se référer à l'une ou l'autre norme, sans conséquences pratiques. Ce RFC 6535 ne le dit pas mais c'est pour des raisons politiciennes qu'ISO 10646 était plus souvent cité, l'ISO, organisation privée, tout comme le consortium Unicode, étant parfois considérée par certains comme plus ouverte (alors que l'essentiel de ses documents n'est pas distribué en ligne).

Le Web est une des applications où l'internationalisation est la plus avancée, ayant été prise en compte pratiquement dès le début. C'est le rôle du W3C, qui gère des normes comme XML (dont le modèle de caractères est Unicode depuis la première version).

Enfin, et c'est important dans le contexte de l'internationalisation, il existe aussi un certain nombres d'organismes nationaux qui ont parfois une activité touchant à ce sujet.

Comme le cœur de l'internationalisation des protocoles est la définition d'un jeu de caractères commun, la section 3.2 liste le vocabulaire spécifique d'Unicode. Il faut par exemple savoir ce que sont UCS-2, UTF-16 et UCS-4/UTF-32, que le BMP (Basic Multilingual Plane) est composé des 65 536 premiers caractères d'Unicode (qui sont traités à part par certains encodages), qu'UTF-8, normalisé dans le RFC 3629, est l'encodage recommandé pour tous les protocoles IETF, mais que l'IETF a un encodage spécifique pour les noms de domaines, Punycode, normalisé dans le RFC 3492. Encodant n'importe quel chaîne Unicode avec uniquement des caractères ASCII, Punycode peut sembler une solution tentante au problème d'internationalisation d'un vieux protocole, mais il vient aussi avec ses propres problèmes (cf. RFC 6055).

On l'a dit, il existe souvent des SDO nationales qui, avant l'avènement d'Unicode, ont souvent développé des jeux de caractères locaux, permettant de représenter les écritures utilisées dans leur pays. La section 3.3 rappelle ainsi que ces jeux de caractères sont encore souvent très utilisés, comme Shift-JIS pour le japonais.

Ce sont ces jeux de caractères, et leurs encodages (dans la plupart des définitions, le jeu de caractères et l'encodage sont intrinsèquement liés ; Unicode est une exception), qui sont enregistrés sous le nom de charsets à l'IANA, dans https://www.iana.org/assignments/character-sets. Cette liste n'est pas connue pour sa grande rigueur : beaucoup de noms ont été ajoutés au pifomètre. Elle ne s'appuie pas toujours sur des normes reconnues.

Le plus connu des charsets est évidemment US-ASCII, historiquement le jeu par défaut de l'Internet, depuis le RFC 20. Sa domination a officiellement pris fin lors de la sortie du RFC 2277, qui le remplaçait comme charset par défaut par son sur-ensemble UTF-8. À noter que la norme ASCII originale était uniquement un jeu de caractères, et que le terme « ASCII » utilisé à l'IETF lui ajoute un encodage spécifique aux protocoles Internet (champ de huit bits, le bit de plus fort poids toujours à zéro, les sept autres stockant le code ASCII) qui n'a été formellement décrit qu'avec le RFC 5198, bien plus tard...

Ces histoires de caractères font surgir plein d'autres problèmes de terminologie. D'où la section 4, qui lui est consacrée. Ainsi, un point de code (code point) est le numéro que la plupart des normes attribuent à chaque caractère, pour le référencer sans ambiguité. C'est en général un nombre entier strictement positif mais, dans la norme ASCII originale, c'était un couple de nombres, identifiant la ligne et la colonne d'une table. « A » était ainsi 4/1 (ligne 4, colonne 1), en ASCII, alors qu'il est 65 en décimal et U+0041 en Unicode.

Et connaissez-vous les caractères combinants (combining characters) ? Il s'agit d'une particularité d'Unicode, qui met en cause la définition typographique de « caractère » puisqu'un caractère combinant se... combine avec son prédécesseur (par exemple, U+0301 est l'accent aigu combinant, donc U+0065 suivi de U+0301 fait un « é »).

Autre concept important pour les chaînes de caractères, la canonicalisation (normalization ; notez que, en anglais, « canonicalization a un sens très précis dans Unicode, et distinct de celui de normalization, qui justifie l'emploi d'un mot séparé). C'est le processus par lequel une chaîne de caractères est mise sous une forme canonique, permettant les comparaisons (autrement, comparer U+00E9 avec U+0065 U+0301 pourrait échouer alors que, dans les deux cas, il s'agit d'un é).

Quant à la casse (case), c'est le fait pour un caractère d'exister en deux formes, une majuscule et une minuscule. Souvent, la correspondance entre les deux formes est un-un (chaque minuscule a une et une seule majuscule, et réciproquement) mais ce n'est pas toujours le cas. Pire, le changement de casse peut dépendre de la langue. Cette dépendance est mise en œuvre, par exemple, en Java et, outre qu'elle est très coûteuse en ressources, elle produit forcément des résultats différents selon la locale (voir section 8 pour ce terme).

Enfin, place au tri (sorting) et au classement (collation). Le classement est le fait de d'ordonner les caractères. C'est un sujet très vaste. Même en ASCII, il existe au moins deux classements distincts (un par les numéros, A, B, C, D..., a, b, c, et un selon l'ordre alphabétique, A, a, B, b, C, c...). En ISO 8859-1, le cas des caractères composés n'est pas traité de manière uniforme car le classement dépend de la langue (comparez un annuaire téléphonique en France et en Suède pour voir où sont placés les noms propres commençant par un caractère composé). Sans connaître la langue, on ne peut pas espérer classer les caractères Unicode d'une manière qui ne surprenne pas l'utilisateur. Quant au tri, c'est le processus effectif de mise des caractères dans l'ordre du classement. Il fait l'objet d'innombrables algorithmes qui ont fait la joie et le malheur de centaines de milliers d'étudiants en programmation.

Même les adjectifs utilisés pour les différents types de caractères ne sont pas toujours connus. La section 4.1 explique par exemple que le terme d'idéogramme ne décrit pas vraiment correctement les écritures comme la chinoise. Si U+260E est bien une icône (☎, un téléphone), beaucoup de caractères chinois sont utilises phonétiquement, sans coder une idée.

En tout cas, en français, une chose est sûre, on ne devrait pas parler de « caractère accentué » pour des signes comme ç qui n'ont pas d'accent. Le terme Unicode de diacritique (diacritic) convient mieux. Et, évidemment, il ne s'agit pas de caractères spéciaux.

Unicode soulève un autre problème intéressant : la liste des caractères est très longue et il est souvent utile d'en définir des sous-ensembles. Mais attention : contrairement à ASCII ou aux ISO 8859, qui étaient statiques, Unicode grossit tout le temps (la dernière version a été la 6). Un sous-ensemble défini en intension comme « toutes les lettres majuscules » grossira donc lui aussi à chaque nouvelle version d'Unicode (une question qu'il a fallu résoudre pour IDN, voir le RFC 5892).

On l'a dit, le but de l'internationalisation est d'aider les humains, de leur rendre la vie plus facile. Il faut donc un peu se pencher sur les interfaces utilisateur, même si celles-ci sont traditionnellement hors de la portée de l'IETF (qui normalise « au dessus du câble et en dessous de l'application »). En effet, certaines caractéristiques des interfaces utilisateur peuvent affecter les protocoles. D'où l'importance d'apprendre quelques nouveaux termes.

Une méthode d'entrée (input method) est un mécanisme qui permet d'envoyer du texte à une application. Le périphérique d'entrée est souvent un clavier mais les claviers ayant des tailles limitées, les différentes méthodes d'entrée fournissent des mécanismes pour saisir d'autres caractères. Le clavier sur lequel je suis en train de taper n'a pas de majuscules avec diacritiques donc, pour faire un É, je tape Compose (touche dite Windows, sur mon clavier) puis E puis ' (le signe sous le 4). Plus complexe, et ayant bien plus de caractères qu'il n'y a de touches sur un clavier, l'écriture chinoise peut être saisie par plusieurs méthodes différentes : taper les sons au clavier, par exemple.

Les protocoles IETF ont bien de la chance : ils n'échangent que des bits, sans se soucier de savoir comment les afficher. Un serveur HTTP, par exemple, n'a aucun besoin de connaître l'écriture arabe ou la chinoise (ou même de comprendre Unicode), il se contente d'envoyer les octets. Mais le navigateur Web, lui, va devoir afficher les textes pour l'utilisateur. Il s'appuie pour cela sur les règles de rendu (rendering rules), qui sont les algorithmes d'affichage du texte à l'écran. Avec certaines écritures, c'est encore relativement simple : chaque caractère est représenté par un glyphe dans une police de caractères et on pousse simplement ce glyphe vers le périphérique de sortie. Mais dans d'autres écritures, il faut modifier le caractère selon le contexte (par exemple, avec l'écriture arabe, selon qu'il est au début ou à la fin de la phrase). Et, bien sûr, une des choses les plus difficiles pour un moteur de rendu, est de gérer le bidi. Comme je l'ai dit, les protocoles IETF n'ont pas besoin de connaître ces subtilités (un serveur HTTP envoie des textes en alphabet arabe comme ceux en alphabet latin : dans l'ordre de saisie). Mais il est bon que leurs concepteurs soient au courant de ce qui attend les logiciels de l'utilisateur.

Après ces définitions indispensables, quelle est la situation actuelle du texte dans les protocoles IETF ? La section 6 étudie la question. Il n'y a pas de règle générale, car certains protocoles IETF étaient internationalisés depuis le début (comme XMPP), d'autres ne l'ont été qu'après un long et pénible processus (cas du courrier électronique, créé sans penser à l'internationalisation et largement déployé, donc difficile à changer, lorsqu'on a voulu l'adapter à un monde vaste et varié).

Il y a donc encore du vocabulaire à apprendre. Ainsi, les éléments de protocole (protocol elements) sont les éléments qui nomment une partie du protocole. Certains ne sont pas textuels, comme les numéros de port dans TCP, d'autres le sont (comme les commandes SMTP, par exemple EHLO et MAIL FROM) mais ne sont pas vus par l'utilisateur et donc, ne sont pas sujets à l'internationalisation (d'ailleurs, EHLO n'est pas de l'anglais non plus...).

Quant à l'encodage sur le câble (on-the-wire encoding), il désigne les bits qui passent effectivement sur le réseau. Cet encodage est souvent très différent de la forme texte que verront les humains.

Mais il ne pose pas de problèmes d'internationalisation, au contraire du texte analysé (parsed text) qui désigne le texte libre qu'un programme va analyser pour essayer d'y trouver des éléments de protocole. Le cas le plus connu est sans doute la convention d'ajouter un Re: (pour Reply) dans le sujet d'un message. Un tel système est clairement très fragile, la localisation de ce préfixe suffisant à empêcher l'analyse. Il ne devrait pas apparaître dans les protocoles récents.

Lorsqu'un protocole transporte du texte, et que la connaissance de la langue dans laquelle est écrit ce texte est importante (par exemple pour déterminer l'ordre de classement), il faut utiliser une identification de langue (language identification). C'est un mécanisme par lequel on indique la langue utilisée, en se servant des étiquettes de langue du RFC 5646. Ainsi, HTTP va utiliser l'en-tête Content-Language: gsw-FR dans la réponse, pour indiquer que le document servi est en alsacien.

Le texte contenu dans les échanges normalisés par un protocole IETF est souvent décrit par ASN.1. Ce langage permet plusieurs sortes de chaînes de caractère, de la traditionnelle IA5String, qui contient les caractères ASCII, à UTF8String qui, comme son nom l'indique, peut stocker tout Unicode. Ainsi, lorsque le RFC 5280 utilise ce type pour des champs d'un certificat X.509, il permet à ce format d'avoir des noms de CA ou d'utilisateurs complètement internationalisés.

Il existe également toute une terminologie spécifique aux IDN. On la trouve dans le RFC 5890 et résumée dans la section 7.

Plus nouveau est le problème des variantes (variants). Il date du RFC 3743 et peut se définir comme « des chaînes de caractères que certains humains, dans certaines conditions, considèrent comme équivalents ». Dans le RFC 3743, il ne s'agissait que de la différence entre les sinogrammes traditionnels et les sinogrammes simplifiés, pour lesquels une solution était recommandée dans le RFC 4713. Mais la question des variantes peut surgir dans bien d'autres cas :

  • Des caractères que l'œil peut confondre comme le 1 et le l de l'alphabet latin, ou comme le a latin et le а cyrillique.
  • Des caractères qui sont « le même » d'un certain point de vue, mais à qui Unicode a quand même affecté des numéros différents. Un exemple typique est le σ grec, qui s'écrit ς à la fin d'un mot, alors qu'il s'agit du même sigma. Autre exemple, le ي arabe (le yeh), qui est codé différemment dans d'autres langues, par exemple ی en persan.
  • Et bien sûr les variantes orthographiques. Est-ce que color et colour, ou bien theatre et theater sont le même mot en anglais ? Et strasse et straße en allemand ? Concrètement, un protocole Internet doit-il les considérer comme liés, comme faisant partie du même lot, l'un étant une variante de l'autre ?

La question des variantes a donc deux sous-questions : comment classer les caractères et les chaînes en lots (où les membres d'un lot sont considérés variantes l'un de l'autre) ? Et, surtout, le protocole doit-il intégrer cette notion, ou bien considérer plus traditionnellement que deux chaines de caractère sont différentes si elles ont des numéros Unicode différentes, point ?

Dernière section avec des définitions, la section 8 est consacrée aux termes divers. On y trouve, par exemple, le profil local (locale), qui est l'ensemble des informations qui varient selon le lieu ou la culture, et qui sont nécessaires pour que le programme, non seulement parle la langue de l'utilisateur, mais lui présente des informations comme la date ou la monnaie locale.

Les profils locaux sont une source de questions philosophiques sans fin. Par exemple, pour afficher un texte, faut-il utiliser le profil de l'auteur du texte ou bien celui du lecteur ? Et le profil doit-il dépendre de la personne, ou bien de sa localisation physique ? (Si je suis à Tokyo, je veux l'heure locale mais mes textes toujours en français.)

Autres termes utile, ceux de translittération (transliteration), de transcription (transcription) et de romanisation (romanization). La translittération est la conversion d'une écriture dans une autre, en général lettre par lettre. Elle est réversible, la plupart du temps, puisque chaque lettre a été convertie. Cela marche bien entre écritures alpabétiques. La transcription, elle, suit les sons (et non pas les lettres) et va donc être différente selon la langue cible. C'est c'est ainsi que le nom du fondateur du parti bolchevique russe, Ульянов, peut être translittéré Ul'yánov (le résultat exact dépend de la norme suivie car il existe plusieurs normes de translittération de cet alphabet) mais est transcrit Ulyanov en anglais et Oulianov en français. Avec les écritures comme le chinois, la translittération n'est en général pas possible et il n'y a que des transcriptions, comme le pinyin. On nomme romanisation une conversion (translittération ou transcription, même si le RFC n'indique que la première possibilité) vers l'alphabet latin.

Quels sont les changements depuis le précédent RFC, le RFC 3536 ? L'annexe C les résume. Il y a des clarifications, pas de retraits mais plusieurs ajouts, notamment sur la question des variantes. La section 7, sur la terminologie spécifique aux IDN, est toute nouvelle.

Il existe bien sûr d'autres documents qui ont développé un vocabulaire cohérent sur l'internationalisation, et qui ont donc inspiré ce RFC. On peut citer la norme Unicode, le « Character Model for the World Wide Web » du W3C, et les RFC 2277, RFC 5646 et RFC 5890. Patrick Andries a un excellent glossaire de l'internationalisation en français.

L'annexe A contient une bibliographie sur le sujet de l'internationalisation, où on trouve des ouvrages de référence comme la somme sur les écritures du monde, « The world's writing systems ». Sur le sujet d'Unicode, je recommande ces livres :

Enfin, on trouve plein de choses en français sur le site de Patrick Andries.


Téléchargez le RFC 6365


L'article seul

RFC 6360: Conclusion of FYI RFC Sub-Series

Date de publication du RFC : Août 2011
Auteur(s) du RFC : R. Housley (Vigil Security)
Pour information
Première rédaction de cet article le 22 août 2011


Les RFC, textes sacrés de l'Internet, comportaient un sous-ensemble, dénommé FYI (For Your Information), qui visait un public plus large que les ingénieurs réseaux et les programmeurs. Cette sous-série n'a pas été un grand succès, malgré la qualité des documents produits, et est officiellement abandonnée.

Lancée par le RFC 1150 en 1990, la sous-série FYI visait à élargir le lectorat des RFC et à fournir de l'information utile et techniquement correcte (puisque écrite directement par les experts) à un large public, celui de tous les utilisateurs de l'Internet (les autres RFC n'étant lus que par des geeks barbus). Trente-huit RFC ont été publiés dans cette sous-série, chacun recevant un numéro FYI. Ainsi, le RFC 1178 (FYI 5) expliquait comment choisir un nom pour son ordinateur, le RFC 1359 (FYI 16) détaillait l'intérêt et les bénéfices de se connecter à l'Internet (tout le monde n'était pas encore convaincu), et le dernier de la sous-série, le RFC 3098 (FYI 38) expliquait à quel point c'était mal de spammer. Parfois, le RFC était mis à jour, son successeur héritant de son numéro de FYI. Rappelez-vous qu'un RFC n'est jamais modifié, donc le nom « RFC 1594 » désigne toujours le même document alors que le nom « FYI 4 » a désigné plusieurs RFC successivement, depuis le RFC 1325, intéressant document historique, puisque c'est une FAQ pour les nombreux nouveaux utilisateurs de l'Internet (le dernier RFC pointé par « FYI 4 » a été le RFC 2664).

Depuis 2001, aucun numéro de FYI n'avait été attribué et le groupe de travail qui les gérait ne s'est pas réuni. Ce RFC 6360 ne formule pas d'hypothèse sur cet arrêt mais on peut penser que les experts n'avaient pas forcément le temps ou la compétence d'écrire pour les utilisateurs, et que le modèle des RFC (documents très stables et accessibles sur le long terme) n'était pas forcément adapté à des publications de ce type dans un Internet changeant très vite. Bref, la sous-série a tourné court. Dans d'autres organisations, on aurait continué pendant longtemps la fiction mais l'IETF préfère (et parfois réussit) nettoyer. Ce RFC 6360 marque donc officiellement la fin des FYI. Les documents existants restent accessibles mais il n'y aura pas de nouveautés.

Pour ceux qui veulent accéder à ces excellents documents, la liste est disponible en http://www.rfc-editor.org/fyi-index.html.


Téléchargez le RFC 6360


L'article seul

RFC 6352: vCard Extensions to WebDAV (CardDAV)

Date de publication du RFC : Août 2011
Auteur(s) du RFC : C. Daboo (Apple)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF vcarddav
Première rédaction de cet article le 1 septembre 2011
Dernière mise à jour le 18 août 2014


De même que le format de fichiers iCal, décrivant des événements, avait son protocole CalDAV pour synchroniser des agendas entre machines, le format vCard décrivant des informations sur une personne a désormais son protocole CardDAV, pour synchroniser des carnets d'adresses.

Lorsque ce RFC sera largement déployé, on pourra donc sauvegarder, distribuer, partager son carnet d'adresses de manière standard. Cela se fait en définissant, comme pour CalDAV, des extensions au protocole WebDAV (RFC 4918).

Ce n'est pas qu'on manquait de protocoles pour l'accès à un carnet. Comme le rappelle la section 1, on avait LDAP (RFC 4510), IMSP et ACAP (RFC 2244), ainsi que SyncML. Mais bâtir sur WebDAV (RFC 4918) permettait de récupérer les fonctions perfectionnées de ce protocole. Le nouveau CardDAV permet d'avoir plusieurs carnets d'adresses, d'en protéger l'accès par des autorisations (RFC 3744), de faire des recherches côté serveur (sans avoir besoin de récupérer tout le carnet d'adresses chez le client), etc. WebDAV étant lui-même bâti sur HTTP, on récupère aussi les fonctions de HTTP comme la sécurité avec TLS (RFC 2818). CardDAV utilise le format vCard. Ce format avait été normalisé dans le RFC 2426 et se trouve désormais dans la RFC 6350. CardDAV dépend de certaines extensions à WebDAV et tout serveur WebDAV ne conviendra pas forcément. La section 3 résume les exigences de CardDAV (serveur permettant de créer des collections avec MKCOLRFC 5689 et exemple d'usage en section 6.3.1, versionnement - RFC 3253, etc). Par contre, il n'y a pas encore dans le protocole CardDAV de mécanisme de notification asynchrone (« Machin a changé de numéro de téléphone »). Le RFC ne le précise pas mais il y a un inconvénient à utiliser WebDAV, la complexité. Notre RFC 6352 fait 56 pages, et il faut avoir compris WebDAV avant...

La section 4 du RFC explique le modèle de données utilisé pour le carnet : chaque carnet d'adresses est une collection WebDAV et chaque entrée dans le carnet est une ressource WebDAV, adressable et verrouillable séparement. En même temps que les carnets d'adresses, un serveur CardDAV peut aussi gérer avec WebDAV d'autres ressources (un exemple serait un serveur où le carnet d'adresses de Lisa serait en /addressbooks/lisa et son agenda, via CalDAV, en /calendars/lisa). Le serveur publie le fait qu'il gère CardDAV en ajoutant addressbook à la réponse à la requête HTTP OPTIONS.

La section 5 passe ensuite à ces ressources. Chacune d'elles est une entrée du carnet, typiquement exprimée en format vCard (le serveur peut gérer également d'autres formats).

Emprunté au RFC (section 6.1), voici un exemple de connexion à un serveur CardDAV :

(Le client demande)
OPTIONS /addressbooks/ HTTP/1.1
Host: addressbook.example.com

(Le serveur répond)
HTTP/1.1 200 OK
Allow: OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, COPY, MOVE
Allow: MKCOL, PROPFIND, PROPPATCH, LOCK, UNLOCK, REPORT, ACL
DAV: 1, 2, 3, access-control, addressbook
DAV: extended-mkcol
Date: Sat, 11 Nov 2006 09:32:12 GMT
Content-Length: 0

Le client sait désormais que le serveur gère CardDAV (le addressbook dans l'en-tête DAV).

Différentes propriétés WebDAV (RFC 4918, section 4 ; les propriétés sont les métadonnées de WebDAV) permettent de se renseigner sur les carnets d'adresses. Elles sont formatées en XML. Ici, addressbook-description (section 6.2.1 ; son nom indique bien à quoi elle sert) peut valoir, par exemple (notez l'attribut xml:lang qui illustre les capacités d'internationalisation de CardDav) :


       <carddav:addressbook-description xml:lang="fr-CA"
          xmlns:carddav="urn:ietf:params:xml:ns:carddav">
         Adresses de Oliver Daboo
       </carddav:addressbook-description>


Et pour créer des entrées dans le carnet d'adresses, ce qui est quand même la tâche la plus importante de CardDAV ? CardDAV étant fondé sur HTTP, on utilise évidemment une requête PUT (de même que la lecture se ferait par un GET). La section 6.3.2 nous fournit un exemple, avec l'entrée au format vCard :

   PUT /lisa/addressbook/newvcard.vcf HTTP/1.1
   If-None-Match: *
   Host: addressbook.example.com
   Content-Type: text/vcard
   Content-Length: xxx

   BEGIN:VCARD
   VERSION:3.0
   FN:Cyrus Daboo
   N:Daboo;Cyrus
   ADR;TYPE=POSTAL:;2822 Email HQ;Suite 2821;RFCVille;PA;15213;USA
   EMAIL;TYPE=INTERNET,PREF:cyrus@example.com
   NICKNAME:me
   NOTE:Example VCard.
   ORG:Self Employed
   TEL;TYPE=WORK,VOICE:412 605 0499
   TEL;TYPE=FAX:412 605 0705
   URL:http://www.example.com
   UID:1234-5678-9000-1
   END:VCARD

Le If-None-Match dans la requête (RFC 7232, section 3.2) est là pour garantir qu'une ressource du même nom n'existe pas déjà. Cela évite d'effacer une ressource existante. Le .vcf à la fin de l'URL est l'extension commune des fichiers vCard.

Les carnets d'adresses sont évidemment des choses assez personnelles, on a donc des moyens de les protéger (section 7). Un serveur CardDAV permet de définir des ACL, comme normalisé dans le RFC 3744.

Récupérer un carnet d'adresses avec GET est simple mais ne laisse guère de choix. La section 8 présente des mécanismes plus sophistiqués. CardDAV a la méthode HTTP REPORT du RFC 3253 pour produire des extractions du carnet. Mais il a aussi des fonctions de recherche et de tri. Celles-ci posent le problème des règles de comparaison (rappelez-vous qu'un fichier vCard est de l'Unicode et peut contenir des caractères de toute sorte). La section 8.3 précise donc :

  • Ces règles sont exprimées en utilisant la terminologie du RFC 4790, qui fournit une liste de règles,
  • Parmi ces règles, le serveur doit accepter au moins les comparaisons ASCII i;ascii-casemap du RFC 4790 et les comparaisons Unicode i;unicode-casemap du RFC 5051,
  • Les opérations possibles sont au minimum le test d'égalité et le test de sous-chaîne (« strauss » doit trouver « strauss-kahn »), avec ses options « au début de la chaîne » et « à la fin de la chaîne ».

Voici un exemple de commande REPORT en ajoutant une condition pour ne sélectionner que les entrées du carnet dont le NICKNAME est exactement égal à « me » :


La requête :

   REPORT /home/bernard/addressbook/ HTTP/1.1
   Host: addressbook.example.com
   Depth: 1
   Content-Type: text/xml; charset="utf-8"
   Content-Length: xxxx

   <?xml version="1.0" encoding="utf-8" ?>
   <carddav:addressbook-query xmlns:dav="DAV:"
                     xmlns:carddav="urn:ietf:params:xml:ns:carddav">
     <dav:prop>
       <dav:getetag/>
       <carddav:address-data>
         <carddav:prop name="VERSION"/>
         <carddav:prop name="UID"/>
         <carddav:prop name="NICKNAME"/>
         <carddav:prop name="EMAIL"/>
         <carddav:prop name="FN"/>
       </carddav:address-data>
     </dav:prop>
     <carddav:filter>
       <carddav:prop-filter name="NICKNAME">
         <carddav:text-match collation="i;unicode-casemap"
                       match-type="equals">
            me
         </carddav:text-match>
       </carddav:prop-filter>
     </carddav:filter>
   </carddav:addressbook-query>

La réponse :

   HTTP/1.1 207 Multi-Status
   Date: Sat, 11 Nov 2006 09:32:12 GMT
   Content-Type: text/xml; charset="utf-8"
   Content-Length: xxxx

   <?xml version="1.0" encoding="utf-8" ?>
   <dav:multistatus xmlns:dav="DAV:"
                  xmlns:carddav="urn:ietf:params:xml:ns:carddav">
     <dav:response>
       <dav:href>/home/bernard/addressbook/v102.vcf</dav:href>
       <dav:propstat>
         <dav:prop>
           <dav:getetag>"23ba4d-ff11fb"</dav:getetag>
           <carddav:address-data>BEGIN:VCARD
   VERSION:3.0
   NICKNAME:me
   UID:34222-232@example.com
   FN:Cyrus Daboo
   EMAIL:daboo@example.com
   END:VCARD
   </carddav:address-data>
         </dav:prop>
         <dav:status>HTTP/1.1 200 OK</dav:status>
       </dav:propstat>
     </dav:response>
   </dav:multistatus>

Écrire un client CardDAV n'est pas trivial, pas seulement à cause de la longueur du RFC mais aussi parce qu'il existe plusieurs pièges. La lecture de la section 9 est donc recommandée. Elle rappelle par exemple que le client peut ne demander qu'une partie des données (dans l'exemple ci-dessus, le client demande à ne voir que VERSION, UID, NICKNAME, EMAIL et FN). Cela lui évite de devoir télécharger des données qui peuvent être de grande taille comme PHOTO ou SOUND. Par contre, cette astuce ne marche qu'en lecture, pas en écriture : un PUT doit transmettre la totalité de la vCard et le protocole ne fournit pas de moyen de ne mettre à jour qu'un seul champ. Le client doit donc récupérer toute la vCard, changer un champ et renvoyer toute la vCard modifiée.

Piège classique dans ce cas, la « mise à jour perdue ». Que se passe-t-il si les données ont été changées entre leur récupération et le renvoi ? Ce changement risque d'être écrasé. Pour éviter cela, le client a tout intérêt à utiliser l'option If-Match: de la requête HTTP, en indiquant comme paramètre un Etag récupéré précedemment (les Etags sont décrits dans la section 2.3 du RFC 7232). Ainsi, dans le cas cité ci-dessus, le renvoi du vCard modifié sera refusé, préservant la mise à jour qui avait été faite parallèlement. (Emmanuel Saint-James me fait remarquer qu'on aurait aussi pu utiliser If-Unmodified-Since:, si le serveur CardDAV met les informations dans une base de données qui stocke la date de modification, par exemple le système de fichiers Unix ; cette possibilité n'est pas mentionnée par le RFC.)

Comment configure-t-on un client CardDAV (section 9.3) ? On a vu que l'URL utilisé était arbitraire, au choix de l'implémenteur. Le client doit donc être configuré avec cet URL. Il existe bien deux mécanismes de découverte automatique, décrits dans le RFC 5397 et dans le RFC 6764, mais qui ne sont pas forcément présents partout. (iOS utilise celui du RFC 6764 donc si vous voyez des requêtes /.well-known/carddav passer, c'est lui.)

Et le nom du serveur ? La section 11 décrit un enregistrement SRV pour le trouver. Le nom _carddav._tcp.domain.example permet donc de trouver le serveur CardDAV du domain domain.example (et _carddavs pour utiliser TLS). Si l'enregistrement SRV vaut :

_carddav._tcp     SRV 0 1 80 addressbook.example.com.

Cela indique que ce serveur est addressbook.example.com et qu'il est accessible sur le port 80. Si ces enregistrements SRV sont présents, et si la propriété current-user-principal-URL du RFC 5397 est utilisée, il n'y a plus à configurer que le nom de domaine, le nom de l'utilisateur et un mot de passe.

Et si on veut accéder au carnet d'un autre utilisateur, ce qui peut arriver en cas de carnets partagés ? La section 9.4 rappelle l'existence de la propriété principal-property-search du RFC 3744, qui peut permettre de demander un REPORT en cherchant le carnet sur divers critères. Ici, on cherche le carnet de Laurie :


   REPORT /home/bernard/addressbook/ HTTP/1.1
   Host: addressbook.example.com
   ...
   <dav:principal-property-search xmlns:dav="DAV:">
     <dav:property-search>
       <dav:prop>
         <dav:displayname/>
       </dav:prop>
       <dav:match>Laurie</dav:match>
     </dav:property-search>
     <dav:prop>
       <carddav:addressbook-home-set
          xmlns:carddav="urn:ietf:params:xml:ns:carddav"/>
       <dav:displayname/>
     </dav:prop>
   </dav:principal-property-search>

Notez que, CardDAV s'appuyant sur XML, il hérite de ses capacités d'internationalisation (section 12), notamment l'usage d'Unicode.

Et question sécurité ? Des failles dans CardDAV ? La section 13 tente de prévenir les problèmes : d'abord, CardDAV hérite des questions de sécurité de HTTP. Si on n'utilise pas HTTPS, les requêtes et réponses circulant sur le réseau peuvent être lues et/ou modifiées. C'est particulièrement important si on utilise l'authentification HTTP de base, avec envoi d'un mot de passe.

Ensuite, une fois les utilisateurs authentifiés, encore faut-il éviter qu'un utilisateur ne tripote les carnets des autres. L'extension « ACL » du RFC 3744 permet d'atteindre cet objectif. Elle permet d'avoir des carnets publics, partagés ou complètement privés. Le serveur doit ensuite veiller au respect de cette classification.

Le schéma XML complet pour les éléments CardDAV figure en section 10. Question implémentations, on peut regarder la liste gérée par les gens de Zimbra, celle de Trinity, celle de Wikipédia. Parmi les programmes qui gèrent CardDAV, citons le serveur Davical, Radicale ou Evolution. le client Kontact de KDE n'est plus maintenu. Pour Firefox, c'est en discussion. Merci à Mathieu Dupuy pour les détails.


Téléchargez le RFC 6352


L'article seul

RFC 6350: vCard Format Specification

Date de publication du RFC : Août 2011
Auteur(s) du RFC : S. Perreault (Viagenie)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF vcarddav
Première rédaction de cet article le 1 septembre 2011


vCard, désormais en version 4 avec ce RFC est le format standard de carnet d'adresses sur l'Internet. Tous les logiciels de gestion de carnet d'adresses peuvent (ou devraient pouvoir) lire et écrire du vCard. Ce RFC met à jour la norme vCard.

vCard est simplement un modèle de données (très léger) et une syntaxe pour représenter des données permettant de contacter des individus ou organisations. Par exemple, une entrée vCard pour mon employeur, l'AFNIC, pourrait être :

    BEGIN:VCARD
    VERSION:4.0
    FN:Association Française pour le Nommage Internet en Coopération
    KIND:org
    GENDER:N
    NICKNAME:AFNIC
    LANG;PREF=1:fr
    LANG;PREF=2:en
    ADR:;;Immeuble International;Saint-Quentin-en-Yvelines;;78181;France
    LOGO:http://www.afnic.fr/images/logo.png
    TEL;VALUE=uri:tel:+33-1-39-30-83-00
    EMAIL:afnic@afnic.fr
    GEO:geo:2.0455,48.7873
    BDAY:19980101
    TZ:Paris/Europe
    URL:http://www.afnic.fr/
    NOTE;LANGUAGE=en:@AFNIC on Twitter\,
     AFNIC on Facebook.
    END:VCARD

Ce texte peut ensuite être lu et interprété par les logiciels de gestion de carnet, être envoyé via l'Internet, etc. Un exemple courant est l'envoi d'une vCard dans le courrier, via MIME et le type text/vcard (section 10.1 pour l'enregistrement de ce type). Le cas échéant, il est relativement compréhensible par un humain (s'il comprend l'anglais et quelques sigles), ce qui justifie le type MIME text indiqué plus haut.

La version de vCard dans ce RFC est largement terminée depuis mi-2010. Mais de nombreux détails avaient été discutés jusqu'au dernier moment. Si la syntaxe ne pose guère de problèmes (on notera qu'il existe une variante XML normalisée, dans le RFC 6351, et une autre en JSON, dans le RFC 7095), le modèle de données peut susciter des discussions sans fin.

Pour prendre des exemples de cette discussion, voici quelques sujets qui avaient été abordés lors de la réunion du groupe de travail à l'IETF de Pékin en 2010 :

  • La nouvelle propriété RELATED qui peut valoir spouse, friend, etc. Une jolie liste des valeurs possibles est http://gmpg.org/xfn/11. On pourra coder toutes les relations Facebook en vCard.
  • La longue discussion passionnée à propos du remplacement de l'ancien attribut SEX de vCard 3 par GENDER. La moitié des participants se sont exprimés, ce qui est rare à l'IETF. Le sexe est déterminé biologiquement et, en toute première approximation, peut être considéré comme binaire (homme ou femme). Le genre est construit socialement et peut prendre bien plus de valeurs. GENDER pourra donc être du texte libre (une des propositions discutées à Pékin avait été de créer un registre IANA des différents genres possibles...) et les exemples du RFC (avec des valeurs comme grrrl, intersex ou complicated) illustrent la difficulté du problème. Le changement dans vCard permet donc de mieux prendre en compte des cas comme celui des transsexuels ou, tout simplement, des gens qui ont une autre identité que celle que leur impose la biologie. L'ironie de la longue et animée discussion est qu'il n'y avait que des hommes dans la salle. (GENDER est désormais décrit en détail dans la section 6.2.7 du RFC, avec notamment sa façon subtile de combiner deux champs, un énuméré et un en texte libre.)
  • Plus triste, une discussion avait eu lieu sur la propriété DEATH permettant, si nécessaire, d'indiquer la date de la mort de l'entitée considérée. Elle a finalement été retirée. Mettre du vCard sur une pierre tombale aurait pourtant été curieux... Cela a finalement été possible quelque temps après, avec l'approbation du RFC 6474.
  • Et les adresses de courrier électronique en Unicode du RFC 6532 ont évidemment suscité bien de la perplexité. Finalement, la propriété EMAIL permettra de telles adresses (voir la section 6.4.2 pour les détails).

J'espère que cette liste amusante vous aura donné une idée des problèmes que pose la définition d'un modèle de données standard. Retournons maintenant à la technique. D'abord, le niveau lexical (sections 3.1 et 3.2) : les fichiers vCard sont en UTF-8 (la possibilité d'autres encodages a été retirée, avec cette version de vCard), et sont composés de lignes terminées par CRLF (c'est-à-dire les deux caractères U+000D et U+000A). Comme pour les en-têtes du courrier électronique, on peut continuer sur plusieurs lignes : si une ligne commence par un espace ou une tabulation, c'est une continuation (regardez la NOTE dans l'exemple plus haut). Du fait de ces continuations, un outil mono-ligne comme grep n'est pas bien adapté pour chercher dans des vCards.

Ensuite, la syntaxe (section 3.3). Elle est très simple et indiquée en ABNF (RFC 5234). Une « carte » commence par la ligne BEGIN:VCARD, continue par une ligne avec le numéro de version, puis par une ou plusieurs lignes comportant les données, et se termine avec END:VCARD. Les données sont composées de propriétés, chaque ligne étant un nom de propriété (insensible à la casse, même si la convention recommandée est de les mettre en majuscules), suivi d'un :, puis de la valeur de la propriété (celle-ci pouvant elle-même être structurée, comme dans l'ADR ci-dessus).

Certains caractères sont spéciaux, comme la virgule et, si on veut les avoir comme valeur, doivent subir un échappement avec la barre inverse (section 3.4).

Les données peuvent avoir des paramètres. La section 5 décrit ce concept. Un paramètre permet de préciser des métadonnées sur une propriété. Par exemple, LANGUAGE permet d'indiquer la langue d'un texte. PREF permet de spécifier, lorsqu'il existe plusieurs exemplaires d'une propriété, laquelle est préférée (celle qui a la valeur la plus basse). Ainsi, dans l'exemple de l'AFNIC ci-dessus, c'est le français qui est la langue de contact préférée. SORT-AS permet de définir un tri entre les valeurs (un problème difficile pour les noms d'humains). TYPE permet d'indiquer, pour une ADR, si elle concerne la maison ou le travail. (vCard version 3 avait un mécanisme plus riche, qui aurait permis, dans l'exemple de l'AFNIC ci-dessus, d'indiquer la différence entre l'adresse postale - TYPE=postal et l'adresse physique - TYPE=parcel. Trop confus, il a été supprimé.) Et il existe plusieurs autres paramètres.

La sémantique est décrite dans la suite de cette section 3.3 et, pour chaque propriété, dans les sections 4, 5 et 6. Notons qu'une seule propriété est obligatoire (à part VERSION), FN, le nom de l'entité décrite dans la vCard. Pour chaque propriété, la section 4 indiquera si des valeurs multiples sont autorisées. Par exemple, on peut avoir plusieurs NICKNAME (surnom), mais un seul (facultatif) GENDER (genre).

Je ne vais évidemment pas lister toutes les propriétés que décrit la section 5 (voir le registre IANA pour une liste à jour). Pour chacune, elle donne son nom, sa cardinalité (zéro, zéro-ou-une, une, zéro-ou-plus, une-ou-plus occurrence) et son type. Pour ce dernier, il y a de nombreuses possibilités comme, par exemple, du texte libre, un URI, une date ou un temps (en utilisant la norme ISO 8601 et pas le plus simple RFC 3339), un booléen, un nombre entier, une langue (représentée selon le RFC 5646), etc.

À certains égards, la section 6 est la plus importante du RFC. C'est la liste de toutes les propriétés possibles actuellement, avec leurs caractéristiques. Quelques exemples, non limitatifs :

  • N indique le nom, sous forme d'une série de composants (dont la plupart sont facultatifs). Pour les humains, je rappelle surtout que le fait d'avoir Prénom + Nom est très loin d'être universel.
  • KIND indique quelle est la catégorie de l'entité décrite par cette « carte » (personne physique, organisation - comme dans l'exemple de l'AFNIC plus haut, etc).
  • PHOTO est l'URI (éventuellement de plan data:, c'est-à-dire fournissant directement le contenu) d'une photo de la personne. LOGO joue un rôle analogue pour les organisations.
  • BDAY est la date de naissance de l'entité.
  • IMPP indique le moyen de contacter l'entité par messagerie instantanée.
  • LANG permet d'indiquer, sous la forme d'une étiquette de langue comme fr ou pt-BR, la langue à utiliser pour contacter l'entité.
  • GEO est la localisation physique habituelle de l'entité, en suivant de préférence la syntaxe du RFC 5870. (Notez le « de préférence ». Analyser la syntaxe d'une vCard est très simple, mais accéder à la sémantique est bien plus complexe, en raison du choix qui est laissé pour le codage d'informations comme le numéro de téléphone ou la position physique.)
  • KEY permet de distribuer des clés cryptographiques (attention à comment on a récupéré le vCard avant de leur faire confiance...)

Notez que la liste n'est pas figée dans le temps (c'est une nouveauté de vCard version 4). Des propriétés ou paramètres nouveaux pourront être enregistrés, selon la procédure décrite dans la section 10.2. Il faudra d'abord les discuter sur la liste vcarddav@ietf.org, puis il y aura un examen par un expert. Si accepté, le nouvel élément sera enregistré à l'IANA.

Le reste du RFC est consacré à des points d'utilisation des vCard. Par exemple, la section 7 est consacrée à la synchronisation des vCards entre deux engins (par exemple l'ordinateur du bureau et le smartphone). Que faire si une entrée a été modifiée sur un carnet et détruite dans un autre ? Deux mécanismes sont fournis pour aider à une fusion intelligente des deux carnets, une propriété UID qui identifie de manière unique et non ambigüe une entité (de préférence en utilisant le RFC 9562) et PID qui identifie une propriété. Les section 7.1.1 et 7.1.2 détaillent l'algorithme à utiliser lorsqu'on synchronise deux carnets. Par exemple, si on a identifié, grâce à UID, une entrée dans les deux carnets, et qu'une propriété est différente entre les carnets, alors, si la cardinalité d'une propriété est de 1, ou bien si le PID est le même, les deux propriétés doivent être fusionnées. Sinon, le synchroniseur est libre de fusionner, ou tout simplement de mettre les deux propriétés côte-à-côte. La section 7.2 donne des exemples détaillés de fusions. À noter qu'il existe un protocole pour la synchronisation des cartes avec un serveur, CardDAV, normalisé dans le RFC 6352.

Le message d'enregistrement du type MIME text/vcard, qui commençait la procédure, avait été fait en août 2010.

Publier ainsi de l'information, parfois sensible, sur l'Internet, n'est pas sans conséquences. La section 9 couvre les risques de sécurité de vCard. Par exemple, la carte en elle-même n'offre aucune garantie d'authentification ou d'intégrité. Rien ne prouve qu'une carte indiquant FN:Theo de Raadt vient réellement de de Raadt. Et même si la carte était authentique au départ, rien n'indique qu'elle n'a pas été modifiée en cours de route, sauf si elle a été transportée de manière fiable (par exemple dans un message signé avec PGP). Bref, ne vous fiez pas aveuglément à n'importe quelle vCard trouvée sur l'Internet !

Autre risque, celui pour la vie privée. Ce n'est pas par hasard ou par oubli que vous ne trouverez pas BDAY ou ADR sur ma carte, un peu plus loin. Une carte doit donc ne comporter que des informations publiques, ou bien être uniquement transportée de manière sûre (par exemple via un canal chiffré) et vers des gens de confiance.

Les changements de vCard depuis la version 3 (qui était normalisée dans les RFC 2425 et RFC 2426) sont décrits dans l'annexe A. La liste est longue et pas facile à résumer (ce n'est qu'une accumulation de changements ponctuels). Le changement que je trouve le plus spectaculaire est la possibilité d'enregistrer de nouveaux éléments sans changer de RFC, juste par un processus d'enregistrement IANA. Sinon, voir la section 6.7.9 pour le rôle de la propriété VERSION pour gérer le fait que les cartes en circulation aient des versions différentes.

Si vous voulez en savoir plus sur vCard, le site Web du groupe de travail est très riche, quoique plutôt difficile d'accès (il est conçu pour le travail du groupe, pas pour la pédagogie).

Et du point de vue pratique, quels outils le programmeur a à sa disposition s'il veut lire et/ou écrire du vCard ? Il existe une bibliothèque pour les programmeurs C (le paquetage se nomme libvc-dev sur Debian), qui est utilisée dans des applications comme rolo. Elle n'est distribuée avec aucune documentation digne de ce nom et pas d'exemples. Pour les programmeurs Perl, il existe Text::vCard. Attention à son analyseur : très laxiste, il accepte des vCards bourrées d'erreurs de syntaxe.

Voici un exemple d'usage de cette bibliothèque Perl :

#!/usr/bin/perl

use Text::vCard::Addressbook;

for $file (@ARGV) {
    my $address_book = Text::vCard::Addressbook->new({
	'source_file' => $file});
    $number = 0;
    foreach my $vcard ($address_book->vcards()) {
	print "Got card for " . $vcard->fullname() . "\n";
	$number++;
    }
    if (!$number) {
	print "No correct vCard in $file\n";
    }
}

Ah, et si vous voulez me contacter, voici une carte pour moi :

BEGIN:VCARD
VERSION:4.0
FN:Stéphane Bortzmeyer
N:Bortzmeyer;Stéphane;;;
UID:urn:uuid:a06340f8-9aca-41b8-bf7a-094cbb33d57e
GENDER:M
KIND:individual
EMAIL:stephane+blog@bortzmeyer.org
TITLE:Indigène de l'Internet
PHOTO:http://www.bortzmeyer.org/images/moi.jpg
LANG;PREF=1:fr
LANG;PREF=2:en
IMPP;PREF=1:xmpp:bortzmeyer@dns-oarc.net
IMPP;PREF=2:xmpp:bortzmeyer@gmail.com
URL:http://www.bortzmeyer.org/
KEY:http://www.bortzmeyer.org/files/pgp-key.asc
END:VCARD

Merci à Simon Perreault pour sa relecture.


Téléchargez le RFC 6350


L'article seul

RFC 6349: Framework for TCP Throughput Testing

Date de publication du RFC : Août 2011
Auteur(s) du RFC : B. Constantine (JDSU), G. Forget (Bell Canada), R. Geib (Deutsche Telekom), R. Schrage (Schrage Consulting)
Pour information
Réalisé dans le cadre du groupe de travail IETF ippm
Première rédaction de cet article le 22 août 2011


La mesure des performances du réseau intéresse évidemment fortement les utilisateurs (combien de temps me faudra-t-il pour télécharger justin-bieber.flac ?) et les décideurs qui cherchent à savoir, par exemple, quelle capacité offre un FAI, s'il délivre bien le service promis, ou encore s'il limite artificiellement les débits. La plupart des métriques définies rigoureusement, et des outils qui les mettent en œuvre, concernent des phénomènes de bas niveau, comme le taux de perte de paquets (RFC 7680), C'est ainsi que, lorsqu'il existe des SLA formalisés, ils portent en général sur ces phénomènes proches du réseau. Ces métriques sont utiles et relativement faciles à mesurer objectivement, mais elles sont très éloignées de l'expérience ressentie par l'utilisateur final. Ce dernier voudrait plutôt savoir comment l'intégration de toutes ces métriques de bas niveau se traduit en un petit nombre de chiffres faciles à comprendre. Ce n'est pas une tâche triviale que de passer des métriques de base au ressenti utilisateur, et ce RFC est une première étape sur le chemin.

L'idée est de préciser les conditions de mesure de débit sur une connexion TCP, de bout en bout (donc tenant compte du comportement de tous les liens et équipements intermédiaires). Le débit mesuré en TCP donne une première idée de la capacité du réseau, qui est elle-même souvent la première métrique qui intéresse les utilisateurs (c'est en tout cas en général celle qui est mise en avant dans les publicités). Mais cette mesure contient de nombreux pièges et l'un des buts de ce RFC est de les lister. Au final, ce RFC ne permet pas de répondre simplement à la question de M. Toutlemonde « ça va moins ramer avec le fournisseur X qu'avec son concurrent Y ? », mais il avance quand même dans cette direction.

On grimpe donc d'une couche et on passe des mesures traditionnelles (taux de pertes, comme cité plus haut, ou bien capacité du lien au niveau 2) vers le niveau 4. Le désir de mesurer rigoureusement le débit atteignable avec TCP oblige à apporter quelques restrictions. Par exemple, le cadre de mesure décrit dans ce RFC se limite aux réseaux dont tous les aspects sont contrôlés par un fournisseur unique, avec des garanties explicites. Cela concerne donc plutôt la clientèle « entreprises ». La section 2 détaille tout ce qui n'est pas un objectif de ce RFC :

  • Le comportement de TCP en dehors de l'équilibre (voir plus loin),
  • La comparaison des mises en œuvre de TCP,
  • La mesure en continu d'un réseau de production (pour cela, il vaut mieux utiliser la MIB TCP du RFC 4898).

Le but est au contraire de pouvoir mesurer, de manière objective et reproductible, les performances TCP d'un chemin donné, en fonction d'un certain nombre de réglages, bien définis. Les outils existants comme iperf ou ttcp permettent d'ajuster ces réglages.

Passons maintenant à la technique (la section 1.1 liste la terminologie employée) : TCP utilise à tout moment deux fenêtres, une pour l'envoyeur (congestion windows) et une pour le récepteur (receive window). Le débit théorique est limité par la bande passante (capacité de la couche 2) et par le RTT. Leur produit, le BDP (Bandwidth*Delay Product), va déterminer la taille des tampons optimaux (le tableau en section 3.3.1 donne des valeurs numériques). Ce BDP est, en gros, le nombre d'octets qui peuvent se trouver en transit à un moment donné. Ensuite, la fenêtre de congestion sera ajustée pour tenir compte du taux de pertes. Le nombre d'octets en route à un moment donné dépendra de la fenêtre la plus petite (si on a une grande congestion window mais que l'autre partie annonce une petite receive window, le débit restera faible : un émetteur TCP n'est pas censé noyer son pair sous les octets non désirés).

Toutes ces variables vont déterminer le débit effectivement atteint. Avant de tenter de mesurer celui-ci, le RFC insiste bien sur le fait que les tests de bas niveau (couches 2 et 3) doivent quand même être faits, pour déterminer que le réseau fonctionne bien. Le RFC note qu'un taux de pertes de paquets de 5 %, ou bien une gigue dans le délai d'acheminement de 150 ms, sont trop élevées pour que les mesures de débit TCP aient un sens. La méthodologie du RFC 2544 (bien que conçue à l'origine pour un environnement de laboratoire) peut être utilisée pour ces tests de bon fonctionnement.

Ensuite, notre méthodologie ne concerne que les connexions TCP ayant atteint l'état d'équilibre (section 1.2). Rappelons qu'une connexion TCP établie peut avoir trois comportements par rapport à la congestion : l'état d'équilibre où TCP essaie de remplir le tuyau au maximum, le démarrage en douceur, utilisé au début de la connexion, où TCP commence à sonder prudemment le réseau, en augmentant doucement son débit, et le troisième comportement, la récupération en cas de pertes, où TCP réduit brusquement son débit, avant de repartir plus ou moins doucement. En pratique, un certain nombre de connexions utilisées pour HTTP, par exemple, n'atteindront jamais cet équilibre, car elles durent trop peu de temps. C'est un bon exemple de la distance entre les mesures techniques et le vécu de l'utilisateur !

Dans un réseau idéal, à l'équilibre, TCP devrait avoir un débit très proche de la bande passante offerte.

La section 3 du RFC présente la méthodologie de mesure détaillée, avant que la section 4 ne décrive les métriques utilisées. La mesure impose d'utiliser un équipement capable de saturer le lien (donc, pas un vieux PC). Les mesures à plus de 100 Mb/s peuvent donc exiger une machine dédiée. La mesure exige ensuite les étapes suivantes :

  • Déterminer la PMTU (en utilisant le RFC 4821, pour tenir compte des nombreux réseaux mal configurés qui bloquent ICMP) pour ensuite configurer le logiciel de test de manière à ce que les paquets soient assez petits pour éviter toute fragmentation (qui changerait drastiquement les performances). Par exemple, avec iperf (cité plus loin), l'option --mss permet de changer la taille des segments (des paquets TCP).
  • Déterminer le RTT minimum et la bande passante offerte par les couches basses. Cela servira à optimiser des paramètres comme le tampon d'envoi. Sur un réseau de production, cette mesure doit se faire aux heures creuses, pour être sûr d'obtenir vraiment la valeur « réelle ». Il existe plusieurs façons de mesurer le RTT. Le choix dépend de la précision souhaitée. Si on se contente de la milli-seconde, les paquets ICMP echo de ping conviennent (mais c'est quand même la technique la moins fiable, surtout s'il y a un traitement différencié pour ICMP dans le réseau, ou dans les machines de test). Si on veut se promener du côté de la micro-seconde, il faudra peut-être un dispositif de mesure spécialisé (voir section 5), et des protocoles comme celui du RFC 5357. Il y a aussi l'analyse des paquets capturés, avec un outil comme tcptrace, ou les statistiques gardées par TCP lui-même (RFC 4898). Quant à la mesure de la « bande passante » (un terme que je n'aime pas mais qui est utilisé par le RFC), elle devrait être faite suivant les règles du RFC 5136. Il ne faut pas oublier de la mesurer dans les deux directions, surtout avec les liens asymétriques comme l'ADSL.
  • En enfin, faire les tests avec TCP, après avoir configuré le logiciel de test. La section 5 recommande un test d'au moins trente secondes, pour lisser les variations du réseau (avec iperf, c'est l'option --time, avec ipmt, c'est -d). Compte-tenu de la variété des mécanismes de tripotage du réseau qui existent, il peut être prudent de faire plusieurs mesures (par exemple de voir si une seule connexion obtient bien N fois ce qu'obtenait chacune des connexions d'un groupe de N connexions simultanées, cf. section 5.1).

Les métriques utilisées sont définies dans la section 4 du RFC. Elles sont au nombre de trois. La première est le ratio du temps de transfert, soit le rapport entre le temps nécessaire pour transférer N octets par rapport à la situation idéale (compte-tenu de la bande passante). Le calcul exact de cette situation idéale figure en section 4.1.1. Par exemple, pour une ligne T3 à 44,21 Mb/s exploitée en PPP, une MTU de 1500 octets, vus les en-têtes TCP, on arrive à 42,8 Mbps. Si on mesure un débit maximal de 40 Mbps, le ratio sera donc de 1,07 (rappelez-vous que c'est un rapport des temps de transfert, pas des débits). Pour un Ethernet 1 Gb/s, le cas idéal, qu'aucune amélioration du logiciel ne permettra de dépasser, est de 949 Mbps. L'utilisation de jumbo frames permettrait bien sûr de faire mieux.

La seconde métrique est l'efficacité de TCP. C'est le pourcentage des octets qui n'ont pas été retransmis. Il vaut donc 1 en l'absence de pertes (ou de retards qui mèneraient TCP à croire à une perte de paquets).

Plus subtile, la troisième métrique est le retard dû aux tampons. C'est le rapport entre l'excès de RTT (par rapport au RTT minimum, celui imposé par les caractéristiques de la ligne) et le RTT minimum. Par exemple, si le RTT minimum (qui, sur les lignes à grande distance, est souvent dépendant essentiellement de la vitesse de la lumière) est de 25 ms, et qu'on observe un RTT moyen de 32 ms pendant un transfert TCP, le retard dû aux tampons est donc de 28 %.

La première métrique est celle qui est la plus directement pertinente pour l'utilisateur. Les deux autres fournissent surtout un moyen de diagnostic : si le ratio du temps de transfert est mauvais, l'examen de l'efficacité et du retard dû aux tampons nous indiquera peut-être pourquoi.

Voilà, la norme est définie. La section 5, elle, revient sur les conditions pratiques de mesure. Entre autres, elle expose les règles du choix entre une seule connexion TCP et plusieurs. Ce choix dépend des caractéristiques du réseau (si le produit bande passante * délai est de 2 Moctets, une seule connexion TCP ne pourra pas remplir le tuyau, cf. le tableau des valeurs numériques en section 5.1).

Reste l'interprétation des résultats (section 5.2). Les résultats devraient toujours être accompagnés de la valeur des paramètres indiqués plus haut (ce que font les outils existants, cf. plus loin). Le RFC demande évidemment que les valeurs des trois métriques citées plus haut soient affichées, ce qui n'est pas (encore ?) le cas avec les logiciels Unix de mesure existants. Une fois qu'on a ces valeurs, si elles ne correspondent pas aux valeurs idéales, on peut se livrer aux joies du débogage : la congestion avec des tampons de petite taille dans les routeurs fera sans doute grimper les pertes de paquets, ce qui se traduira par une mauvaise efficacité TCP. Si les routeurs ont de quoi stocker les paquets en attente, c'est le RTT qui augmentera, ce qui se verra dans le retard dû aux tampons. Mais il peut aussi y avoir ralentissement délibéré par le réseau (policing), tampons trop petits sur les machines de test (qui ont, après tout, une mémoire limitée, qui peut être trop faible pour les réseaux à haute performance d'aujourd'hui). Les machines Unix ont de tels tampons aussi bien globalement pour tout le système que par socket. On peut fixer ces derniers (la valeur idéale est le BDP, le produit bande passante*délai) dans le programme, mais aussi les laisser s'ajuster automatiquement (service auto-tuning, qui existe dans Linux et FreeBSD ainsi que, depuis moins longtemps, Windows et Mac OS). Il faut également regarder du côté du mécanisme de window scaling (RFC 7323) sans lequel il est impossible d'exploiter les réseaux à très fort BDP qu'on trouve aujourd'hui. Et, bien sûr, émettre des paquets ayant la taille maximale possible sans fragmentation est aussi une bonne tactique.

Bien d'autres réglages de TCP sont possibles, comme l'option d'estampille temporelle (RFC 7323) qui permet à TCP de mieux calculer le RTT (et qui protège contre les numéros de séquence TCP qui reviennent à leur valeur initiale, un problème qui devient sérieux au delà de 100 Mb/s), les accusés de réception spécifiques (SACK) du RFC 2018, qui permettent de limiter les retransmissions, etc.

À titre d'exemple, voici des exemples de mesure, plus ou moins compatibles avec notre RFC, dans le cas de certains outils libres. Le premier est iperf. Existant sous forme de paquetage pour divers systèmes Unix (ici, Debian), il est facile à installer. On doit le lancer côté client et côté serveur (c'est un point commun entre tous ces outils : il faut un compte sur les deux machines ; on ne peut donc pas les utiliser pour tester son débit possible avec YouTube).

# Serveur
% iperf -s
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size: 85.3 KByte (default)

# Client
% iperf --print_mss --client test.bortzmeyer.org
------------------------------------------------------------
Client connecting to test.bortzmeyer.org, TCP port 5001
TCP window size: 16.0 KByte (default)
------------------------------------------------------------
[  3] local 192.0.2.69 port 46908 connected with 203.0.113.232 port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-10.0 sec    173 MBytes    145 Mbits/sec
[  3] MSS size 1448 bytes (MTU 1500 bytes, ethernet)

On peut aussi changer la taille de la fenêtre TCP. Les 145 Mb/s obtenus ci-dessus sont probablement indépassables mais, parfois, ce changement améliore les performances. Il peut aussi les dégrader, ici, on choisit une fenêtre très petite :

% iperf --window 1K --client test.bortzmeyer.org 
...
TCP window size: 2.00 KByte (WARNING: requested 1.00 KByte)
------------------------------------------------------------
...
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-10.0 sec  27.3 MBytes  22.9 Mbits/sec

Cet exemple illustre l'importance de documenter, lorsqu'on publie les résultats de la mesure, les options utilisées. Ici, on a divisé la capacité utile par sept... (Quant au message d'avertissement, il vient de l'habitude du noyau Linux de fixer la taille de la fenêtre à une valeur double de celle qui est demandée.) iperf permet théoriquement de faire fonctionner plusieurs sessions TCP simultanées (option --parallel) mais j'avoue n'avoir pas réussi à la faire fonctionner.

Un autre outil traditionnel est ttcp. Très ancien, il a depuis été remplacé par des versions plus récentes. Je vais utiliser nuttcp, également en paquetage dans tous les bons systèmes. Son serveur a la désagréable habitude de passer en arrière-plan immédiatement (et il ne semble pas y avoir d'option pour changer cela), et on risque donc facilement d'oublier un serveur qui tourne. Le mieux est donc de toujours le lancer avec l'option -1 qui ne permet qu'un seul test.

# Serveur
% nuttcp -1

# Client
% nuttcp -v -t 203.0.113.232    
nuttcp-t: v6.1.2: socket
nuttcp-t: buflen=65536, nstream=1, port=5001 tcp -> 203.0.113.232
nuttcp-t: time limit = 10.00 seconds
nuttcp-t: connect to 203.0.113.232 with mss=1448, RTT=2.173 ms
nuttcp-t: send window size = 16384, receive window size = 87380
nuttcp-t: available send window = 12288, available receive window = 65535
nuttcp-t: 166.5708 MB in 10.00 real seconds = 17056.72 KB/sec = 139.7286 Mbps
nuttcp-t: retrans = 0
nuttcp-t: 2666 I/O calls, msec/call = 3.84, calls/sec = 266.60
nuttcp-t: 0.0user 0.0sys 0:10real 0% 0i+0d 592maxrss 0+2pf 893+0csw

On note des chiffres proches de ceux de iperf, ce qui est rassurant. nuttcp a le même genre d'options que iperf (-l pour changer la taille des tampons, -w pour la fenêtre TCP, etc). Il peut utiliser plusieurs sessions TCP (option -N) mais ne semble pas permettre de fixer la MSS.

Un outil plus récent, encore un peu expérimental mais qui a bien marché sur mes machines est ipmt. On lance le serveur ainsi :

% tcptarget
IPv6 (and IPv4) protocol
Using port 13000
...

Et le client avec :

% ./tcpmt test2.bortzmeyer.org      
IPv4 protocol

Time         Packets    Total      |    Kbit/s  Avg 10  Avg
33496.429     486       486        |    5045    5045    5045
33497.345     179       665        |    2283    3805    3805
33498.467     134       799        |    1394    2950    2950
...

et les résultats sont affichés en continu (utile si le réseau change).

Enfin, le traditionnel Netpipe ne semble plus guère maintenu et fonctionne mal sur les Unix récents.

Le RFC mentionne aussi d'autres outils comme tcptrace, outil d'analyse des sessions capturées au format pcap et qui, avec ses options -r et -l, permet de calculer des choses comme le RTT.

Un petit avertissement de sécurité, pour finir (section 6). Les mesures de ce RFC sont des mesures actives, susceptibles de perturber sérieusement le réseau. Le principe étant d'occuper tout le tuyau, la mesure ressemble fort à une DoS. Soyez donc prudent (RFC 4656 et RFC 5357).


Téléchargez le RFC 6349


L'article seul

RFC 6347: Datagram Transport Layer Security version 1.2

Date de publication du RFC : Janvier 2012
Auteur(s) du RFC : E. Rescorla (RTFM), N. Modadugu (Stanford University)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF tls
Première rédaction de cet article le 21 janvier 2012


Le protocole de cryptographie TLS, normalisé dans le RFC 5246, ne s'appliquait traditionnellement qu'à TCP. Les applications utilisant UDP, comme le fait souvent la téléphonie sur IP, ne pouvaient pas utiliser TLS pour protéger leur trafic contre l'écoute ou la modification des données. Mais cette limitation a disparu avec DTLS, qui permet de protéger du trafic UDP. Ce RFC met à jour DTLS (initialement normalisé dans le RFC 4347) pour TLS 1.2. (Depuis, la version 1.3 est sortie, dans le RFC 9147.)

TLS ne tournait que sur TCP car il avait besoin d'un transport fiable, garantissant que les données arrivent toutes, et dans l'ordre. Le grand succès de TLS (notamment utilisé pour HTTP et IMAP) vient de sa simplicité pour le programmeur : rendre une application capable de faire du TLS ne nécessite que très peu de code, exécuté juste avant l'envoi des données. Par contre, cela laissait les applications UDP comme SIP non protégées (section 1 de notre RFC). Les solutions existantes comme IPsec ne sont pas satisfaisantes (cf. RFC 5406), notamment parce qu'elles n'offrent pas la même facilité de déploiement que TLS, qui tourne typiquement dans l'application et pas dans le noyau.

DTLS a été conçu pour fournir TLS aux applications UDP. Il offre les mêmes services que TLS : garantie de l'intégrité des données et confidentialité.

La section 3 explique les principes de DTLS : protégé ou pas par DTLS, UDP a la même sémantique, celle d'un service de datagrammes non fiable. D'autre part, DTLS est une légère modification de TLS : il en garde les principales propriétés, bonnes ou mauvaises.

Mais pourquoi ne peut-on pas faire du TLS normal sur UDP ? Parce que TLS n'a pas été conçu pour tourner au dessus d'un protocole non fiable. TLS organise les données en enregistrements (records) et il ne permet pas de déchiffrer indépendamment les enregistrements. Si l'enregistrement N est perdu, le N+1 ne peut pas être déchiffré. De même, la procédure d'association initiale de TLS (handshake) ne prévoit pas de perte de messages et ne se termine pas si un message est perdu.

Le premier problème fait l'objet de la section 3.1. La dépendance des enregistrements TLS vis-à-vis de leurs prédécesseurs vient du chaînage cryptographique (le chiffrement par chaînagestream cipher - est donc supprimé en DTLS) et de fonctions anti-rejeu qui utilisent un numéro de séquence, qui est implicitement le rang de l'enregistrement. DTLS résout le problème en indiquant explicitement le rang dans les enregistrements.

Et la question de l'association initiale est vue dans la section 3.2. Pour la perte de paquets lors de l'association, DTLS utilise un système de retransmission (section 3.2.1) et pour l'éventuelle réorganisation des paquets, DTLS introduit un numéro de séquence (section 3.2.2). En prime, DTLS doit gérer la taille importante des messages TLS (souvent plusieurs kilo-octets), qui peut être supérieure à la MTU. DTLS permet donc une fragmentation des paquets au niveau applicatif, un message pouvant être réparti dans plusieurs enregistrements (section 3.2.3).

Enfin, l'anti-rejeu a été modifié pour tenir compte du fait que la duplication de paquets, en UDP, n'est pas forcément malveillante (sections 3.3 et 4.1.2.6).

La définition formelle du nouveau protocole est en section 4. DTLS étant une légère évolution de TLS, la définition se fait uniquement en listant les différences avec TLS. Il faut donc garder le RFC 5246 sous la main.

Dans le Record Protocol de TLS, l'enregistrement spécifié dans la section 6.2.1 du RFC 5246 gagne deux champs (section 4.1) :

  struct {
         ContentType type;
         ProtocolVersion version;
         uint16 epoch;                                    // NOUVEAU
         uint48 sequence_number;                          // NOUVEAU
         uint16 length;
         opaque fragment[DTLSPlaintext.length];
       } DTLSPlaintext;

notamment le numéro de séquence sequence_number (qui était implicite dans TLS, puisque TCP garantissait l'ordre des messages). Pour éviter la fragmentation et les ennuis associés, les mises en œuvre de DTLS doivent déterminer la MTU du chemin et n'envoyer que des enregistrements plus petits que cette MTU (section 4.1.1).

Contrairement à IPsec, DTLS n'a pas la notion d'identificateur d'association. Une machine qui reçoit du TLS doit trouver l'association toute seule, typiquement en utilisant le tuple (adresse IP, port).

En toute rigueur, DTLS n'est pas spécifique à UDP, il peut marcher sur n'importe quel protocole de transport ayant une sémantique « datagrammes ». Certains de ces protocoles, comme DCCP (cf. RFC 5238), ont leur propres numéros de séquence et ils font donc double emploi avec ceux de DTLS. Petite inefficacité pas trop grave.

Au niveau du Hanshake protocol, les modifications que DTLS apporte à TLS font l'objet de la section 4.2. Les trois principales sont :

  • L'ajout d'un gâteau pour limiter les risques de DoS,
  • Modification des en-têtes pour gérer les pertes ou réordonnancements des paquets (section 4.2.2),
  • Ajouts de minuteries pour détecter les pertes de paquets (section 4.2.4).

Les gâteaux de DTLS sont analogues à ceux de Photuris ou IKE (section 4.2.1). Le message ClientHello de la section 7.4.1.2 du RFC 5246 y gagne un champ :

 opaque cookie<0..32>;         // NOUVEAU

Évidemment, ils ne protègent pas contre un attaquant qui utilise sa vraie adresse IP, puisque celui-ci pourra lire la réponse.

OpenSSL gère DTLS depuis la version 0.9.8 (on peut aussi consulter le site Web du développeur). Un exemple d'utilisation se trouve dans http://linux.softpedia.com/get/Security/DTLS-Client-Server-Example-19026.shtml. Il me reste à inclure ce protocole dans echoping. GnuTLS a un support DTLS plus récent.

Et les nouveautés de DTLS 1.2 par rapport au 1.0 du RFC 4347 ? (Il n'y a pas eu de DTLS 1.1.) Elles sont résumées dans la section 8. La principale nouveauté est que DTLS est désormais défini par rapport à TLS 1.2 et non plus 1.0. Cela a notamment permis d'inclure les numéros de séquence explicites de TLS 1.1, nécessaires contre l'attaque BEAST (section 4.1.2.1). Une autre nouveauté est la section 4.1.2.7 qui discute le traitement des paquets invalides. Contrairement à TLS, DTLS peut fonctionner en présence de tels paquets, avec une sémantique proche de celle d'UDP : les laisser tomber et attendre que l'application se débrouille (en demandant leur réémission ou bien en passant à autre chose). Enfin, d'autres clarifications ont été apportées, par exemple à la détection de la PMTU ou bien à l'enregistrement dans les registres IANA.

Une très bonne description de la conception de Datagram TLS et des choix qui ont été faits lors de sa mise au point, se trouve dans l'article The Design and Implementation of Datagram TLS, écrit par les auteurs du RFC. C'est une lecture très recommandée.


Téléchargez le RFC 6347


L'article seul

RFC 6346: The A+P Approach to the IPv4 Address Shortage

Date de publication du RFC : Août 2011
Auteur(s) du RFC : R. Bush (Internet Initiative Japan)
Expérimental
Première rédaction de cet article le 28 août 2011


Pendant longtemps, le problème technique posé à l'IETF par l'épuisement des adresses IPv4 était traité par la perspective d'une migration vers IPv6, et les efforts de l'IETF allaient vers la création de jolis mécanismes de transition vers ce nouveau protocole. Mais la migration est très loin d'être terminée (sur beaucoup de sites, elle n'a même pas réellement commencé) et, dans des régions comme l'Asie, les adresses IPv4 ne sont plus seulement difficiles à obtenir et chères, elles sont tout simplement toutes utilisées. Il faut donc maintenant, en urgence, mettre au point des mécanismes qui permettront de vivre pas trop mal en attendant le déploiement d'IPv6. C'est le cas du mécanisme A+P (Address plus Port) de ce RFC.

Tous ces mécanismes sont pour le court terme. À moyen et à long terme, la solution correcte, comme avant, reste le passage à IPv6. Toutefois, pour tous les paresseux et les irresponsables qui n'ont pas encore commencé cette migration, il est trop tard : même s'ils se réveillaient demain, ils n'auraient pas le temps de terminer leur transition vers IPv6 avant que le manque d'adresses IPv4 ne devienne un vrai blocage pour leur activité.

A+P, présenté dans ce RFC, propose une solution pour limiter les dégâts, chez les derniers utilisateurs d'IPv4. Cet article va être relativement court, par manque de temps pour explorer en détail cette technologie, mais aussi parce que je suis sceptique : c'est très gentil d'essayer de maintenir la tête des utilisateurs IPv4 hors de l'eau encore quelques mois ou quelques années, mais cela va coûter pas mal d'efforts, qui seraient mieux employés à leur apprendre à nager (à déployer IPv6).

Donc, quels sont les principes d'A+P ? Comme les miracles n'existent pas, l'idée de base est un compromis. On va sacrifier quelques bits du numéro de port pour les donner à l'adresse IP. Ce faisant, on réduit la capacité des applications à allouer beaucoup de connexions ouvertes (chacune nécessitant un port) mais il n'y a plus guère le choix. Comme le note le RFC, « the need for addresses is stronger than the need to be able to address thousands of applications on a single host » ou, en termes plus brutaux, « en cas de famine, on ne réclame pas d'assaisonnement sur tous les plats ».

Cette famine fait que le partage d'adresses IPv4, déjà largement réalisé au sein d'une même maison ou entreprise, va forcément s'étendre et que des clients différents, sans lien entre eux, partageront la même adresse IP. L'idée d'A+P est que, même si l'adresse ne sera plus unique, le couple {adresse, partie du port} restera unique par client. Avec 65536 ports possibles, on peut mettre 65536 clients sur une même adresse IP (si chacun se contente d'un seul port), 256 (avec 256 ports chacun), ou un seul (avec le système actuel où le client a 65536 ports)... L'un des intérêts d'A+P est qu'il limite (sans toutefois le supprimer) le recours au NAT et à tous ses inconvénients.

En effet, une alternative à A+P serait de déployer des gros routeurs NAT (CGN, pour Carrier-grade NAT) dans les réseaux des FAI, routeurs qui traduiraient pour plusieurs clients (au contraire du routeur NAT typique d'aujourd'hui, qui n'opère que pour un seul client). La section 1.1 explique pourquoi c'est une mauvaise idée : le CGN ne maintient pas la connectivité de bout en bout, qui est au cœur d'Internet. Par exemple, le déploiement d'une nouvelle application qui échange des adresses serait bloqué tant que le routeur CGN (qui est sous le contrôle du FAI) n'est pas mis à jour avec un nouvel ALG. Les techniques qui permettent de rendre les routeurs NAT actuels un peu moins insupportables (configuration manuelle de la redirection de port, UPnP) ne marchent en effet pas sur un CGN. Enfin, les routeurs CGN stockent un état considérable (des centaines ou des milliers de clients) et sont donc un point de faiblesse du réseau : si un routeur CGN redémarre, tout est perdu.

La section 3 détaille les contraintes que s'impose A+P, afin d'éviter ces défauts :

  • Maintien, dans la mesure du possible, du principe de bout en bout (ne pas utiliser l'épuisement des adresses v4 comme excuse pour limiter l'usage que les utilisateurs peuvent faire de l'Internet),
  • Compatibilité avec l'existant, par exemple, les anciennes applications doivent marcher comme avant,
  • Ne pas garder trop d'état dans le réseau du FAI,
  • Traçabilité des utilisateurs, c'est-à-dire capacité à fliquer quel ordinateur a fait telle action,
  • Ne pas décourager la migration vers IPv6, comme, dit le RFC, le fait le NAT444 (ou « double-NAT »).

Ce cahier des charges est-il réaliste ? Le reste de la section 3 raconte comment fonctionne A+P. Il y a trois fonctions :

  • Traduction : pour gérer les anciennes applications, qui allouent des ports sans restriction, et tournent sur une machine qui imagine être la seule au monde à avoir cette adresse IP, il faudra une fonction de traduction analogue au NAT actuel,
  • Encapsulation et décapsulation : s'il y a des anciens routeurs sur le trajet, il faudra encapsuler les paquets. Ce sera le travail du PRR (Port Range Router),
  • Signalisation : les machines nouvelles (qui connaissent A+P), ont besoin de savoir quelle plage de ports leur a été allouée.

Le traducteur devra faire bien attention, contrairement au NAT actuel, à n'utiliser en sortie que des ports appartenant à la plage allouée.

La signalisation est le gros morceau (section 3.3.1). A+P peut utiliser plusieurs protocoles pour cela (à ma connaissance, tous sont encore au stade de brouillon). Le protocole doit permettre d'informer une machine A+P de l'adresse IPv4 publique à utiliser, des plages de ports réservées pour elle, de la durée pendant laquelle ces allocations restent valables, etc. L'allocation des ports peut être statique (« tu as de 20 000 à 31 000 ») ou dynamique par des nouveaux protocoles comme UpNPv2.

Si on a un site client réduit, avec une seule machine, qui connaît A+P, et un équipement A+P chez le FAI, et que l'adresse IPv4 publique donnée au site client est {192.0.2.1, ports 20 000 à 31 000}, un paquet sortant du site client est émis tel quel (la machine sait n'utiliser comme port source que ceux alloués) et le paquet rentrant est traité ainsi dans l'équipement A+P :

  • En regardant le port de destination, on trouve à quel client est destiné ce paquet (routage par le port, l'adresse IP ne suffisant plus, car elle est partagée entre plusieurs clients),
  • On lui transmet.

Dans ce cas, pas besoin de traduction. Évidemment, dans la réalité, ce sera plus compliqué : il y aura plusieurs machines sur le site du client et, surtout, ces machines ne connaîtront pas toutes A+P et émettront donc des paquets avec des ports source quelconques. Cette fois, on ne pourra pas se passer de traduction : une machine chez le client (et non pas chez le FAI) va alors traduire ces paquets pour mettre l'adresse source allouée et changer le port source pour un des ports alloués. Au retour, ce même traducteur fera l'opération inverse, très proche de celle des routeurs NAT d'aujourd'hui.

Est-ce que tout cela marche vraiment en pratique ? La section 3.4 rend compte des essais effectués à France Télécom. Les plus gros problèmes sont survenus avec des mises en œuvre de BitTorrent, qui veulent accepter des connexions entrantes sur un port précis mais, globalement, il n'y a pas eu trop de problèmes.

Si vous aimez les considérations pratiques, la section 5 est vouée aux problèmes de déploiement. Par exemple, pour des sites client en ADSL ou connectés par le câble, le modèle le plus logique est que les fonctions de traduction soient dans la box, le FAI allouant les plages de ports et les communiquant audit CPE. (Pour un réseau 3G, c'est plus complexe, car le smartphone ne peut pas forcément assurer beaucoup de fonctions.)

Comment le FAI décide-t-il de l'allocation des ports (section 5.2) ? Une solution évidente est de diviser équitablement. Si on met cent clients par adresse IP, chacun a 655 ports et se débrouille avec. Le risque de cette allocation statique est alors que les clients les plus gourmands soient limités, alors que les autres ont des ports libres. L'idéal serait donc que l'allocation soit dynamique, s'ajustant à la demande.

Comme avec le NAT, certains protocoles vont poser des problèmes particuliers. Ainsi, ICMP (section 5.3.2), n'ayant pas le concept de port, va être difficile à faire passer. Pour les messages d'erreur transportés par ICMP, comme ils incluent le début du paquet qui a provoqué l'erreur, on peut y trouver un numéro de port et router par ce biais. Pour les messages d'écho (ceux qu'utilise ping), il n'y a pas d'autre solution que de bricoler avec des champs comme l'identificateur du message ICMP, ou comme le numéro de séquence ICMP, en les utilisant comme numéros de port.

Parmi les autres problèmes concrets que devra résoudre la machine A+P, il y a enfin la fragmentation, source traditionnelle d'ennuis. Ici, le routage se faisant en fonction du port de destination, un réassemblage des fragments entrants est nécessaire, pour déterminer ledit port.

A+P, on l'a vu, est un système complexe. Il a quelques limitations, documentées en section 5.3.4. La principale est que les ports bien connus, notamment le célébrissime port 80, utilisé par les serveurs HTTP, ne seront pas forcément disponibles. Si le client qui a obtenu une plage de ports située au début (du côté des ports bien connus, en dessous de 1024) est heureux (et on peut même envisager de le faire payer plus cher pour ce « privilège »), les autres n'ont pas de solution, s'ils veulent faire tourner un serveur HTTP sur leur machine.

Enfin, A+P marche mal ou pas du tout avec IPsec, bien qu'il soit possible de contourner le problème avec les techniques du RFC 3715.

Et question sécurité, ça se passe comment ? La section 7 fait la liste des questions de sécurité liées à A+P. La première est la difficulté de suivre à la trace un utilisateur. Pour savoir qui a osé commettre un délit aussi grave que de partager de la culture, il faut que l'espion qui surveille le trafic ait noté le numéro de port source (cf. RFC 6302), et que l'équipement A+P ait enregistré qui avait la plage où se trouve ce numéro. A+P est donc plus efficace pour le flicage qu'un CGN ou qu'un NAT traditionnel, qui doit noter une information bien plus évanescente (qui avait ce port à ce moment-là). Reste à savoir si c'est un avantage...

Quel est l'état des implémentations de A+P au moment de la publication de ce RFC ? L'ISC a A+P dans son routeur logiciel (surtout connu pour DS-Lite) AFTR (qui ne semble actuellement pourvoir faire que de l'allocation de ports statique), France Télécom / Orange a également un logiciel libre en http://opensourceaplusp.weebly.com/, et il existe le logiciel 4RD de la société ipinfusion.com. Pour le futur, Iskratel et, dans une moindre mesure, Cisco et Juniper, ont indiqué qu'ils y travaillaient.


Téléchargez le RFC 6346


L'article seul

RFC 6336: IANA Registry for Interactive Connectivity Establishment (ICE) Options

Date de publication du RFC : Juillet 2011
Auteur(s) du RFC : M. Westerlund (Ericsson), C. Perkins (University of Glasgow)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF mmusic
Première rédaction de cet article le 20 juillet 2011


Le protocole de traversée des NAT, ICE (normalisé dans le RFC 5245), offre la possibilité d'ajouter des options, identifiées par un nom (section 14 du RFC 5245). Mais aucun registre n'existait pour stocker les noms de ces options et éviter des collisions. C'est désormais fait.

Il n'y a pas encore une seule option utilisée par les mises en œuvre d'ICE. Mais une est en cours de développement et cela a motivé la création de ce registre. Donc, une option a un nom, composé d'une série de caractères alphanumériques (on peut aussi utiliser le + et le /). Ce nom est enregistré en suivant la règle « spécification (écrite et publique) obligatoire » de la section 4.1 du RFC 5226, et en indiquant diverses métadonnées comme les coordonnées de la personne ou de l'organisme qui enregistre.

Et c'est tout, le registre (actuellement vide) se trouve en https://www.iana.org/assignments/ice-options/ice-options.xml.


Téléchargez le RFC 6336


L'article seul

RFC 6335: Internet Assigned Numbers Authority (IANA) Procedures for the Management of the Transport Protocol Port Number and Service Name Registry

Date de publication du RFC : Août 2011
Auteur(s) du RFC : M. Cotton (ICANN), L. Eggert (Nokia), A. Mankin (Johns Hopkins Univ.), J. Touch (USC/ISI), M. Westerlund (Ericsson), S. Cheshire (Apple)
Réalisé dans le cadre du groupe de travail IETF tsvwg
Première rédaction de cet article le 3 septembre 2011


Ce RFC parle autant de gouvernance que de technique. Il refond considérablement les procédures utilisées pour enregistrer les numéros de port à l'IANA. Bien que moins médiatisé que l'enregistrement des noms de domaine, ou même que celui des adresses IP, cet enregistrement des ports a déjà suscité des conflits, et peut en faire encore plus maintenant qu'une des plages utilisées approche de la saturation. L'ancien mécanisme d'enregistrement était peu documenté, avait plusieurs limites techniques, et était éclaté entre plusieurs registres ayant des règles différentes. Le nouveau vise à unifier tout cela et à suivre de bons principes, soigneusement explicités.

D'abord, de quoi s'agit-il (section 3) ? Les ports sont des numéros, codés sur 16 bits, qui servent à démultiplexer les paquets IP entrant dans une machine (port de destination 62981 -> processus 7653, qui fait tourner dig, etc) et à identifier le protocole utilisé (port 80 -> HTTP, port 22 -> SSH, etc). Les noms de services, eux, sont des courts identificateurs alphabétiques, qui servent à s'abstraire du numéro de port, en permettant aux applications d'utiliser un nom de service pour récupérer dynamiquement un numéro de port (par exemple avec les enregistrements SRV du DNS, ou bien avec un appel à getservbyname()). Sur Unix, vous avez une liste (incomplète) de ces noms, avec le numéro de port correspondant, dans le fichier /etc/services. Pendant longtemps, les registres officiels stockaient à la fois un nom de service et un numéro de port. Désormais, ils pourront ne contenir qu'un nom de service.

Le port n'est pas indiqué dans l'en-tête IP mais dans celle du protocole de couche 4 au dessus. On peut donc techniquement utiliser le même numéro de port pour des applications différentes, si l'une utilise UDP et l'autre TCP. La procédure d'enregistrement, elle, est désormais la même pour tous les protocoles de transport.

Les en-têtes de couche 4 incluent deux ports, celui de source et celui de destination, et, avec les adresses IP source et destination et l'identificateur du protocole de transport, ils servent aussi à identifier une connexion de manière unique.

Du fait que l'ancien système d'enregistrement à l'IANA allouait en même temps un nom de service et un numéro de port, bien des applications savent utiliser ce nom de service. Par exemple, avec telnet, on peut se connecter à un serveur de courrier avec telnet mail.example.net 25 (le numéro de port) mais aussi avec telnet mail.example.net smtp (le nom du service). Le port ainsi enregistré est dit « bien connu » (80 pour HTTP...) Mais attention : de nos jours, il est courant de faire tourner une application sur un port autre que celui prévu à l'origine (parce que le pare-feu ne laisse passer que le port 80, pour échapper à la détection, ou encore parce qu'on veut faire tourner deux mises en œuvre différentes du protocole sur la même machine, ou derrière le même routeur NAT). Enfin, certaines applications n'ont pas de port fixe et comptent sur les enregistrements SRV du DNS (RFC 2782), ou bien sur d'autres méthodes (comme les trackers dans BitTorrent).

Un dernier points sur les numéros de port : comme ils sont stockés sur seulement 16 bits, il n'y a que 65 536 valeurs possibles. C'est très peu. La première plage, celle des ports bien connus, est déjà pleine à 76 %. Un des objectifs de la politique d'allocation des ports est donc d'épargner cette ressource limitée, notamment en conseillant fortement aux applications d'utiliser uniquement un nom de service, sans réserver de numéro de port.

Le plan du RFC commence par expliquer la situation actuelle et pourquoi elle n'est pas satisfaisante. Mais je préfère partir de la nouvelle situation, celle qui est désormais l'officielle, et parler du passé tout à la fin de cet article.

D'abord, les noms de services (section 5). Ce sont les clés d'accès au registre des services. Les applications les utilisent pour chercher un numéro de port, typiquement via les enregistrements SRV du RFC 2782. Il peut y avoir plusieurs services qui se partagent un numéro de port, par exemple :

  • Parce que l'un est une extension de l'autre (cas de TURNRFC 8656, qui est une extension de STUNRFC 8489 ; le fait d'avoir un service nommé turn permet à une application d'obtenir tout de suite un serveur ayant l'extension TURN, sans tester plusieurs serveurs STUN),
  • Par accident (un exemple typique est la coexistence de deux services www et http qui pointent vers le même port 80 ; seul http est correct, aujourd'hui),
  • Ou suite à la sortie de notre RFC qui introduisait des nouvelles règles de syntaxe pour les noms de services, rendant parfois nécessaire la création d'alias (l'ancien et le nouveau nom).

Les noms de services dans le registre sont enregistrés sur une base « premier arrivé, premier servi », tel que décrit dans le RFC 5226 (voir aussi la section 7.2). Contrairement aux numéros de port, il n'y a pas de pénurie et donc pas de raison de faire des économies, sauf si l'IANA détecte un problème (comme un enregistrement massif de noms) auquel cas elle peut passer au mécanisme Expert review, où un examen de fond est fait. Les noms doivent être courts (quinze caractères maximum) et informatifs, et éviter les redondances (comme de mettre protocole ou port dans le nom).

La syntaxe des noms (une nouveauté de ce RFC) est décrite en section 5.1. En résumé, seuls les lettres d'ASCII, les chiffres et le tiret sont admis. Il faut au moins une lettre, pour éviter des noms de service comme 23, qui pourrait être pris pour un numéro de port. 98 % des noms du registre étaient déjà conformes à cette syntaxe avant ce RFC, les 2 % restants ont dû changer de nom pour se plier à la nouvelle syntaxe. C'est ainsi que, par exemple, z39.50 (pour le protocole du même nom) est devenu z39-50.

Dans le cas le plus courant, l'application va traduire ces noms en numéro de port via une requête DNS. Prenons l'exemple de XMPP. Si le serveur de messagerie instantanée de Google Talk veut contacter un utilisateur dont l'adresse XMPP est martinedurand@dns-oarc.net, le serveur de Google va faire une requête SRV pour le service xmpp-server, protocole TCP (RFC 6120, section 3.2.1). Il trouvera :

% dig SRV _xmpp-server._tcp.dns-oarc.net
...
;; ANSWER SECTION:
_xmpp-server._tcp.dns-oarc.net.	3600 IN	SRV	0 0 5269 jabber.dns-oarc.net.

et saura donc qu'il doit se connecter au port 5269. (Le fait que le champ « service » du RFC 2782 doive être un nom de service enregistré n'était pas clair : c'est notre nouveau RFC qui impose cette règle.)

L'enregistrements des numéros de port est plus complexe, en raison du risque de pénurie (section 6). Il y a trois plages de numéros de port :

  • Les ports « système », dits aussi « bien connus », de 0 à 1023.
  • Les ports « utilisateur », de 1024 à 49151.
  • Et les ports « dynamiques », dits aussi « éphémères », de 49152 à 65535. Contrairement aux deux précédentes plages, ils ne font jamais l'objet d'un enregistrement à l'IANA.

Il y a trois statuts possibles pour un numéro de port :

  • Affecté : il apparaît alors dans le registre,
  • Non affecté,
  • Réservé : ils ne sont pas affectés et ne doivent normalement pas l'être. Par exemple, les ports extrêmes de la plage des bien connus, 0 et 1023, sont réservés, au cas où il faille un jour étendre cette plage ; on les utiliserait alors comme indiquant un échappement.

Aujourd'hui, 76 % des ports système et 9 % des ports utilisateur sont affectés.

Il existe aussi des ports voués à des usages expérimentaux (section 6.1, voir aussi le RFC 3692), les ports 1021 et 1022. Comme des tas de protocoles peuvent s'y bousculer, les applications qui utilisent ces ports doivent s'assurer qu'elles se connectent bien au service attendu (par exemple, le client peut vérifier que le serveur envoie un nombre magique caractéristique de l'application).

Comment enregistre-t-on un nouveau numéro de port ? La section 7 décrit les grands principes. Le plus important est la nécessité d'allouer lentement, pour éviter d'épuiser ce qui reste de cette ressource (si vous développez un nouveau protocole, rappelez-vous que la méthode recommandée est de ne pas réclamer de numéro de port du tout, mais d'utiliser un nom de service). Environ 400 ports par an sont affectés, et le chiffre est stable depuis des années. Cela devrait permettre de tenir jusqu'à la fin du 21ème siècle.

Compte-tenu de cela, les nouveaux principes, exposés en section 7.2 sont :

  • Un seul numéro de port par application : si celle-ci est composée de plusieurs services, l'application doit néanmoins tout mettre sur le même numéro de port et démultiplexer elle-même.
  • Même chose en cas de mise à jour d'un service : on n'alloue pas de nouveau numéro de port. La technique recommandée est que le service inclue un champ Version dans ses messages, pour qu'il puisse les séparer facilement.
  • Affectation uniquement pour le protocole de transport indiqué (c'est une grande nouveauté par rapport aux précédentes règles). Si l'application ne fonctionne que sur TCP, aucune allocation de port n'est faite pour UDP.
  • Rien n'est éternel et une allocation de numéro de port peut être reprise par l'IANA.

Les ports « repris » auront le statut Réservé (sur l'Internet, il n'est pas prudent de réallouer des ports trop tôt, on ne peut jamais être sûr de ce qui traîne dans des vieilles applications, cf. section 8.3). Le jour où une plage de numéros de port est épuisée, l'IANA pourra recycler ces vieux numéros en les affectant.

Tout le détail des procédures bureaucratiques est en section 8. Si on veut un numéro de port ou un nom de service, il faut remplir un formulaire (section 8.1.1) indiquant les coordonnées du demandeur (pour les normes au sens propre, ce demandeur sera l'IETF), une description du protocole prévu et le nom du protocole de transport (TCP, UDP, etc). Si on veut un numéro de port, on peut préciser lequel (et l'IANA le donnera, sauf bonne raison contraire). Les ports rigolos comme 42, 666 ou 1984 (utilisé par un logiciel de surveillance) sont déjà pris.

Rappelez-vous qu'il y aura une grosse différence entre demande d'un numéro de port et demande d'un simple nom de service. Les premiers feront l'objet d'une Expert Review (cf. RFC 5226), le seconds seront distribués sans trop de formalité. Pour les numéros de port, cela dépendra en outre de la plage visée. La plage dynamique ne permet pas de réservation du tout, la plage utilisateur est recommandée pour les nouvelles réservations, la plage système, celle des ports bien connus, est tellement pleine que l'enregistrement est découragé, un avis d'expert ne suffira pas, il faudra un IETF review et encore, après avoir expliqué en détail pourquoi ne pas utiliser un port de la plage utilisateur.

Nouveauté de notre RFC, il y a désormais des procédures explicites pour le retrait d'un enregistrement (section 8.2 ; cela concerne surtout les numéros de port, les noms de service peuvent rester enregistrés sans que cela ne gène personne). Le demandeur original peut demander un retrait, s'il n'a plus besoin de l'enregistrement. Mais l'IANA peut aussi le faire d'autorité, si cela semble vraiment nécessaire.

Dans tous les cas, l'IANA tentera de déterminer si le port est encore utilisé.

En revanche, le transfert d'un enregistrement (numéro de port ou nom de service) d'un protocole à un autre est formellement interdit (section 8.4), même entre adultes consentants. Pas de marché des numéros de port, qui aurait permis à ceux qui avaient déposé des numéros il y a longtemps de gagner de l'argent en les vendant maintenant qu'ils sont rares. Si on veut récupérer un numéro de port, il faut le faire désaffecter, puis candidater pour l'avoir.

Il y aura sans doute des désaccords et des crises (comme dans l'affaire CARP). La procédure habituelle de gestion des conlits à l'IETF (section 7 du RFC 5226) sera donc utilisée.

Un peu d'histoire, maintenant. Quels étaient les procédures avant notre RFC ? Les règles IANA étaient dans le RFC 2780 et notre RFC remplace ses sections 8 et 9. Il y avait aussi des règles spécifiques aux différents protocoles de transport : RFC 3828 pour UDP-Lite, RFC 4340 pour DCCP, et RFC 4960 pour SCTP. Mais elles n'étaient pas complètes (une partie de la procédure était également dans les formulaires Web de soumission à l'IANA, une autre partie était dans le texte du registre), et aussi bien l'IANA que ses « clients » se plaignaient de leur flou (section 1). La section 7.1 de notre RFC 6335 tente de résumer a posteriori les règles (largement informelles) qui étaient utilisées (affectation du port pour TCP et UDP simultanément, pas d'enregistrement des noms de service séparément des ports, SCTP et DCCP traités à part, etc).

En outre, les enregistrements SRV du RFC 2782 ajoutaient leurs propres concepts (nom de service, notion mal définie dans le RFC 2782) et leur propre registre. Ainsi, comme les procédures de l'IANA ne permettaient pas d'enregistrer un nom de service sans obtenir en même temps un numéro de port, on a vu apparaître un registre informel des noms de service (qui a fusionné avec l'officiel, cf. section 10). Un des changements importants de ce RFC 6335 est d'unifier les procédures d'enregistrement et les registres.

La syntaxe admissible pour les noms de service n'avait même jamais été spécifiée (section 2). Les formulaires de l'IANA donnaient une limite de longueur (arbitraire et, d'ailleurs, pas toujours respectée dans le registre) à 14 caractères, mais sans préciser si des caractères comme le + ou le / étaient autorisés. On trouvait donc des noms avec des caractères non-alphanumériques comme whois++ (RFC 2957) ou sql*net.

D'autre part, il n'existait aucune procédure écrite pour les opérations postérieures à l'enregistrement : changement, ou suppression (volontaire ou forcée).

PS : si vous vous intéressez aux questions d'enregistrement de paramètres pour les protocoles, voyez la nouvelle liste de discussion happiana.


Téléchargez le RFC 6335


L'article seul

RFC 6333: Dual-Stack Lite Broadband Deployments Following IPv4 Exhaustion

Date de publication du RFC : Août 2011
Auteur(s) du RFC : A. Durand (Juniper Networks), R. Droms (Cisco), J. Woodyatt (Apple), Y. Lee (Comcast)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF softwire
Première rédaction de cet article le 14 août 2011


Il existe une myriade de techniques de coexistence entre l'ancien protocole IPv4 et le nouvel IPv6, à tel point qu'on peut même avoir du mal à faire son choix (voir mon exposé à ce sujet). Et le groupe de travail Soft Wires (réseaux virtuels variés) de l'IETF en invente de temps en temps des nouvelles. Pour ne pas s'affoler devant cette multitude, il faut se rappeler que chacune de ces techniques a un but bien précis et sert dans un cas donné. DS-Lite (Dual-Stack Lite), objet de ce RFC, vise les FAI récents, qui n'ont jamais eu d'adresses IPv4 publiques en quantité et dont le réseau interne est en IPv6 depuis le début.

Donc, DS-Lite est à l'opposé de, par exemple, 6rd (RFC 5969), qui vise les FAI existants qui n'ont pas le courage de mettre à jour leur réseau IPv4. DS-Lite vise un autre problème : si, en 2011, je crée un nouveau FAI en Asie (APNIC a été le premier RIR dont le stock d'adresses IP est tombé à zéro), je n'obtiendrai dans le meilleur des cas qu'une poignée d'adresses IPv4 publiques. Mais le reste de l'Internet (et même le réseau local de mes clients, et leurs applications) est majoritairement en IPv4. Mon beau réseau tout neuf, qui pourra être IPv6 depuis le début puisqu'il n'aura pas à porter le poids de l'héritage, ne me servira donc à rien (sauf à voir ce blog, qui est accessible en IPv6). Ce cas n'était pas prévu à l'origine ; il y a eu largement assez de temps pour faire une transition plus simple de IPv4 vers IPv6 mais beaucoup d'acteurs ont traîné les pieds, nous amenant à la situation actuelle, où il faut déployer IPv6 sans pouvoir compter sur des adresses v4 publiques en quantité suffisante. DS-Lite arrive alors à la rescousse.

Le principe de DS-Lite est donc de connecter à l'Internet IPv4 (et bien sûr aussi IPv6) des machines IPv4 (les machines des clients) au dessus d'un FAI v6, et sans avoir beaucoup d'adresses IPv4 publiques. (Les machines purement IPv6 ne sont donc pas concernées, elles ont une connexion native normale, seules les machines/applications qui utilisent encore IPv4 doivent passer par ce bricolage.) Le principe : le réseau local du client a des adresses privées v4. La box encapsule les paquets v4 au dessus du réseau v6 (tunnel IPv4-dans-IPv6) jusqu'à un NAT géant (CGN) qui traduit ces adresses en adresses publiques (il faut donc avoir au moins quelques adresses IPv4 publiques). DS-Lite réutilise donc deux techniques éprouvées, le tunnel et le NAT.

Pour suivre la description détaillée, un peu de vocabulaire (section 3). DS-Lite nécessite deux composants :

  • Le B4 (Basic Bridging Broadband element, le B4 étant un jeu de mots car il se prononce comme before, indiquant que ce composant est avant le tunnel), qui est dans le réseau de M. Toutlemonde, et tunnele les paquets IPv4 de ce M. Toutlemonde vers :
  • L'AFTR (Address Family Transition Router, ce qui se prononce comme after, indiquant que cet élément est après le tunnel), le CGN (routeur NAT géant) qui traduit des adresses IPv4 privées de M. Toutlemonde vers la poignée d'adresses IPv4 publiques qu'a pu obtenir le FAI.

Entre le B4 et l'AFTR, il n'y a qu'IPv6 : tous les paquets IPv4 doivent être tunnelés. Enfin, pour suivre ce RFC, il peut être utile de réviser le vocabulaire de la double-pile (RFC 4213) et du NAT (RFC 4787).

Voici un schéma d'une communication avec le serveur Web d'adresse 192.0.2.23. L'adresse IPv4 publique utilisée par l'AFTR est 203.0.113.201. Le réseau IPv6 du FAI utilise 2001:db8::32. Le réseau local reçoit des adresses en 10.0.0.0/24 : ds-lite

La section 4 décrit plus en détail les scénarios envisageables pour DS-Lite. Rappelez-vous d'un des points les plus importants des techniques de transition/coexistence v4/v6 : on n'est pas obligés de les déployer toutes, bien au contraire. Chacune s'applique à des cas spécifiques. Les avantages essentiels de DS-Lite, vus par le RFC :

  • Une machine v4 ne communique qu'avec des machines v4 et une v6 qu'avec des v6. La traduction d'adresses se fait uniquement à l'intérieur d'une même famille (contrairement au NAT64 du RFC 7915).
  • DS-Lite découple le déploiement d'IPv6 dans chacun des trois réseaux : celui du client final, celui du FAI et celui de l'Internet global. Plus besoin d'attendre que quelqu'un d'autre commence ou s'y mette.
  • Le FAI n'a pas les limitations d'IPv4 dans son réseau interne (un vrai problème pour certains gros FAI, qui n'ont même pas assez d'adresses v4 pour leur propre réseau interne).
  • Le tunnel entre le B4 et l'AFTR peut être situé où le FAI le désire. Le mode le plus courant sera sans doute avec le B4 dans le CPE et l'AFTR en sortie du réseau du FAI mais ce n'est nullement obligatoire. Cette souplesse permet à la solution de grossir tranquillement. Par exemple, si seuls les clients d'une certaine région utilisent DS-Lite, on met l'AFTR dans cette région puis, si on étend la solution à tout le monde, on reporte simplement le ou les AFTR plus loin et plus près du centre du réseau (cf. annexe A).
  • Comme, du point de vue IPv4, les B4 sont directement connectés à l'AFTR, on peut envisager des techniques de contrôle du NAT par l'utilisateur (par exemple, réserver un port donné), peut-être avec le protocole PCP (Port Control Protocol, RFC 6887).

J'ai indiqué qu'un déploiement typique mettrait le B4 dans le CPE, dans la box. Ce n'est pas la seule possibilité. Mais ce sera sans doute la plus fréquente (l'annexe B décrit les différentes architectures, avec le détail des adresses). La section 4.2 décrit les caractéristiques d'un CPE ayant une fonction DS-Lite : il inclut un serveur DHCP pour distribuer des adresses IPv4 privées (RFC 1918) sur le réseau local, il ne fait pas de NAT lui-même (contrairement aux CPE d'aujourd'hui), il n'a pas d'adresse IPv4 publique, et, en IPv6, il est simplement un routeur ordinaire, sans traduction, ni particularités (connexion IPv6 native pour les clients qui en sont capables).

S'il n'y a pas de CPE (cas typique d'un smartphone connecté à un réseau 3G), la section 4.3 prend le relais : dans ce cas, la machine connectée doit être son propre B4.

La section 5 décrit en détail la fonction B4. Elle comprend la tunnelisation des paquets IPv4 vers l'AFTR. Au fait, comment le B4 connait-il son AFTR (section 5.4) ? Il doit être configuré avec l'adresse IPv6 de celui-ci, ou bien la récupérer via DHCP avec l'option du RFC 6334.

Pour le service DNS, le B4 doit connaître les adresses IPv6 des serveurs récursifs du FAI (rappelez-vous que la machine qui fait le B4 n'a typiquement pas d'adresse IPv4 publique), par exemple via DHCPv6. Les machines du réseau local, n'ayant pas forcément IPv6, il faut leur fournir un serveur récursif v4. Le RFC recommande que le B4 joue ce role et s'annonce lui-même comme récurseur (et suive alors les recommandations du RFC 5625).

Enfin, le B4 a besoin d'une adresse IPv4 à lui, pour les paquets dont il est l'origine. La plage 192.0.0.0/29 a été réservée pour cela (cf. section 10), le 192.0.0.2 étant pour le B4. Ce préfixe a d'ailleurs été élargi ultérieurement à d'autres systèmes que DS-Lite dans le RFC 7335.

La section 6 fait la même chose (décrire tous les détails) pour la fonction AFTR, qui est à la fois la terminaison du tunnel IPv4-and-IPv6 et le CGN (Carrier-Grade NAT). Par exemple, l'AFTR n'a pas de fonction DNS à assurer (le B4 fait la résolution sur IPv6). Il a lui aussi une adresse bien connue, 192.0.0.1, et c'est celle qu'on verra sans doute souvent lors des traceroute.

Pour que tout cela marche bien, il y a quelques détails techniques à régler. La section 7 couvre ceux qui concernent le réseau : notamment, le tunnel doit respecter les règles des RFC 2473 et RFC 4213. Et la section 8 couvre les détails liés au NAT : possibilité pour un AFTR d'avoir plusieurs plages d'adresses IPv4 publiques, pour des ensembles de B4 différents, conformité impérative aux RFC sur le NAT, comme les RFC 4787, RFC 5508 et RFC 5382, précisions sur la possibilité pour l'AFTR d'être aussi un ALG (découragée, vue le nombre de clients que sert un AFTR, et le nombre de protocoles applicatifs présents et futurs), rappel que tout partage d'adresses, que ce soit par DS-Lite ou une autre méthode, engendre des ennuis (RFC 6269), etc.

L'annexe A du RFC est particulièrement intéressant pour les administrateurs réseaux car il détaille les scénarios de déploiement possibles. Il couvre des questions comme le placement des AFTR dans le réseau, ou la fiabilité requise des AFTR (ils ont un état donc on ne peut pas juste en multiplier le nombre).

Comme tout nouveau protocole, DS-Lite va soulever des questions de sécurité nouvelles, qu'étudie la section 11 du RFC. En soi, les problèmes de sécurité liés au NAT sont bien connus (RFC 2663 et RFC 2993). Mais déplacer la fonction NAT depuis une machine située chez l'utilisateur vers le réseau du FAI crée des nouveaux défis. Par exemple, les adresses IPv4 publiques, qui n'étaient partagées qu'entre les membres d'une même famille ou les employés d'une même entreprise, vont désormais être partagées entre des clients du même FAI, clients qui ne se connaissent pas. Si la HADOPI voit 203.0.113.201 commettre un crime grave (par exemple partager des œuvres d'art), et qu'elle veut couper l'utilisateur de cette adresse, la probabilité de bavure devient bien plus élevée. Enregistrer les adresses IP ne suffit donc plus, il faut noter l'adresse IP et le port (RFC 6302) et que l'AFTR enregistre ses tables de correspondance (identité du tunnel, protocole, adresses et ports), comme précisé en section A.4.

Vu le partage intensif d'adresses (bien plus important qu'avec les NAT sur le CPE), le nombre de ports devient une ressource critique. L'AFTR doit donc faire attention à empêcher les utilisateurs de monter une DoS (volontairement ou par accident) en s'attribuant tous les ports possibles. Par exemple, l'AFTR peut limiter le rythme d'allocation des ports, ou bien mettre une limite absolue au nombre de ports qu'un B4 peut s'allouer.

Enfin, l'AFTR doit veiller à ne pas se transformer lui-même en un outil facilitant les DoS. Par exemple, il ne doit pas permettre à l'autre extrémité du tunnel d'injecter des paquets IPv4 avec d'autres adresses sources que celles prévues (autrement, les réponses à ces paquets frapperaient un innocent).

Notre RFC ne mentionne pas les inconvénients et problèmes de DS-Lite : c'est un mécanisme complexe, avec plusieurs composants qui doivent travailler en bonne intelligence. DS-Lite dépend notamment d'un composant très sollicité, le CGN. Sera t-il suffisant lorsque des dizaines ou des centaines de réseaux locaux utiliseront le même AFTR ? En outre, comme indiqué plus haut, DS-Lite souffre des problèmes liés au partage d'adresses : les lois HADOPI ou LCEN ne seront pas contentes.

Si, à ce stade, vous êtes convaincu de l'intérêt de DS-Lite dans votre cas, où trouver des implémentations ? Il existe un AFTR en logiciel libre à l'ISC, disponible en http://www.isc.org/software/aftr. Comcast a aussi produit un code pour Linksys (apparemment pas très stable mais suffisant pour des tests) et un pour Mac OS (nommé ComcastDSLiteClient). L'ISC a rassemblé une documentation globale sur le B4. Enfin, les routeurs d'A10 ont la fonction d'AFTR. Verrons-nous bientôt la fonction de B4 dans tous les routeurs et boxes ? Impossible à dire pour l'instant.

Merci à Fabien Delmotte pour ses connaissances sur les mises en œuvre de DS-Lite.


Téléchargez le RFC 6333


L'article seul

RFC 6319: Issues Associated with Designating Additional Private IPv4 Address Space

Date de publication du RFC : Juillet 2011
Auteur(s) du RFC : M. Azinger (Frontier Communications), L. Vegoda (ICANN)
Pour information
Première rédaction de cet article le 20 juillet 2011


Il y a bien longtemps que la pénurie d'adresses IPv4 est une réalité. Longtemps avant leur épuisement complet, ces adresses étaient très difficiles à obtenir, nécessitant un long processus bureaucratique (et le remplissage de nombreux documents), ou tout simplement l'abonnement à une offre qualifiée de « professionnelle » ou « gold » dont le seul intérêt était d'avoir quelques adresses de plus. Résultat, beaucoup d'organisations ont choisi des adresses IP privées et des systèmes de relais ou de traduction d'adresses pour se connecter à l'Internet. Si l'organisation ne grossit pas par la suite, tout va bien. Mais si elle devient plus importante et dépasse la taille permise par les plages d'adresses privées existantes, que se passe-t-il ?

La section 3 du RFC détaille les mécanismes utilisés pour se connecter à l'Internet malgré l'absence d'adresses IP publiques. La principale est sans doute le NAT (RFC 2993 et RFC 3022). Le NAT a de multiples inconvénients, notamment pour les applications pair-à-pair, même si certaines techniques (comme ICE, RFC 8445) permettent de contourner partiellement le problème.

On peut emboîter plusieurs niveaux de NAT, mettant par exemple un traducteur dans la maison ou le bureau et un autre sur le réseau du FAI (on nomme souvent ce double-NAT NAT444). Si le FAI contrôle le CPE et donc les adresses IP qu'il alloue (cas de la Freebox par défaut, par exemple), cela peut marcher. C'est bien plus délicat si le CPE alloue les adresses qu'il veut car, alors, rien ne garantit qu'elles ne seront pas en conflit avec celles utilisées dans le réseau interne du FAI. Bref, le NAT444 ajoute de la complexité et des problèmes. Enfin, toute traduction d'adresses effectuée hors du réseau local de l'abonné soulève les problèmes liés au partage d'adresses que le RFC 6269 documente.

Le plus large bloc privé est le 10.0.0.0/8 (cf. RFC 1918). Il a parfois été suggéré d'allouer de nouveaux blocs pour agrandir l'espace privé mais ce projet a très peu de chances de se matérialiser désormais, vu l'épuisement des adresses IPv4. Ce bloc 10.0.0.0/8 comprend 16 777 216 adresses IP. Qui peut en consommer autant ? Comme le résume la section 2 de notre RFC, les gros opérateurs, par exemple un câblo-opérateur national (comme Comcast, non cité mais qui est effectivement dans ce cas), un opérateur de téléphonie mobile 3G, un gros fournisseur VPN, l'intranet d'une grosse entreprise, peuvent tous se trouver à l'étroit dans ce /8.

Quelles sont les possibilités une fois les adresses du RFC 1918 épuisées ? La section 4 les passe en revue. La première (section 4.1) est évidemment de passer enfin à IPv6, ce qui aurait dû être fait depuis longtemps. Le RFC note à juste titre que déployer IPv6 sur un réseau dont la taille est telle qu'il arrive à épuiser un /8 entier n'est pas une opération triviale. Elle va prendre du temps et c'est pour cela que ces opérateurs auraient dû commencer il y a des années. Si cela n'a pas été fait, l'opérateur peut se trouver dans le cas où les adresses du RFC 1918 sont épuisées et où il n'a matériellement pas le temps de déployer IPv6.

Notons que les adresses IPv6 utilisées ne sont pas forcément globales, on peut aussi déployer IPv6 avec des ULA (RFC 4193). Toutefois, celles-ci ne sont que pseudo-uniques donc, dans des cas comme celui du fournisseur de VPN, le risque de collision existe.

Bon, et pour les administrateurs réseaux qui, en 2011, n'ont toujours pas déployé IPv6, quelles solutions ? La section 4.2 liste les solutions purement v4. Obtenir de nouvelles adresses était la solution classique. Mais ajourd'hui, où les RIR qui ont encore des adresses IPv4 les épuisent vite et passent à la politique d'allocation finale, cela ne parait pas très réaliste.

La seconde solution est d'acquérir des adresses IP d'autres organisations, comme l'avait fait Microsoft dans une opération fameuse. Cette opération peut désormais être légale vis-à-vis des RIR comme le montre l'étude comparée de leurs politiques de transfert. Les possibilités pratiques d'un tel transfert sont très incertaines. Y aura-t-il assez d'adresses sur ce « marché » ? Et à quel coût ? Personne ne le sait trop. Mais le RFC est pessimiste : on ne trouvera probablement pas de larges blocs d'adresses continus ainsi, il est plus probable qu'il n'y aura qu'une poussière de /24 et /23. (Le RFC discute aussi la possibilité de locations de tels blocs, encore pire car sans garantie sur ce qui arrivera au terme de la location.)

Il y a bien sûr une autre possibilité. Après tout, qui a dit qu'il fallait être honnête et respecter les règles de vie en société ? Comme le montre l'exemple d'innombrables hommes d'affaires, on réussit bien mieux en violant ces règles et en écrasant les autres. La section 4.2.2 du RFC est donc consacrée à la solution libérale : prendre ce qui vous intéresse sans se poser de questions, ici, utiliser des adresses IP non encore allouées, ou bien allouées à quelqu'un mais pas annoncées dans la table de routage mondiale. L'article de Duane Wessels montre bien que l'espace non alloué est déjà utilisé. C'est évidemment très mal de faire cela : les rares blocs non encore alloués vont l'être bientôt (et cela fera une collision avec ceux du voleur, avec des conséquences imprévisibles), et ceux qui ne sont pas annoncés dans la table de routage publique le seront peut-être demain. Même si ce n'est pas le cas, la collision est toujours possible (cela dépend de la façon dont est configuré le réseau qui utilisait ces adresses mais, par exemple, les adresses internes fuient souvent, par exemple dans les en-têtes de courrier). La section 2.3 du RFC 3879 discute plus en détail ce problème. Il y a aussi bien sûr des risques juridiques à jouer avec les adresses des autres. Cela peut expliquer pourquoi les voleurs d'adresses préfèrent utiliser des préfixes alloués à des opérateurs peu dangereux juridiquement, par exemple en Afrique.

Quelle solution pourrait-on développer ? La section 5 examine plusieurs possibilités : la première est d'agrandir le RFC 1918 en y ajoutant des préfixes actuellement marqués comme publics. Cela réduirait encore plus le stock d'adresses IPv4 disponibles. Plusieurs propositions avaient été faites de réserver, par exemple un /8 supplémentaire. Par exemple, le réseau 1.0.0.0/8 était tentant car son utilisation publique soulevait des problèmes. Comme indiqué plus haut, il est clair que cela se fait déjà, de manière officieuse. Aucune de ces propositions n'a été adoptée officiellement et leurs chances semblent désormais nulles. (Voir la discussion à NANOG.)

Il y a en effet pas mal de systèmes qui traitent les adresses du RFC 1918 de manière spéciale, et où ces adresses sont codées en dur. Il y a peu de chances de pouvoir mettre à jour tous ces systèmes. Déjà, dé-bogoniser les plages allouées est très difficile.

Dernière possibilité, réaffecter une plage réservée, 240.0.0.0/4, qui avait été mise de côté pour des usages futurs qui ne se sont jamais concrétisés. Le problème est que beaucoup de systèmes déployés traitent de manière spécifique ces adresses et qu'il y a peu de chance de pouvoir les changer tous. En pratique, elles seront donc largement inutilisables. Par exemple, sur Linux :

% sudo ifconfig eth1 240.0.0.1/24 
SIOCSIFADDR: Invalid argument

(Mais ça marche sur FreeBSD et NetBSD). L'Internet-Draft draft-fuller-240space documente ce problème pour quelques systèmes.)

Bref, même si le RFC ne le rappelle pas, il n'y a pas vraiment d'autre solution que de migrer vers IPv6.


Téléchargez le RFC 6319


L'article seul

RFC 6317: Basic Socket Interface Extensions for Host Identity Protocol (HIP)

Date de publication du RFC : Juillet 2011
Auteur(s) du RFC : M. Komu (Helsinki Institute for Information Technology), T. Henderson (The Boeing Company)
Expérimental
Réalisé dans le cadre du groupe de travail IETF hip
Première rédaction de cet article le 23 juillet 2011


Il ne sert à rien de disposer d'un nouveau protocole si les applications ne s'en servent pas. Et, pour qu'il y ait une chance qu'elles s'en servent, il faut qu'elles aient une API standard pour cela. Ce RFC spécifie une possible API pour le protocole HIP (RFC 9063), un protocole qui sépare l'adresse IP de l'identité d'une machine. Celle-ci est désormais une clé cryptographique et l'API permet d'établir des connexions en connaissant la clé.

Cette API ne concerne pour l'instant que le langage C. Son utilité principale commence lorsque l'identificateur HIP a été obtenu (par exemple par le DNS, cf. RFC 8005) et lorsque l'adresse IP est connue. Elle prévoit toutefois d'autres cas. Spécifique à HIP, elles pourrait toutefois être étendue dans le futur à d'autres protocoles réalisant une séparation du localisateur et de l'identificateur, comme SHIM6 (RFC 5533). Notez que cette API utilise déjà certaines extensions créées pour SHIM6 et spécifiées dans le RFC 6316.

À quoi ressemblent les identificateurs que manipule cette API ? Nommés HIT pour Host Identity Tag, ce sont des résumés cryptographiques des clés publiques des machines (clés nommées HI pour Host Identity). Stockés sur 128 bits, ils sont, pour faciliter leur traitement, représentés sous forme d'adresses IPv6, en utilisant le préfixe ORCHID décrit dans le RFC 4843. Par exemple, 2001:10::1 est un HIT.

Certaines applications, ignorantes de ce qui se passe dans les couches basses, n'auront pas besoin d'être modifiées pour HIP (cf. RFC 5338). Les autres doivent suivre notre RFC, dont la section 1 expose les principes généraux :

  • Extension à l'interface socket telle que décrite dans le RFC 3493.
  • Nouvelle famille d'adresses, AF_HIP.
  • Possibilité de se connecter à un pair dont on connait l'identité mais aussi, en mode « opportuniste » à un pair inconnu (cf. section 4.1.6 du RFC 5201).

Bien, commençons par le commencement, la résolution de noms (section 3). D'abord, le cas où l'application a un résolveur à sa disposition (section 3.1). Celui-ci, en échange d'un nom de domaine, fournit les informations qu'il a trouvées, typiquement dans le DNS : HIT ou HI, adresses IP et peut-être des serveurs de rendez-vous (RFC 8004). L'application a donc uniquement à appeler getaddrinfo() et elle récupère des HIT, qu'elle utilise pour remplir les informations transmises à la prise. Le résolveur a fourni à HIP les informations auxiliaires comme la correspondance entre un HI et des adresses IP.

Et si on n'a pas de résolveur HIP (section 3.2) ? Cette API permet à une application, de fournir quand même tous les détails nécessaires pour réussir une connexion (notamment les adresses IP associées à un HI).

La section 4 définit formellement la nouvelle API. D'abord, les structures de données. Le nouveau type sockaddr est défini ainsi :

           typedef struct in6_addr hip_hit_t;

           struct sockaddr_hip {
                     uint8_t        ship_len;
                     sa_family_t    ship_family;
                     in_port_t      ship_port;
                     uint32_t       ship_flags;
                     hip_hit_t      ship_hit;
           };

Le résolveur prend des nouvelles options (section 4.2). La nouvelle famille AF_HIP, passée à getaddrinfo(), indique que l'application veut uniquement parler HIP et que toutes les sockaddr doivent donc être de ce type, quant à l'option AI_NO_HIT, elle indique au contraire que l'application ne veut pas entendre parler de HIP.

Une fois la connexion HIP établie, l'application peut se servir de getsockname() et getpeername() pour trouver des informations sur la machine paire (section 4.3). Elles permettent par exemple d'accéder au HIT de celle-ci (ce qui est utile si l'application acceptait n'importe quel HIT).

Si la machine dispose de plusieurs identités, le choix du HIT utilisé comme source est laissé à l'initiative du système. Si l'application veut l'influencer, elle peut se servir de mécanismes analogues à ceux du RFC 5014 : une option de setsockopt(), HIT_PREFERENCES (section 4.4), et deux valeurs possibles :

  • HIT_PREFER_SRC_HIT_TMP : donner la préférence aux HIT temporaires (dits aussi « anonymes », cf. sections 5.1.2 et 7 du RFC 5201),
  • HIT_PREFER_SRC_HIT_PUBLIC : donner la préférence aux HIT publics.

Si HIP_HIT_ANY signifiait qu'on exigeait une connexion HIP mais avec n'importe qui, HIP_ENDPOINT_ANY indiquait qu'on n'avait même pas cette préférence et que des connexions non-HIP étaient possibles. Mais, après coup, on veut parfois savoir ce qu'on a obtenu et la nouvelle fonction sockaddr_is_srcaddr() (section 4.5) permet de savoir si le pair avec lequel on s'était connecté utilisait HIP ou pas. (Il y a aussi une fonction hip_is_hit() qui teste simplement si une valeur de 128 bits est bien un HIT.)

On l'a vu, cette API permet, dans une large mesure, à une application de se connecter en HIP en ignorant presque tout de ce protocole : il suffit d'indiquer AF_HIP au lieu de AF_INET6 et ça roule. La traduction des HIT en localisateurs est notamment effectuée automatiquement, l'application ne se souciant pas de ces derniers. Toutefois, certaines applications peuvent vouloir davantage de contrôle, notamment sur le choix des localisateurs (les adresses IP). La section 4.6 est faite pour elles. Elle s'appuie sur les options SHIM6 du RFC 6316. Par exemple, l'option SHIM_LOC_PEER_PREF permet, avec setsockopt(), de définir le localisateur préféré et, avec getsockopt(), de découvrir le localisateur utilisé.

Quelques points sur la sécurité viennent compléter ce RFC, en section 6. Ainsi, l'option HIP_ENDPOINT_ANY dit explicitement qu'on accepte des pairs non-HIP, pour les connexions entrantes ou sortantes. On peut donc se retrouver sans la sécurité associée à HIP (notamment l'authentification du pair). Les applications soucieuses de sécurité devraient donc utiliser HIP_HIT_ANY et pas HIP_ENDPOINT_ANY.

Aujourd'hui, cette extension de l'API traditionnelle ne se retrouve pas encore dans Linux, ni dans un des BSD. Pour cela, un programme comme echoping n'a donc pas encore de possibilité d'utiliser HIP (cf. bogue #3030400.)


Téléchargez le RFC 6317


L'article seul

RFC 6314: NAT Traversal Practices for Client-Server SIP

Date de publication du RFC : Juillet 2011
Auteur(s) du RFC : C. Boulton (NS-Technologies), J. Rosenberg (Skype), G. Camarillo (Ericsson), F. Audet (Skype)
Pour information
Première rédaction de cet article le 23 juillet 2011


Aujourd'hui, il est rare pour une machine individuelle (ordinateur de bureau, ordinateur portable, smartphone, tablette, etc) d'avoir un vrai accès Internet. Presque toujours, la malheureuse machine est limitée à une adresse IP privée et coincée derrière un NAT qui traduira cette adresse à la volée. Cela ne gêne pas trop certains protocoles (SSH sortant, par exemple) mais est beaucoup plus gênant pour d'autres, notamment le protocole de téléphonie sur IP SIP. Ce RFC décrit l'ensemble des techniques que doivent mettre en œuvre les clients SIP pour arriver à passer quand même. C'est la meilleure lecture pour commencer à se pencher sur le problème « pourquoi a-t-on si souvent des problèmes avec SIP ? ».

Pour comprendre pourquoi SIP (RFC 3261) est particulièrement affecté, il faut se rappeler qu'il utilise des références : le client SIP indique au serveur à quelle adresse répondre, par exemple à quelle adresse envoyer les paquets audio du protocole compagnon RTP (RFC 3550). En présence d'un NAT, la machine ne connait pas son adresse IP telle que vue de l'extérieur et, de toute façon, le NAT traditionnel (qui agit sur le port, pas seulement sur l'adresse en dépit de son nom) bloque les paquets entrants, ne sachant pas que le flux RTP est lié à la connexion SIP. Pire, les différents routeurs NAT ont des comportements différents et il est donc difficile de trouver une solution qui marche partout (RFC 4787).

Ces problèmes du NAT sont bien connus et documentés. L'essentiel du code réseau d'un client SIP est consacré à contourner le NAT. Des solutions partielles ont été développées comme STUN (RFC 5389), TURN (RFC 5766), ICE (RFC 8445) ou bien des solutions spécifiques à SIP comme le RTP symétrique (RFC 4961), ou le SIP sortant (RFC 5626). Toutes ces solutions sont partielles et il manquait un document de haut niveau, décrivant le mécanisme général. Ce RFC 6314 ne propose donc pas « encore un nouveau protocole » mais explique la marche à suivre et les bonnes pratiques pour passer outre les routeurs NAT.

SIP peut être utilisé dans des contextes très différents : ce RFC se focalise sur l'utilisation en « client-serveur » où un client SIP (par exemple un softphone) appelle un fournisseur SIP qui routera l'appel vers le destinataire. Le SIP pair-à-pair (actuellement expérimental) n'utilisera pas forcément les mêmes techniques.

La section 3 détaille le problème que rencontrent les clients SIP en présence du NAT. Si le routeur NAT contient un ALG, celui-ci peut interférer avec SIP, par exemple en interdisant les communications chiffrées, ou bien en imposant que le même chemin soit emprunté à l'aller et au retour. Comme documenté dans les RFC 4787, RFC 3424 et RFC 8445, les ALG sont donc une solution limitée.

Et s'il n'y a pas d'ALG ? Dans ce cas, voyons comment SIP établit une connexion avec son fournisseur, par défaut. Le client envoie une requête sur UDP et le serveur est censé répondre au couple {adresse, port} de l'en-tête Via: de cet en-tête. Mais, après le passage du routeur NAT, cette adresse et son port, mis là par le client original, ne correspondent plus à rien d'utile. Même si le paquet de réponse atteint le NAT, il sera typiquement jeté par lui. Même si le client SIP s'était connecté en utilisant TCP, les appels qu'il recevra (INVITE) ne seront pas routés sur cette connexion TCP mais envoyés à l'adresse indiqué ce qui, là encore, ne marchera pas (sans compter d'autres problèmes comme la fermeture automatique de la session par le NAT après un délai de garde).

Cela, c'était pour la signalisation, pour le protocole SIP lui-même. Mais un coup de téléphone complet nécessite aussi de faire passer les données, les paquets audio. Ceux-ci voyagent en général via la protocole RTP (RFC 3550, le protocole à utiliser, les ports où envoyer les données, etc, étant indiqués via SDP (RFC 4566) ou bien via une requête SIP spécifique (RFC 3264). Même si la session SIP a été bien établie, ces paquets RTP risquent fort de ne pas arriver, les adresses et les numéros de port qu'indiquent SDP ou SIP n'ayant pas de signification en dehors du réseau local.

Donc, pour résumer cette section 3, SIP a deux problèmes avec le NAT :

  • Pour la signalisation (SIP à proprement parler), requêtes entrantes et sortantes (pours des raisons différentes),
  • Et pour les données (en général SDP + RTP).

Soyons maintenant positifs et voyons les solutions (section 4). Pour la signalisation, la section 4.1 expose les méthodes possibles :

  • Pour les requêtes sortantes, la réponse symétrique, où la réponse est envoyée au port d'origine (comme le font d'autres protocoles UDP comme le DNS), port ouvert sur le NAT par l'envoi de la requête. Cette méthode est décrite dans le RFC 3581.
  • Pour les requêtes entrantes (RFC 5626), le fournisseur SIP doit garder trace du port utilisé et s'en servir pour acheminer les appels entrants.

Pour le transport des données, la section 4.2 cite :

  • Le RTP symétrique (RFC 4961) qui permet d'ouvrir un trou dans le NAT depuis l'extérieur, avant de demander au pair d'y envoyer le trafic.
  • RTCP (section 6 du RFC 3550) et le RFC 3605 pour indiquer le port à utiliser.
  • Et surtout la solution totale, la combinaison de STUN (RFC 5389) et TURN (RFC 5766), orchestrés par ICE (RFC 8445). STUN permet de découvrir l'adresse IP publique qui va être utilisée pour les communications externes, TURN va relayer le trafic pour les cas où le routeur NAT est particulièrement désagréable et empêche STUN de fonctionner (TURN est très coûteux en ressources puisque chaque paquet de données doit être ainsi relayé, mais il marche dans tous les cas), et ICE a pour rôle d'essayer successivement et intelligement plusieurs méthodes de traversée de NAT (STUN, TURN et d'autres) pour choisir la plus adaptée.

La section 5 illustre ensuite ces méthodes par divers exemples. En voici un très simple, pour la signalisation, où le client, 192.168.1.2 est derrière un NAT (qui réécrit son adresse en 172.16.3.4) et s'enregistre auprès d'un fournisseur SIP, Example.com. La requête est :


   REGISTER sip:example.com SIP/2.0
   Via: SIP/2.0/UDP 192.168.1.2;rport;branch=z9hG4bKnashds7
   Max-Forwards: 70
   From: Bob <sip:bob@example.com>;tag=7F94778B653B
   To: Bob <sip:bob@example.com>
   Call-ID: 16CB75F21C70
   CSeq: 1 REGISTER
   Supported: path, outbound
   Contact: <sip:bob@192.168.1.2 >;reg-id=1
       ;+sip.instance="<urn:uuid:00000000-0000-1000-8000-AABBCCDDEEFF>"
   Content-Length: 0

Le client SIP a utilisé le paramètre rport (RFC 3581) dans l'en-tête Via: pour indiquer que le serveur doit répondre au port d'où vient la requête (et que le routeur NAT a ouvert). La réponse est :


   SIP/2.0 200 OK
   Via: SIP/2.0/UDP 192.168.1.2;rport=8050;branch=z9hG4bKnashds7;
        received=172.16.3.4
   From: Bob <sip:bob@example.com>;tag=7F94778B653B
   To: Bob <sip:bob@example.com>;tag=6AF99445E44A
   Call-ID: 16CB75F21C70
   CSeq: 1 REGISTER
   Supported: path, outbound
   Require: outbound
   Contact: <sip:bob@192.168.1.2 >;reg-id=1;expires=3600
        ;+sip.instance="<urn:uuid:00000000-0000-1000-8000-AABBCCDDEEFF>"
   Content-Length: 0

et le paramètre received du champ Via: indique l'adresse IP source qu'avait vue le serveur. (Une autre solution aurait été d'utiliser TCP.) Les amateurs de scénarios plus complexes seront comblés, avec le reste de la longue section 5.

À noter qu'un argument souvent présenté en faveur de Skype, par rapport à SIP, est son meilleur comportement en présence de NAT hostiles (parfois très hostiles, par exemple ne laissant passer que HTTP). Il est amusant de noter que deux des auteurs du RFC travaillent chez Skype. Mais, surtout, si les clients SIP ont souvent moins de succès que Skype lors de la traversée de routeurs très fermés, c'est pour trois raisons :

  • Tous les logiciels SIP ne mettent pas encore en œuvre l'intégralité des recommandations résumées dans ce RFC 6314. La qualité des clients et serveurs SIP existants est très variable.
  • Skype utilise également des méthodes non-standard (par exemple il peut tunneler la voix sur HTTP, bricolage très contestable mais qui est parfois la seule voie restée ouverte),
  • Et Skype utilise également des méthodes de parasite, comme d'enrôler comme relais des machines qui n'ont rien demandé ce qui, à juste titre, suscite des protestations.

Téléchargez le RFC 6314


L'article seul

RFC 6305: I'm Being Attacked by PRISONER.IANA.ORG!

Date de publication du RFC : Juillet 2011
Auteur(s) du RFC : J. Abley (ICANN), W. Maton (NRC-CNRC)
Pour information
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 14 juillet 2011


Un RFC très inhabituel, non seulement par son titre amusant mais aussi parce que le public visé n'est pas le programmeur qui va mettre en œuvre des normes, ni même l'administrateur réseaux qui s'occupe de grands réseaux complexes, mais un public bien plus large, celui des gens qui gèrent un petit réseau, ont installé comme pare-feu ou IDS une boîte noire à laquelle ils ne comprennent rien, et qui voient arriver des messages d'alerte comme quoi leur petit réseau serait attaqué par un mystérieux prisoner.iana.org. Ce RFC a été écrit pour fournir à l'IANA et aux opérateurs de serveurs de l'AS112 (décrit dans le RFC 7534) une réponse toute faite à envoyer à ces angoissés.

En effet, l'« attaque » en question n'est pas une attaque et ne vient pas de l'IANA ou de l'AS112. Elle est entièrement de la faute des administrateurs de ces réseaux soi-disant attaqués. Un certain nombre de petits réseaux utilisent, soit parce qu'il n'y a plus d'adresses IPv4 disponibles, soit parce qu'ils croient à tort que cela leur apporte une certaine sécurité, des adresses IP privées, tirées du RFC 1918. Ces adresses étant spécifiques à un certain réseau, n'ayant pas de signification globale, les requêtes DNS demandant les noms associés à ces adresses ne devraient jamais sortir du réseau local (section 2 du RFC) et être toujours traitées par un serveur DNS interne. Mais, en pratique, c'est loin d'être le cas, et les serveurs de in-addr.arpa, le domaine utilisé pour la résolution d'adresses IP en noms (section 3), reçoivent un trafic important et inutile. Pour le traiter sans charger ces serveurs, les domaines servant aux plages d'adresses du RFC 1918 sont déléguées à l'AS112 (RFC 7534) qui est chargé de répondre « ce domaine n'existe pas » à toutes ces requêtes.

Mais, comme les requêtes de ce type sont des erreurs (rappelez-vous qu'elles n'auraient normalement jamais dû sortir), les réponses qu'envoie l'AS112 sont souvent inattendues pour le réseau local. Et, si le pare-feu ou l'IDS sont bizarrement configurés (ce qui est fréquent sur ces réseaux mal gérés), la réponse DNS à leur question leur apparait comme une tentative d'attaque ! S'ils se plaignent, l'idée est de simplement leur renvoyer ce RFC 6305 à lire.

Ce RFC explique donc en termes simples ce que sont les adresses privées, ce qu'est la résolution d'adresses en noms, les raisons pour lesquelles est déployé l'AS112 (section 4 du RFC), et les noms et adresses des serveurs de l'AS112 (section 5) notamment le prisoner.iana.org qui donne son titre au RFC. Pour augmenter les chances que Google trouve cet article, je cite ici ces informations :

  • PRISONER.IANA.ORG (192.175.48.1),
  • BLACKHOLE-1.IANA.ORG (192.175.48.6),
  • Et BLACKHOLE-2.IANA.ORG (192.175.48.42).

La section 6 explique ensuite le mécanisme par lequel la fausse alerte est déclenchée : un résolveur DNS du réseau local envoie la requête, par exemple PTR 1.2.20.172.in-addr.arpa, elle arrive aux serveurs de l'AS112, qui répondent, mais leurs réponses sont, pour des raisons diverses, bloquées. Normalement, le pare-feu ne couine pas pour chaque paquet bloqué mais, ici, les requêtes étant souvent déclenchées automatiquement par un logiciel, elles peuvent être nombreuses, provoquant de fréquentes réponses, qui peuvent ressembler à une attaque. Deux autres phénomènes expliquent cette perception : si la réponse est bloquée, la machine à l'origine de la requête va réessayer, souvent très vite. Et si le résolveur DNS refait ces essais avec des numéros de port croissant régulièrement, les réponses ressembleront à un balayage de ports.

Que devrait donc faire l'administrateur du site au lieu de harceler l'IANA ou les opérateurs de l'AS112 ? La section 7 lui donne quelques pistes, pour résoudre le problème qu'il a causé :

  • Convaincre les machines terminales de ne pas chercher à résoudre les adresses en noms. Cela coupe le problème à la source, mais c'est évidemment assez difficile à faire dans un grand réseau, où l'administrateur du pare-feu ne contrôle pas forcément chaque machine. Par exemple, une bonne partie du trafic de l'AS112 provient des réseaux de téléphonie mobile et l'opérateur du pare-feu ne peut évidemment pas intervenir sur chaque téléphone.
  • Bloquer sur le pare-feu non pas les réponses de l'AS112 mais les questions envoyées à ce service. Cela résoudrait complètement le problème de l'AS112 mais, sur le site, les résolutions des adresses en noms se bloqueraient, ce qui pourrait avoir des conséquences gênantes.
  • Configurer les résolveurs du réseau local pour répondre avec autorité pour les zones correspondant aux adresses privées. C'est sans doute la solution la plus simple et le plus efficace à la fois. Elle est décrite avec plus de détails dans le RFC 6303.
  • Plus geek, mettre en place une instance locale de l'AS112 (RFC 7534).

Téléchargez le RFC 6305


L'article seul

RFC 6304: AS112 Nameserver Operations

Date de publication du RFC : Juillet 2011
Auteur(s) du RFC : J. Abley (ICANN), W. Maton (NRC-CNRC)
Pour information
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 14 juillet 2011


Le système AS112, autrefois décrit dans ce RFC, est à la fois un utile composant du DNS, améliorant les performances et reduisant la charge du réseau, un banc d'essai pour des nouvelles techniques comme l'anycast, et une expérimentation sociale, celle d'un service 100 % acentré. Il est désormais documenté dans le RFC 7534.

Comme beaucoup de bonnes choses sur l'Internet, la documentation arrive comme les carabiniers, longtemps après. Car l'AS112 tourne depuis des années. Pour comprendre son rôle, il faut d'abord se pencher sur le problème à résoudre.

Un certain nombre de sites connectés à l'Internet utilisent des adresses IP privées, tirées du RFC 1918. Bien des logiciels, lorsqu'ils voient passer un nouveau client, font une résolution DNS pour obtenir le nom du client en fonction de son adresse IP (résolution dite PTR). C'est par exemple le cas du serveur de courrier Postfix, chez qui ce comportement n'est pas débrayable. Lorsque l'adresse IP est privée, il ne sert à rien de poser la question au DNS public. Par définition, celui-ci ne peut pas savoir que MaPetiteEntreprise utilise 192.168.1.0/24 et a attribué 192.168.1.33 à posteclientX.mapetiteentreprise.com. La bonne pratique est donc que l'administrateur réseaux d'un site qui utilise ces adresses privées doit configurer des serveurs DNS pour répondre aux requêtes PTR (cf. RFC 6303). Pour voir cela, on peut utiliser l'option -x de dig, qui permet de faire automatiquement une résolution d'adresse en nom. Le domaine in-addr.arpa (RFC 5855) accueille la forme inversée des adresses (192.168.1.33 devient 33.1.168.192.in-addr.arpa). Testons ici une adresse publique :

% dig -x 192.134.4.20
...
;; ANSWER SECTION:
20.4.134.192.in-addr.arpa. 172800 IN    PTR     rigolo.nic.fr.

Mais beaucoup d'administrateurs réseaux sont négligents, surchargés de travail, incompétents ou les trois à la fois. Ils ne configurent pas ces serveurs DNS et, résultat, la requête PTR sort de leur réseau et va taper sur les serveurs DNS de la racine puis à ceux de in-addr.arpa. (Une bonne partie du trafic semble ainsi venir des réseaux 3G, où le smartphone ne reçoit qu'une adresse privée et où le résolveur DNS qui lui est indiqué ne connait pas les zones correspondantes.) Ceux-ci ont normalement autre chose à faire que de répondre à des requêtes qui sont, dès le départ, des erreurs. Ils délèguent donc à l'AS112, un ensemble de serveurs de noms qui est chargé de répondre « ce nom n'existe pas » à toutes ces requêtes parasites. L'AS112 est donc un puits où finissent les erreurs.

On peut voir la délégation de l'AS112 avec dig :


% dig NS 168.192.in-addr.arpa

; <<>> DiG 9.7.1 <<>> NS 168.192.in-addr.arpa
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 56273
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 3

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;168.192.in-addr.arpa.          IN      NS

;; ANSWER SECTION:
168.192.in-addr.arpa.   300     IN      NS      blackhole-2.iana.org.
168.192.in-addr.arpa.   300     IN      NS      blackhole-1.iana.org.

;; ADDITIONAL SECTION:
blackhole-1.iana.org.   3500    IN      A       192.175.48.6
blackhole-2.iana.org.   3500    IN      A       192.175.48.42

;; Query time: 29 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Wed Jul  6 12:34:19 2011
;; MSG SIZE  rcvd: 141

La délégation va être conservée dans les mémoires caches des résolveurs DNS et la racine ou in-addr.arpa ne seront donc plus embêtés, après la première requête.

Mais qui sont ces machines 192.175.48.6 et 192.175.48.42 ? Des très gros serveurs payés par un mécène et installées à un endroit bien connecté ? Pas du tout. C'est ici que rentre en jeu l'AS112. Ce dernier est composé d'un réseau informel de dizaines de machines un peu partout dans le monde et qui annoncent toutes être 192.175.48.6 et 192.175.48.42. Chacune de ces machines encaisse une partie de la charge. L'AS112 n'a pas de chef, juste un site Web et, depuis aujourd'hui, un RFC, ce RFC 6304.

L'AS112 doit son nom au numéro de système autonome qui lui a été attribué. Ses serveurs utilisent l'anycast (RFC 4786) pour distribuer la charge entre eux. Avant Global Anycast, c'était donc le premier projet d'anycast entre serveurs faiblement coordonnés.

Les détails pratiques, maintenant. La liste des zones servies figure en section 2.1. Elle comprend 10.in-addr.arpa pour le réseau 10.0.0.0/8, de 16.172.in-addr.arpa à 31.172.in-addr.arpa pour le 172.16.0.0/12, et 168.192.in-addr.arpa pour le 192.168.0.0/16, les préfixes du RFC 1918. Elle inclus aussi 254.169.in-addr.arpa pour le préfixe « local au lien » du RFC 5735. Pour aider à l'identification du nœud qui répond, les serveurs de l'AS112 servent également la zone hostname.as112.net, ici à Paris :


% dig +nsid TXT hostname.as112.net

; <<>> DiG 9.7.3 <<>> +nsid TXT hostname.as112.net
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 1078
;; flags: qr rd ra; QUERY: 1, ANSWER: 5, AUTHORITY: 2, ADDITIONAL: 3

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;hostname.as112.net.            IN      TXT

;; ANSWER SECTION:
hostname.as112.net.     267     IN      TXT     "Unicast IP: 193.17.192.194"
hostname.as112.net.     267     IN      TXT     "See http://as112.net/ for more information."
hostname.as112.net.     267     IN      TXT     "See http://noc.hivane.net/cgi-bin/dsc-grapher.pl for local information."
hostname.as112.net.     267     IN      TXT     "Paris, FR"
hostname.as112.net.     267     IN      TXT     "Hivane Networks"

;; AUTHORITY SECTION:
hostname.as112.net.     267     IN      NS      blackhole-2.iana.org.
hostname.as112.net.     267     IN      NS      blackhole-1.iana.org.

;; ADDITIONAL SECTION:
blackhole-1.iana.org.   241     IN      A       192.175.48.6
blackhole-2.iana.org.   241     IN      A       192.175.48.42

;; Query time: 1 msec
;; SERVER: 217.70.184.225#53(217.70.184.225)
;; WHEN: Wed Jul  6 12:36:14 2011
;; MSG SIZE  rcvd: 348

On note que les préfixes IPv6 n'y figurent pas. Une des discussions les plus vives sur ce RFC, et qui explique le temps très long qu'il a mis à sortir, portait sur la délégation de préfixes d'ip6.arpa à l'AS112. Aucune décision n'a encore été prise et, pour l'instant, notre RFC 6304 décrit l'état actuel de l'AS112 (on peut avoir une liste à jour sur le site officiel).

La section 2.2 décrit les serveurs de noms qui reçoivent la délégation, joliment (mais incorrectement, puisqu'ils répondent) nommés blackhole-1.iana.org et blackhole-2.iana.org (en dépit de leurs noms, les serveurs de l'AS112 ne sont pas gérés par l'IANA, cf. section 7). Dans le champ MNAME du SOA de la zone déléguée, on trouve également prisoner.iana.org dont la tâche principale est de répondre aux mises à jour dynamiques (RFC 2136) que certaines machines envoient audit MNAME.

Ce RFC 6304 n'est pas seulement la description d'une technique mais également un HOWTO sur la configuration d'un serveur de l'AS112. De tels textes, prévus pour les administrateurs système, sont rares dans les RFC. La section 3 décrit ainsi tout ce que doit savoir le volontaire qui va créer un nouveau nœud. Il doit connaître BGP (RFC 4271), nécessaire pour l'anycast (RFC 4786) et la gestion d'un serveur DNS faisant autorité. Les serveurs de l'AS112 peuvent être situés n'importe où mais ils sont surtout utiles dans les endroits bien connectés, notamment les points d'échange. Ils peuvent être locaux (annonçant les routes avec la communauté BGP no-export, 0xFFFFFF01, cf. RFC 1997), ou globaux (servant le monde entier). Et naturellement, ils doivent se coordonner (via une liste de diffusion) avec les autres serveurs de l'AS112.

L'AS112 n'impose pas de système d'exploitation particulier (section 3.3) mais tous les serveurs existants semblent utiliser Unix et tous (c'est difficile à dire, puisque l'AS112 ne contrôle pas tout ce qui se passe sur les serveurs) se servent de BIND. Il est recommandé que la machine AS112 soit dédiée à cette tâche : ces serveurs reçoivent parfois un trafic intense qui pourrait perturber leurs autres activités.

Le serveur signale son existence et sa disponibilité en BGP. Il faut donc coupler le serveur de noms au serveur BGP, pour que l'arrêt du serveur DNS entraîne l'arrêt de l'annonce (le RFC ne fournit pas de script pour cela). Un exemple de comment cela peut se réaliser sur Linux, avec les adresses de l'AS112 attachées à une interface dummy, est (code utilisé sur un serveur anycast réel, quoique pas de l'AS112) :

# Load the variables (the machine is a RedHat)
. /etc/sysconfig/network-scripts/ifcfg-eth0

# Test if the name server actually works. Do not use ps: the server
may be there but unresponsive
TMP=(`dig +short +time=1 +tries=1 @${IPADDR} SOA example.`)
MASTER=${TMP[0]:=somethingwaswrong}

# Normal reply or not?
if test ${MASTER} != "nsmaster.nic.example."
then
    # Disable the interface: Quagga will stop announcing the route
    ifdown dummy0
    # Raise an alarm, send SMS, etc
fi

Le serveur BGP annonce le préfixe 192.175.48.0/24 qui couvre les adresses de tous les serveurs et l'origine est évidemment 112.

Les exemples du RFC supposent que le serveur BGP est Quagga mais cela peut évidemment marcher avec d'autres. Dans l'exemple ci-dessous, tiré du RFC (section 3.4), le router ID est 203.0.113.1 et le serveur BGP a deux pairs, 192.0.2.1 et 192.0.2.2. Voici un extrait du bgpd.conf (la version intégrale est dans le RFC) :

   hostname my-router
...
   router bgp 112
    bgp router-id 203.0.113.1
    network 192.175.48.0/24
    neighbor 192.0.2.1 remote-as 64496
    neighbor 192.0.2.1 next-hop-self
    neighbor 192.0.2.2 remote-as 64497
    neighbor 192.0.2.2 next-hop-self

En farfouillant sur le site officiel (pas très bien organisé, je trouve), on peut trouver d'autres exemples.

Le serveur AS112 a ensuite besoin d'un serveur DNS faisant autorité (section 3.5), évidemment compatible avec toutes les règles du DNS (RFC 1034). Les exemples de configuration du RFC sont fondés sur BIND. Voici un extrait du named.conf (la version intégrale est dans le RFC) :

   options {
     listen-on {
        ...
        // the following addresses correspond to AS112 addresses, and
        // are the same for all AS112 nodes
        192.175.48.1;      // prisoner.iana.org (anycast)
        192.175.48.6;      // blackhole-1.iana.org (anycast)
        192.175.48.42;     // blackhole-2.iana.org (anycast)
     };
     recursion no;        // authoritative-only server
   };

   // RFC 1918
   zone "10.in-addr.arpa" { type master; file "db.empty"; };
   ...

   // RFC 5735
   zone "254.169.in-addr.arpa" { type master; file "db.empty"; };

   // also answer authoritatively for the HOSTNAME.AS112.NET zone,
   // which contains data of operational relevance
   zone "hostname.as112.net" {
     type master;
     file "db.hostname.as112.net";
   };

Un exemple équivalent pour NSD (utilisé sur le nœud AS112 de Paris) est disponible en as112-nsd.conf. Pour simplifier son écriture, il a été produit à partir d'un source en M4, as112-nsd.conf.m4.

Que contiennent les fichiers de zone db.empty et db.hostname.as112.net ? Conformes à la syntaxe de la section 5 du RFC 1035, ils sont communs à BIND et NSD. Le premier, comme son nom l'indique, est un fichier de zone vide, puisque le serveur AS112 ne connait évidemment rien : il ne peut que répondre NXDOMAIN (ce nom n'existe pas) à toutes les requêtes. Il ne contient donc que les informations obligatoires à toute zone (SOA, avec une adresse de contact appropriée) et NS. L'autre zone sert au débogage de l'AS112, lorsqu'on veut obtenir des informations sur le serveur AS112 courant. Un contenu typique est juste composé d'enregistrements TXT :

           TXT     "Human AS112 server" "Minas Tirith, Gondor"
           TXT     "Forbidden to orcs and nazguls."
           TXT     "See http://www.as112.net/ for more information."

et parfois d'une localisation (cf. RFC 1876). Le résultat sur un site réel étant :


% dig ANY hostname.as112.net.

; <<>> DiG 9.7.3 <<>> ANY hostname.as112.net.
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 41528
;; flags: qr rd ra; QUERY: 1, ANSWER: 7, AUTHORITY: 2, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;hostname.as112.net.            IN      ANY

;; ANSWER SECTION:
hostname.as112.net.     604796  IN      LOC     37 58 22.590 N 23 44 43.890 E 100.00m 100m 10m 10m
hostname.as112.net.     604796  IN      TXT     "See http://as112.net/ for more information."
hostname.as112.net.     604796  IN      TXT     "Unicast IP: as112.grnet.gr"
hostname.as112.net.     604796  IN      TXT     "Greek Research & Technology Network" "Athens, Greece"
hostname.as112.net.     604796  IN      SOA     flo.gigafed.net. dns.ryouko.imsb.nrc.ca. 1 604800 60 604800 604800
hostname.as112.net.     604796  IN      NS      blackhole-2.iana.org.
hostname.as112.net.     604796  IN      NS      blackhole-1.iana.org.

;; AUTHORITY SECTION:
hostname.as112.net.     604796  IN      NS      blackhole-1.iana.org.
hostname.as112.net.     604796  IN      NS      blackhole-2.iana.org.

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Wed Jul  6 12:51:53 2011
;; MSG SIZE  rcvd: 391

(La version intégrale des deux fichiers de zone figure dans le RFC.)

Une fois le nœud installé, il faut évidemment le tester (avec dig, par exemple). Si les réponses aux requêtes PTR sont correctes, mais pas celles aux requêtes pour le nom hostname.as112.net, c'est sans doute un problème de routage (on est envoyés sur un autre nœud de l'AS112) et il faut alors sortir traceroute et les looking glasses (section 3.6). Des tests dignes de ce nom doivent être faits depuis plusieurs FAI, et doivent tester les trois adresses IP de l'AS112.

Le bon fonctionnement de l'AS112 ne dépend pas uniquement de sa configuration initiale mais aussi de sa gestion et surveillance quotidiennes. La section 4 est consacrée aux questions opérationnelles. Le nœud doit être surveillé automatiquement, pour s'assurer qu'il répond toujours. S'il doit être arrêté (par exemple pour une maintenance prévue), il faut s'assurer que l'annonce BGP stoppe (autrement, BGP annonce un trou noir, d'où aucune réponse ne reviendra). Autre point important de la gestion opérationnelle d'un serveur de l'AS112, des statistiques, obtenues à partir d'outils comme DSC ou dnstop. Quelle est l'utilisation réelle de l'AS112 ? Ces statistiques n'étant pas consolidées globalement, c'est difficile à dire. Certains opérateurs publient leurs chiffres mais pas tous. Par exemple, le serveur d'Ottawa voit mille requêtes par seconde (cf. « AS112 Intro » par l'un des auteurs du RFC), celui géré par le RIPE-NCC dans les mille cinq cents, et celui à Paris deux fois plus (voir les graphiques), ce qui fait quand même quelques mégabits par seconde. La majorité des types demandés est évidemment du PTR mais il y a aussi un flux important de TXT, apparemment dus à la technologie SD (Service Discovery) d'Apple (voir des statistiques plus détaillées à la fin).

Le nouveau serveur peut alors être annoncé sur les listes appropriées (par exemple, chaque point d'échange a en général la sienne). Enfin, bien que chaque serveur de l'AS112 puisse fonctionner indépendemment des autres, il est évidemment préférable de se coordonner avec les petits camarades (section 5) en écrivant à la liste officielle.

Et dans le futur ? La section 6 explore l'avenir possible de l'AS112. Idéalement, il devrait disparaître petit à petit au fur et à mesure que les administrateurs réseaux prennent soin de ne pas laisser fuir les requêtes PTR pour les réseaux privés, comme recommandé dans le RFC 6303. Le déploiement de logiciels respectant ce principe dès le début pourrait aider. Toutefois, aujourd'hui, les opérateurs de l'AS112 n'observent pas de tendance à la baisse du trafic. Même des années après le déploiement de serveurs mettant en œuvre le RFC 6303, il est probable que le trafic de l'AS112 ne tombera pas à zéro et que ce service restera donc nécessaire.

Il pourrait même s'étendre à IPv6 (cela a été fait début 2015) : les serveurs pourraient répondre en IPv6 (et pas seulement en IPv4 comme aujourd'hui). Un préfixe a déjà été alloué pour cela, 2620:4f:8000::0/48 mais il n'est pas encore publié. Et les serveurs pourraient servir des données de ip6.arpa. Rien n'est encore décidé, gardez un œil sur http://www.as112.net/ si vous voulez être au courant. Un bon exposé du problème est « AS112-bis. » et un plan de déploiement IPv6 est en http://public.as112.net/node/26. Quant aux nouveaux domaines délégués, la solution finalement adoptée a été décrite dans le RFC 7535.

Enfin, qu'en est-il de la sécurité ? Comme le rappelle la section 8, les requêtes DNS auxquelles répond l'AS112 ne devraient jamais y arriver, normalement. Elles auraient dû rester sur le réseau local. En sortant, elles exposent de l'information interne, qui était peut-être privée (qu'il y ait un serveur qui y réponde ou pas ne change guère ce risque).

Plus rigolo, comme ces requêtes sont en général involontaires (comme indiqué, elles auraient dû rester privées), les réponses sont inattendues. Plus d'un IDS a donc crié que l'AS112 essayait d'attaquer le réseau. Le RFC 6305 a été écrit pour fournir une réponse toute faite aux administrateurs incompétents qui accusaient l'IANA ou l'AS112.

Comme l'AS112 n'a pas de chef et que l'anycast ne permet pas de limiter le nombre de participants, il est tout à fait possible de fantasmer sur l'hypothèse d'un nœud AS112 voyou, qui donnerait exprès de mauvaise réponses. Ce problème (purement théorique) n'a pas vraiment de solution. Signer les zones avec DNSSEC semble franchement excessif.

L'annexe A du RFC expose la longue histoire de l'AS112, de ses débuts en 2002 (les adresses IP privées datent de 1996) à son état actuel, après la redélégation en 2011 de in-addr.arpa, autrefois sur les serveurs de la racine (RFC 5855). L'AS112 a été le premier déploiement massif de l'anycast et a donc joué un rôle primordial dans l'évaluation de cette technologie.

On voit que neuf ans ont donc été nécessaires pour documenter ce projet. Une des raisons du retard était la longue discussion pour savoir si le RFC devait documenter l'état actuel de l'AS112 (ce qui a finalement été fait) ou son état souhaité (avec, par exemple, les nouvelles zones IPv6).

À noter que, d'après la liste officielle des sites, il existe au moins un serveur AS112 en France, chez Hivane, désormais (novembre 2011) connecté au France-IX. Malgré cela, les requêtes françaises pour les serveurs de l'AS112 voyagent souvent loin. C'est un problème banal comme le montrait l'excellente présentation « Investigating AS112 Routing and New Server Discovery ».

Voici quelques analyses sur le trafic de ce serveur français, faites avec DNSmezzo. Le fichier pcap fait 6,8 Go. Il y a 43 701 087 paquets DNS dont 21 858 845 sont des requêtes. Les données ont été prises un vendredi, de 13h40 à 15h30 (heure locale). Regardons d'abord les types de données demandés :

dnsmezzo=> SELECT (CASE WHEN type IS NULL THEN qtype::TEXT ELSE type END),
       meaning,                                                           
       count(results.id)*100/(SELECT count(id) FROM DNS_packets WHERE query) AS requests_percent FROM
             (SELECT id, qtype FROM dns_packets
                 WHERE query)  AS Results
          LEFT OUTER JOIN DNS_types ON qtype = value
              GROUP BY qtype, type, meaning ORDER BY requests_percent desc;


 type  |                meaning                 | requests_percent 
-------+----------------------------------------+------------------
 PTR   | a domain name pointer                  |               57
 TXT   | text strings                           |               35
 SOA   | marks the start of a zone of authority |                6
 CNAME | the canonical name for an alias        |                0
 MX    | mail exchange                          |                0
 AAAA  | IP6 Address                            |                0
 40    |                                        |                0
 DS    | Delegation Signer                      |                0
 ...

La première place des PTR est normale. Celle des TXT est plus surprenante. En regardant les noms utilisés (cf._dns-sd._udp.Y.X.243.10.in-addr.arpa...), on voit qu'ils sont dus à la technique Service Discovery d'Apple, un système normalement confiné au réseau local mais qui bave beaucoup à l'extérieur.

Et quels sont les domaines les plus populaires ?

dnsmezzo=> SELECT substr(registered_domain,1,46) AS domain, 
          count(id)*100/(SELECT count(id) FROM DNS_packets WHERE query) AS requests_percent  
       FROM dns_packets WHERE query GROUP BY registered_domain ORDER BY requests_percent DESC LIMIT 30;
      domain      | requests_percent 
------------------+------------------
 10.in-addr.arpa  |               78
 192.in-addr.arpa |               12
 172.in-addr.arpa |                7
 169.in-addr.arpa |                1
 151.in-addr.arpa |                0
 i~-addr.arpa     |                0
 83.in-addr.arpa  |                0
                  |                0
 gfi.private      |                0
 local.de         |                0
 grupofdez.com    |                0
....

On voit que le réseau 10.0.0.0/8 est nettement le plus populaire. On notera les trois derniers, sans doute des erreurs de configuration.

Et quels sont les résolveurs les plus actifs ? En agrégeant les préfixes IPv4 en /28 :

dnsmezzo=>  SELECT set_masklen(src_address::cidr, 28) AS client, count(id)*100/(SELECT count(id) FROM DNS_packets WHERE query) AS requests_percent                                                                  
     FROM dns_packets WHERE query GROUP BY set_masklen(src_address::cidr, 28)
           ORDER by requests_percent DESC LIMIT 30;
       client       | requests_percent 
--------------------+------------------
 CENSURE.160/28     |               29
 CENSURE.0/28       |               10
 CENSURE.16/28      |                8
 CENSURE.96/28      |                6
...

Oui, j'ai préféré ne pas donner les adresses. Je dirai simplement que ces quatre plus gros sont des opérateurs de téléphonie mobile, deux français et deux extrême-orientaux (les mystères du routage...).

Merci à Clément Cavadore pour les données et pour sa relecture.


Téléchargez le RFC 6304


L'article seul

RFC 6303: Locally-served DNS Zones

Date de publication du RFC : Juillet 2011
Auteur(s) du RFC : M. Andrews (ISC)
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 14 juillet 2011


Autrefois, les serveurs DNS récursifs, ceux qui, installés sur un réseau local ou chez un FAI pour ses abonnés, répondent aux requêtes DNS des clients finaux, ne servaient par défaut aucune zone. Tout était demandé aux serveurs DNS faisant autorité, sauf des zones locales configurées à la main. Le problème est que certaines zones privées très répandues étaient oubliées, et que le récurseur allait alors embêter les serveurs faisant autorité avec ces requêtes qui auraient dû rester locales. Ce nouveau RFC demande donc que, par défaut, sans aucune configuration explicite, les récurseurs fassent autorité pour certaines zones locales.

Un exemple typique est celui d'un réseau local numéroté avec les adresses IP privées du RFC 1918, mettons 172.27.0.0/16. Les machines dudit réseau reçoivent en DHCP l'adresse d'un serveur DNS récursif local. Celui-ci, avant la sortie de notre RFC 6303, ne connaissait pas 27.172.in-adr.arpa, le domaine utilisé pour les résolutions d'adresses IP en noms. Il va donc transmettre ces requêtes aux serveurs publics, en l'occurrence ceux de l'AS112 (RFC 7534), les faisant travailler pour rien. La bonne pratique, depuis toujours, est que l'administrateur système local ajoute la zone 27.172.in-adr.arpa à son récurseur. Mais incompétence, manque de temps et négligence (quelqu'un d'autre paie...) se conjuguent pour faire que c'est rarement déployé. L'idée de notre RFC 6303 est donc de déplacer le travail depuis les nombreux administrateurs réseaux vers les nettement moins nombreux auteurs de logiciels serveurs.

La section 3 du RFC décrit le changement chez les résolveurs. Ceux-ci devront répondre avec autorité NXDOMAIN (code de réponse 3), indiquant que le nom demandé n'existe pas. Une façon triviale d'implémenter ce comportement est de servir des zones vides, plus exactement, ne contenant que des SOA et des NS (exactement ce que fait l'AS112, cf. RFC 7534). La valeur recommandée pour le SOA et pour les NS est le nom de la zone et, pour l'adresse de contact, nobody@invalid. Le SOA est nécessaire pour le cache des réponses négatives (et pour les machines qui tiennent à tenter des mises à jour dynamiques du DNS, qui ont également besoin des NS). Sous forme d'un fichier de zone standard, cela donne (avec un TTL de trois heures) :

   @ 10800 IN SOA @ nobody.invalid. 1 3600 1200 604800 10800
   @ 10800 IN NS @

Ce comportement doit être débrayable, de préférence zone par zone, pour le cas des sites qui utilisent les adresses privées et ont configuré leurs serveurs DNS pour résoudre ces adresses en noms.

La liste initiale des zones à servir figure en section 4. Elle sert de point de départ au registre IANA, https://www.iana.org/assignments/locally-served-dns-zones/locally-served-dns-zones.xml, qui est la source faisant autorité (les auteurs de logiciels devraient donc le consulter avant des nouvelles publications de leur logiciel). Le registre est mis à jour (cf. section 6) par le processus « IETF review » décrit dans le RFC 5226, avec un appel au conservatisme : une fois ajoutée au registre, une zone ne pourra jamais être retirée, puisqu'il faudrait mettre à jour tous les logiciels. Il faut donc réfléchir longtemps avant d'ajouter une zone.

Aujourd'hui, ce registre inclut notamment les zones in-addr.arpa correspondant au RFC 1918 et celles correspondant aux réseaux du registre documenté dans le RFC 6890 , qui ne sont pas censés apparaître publiquement (comme les réseaux réservés pour la documentation). Il y a aussi des zones ip6.arpa (domaine utilisé pour la résolution d'adresses IPv6 en noms), comme celles des ULA du RFC 4193 (premier RFC à avoir normalisé cette pratique pour les résolveurs DNS, pour le domaine d.f.ip6.arpa), celles des adresses locales au lien (RFC 4291, section 2.5.6, un exemple étant 8.e.f.ip6.arpa), et celle du réseau réservé pour la documentation (RFC 3849).

En revanche, certaines zones ne sont pas incluses (section 5) comme les anciennes adresses locales au site d'IPv6 (RFC 4291, sections 2.4 et 2.5.7) ou comme des zones plus controversées comme les TLD numériques (pour traiter le cas des logiciels qui feraient des résolutions pour ces adresses, en les prenant pour des noms).

Suivre les recommandations de ce RFC peut-il avoir des effets négatifs ? La section 2 examine le cas. Comme les serveurs sont incités à ne servir les zones privées que si elles n'ont pas été configurées explicitement, les sites qui utilisent le RFC 1918 et ont peuplé les zones en in-addr.arpa ne devraient pas avoir de problème. La section 2 conclut que le problème ne se posera que dans un seul cas, les sites qui utilisent une délégation (typiquement depuis une racine locale, non connectée à l'Internet), sans que les résolveurs ne le voient. Ceux-ci devront explicitement reconfigurer leurs résolveurs pour ne pas servir les zones vides désormais installées par défaut.

Aujourd'hui, plusieurs récurseurs mettent déjà en œuvre ce RFC. C'est le cas par exemple d'Unbound (testé avec la 1.4.9). Un commentaire dans le fichier de configuration livré avec ce serveur dit :

	# defaults are localhost address, reverse for 127.0.0.1 and ::1
	# and nxdomain for AS112 zones. If you configure one of these zones
	# the default content is omitted, or you can omit it with 'nodefault'.

Le commentaire ne semble pas tout à fait correct, Unbound sert aussi par défaut des zones qui ne sont pas gérées par l'AS112 (comme les adresses réservées à la documentation). Voici sa réponse par défaut, lors d'une tentative de trouver le nom correspondant à l'adresse IP 172.27.1.1 :


% dig -x 172.27.1.1
...
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 8856
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

;; AUTHORITY SECTION:
27.172.in-addr.arpa.	10800	IN	SOA	localhost. nobody.invalid. 1 3600 1200 604800 10800

;; Query time: 67 msec
;; SERVER: ::1#53(::1)
;; WHEN: Fri Jul  8 17:47:21 2011
;; MSG SIZE  rcvd: 111

À noter que localhost est mis comme nom de serveur maître, pas 27.172.in-addr.arpa comme le demande le RFC (et je n'ai pas trouvé de moyen de le configurer). Pour le cas cité dans la section 2, où on veut interroger les serveurs faisant normalement autorité, on peut simplement mettre dans la configuration :

        local-zone: "27.172.in-addr.arpa" nodefault

et la zone 27.172.in-addr.arpa ne sera plus traitée comme spéciale, elle ne suivra plus ce RFC.

BIND (testé en version 9.8.0-P2) reconnait un certain nombre de zones automatiquement remplies et prévient au démarrage :

08-Jul-2011 19:43:59.410 automatic empty zone: 2.0.192.IN-ADDR.ARPA
08-Jul-2011 19:43:59.410 automatic empty zone: 100.51.198.IN-ADDR.ARPA
08-Jul-2011 19:43:59.410 automatic empty zone: 113.0.203.IN-ADDR.ARPA
...

Mais cette liste ne comprend pas encore les zones du RFC 1918. Voici le résultat en interrogeant les zones spéciales pour BIND :


% dig -x 192.0.2.1 
...
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 22522
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
...
;; AUTHORITY SECTION:
2.0.192.in-addr.arpa.	86400	IN	SOA	2.0.192.in-addr.arpa. . 0 28800 7200 604800 86400

;; Query time: 1 msec
;; SERVER: ::1#53(::1)
;; WHEN: Fri Jul  8 19:45:03 2011
;; MSG SIZE  rcvd: 86

On note que BIND ne respecte pas encore le RFC (l'adresse de contact n'est pas nobody@invalid) et que sa liste de zones spéciales n'est pas encore celle du registre IANA. Toutefois, tout cela est modifiable. Regardez la section « Built-in Empty Zones » de l'ARM (Administrator Reference Manual). Par exemple, vous pouvez changer l'adresse de contact avec empty-contact nobody@invalid dans la section options. Vous pouvez désactiver le comportement spécial pour une zone avec disable-empty-zone 2.0.192.in-addr.arpa dans la même section (l'équivalent du nodefault d'Unbound). Et bien d'autres possibilités.


Téléchargez le RFC 6303


L'article seul

RFC 6302: Logging recommendations for Internet facing servers

Date de publication du RFC : Juin 2011
Auteur(s) du RFC : A. Durand (Juniper Networks), I. Gashinsky (Yahoo! Inc.), D. Lee (Facebook), S. Sheppard (ATT Labs)
Réalisé dans le cadre du groupe de travail IETF intarea
Première rédaction de cet article le 1 juillet 2011


Ce court RFC prend position clairement en faveur d'un enregistrement, par les serveurs Internet, du numéro de port source du client, en plus de l'adresse IP. Cette recommandation est là pour tenir compte de la pratique de plus en plus répandue du partage d'adresses IP, notamment en raison de la pénurie des adresses IPv4.

En effet, depuis l'épuisement de ces adresses v4 début 2011, le partage d'adresses IP entre machines, par exemple via un routeur NAT, est de plus en plus fréquent. Or, de nombreux serveurs enregistrent dans un journal les adresses IP de leurs clients. Voici un exemple avec Apache :

2001:db8:1:4::1972 - - [29/Jun/2011:12:11:27 +0200] "GET /racine-dns-28-juin-2011.html HTTP/1.1" 200 9392 "-" "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.100 Safari/534.30" www.bortzmeyer.org

et un avec Postfix :

Jun 29 12:04:30 aetius postfix/smtpd[29360]: connect from foo.bar.example[198.51.100.79]

(Les adresses ont été changées.)

Noter les adresses IP seules n'a guère de sens puisque ces adresses n'identifient plus une machine unique. Le RFC recommande donc que le port source soit également noté. Le processus de discussion qui a mené à ce RFC avait commencé au moins deux ans avant, à la réunion d'Hiroshima.

Évidemment, la meilleure solution au partage d'adresses serait le déploiement d'IPv6. Mais comme il va prendre des années, il faut bien gérer la situation existante. Cela implique des solutions comme le NAT44 (le NAT traditionnel, cf. RFC 3022 et mon article sur les différentes formes de NAT), le NAT64 (RFC 6146) ou bien DS-Lite (RFC 6333). Ce partage d'adresses pose des tas de problèmes (documentés dans le RFC 6269) mais celui qui nous intéresse ici est le problème de l'enregistrement de l'adresse du client.

Prenons un NAT44 classique. Le client a une adresse privée (RFC 1918), mettons 192.168.42.1 et utilise le port source 52645. Il passe à travers un routeur NAT et ressort avec l'adresse publique 203.0.113.68 et le port source 61921. Le routeur a mémorisé l'association entre les deux tuples, interne {192.168.42.1, 52645} et externe {203.0.113.68, 61921}. Le serveur auquel se connecte ce client ne verra que le tuple externe. Si le serveur enregistre uniquement l'adresse 203.0.113.68, il ne pourra pas distinguer les requêtes faites par la machine 192.168.42.1 de celles faites par les autres machines situées derrière le même routeur NAT. Ce n'est pas forcément très grave pour du NAT fait à la maison (après tout, l'HADOPI coupera tout le monde, papa, maman et petit frère, si la fille aînée a téléchargé illégalement) mais c'est bien plus gênant pour du CGN, technique récente où plusieurs abonnés sans lien entre eux partagent une adresse IP.

Solution ? Que le serveur enregistre également le port source (ici, 61921). C'est désormais une recommandation officielle de l'IETF (voilà pourquoi ce document se nomme également « BCP 162 » pour Best Common Practices). Cette information, jointe à celle contenue dans le routeur NAT, permettra de retrouver le client original.

Notez le point mis en évidence : tout ceci n'a un sens que si le routeur NAT enregistre aussi les correspondances entre tuples {adresse, port} interne et externe. Le RFC prend soin de préciser que ses recommandations ne s'appliquent qu'aux serveurs, pas aux routeurs NAT qui, en pratique, à l'heure actuelle, n'enregistrent pas cette information (cf. section 3 sur ce point).

La recommandation exacte du RFC figure en section 2. Je la reprends ici :

  • Si (et c'est un gros si) le serveur enregistre l'adresse IP de ses clients, il doit aussi noter le port source,
  • Ainsi qu'une heure précise à la seconde près, et en utilisant une horloge qui soit synchronisée, par exemple via NTP (RFC 5905), et de préférence en UTC,
  • Et des informations comme le protocole de transport utilisé, au cas où le serveur en accepte plusieurs (les correspondances dans le routeur NAT dépendent en général du protocole de transport).

Vous avez bien noté que le RFC ne prend pas position sur la question de savoir si un serveur devrait enregistrer l'adresse IP de ses clients (note au passage : il existe des serveurs qui n'enregistrent pas cette adresse, justement pour éviter de « fliquer » leurs propres clients ; cela leur évite également la responsabilité d'un fichier sensible, puisque contenant des données à peu près nominatives). Il dit juste que, si le serveur le fait, il devrait également noter le port source et l'heure. Enregistrer l'adresse IP seule ne sert pas à grand'chose (sauf, je suppose, si le but est justement de ne pas garder de données trop nominatives. Au passage, un peu de publicité pour le service No Log.)

De la même façon, le RFC évite prudemment les questions de rétention des données (lesquelles, pour combien de temps). Chaque administrateur système doit consulter la loi locale (en France, la LCEN, loi liberticide qui contient des obligations très rigoureuses à ce sujet).

Enregistrer l'heure précise est nécessaire car le serveur ne sait évidemment pas à quel rythme sont réutilisés les numéros de port par le routeur NAT.

Voyons maintenant la mise en œuvre concrète de ces recommandations, avec les deux logiciels cités plus haut. Postfix a cette possibilité depuis assez longtemps (malgré les moqueries assez bêtes de son auteur au début) :

smtpd_client_port_logging = yes

Cela donne :

Jun 29 12:04:39 aetius postfix/smtpd[30055]: connect from foo.bar.example[198.51.100.79]:48525

Par contre, son concurrent sendmail ne semble pas avoir cette capacité (il faudrait peut-être modifier le source, en sendmail/srvrsmtp.c ou bien utiliser un milter smfi_connect, peut-être avec la macro ${client_port}.) Et je n'ai pas d'informations sur d'autres serveurs comme exim.

Pour Apache, cela se fait en ajoutant un %{remote}p dans le LogFormat :

LogFormat "%h %{remote}p %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %v" combined

ce qui donnerait :

2001:db8:1:4::1972 42425 - - [29/Jun/2011:12:11:27 +0200] "GET /racine-dns-28-juin-2011.html HTTP/1.1" 200 9392 "-" "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.100 Safari/534.30" www.bortzmeyer.org

(Le 42425 en deuxième champ.) Attention, si on analyse ses fichiers avec un programme de statistique comme analog, il faut changer également sa configuration, pour qu'il ne soit pas surpris par le champ supplémentaire.

J'ai montré un exemple avec une adresse IPv6. C'est sans doute inutile pour ce protocole (pas de traduction d'adresse/port en IPv6) mais c'est plus simple de mettre la même configuration pour les deux. Le paragraphe suivant présente un exemple où IPv4 et IPv6 sont traités différemment.

Si on veut faire plus joli, et écrire les adresses dans le style habituel des tuples {adresse, port} (adresse, deux-points, port dans le cas d'IPv4 et avec des crochets dans le cas d'IPv6, cf. RFC 3986), c'est plus compliqué. La solution que j'utilise (merci à @bitonio et @siddartha) passe par la définition d'une variable puis son utilisation dans la définition du format. (Une autre solution, due à @Grunt_, aurait été d'avoir un virtual host pour IPv4 et un pour IPv6.) Cela se configure ainsi :

LogFormat "[%h]:%{remote}p %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %v" combinedv6
LogFormat "%h:%{remote}p %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %v" combinedv4

SetEnvIf Remote_Addr : remote-v6
CustomLog /var/log/apache2/access.log combinedv6 env=remote-v6
CustomLog /var/log/apache2/access.log combinedv4 env=!remote-v6

Pour reconnaître une adresse IPv6, je cherche simplement la présence d'un deux-points. Si on veut faire mieux, il existe de jolies expressions rationnelles pour tester les familles d'adresses. Quoi qu'il en soit, le résultat est :

[2001:db8:1:4::1972]:42425 - - [29/Jun/2011:12:11:27 +0200] "GET /racine-dns-28-juin-2011.html HTTP/1.1" 200 9392 "-" "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.100 Safari/534.30" www.bortzmeyer.org

192.0.2.202:53124 - - [01/Jul/2011:08:29:15 +0200] "GET /6269.html HTTP/1.1" 200 37392 "-" "Netvibes (http://www.netvibes.com)" www.bortzmeyer.org

Là aussi, il faut penser aux programmes d'analyse, dont la plupart ne sont pas capables de traiter des cas où le format varie d'une ligne à l'autre. La première solution, moins jolie, était peut-être plus raisonnable.


Téléchargez le RFC 6302


L'article seul

RFC 6301: A Survey of Mobility Support In the Internet

Date de publication du RFC : Juillet 2011
Auteur(s) du RFC : Z. Zhu (UCLA), R. Wakikawa (TOYOTA ITC), L. Zhang (UCLA)
Pour information
Première rédaction de cet article le 10 juillet 2011
Dernière mise à jour le 12 juillet 2011


Dans le monde des réseaux informatiques, on distingue en général le nomadisme (pouvoir changer d'endroit et avoir à peu près les mêmes services) et la mobilité (pouvoir changer d'endroit en maintenant les sessions existantes, comme si on n'avait pas bougé). Aujourd'hui, où beaucoup d'équipements sont mobiles (smartphone, tablette, ...), la mobilité suscite beaucoup d'intérêt. D'où ce RFC qui évalue l'état actuel du déploiement des techniques de mobilité sur l'Internet. (Disons-le tout de suite, il est très faible.)

Je vais me permettre de commencer par une polémique et des opinions personnelles : dans la famille de protocoles TCP/IP, la mobilité, c'est comme le multicast. Beaucoup de RFC, très peu de paquets. Le sujet passionne les experts, pose plein de problèmes techniques amusants, permet d'écrire des algorithmes rigolos... mais touche très peu les utilisateurs. Comment cela, les utilisateurs ne veulent pas se connecter à l'Internet depuis leur maison, puis continuer au bureau ? Si, ils le veulent, mais il n'est pas du tout évident que la mobilité au niveau IP soit nécessaire pour cela. Aujourd'hui, la technique de mobilité la plus courante est DHCP... La machine reçoit une nouvelle adresse IP et ce sont les applications qui gèrent les déconnexions/reconnexions. Prenons l'exemple du client de messagerie instantanée Pidgin et supposons que je me promène avec mon ordinateur portable, connecté via clé USB 3G dans le train, via le Wifi au Starbucks, puis via un câble Ethernet au bureau. J'aurai une adresse IP différente à chaque fois et les sessions IRC ou XMPP seront donc coupées lors des changements. Est-ce grave ? Pas tellement. Pidgin se reconnectera automatiquement à chaque fois et la seule conséquence pratique sera les messages de déconnexion et de reconnexion que verront les abonnés de chaque canal IRC / pièce XMPP. On a là un bon exemple du fait qu'une gestion de la mobilité par l'application cliente (section 5.5 de notre RFC) est suffisante et qu'il n'y a pas besoin d'un service réseau (compliqué et amenant des problèmes de sécurité) pour cela. Même chose avec une application Web : chaque requête HTTP peut utiliser une adresse source différente, l'utilisateur ne s'en rendra pas compte (à part éventuellement une obligation de se réauthentifier si le cookie est lié à l'adresse IP, ce qui se fait parfois pour limiter la réutilisation d'un cookie volé). Les applications qui reposent sur HTTP (les clients Twitter, par exemple) arrivent également à maintenir une « session » lors de changements d'adresse IP.

Bien sûr, une telle gestion par l'application ne couvre pas tous les cas. Un gros transfert de fichiers avec curl ou wget ne peut pas fonctionner ainsi, puisque ce transfert utilise une seule connexion TCP, donc dépend de l'adresse IP source utilisée au départ (cf. section 6.2). (Avec rsync, et un script qui le relance jusqu'à completion, ça marcherait.) Et, évidemment, les sessions SSH ne peuvent pas être maintenues lorsqu'on change d'adresse. Mais il reste quand même énormément de cas où il n'y a pas de vrai problème lié à la mobilité et cela explique largement, à mon avis, pourquoi les techniques de mobilité IP sont si peu déployées. J'arrête là les opinions personnelles et je reviens au RFC.

La section 1 explique que ce RFC est motivé par le fait que la mobilité est depuis longtemps un sujet de recherche actif à l'IETF et que, depuis quelques années, le déploiement des engins mobiles a explosé (smartphones, tablettes, etc). Le besoin est donc nettement plus marqué maintenant que dix ans auparavant, lorsqu'un ordinateur portable était un machin encombrant et lent. Pourtant, les solutions normalisées par l'IETF ont été peu déployées.

Ces solutions utilisent un vocabulaire rappelé en section 2 et dans le RFC 3753. Notons notamment les termes d'identificateur (identifier) qui indique une valeur qui ne change pas lors des déplacements, de localisateur (locator), qui, lui, change lorsqu'on se déplace (en IP classique, c'est le cas de l'adresse IP), de correspondance (mapping), la fonction qui permet de trouver un localisateur en connaissant l'identificateur, de correspondant (CN pour Correspondent Node, la machine avec laquelle l'engin mobile communique), etc.

La section 3 expose les principes de base de la gestion de la mobilité. Le CN doit pouvoir, dans l'Internet actuel :

  • trouver l'adresse IP actuelle du mobile (solutions dites de type 1),
  • ou bien connaître un identificateur du mobile et pouvoir lui envoyer des données en utilisant cet identificateur (solutions de type 2), nettement plus fréquentes.

Un exemple de solution de type 1 est d'utiliser le DNS. Si le mobile met à jour (par exemple par mise à jour dynamique, cf. RFC 2136) le DNS lorsqu'il se déplace, on utilise le nom de domaine comme identificateur, l'adresse IP comme localisateur et le DNS comme correspondance. Le CN peut donc toujours trouver l'adresse IP actuelle par un simple getaddrinfo(). La plupart des techniques normalisées par l'IETF sont, elles, de type 2. Dans celles-ci, l'adresse IP sert d'identificateur (permettant de maintenir les sessions TCP, par exemple dans le cas de SSH). Les paquets envoyés par le CN sont alors transmis à cette adresse IP stable, où un équipement doit ensuite les renvoyer au mobile, alors que les paquets émis par le mobile vers le CN voyagent directement. On parle de routage en triangle. Peu satisfaisant du point de vue des performances, il est en revanche excellent pour la protection de la vie privée : le CN, la machine avec laquelle correspond le mobile, ne sait pas où on est et ne sait pas si on bouge. (Notons que le RFC, et c'est plutôt choquant, ne mentionne pas une seule fois ces questions de protection de la vie privée, même pas dans la section 7 sur la sécurité.)

La section 4 présente ensuite les protocoles de mobilité existants. Je ne vais pas les reprendre tous ici (la liste en compte vingt-deux !) mais simplement en choisir arbitrairement quelques uns. On trouve dans cette liste des ancêtres comme le protocole Columbia de 1991, ou des protocoles plus récents comme le Mobile IP de 1996. Certains des protocoles étudiés n'ont pas été conçus uniquement pour la mobilité, mais la facilitent. C'est le cas de HIP (2003), ILNP (2005) ou LISP (2009).

Columbia, par exemple, le premier conçu, ne fournissait la mobilité qu'à l'intérieur du campus. Dans chaque cellule radio, un routeur spécial, le MSS (Mobile Support Station), assurait le routage des paquets dont l'adresse IP source appartenait au préfixe spécial « mobilité ». Le mobile gardait donc son adresse et les MSS s'arrangeaient entre eux pour acheminer le paquet.

Le principal protocole standard de mobilité est aujourd'hui Mobile IP, normalisé dans les RFC 3344, RFC 6275 et RFC 5454. Il fonctionne en IPv4 ou en IPv6, sur la base des mêmes principes. Chaque mobile a un Home Agent, qui ne bouge pas, et qui fournit au mobile une adresse stable (Home Address). Le mobile a aussi une adresse IP liée à son point d'attache actuelle, l'adresse CoA (Care-of Address). Le mobile prévient le Home Agent de tout changement de CoA. Le correspondant, le CN, écrit toujours à l'adresses Home Address, charge au Home Agent de faire suivre. Mobile IP est donc de type 2 et, par défaut, fait du routage en triangle (une optimisation permet de le supprimer dans certains cas). Il existe aujourd'hui de nombreuses mises en œuvre de Mobile IP, aussi bien pour les mobiles que pour les Home Agents mais très peu de déploiements.

Un exemple de protocole de type 1 est E2E. Dans ce cas, l'identificateur stable du mobile est un nom de domaine, et c'est une simple requête DNS qui indique au correspondant quelle adresse IP utiliser. Le mobile, lorsqu'il change d'adresse IP, utilise les mises à jour dynamiques du DNS pour modifier cette information.

HIP n'était pas conçu uniquement pour la mobilité. Toutefois, en séparant identificateur et localisateur, il facilite celle-ci (RFC 5206). Pour trouver une adresse IP à partir d'un HI (Host Identifier, les identificateurs stables des nœuds HIP), on peut utiliser le DNS mais aussi des « serveurs de rendez-vous » spécifiques à HIP (RFC 5204). La mobilité avec HIP nécessite que le CN soit un nœud HIP également. Lorsqu'un mobile HIP se déplace, il doit prévenir à la fois les CN et le serveur de rendez-vous (message HIP UPDATE, section 5.3.5 du RFC 5201).

Autre protocole de séparation de l'identificateur et du localisateur qui facilite la mobilité, LISP. Bien plus récent, il est encore peu déployé, et ses extensions de mobilité sont seulement sous forme d'un projet de RFC, draft-meyer-lisp-mn.

Armé de ces descriptions, le RFC, dans se section 5, explique les différents choix qui ont été faits pour chaque protocole. C'est la section la plus intéressante du RFC. (La section 6.3 examine plus en détail les avantages et inconvénients de chaque approche.) Par exemple, une approche était de réutiliser le routage, en gardant l'adresse IP fixe pour le mobile, et en comptant sur des protocoles proches de ceux de routage pour assurer l'acheminement du paquet jusqu'au bonne endroit. Le protocole Columbia fonctionnait ainsi. Mais de telles solutions ne marchent bien qu'en réseau local : pas question de changer les routes de l'Internet chaque fois qu'un mobile se déplace.

Deuxième approche : une fonction de correspondance entre un identificateur stable et l'adresse IP actuelle. Au lieu de prévenir le monde entier lorsque son adresse change, le mobile n'aurait plus à prévenir qu'un seul point (le serveur DNS, ou le serveur de rendez-vous, pour les solutions de type 1 ou bien le Home Agent, pour celles de type 2.) Si le CN n'est pas prévenu du changement (cas de Mobile IP, par défaut), on perd en performances (routage en triangle) mais on gagne en intimité et surtout on n'a pas besoin que le CN comprenne le protocole de mobilité (avec Mobile IP, le mobile peut parler à des machines IP normales, qui ignorent tout de ce protocole).

Ce dernier point, couvert en détail dans la section 5.2, est crucial : qui doit être mis au courant de la mobilité ? Il y a quatre parties concernées : le mobile, son correspondant (CN), le réseau (les routeurs) et le composant qui donne un coup de main (Home Agent, serveur DNS, etc). Si le CN doit être mis au courant (cas de HIP, par exemple), il faut mettre à jour toutes les machines avec qui le mobile est susceptible de communiquer, ce qui ne semble pas très réaliste (d'autant plus que les gros serveurs Internet auraient à garder un état considérable, pour se souvenir de tous leurs clients récents). La plupart des approches, à commencer par Mobile IP, gardent donc une adresse IP stable et le CN est une machine ordinaire, qui ne sait même pas qu'elle parle à un mobile. Il existe aussi quelques protocoles où ni le CN, ni le mobile, ne sont au courant et où le réseau fait tout. Dans le futur, toutefois, de plus en plus de machines seront mobiles et il est possible que le premier choix (rendre le CN conscient que son partenaire se déplace) redevienne attirant.

Autre choix à faire, la mobilité doit-elle être contrôlée par le réseau ou par l'utilisateur (section 5.3) ? Dans les réseaux de téléphonie mobile, le terminal ne gère pas la mobilité, le réseau fait tout pour lui, et ça marche. Mais cela prive l'utilisateur de tout contrôle sur la façon dont est gérée la mobilité. (Songez aux scandaleux tarifs d'itinérance, rendus possibles par le fait que l'utilisateur ne peut pas empêcher que tout passe par son opérateur habituel.)

Les différences entre les protocoles de mobilité s'expliquent aussi par le fait que certains visent une solution mondiale, qui doit marcher pour des centaines de millions de mobiles se déplaçant partout dans le monde (ce qui soulève de sérieux problèmes de scalability) alors que d'autres (comme Columbia, cité plus haut), ne cherchent qu'une mobilité locale, problème bien plus facile (section 5.4).

Enfin, les vingt-deux protocoles examinés dans ce RFC ne couvrent pas tout. On peut aussi baptiser « mobilité » des solutions simples comme un serveur OpenVPN - qui jouera un rôle équivalent à celui du Home Agent - plus un client OpenVPN sur chacune des machines de l'utilisateur, avec une adresse IP fixe chacune. Il existe aussi des approches radicalement différentes (section 5.5) comme GTP (qui ne marche qu'à l'intérieur d'un fournisseur donné) ou comme des solutions fondées sur les applications, comme je l'ai prôné au début de cet article. Par exemple, SIP dispose d'une extension pour gérer la mobilité (cf. Schulzrinne, H. et E. Wedlund, « Application-Layer Mobility Using SIP », dans Mobile Computing and Communications Review, 2010) où un nouveau message INVITE est envoyé lorsque le mobile change d'adresse IP pendant une communication.

Je l'ai dit, les protocoles spécifiques de mobilité sont pour l'instant un échec complet. Mais que prévoient les auteurs du RFC pour le futur ? La section 6 analyse d'abord cet échec (section 6.1). Peu ou pas de déploiement en production, donc. Mais pourquoi ? Le RFC estime que c'est en partie le résultat du fait que les machines mobiles ne sont devenues banales que depuis très peu de temps. Mais il reconnait aussi que les protocoles de mobilité sont des usines à gaz complexes et lentes. Certains suggèrent même de simplifier le problème en ignorant les questions de performance et de sécurité (cf. section 7 sur les problèmes de sécurité spécifiques à la mobilité) dans un premier temps (ce conseil vient directement de l'excellente section 3 du RFC 5218).

Puis la section 6 explore les pistes à suivre. Une très bonne lecture pour les concepteurs de protocoles et les étudiants en réseaux informatiques.

Pour la mobilité des téléphones et la fréquence des déconnexions, changements d'adresse IP, etc, je recommande le bon article « A Day in the Life of a Mobile Device ».


Téléchargez le RFC 6301


L'article seul

RFC 6297: A Survey of Lower-than-Best-Effort Transport Protocols

Date de publication du RFC : Juin 2011
Auteur(s) du RFC : M. Welzl (University of Oslo), D. Ros (Institut Télécom / Télécom Bretagne)
Pour information
Réalisé dans le cadre du groupe de travail IETF ledbat
Première rédaction de cet article le 29 juin 2011


Aujourd'hui, de nombreuses applications se battent pour accéder à une ressource critique, la capacité du réseau. Tout le monde veut télécharger plus vite et les applications tentent d'obtenir le meilleur débit possible pour recevoir le dernier épisode de Dr House ou bien la page de ses amis sur Facebook. Pourtant, il existe une catégorie d'applications plus philosophes, qui cherchent à être le moins dérangeantes possibles et à ne transférer des octets que lorsqu'absolument personne d'autre n'a besoin du réseau. Ce RFC examine les techniques utilisées par ces applications tranquilles.

Il existe bien des cas où il n'y a pas d'urgence à transférer des données. Des mises à jour quotidiennes de gros fichiers ou bases de données non critiques, le transport des nouvelles Usenet (cf. RFC 5537), du téléchargement qu'on laisse tourner tout le temps, par exemple. Ces transferts, même s'ils n'ont pas besoin d'être « temps-réel » rentrent actuellement en compétition avec les transferts pressés. Si on télécharge tranquillement, sans être pressé, un gros film, et qu'on a un besoin urgent d'un fichier pendant ce temps, le fichier n'aura, pendant son transfert, que la moitié de la capacité, l'autre étant prise par le film. Il serait donc intéressant d'avoir des applications gentilles, modestes, qui cèdent systématiquement la place aux applications normales, dès que le réseau est encombré. L'IETF a un groupe de travail pour ce sujet du trafic « d'arrière-plan », dit aussi « moins que au mieux » (le trafic normal dans l'Internet étant acheminé « au mieux » - best effort). Ce groupe se nomme LEDBAT (Low Extra Delay Background Transport), et voici son premier RFC, qui étudie les techniques existantes pour atteindre cet objectif.

On pourrait même imaginer des tarifs intéressants ou des conditions d'accès au réseau plus favorables pour ces applications. Après tout, l'essentiel des coûts d'un réseau sont fixes : une fois la fibre posée et allumée, une fois les routeurs et commutateurs installés et configurés, le coût d'exploitation est le même que des bits passent ou pas. Ce qui coûte cher, en exploitation, c'est la congestion, lorsque la capacité du réseau est trop faible, que le service commence à se dégrader, et que les clients réclament une mise à jour de l'infrastructure, qui ne sera pas gratuite. Par contre, si le réseau est inutilisé à certains moments, y faire passer nos transferts de données gentils ne coûte rien. Dans tous les cas, tarifs intéressants ou pas, avoir des applications modestes aideraient certains services gourmands (comme le transfert de fichiers en pair-à-pair) à se faire accepter : on n'hésitera plus à laisser tourner BitTorrent en permanence si on est sûr qu'il cédera toujours aux applications habituelles.

La référence pour le trafic normal est TCP, le protocole de transport qu'utilisent quasiment tous les transferts de données et qui fait au mieux pour utiliser toute la capacité du réseau, ou pour la partager équitablement si elle est insuffisante (RFC 5681). Notre RFC vise donc le trafic « moins que TCP » tel que, s'il y a compétition entre trafic normal et notre trafic d'arrière-plan, le trafic normal ait la part du lion.

Le trafic d'arrière-plan est nommé dans ce RFC LBE pour less than best-effort. Un système LBE doit donc réagir à la congestion plus vite que TCP, pour abaisser son débit. Il y a quatre catégories de systèmes LBE :

  • Ceux qui agissent uniquement au niveau de l'application, et utilisent donc un TCP normal. C'est plus difficile à faire que ça n'en a l'air, car, si on applique strictement le modèle en couches, les applications n'ont pas connaissance de la congestion. Mais ce sont aussi les plus faciles à déployer, puisqu'on a juste à installer une nouvelle application.
  • Ceux qui s'appuient sur un protocole de transport modifié. Il en existe deux catégories, ceux qui se basent sur les délais d'acheminement des paquets (et non sur le taux de pertes, comme le fait TCP), et les autres. Ces protocoles de transport peuvent éventuellement réutiliser une partie de TCP (par exemple son format d'en-tête), facilitant ainsi leur déploiement. (Plusieurs des exemples se nomment « TCP quelque chose » pour cette raison. Wikipédia a une bonne page sur les variantes de TCP.)
  • Ceux qui s'appuient sur le réseau. Ce sont évidemment les plus durs à déployer, car ils nécessitent que tous les routeurs du trajet soient modifiés.

Les sections suivantes fournissent divers exemples (je ne les reprends pas tous ici) de chaque catégorie.

Les solutions dans les applications font l'objet de la section 4. A priori, on pourrait croire que les solutions de shaping comme l'option --bwlimit de rsync atteignent notre objectif de « trafic d'arrière-plan », ne rentrant jamais en compétition avec TCP. Mais ce n'est pas le cas. Les solutions de shaping sont :

  • trop modestes lorsque le tuyau est inutilisé. Si je transfère avec rsync --bwlimit 64, le débit ne dépassera jamais 64 ko/s.
  • trop gourmandes si le tuyau est encombré. rsync essaiera d'avoir ses 64 ko/s dans tous les cas.

Bref, ces options ne sont pas réellement LBE (voir Crovella, M. et P. Barford, « The network effects of prefetching », Proceedings of IEEE INFOCOM 1998, pour une meilleure description d'une solution de limitation de débit) .

De même, essayer de faire tourner les applications LBE aux heures creuses ne convient pas à toutes les applications (par exemple le transfert de fichiers en pair-à-pair). Autre solution, le BITS de Windows, qui surveille en permanence le débit pour ralentir ces transferts de fichiers en arrière-plan si le débit devient trop important. (Le RFC ne fournit pas d'éléments d'évaluation précis de ce service.)

Comment réaliser une application modeste ? Une première possibilité (section 4.1) est d'agir sur la fenêtre de réception, sur la machine destinataire. Le récepteur diminue la fenêtre TCP, par exemple lorsque le délai d'acheminement des paquets augmente (sur Unix, cela doit être mis en œuvre dans le noyau, je ne crois pas que l'application ait accès à cette fenêtre, mais cela ne nécessite pas de modifier le protocole TCP, c'est juste un changement unilatéral de comportement). C'est par exemple ce qui est fait en Spring, N., Chesire, M., Berryman, M., Sahasranaman, V., Anderson, T., et B. Bershad, « Receiver based management of low bandwidth access links ».

Dans les deux catégories de nouveaux protocoles de transport, voyons d'abord ceux fondés sur le délai d'acheminement. Le principe est de mesurer le temps que mettent les paquets à faire le trajet. Si cette durée augmente, c'est sans doute parce que le réseau est encombré et que donc la congestion approche. On diminue donc le débit (TCP, lui, attend bien plus, que les paquets soient effectivement jetés). La section 2 cite comme exemple TCP Vegas, un des premiers à pouvoir partager un lien avec TCP en étant systématiquement moins gourmand que lui, même si, curieusement, ce n'était pas son but initial. TCP Vegas permet au contraire souvent un meilleur débit, lorsqu'il est seul. Cela illustre le fait que ce n'est pas en diminuant le débit (cf. la discussion sur rsync) qu'on atteint l'objectif de modestie.

TCP Vegas est toujours la référence dans ce domaine. Mais, depuis, il existe des améliorations comme TCP Nice (voir Venkataramani, A., Kokku, R., et M. Dahlin, « TCP Nice: a mechanism for background transfers », qui reprennent le même principe de diminuer le débit lorsque le RTT diminue (sans attendre que les pertes de paquets commencent). À noter que TCP Nice a une mise en œuvre dans Linux (citée dans l'article ci-dessus).

Autre cas de protocole fondé sur le délai, TCP-LP, qui utilise le délai en aller simple et pas le RTT comme les deux précédents. C'est normalement un meilleur indicateur (on n'est pas perturbé par le trafic de retour, qui peut n'avoir rien à voir puisque le chemin de retour peut être différent, et/ou moins congestionné) mais il est plus difficile à mesurer (TCP-LP utilise l'option d'estampillage temporel des paquets de TCP, cf. RFC 7323).

Tous ces schémas ont un défaut commun : les études (par exemple McCullagh, G. et D. Leith, « Delay-based congestion control: Sampling and correlation issues revisited ») montrent que le délai d'acheminement n'a qu'un faible rapport avec l'approche de la congestion. Le délai varie souvent pour des raisons qui n'ont rien à voir avec l'encombrement (les tampons devraient être bien plus grands pour mesurer ce délai sans ce bruit ; les liens radio vont varier le délai quel que soit l'encombrement ; etc). En outre, les horloges des machines sont souvent insuffisantes pour mesurer le délai avec une bonne précision, surtout sur un réseau local où les paquets voyagent vite et où l'essentiel du délai est dû au traitement dans les machines, pas au réseau. Enfin, certaines techniques d'optimisation de TCP faussent encore plus cette mesure.

En pratique, ces problèmes peuvent mener à réduire le débit sans raison. Ces « faux positifs » atteignent quand même l'objectif (être moins gourmand que TCP) mais les problèmes de mesure peuvent aussi mener à des faux négatifs, où le protocole de transport ne détecte pas une congestion bien réelle.

Enfin, tout protocole fondé sur le délai d'acheminement donne un avantage aux derniers arrivants : sur un tuyau déjà très encombré, le flot récent voit des délais importants dès le début et ne se rend donc pas compte de la congestion.

Il existe aussi des protocoles de transport LBE (modestes) n'utilisant pas le délai d'acheminement (section 3). Ils jouent sur le rythme d'envoi (qui dépend de la réception des accusés de réception) pour, par exemple, diminuer la fenêtre d'envoi plus vite que TCP. C'est le cas de 4CP ou de MulTFRC (une extension du TFRC du RFC 5348).

Enfin, il y a les solutions qui utilisent une assistance du réseau (section 5). Sur le papier, ce sont les plus efficaces (pas besoin de mesures indirectes, comme celle du délai d'acheminement, le routeur sait parfaitement si le réseau est encombré ou pas) mais aussi les plus dures à déployer car elles nécessitent une modification de tous les routeurs.

Un exemple d'une telle technique est NF-TCP (Arumaithurai, M., Fu, X., et K. Ramakrishnan, « NF-TCP: A Network Friendly TCP Variant for Background Delay- Insensitive Applications ») qui combine ECN (RFC 3168) et RED (RFC 7567) pour diminuer la priorité des flots NF-TCP dans les routeurs dès que la congestion menace.

Armé de la connaissance de toutes ces techniques (on voit que l'imagination des chercheurs et ingénieurs a été intense sur ce sujet), que va faire le groupe de travail LEDBAT ? La section 6 explique que LEDBAT a déjà un système, décrit un l'Internet-Draft, fondé sur le délai d'acheminement » (ceux de la section 2). Ce n'est pas à proprement parler un protocole mais un algorithme, qui pourra être utilisé dans les protocoles concrets. Il a depuis été publié dans le RFC 6817.


Téléchargez le RFC 6297


L'article seul

RFC 6296: IPv6-to-IPv6 Network Prefix Translation

Date de publication du RFC : Juin 2011
Auteur(s) du RFC : M. Wasserman (Painless Security), F. Baker (Cisco Systems)
Expérimental
Première rédaction de cet article le 30 juin 2011


Avec ce RFC, encore expérimental, IPv6 gagne la possibilité de faire de la traduction d'adresses, c'est-à-dire d'avoir dans un réseau local des adresses internes, qui seront dynamiquement traduites en adresses externes par le routeur de sortie, qui pourra également faire l'opération inverse (de l'extérieur vers l'intérieur).

Cette traduction est souvent nommée NAT (Network Address Translation) mais ce terme n'est pas correct : la traduction habituelle en IPv4, celle que tout le monde doit supporter pour sa connexion Internet à la maison et pour son accès 3G, NAT44, ne traduit pas uniquement l'adresse. Pour faire face à la pénurie d'adresses IPv4, elle met en correspondance plusieurs adresses internes (typiquement du RFC 1918), avec une adresse externe, en utilisant les numéros de port pour démultiplexer les paquets entrants. Cette technique devrait donc s'appeler NAPT (Network Address and Port Translation) et pas NAT. Elle a des tas d'inconvénients, décrits dans le RFC 6269.

En IPv6 au contraire, sujet de notre RFC, il n'y a pas de pénurie d'adresses et pas de raison de faire du NAPT. Le protocole de traduction proposé dans ce RFC 6296 mériterait donc, lui, de s'appeler NAT (ou peut-être NAT66), mais, comme ce terme est désormais très galvaudé, ses auteurs ont plutôt choisi NPT pour Network Prefix Translation. NPTv6 permet une correspondance univoque (1:1) entre les adresses internes et les adresses externes, évitant ainsi le partage d'adresses dont le RFC 6269 décrit les défauts. Pour diverses raisons (cf. RFC 2993 et section 5 de notre RFC), l'IETF n'encourage pas les systèmes de traduction mais, si un utilisateur tient à en faire, ce RFC lui fournit un protocole bien étudié. Il n'évite pas tous les problèmes de la traduction (RFC 4864, RFC 5902) mais les limite.

N'utilisant pas les ports, NPTv6 fonctionne donc avec tous les protocoles de transport, contrairement au NAT44 traditionnel (cf. section 6). Il est sans état (chaque paquet est traduit indépendemment des autres) donc le routeur qui fait la traduction n'a pas de problèmes comme le remplissage de la table (fréquent avec NAT44). Ainsi, un réseau peut être servi par deux traducteurs (par exemple pour la redondance) sans qu'ils aient à partager un état. Mais ce caractère sans état a aussi d'autres conséquences :

  • NPT est juste une technique de traduction, il ne fournit pas de filtrage, ce n'est pas un pare-feu (les routeurs NAT44 mélangent les deux fonctions de traducteur et de pare-feu avec état), si on veut un pare-feu, il faut donc le faire en plus (cf. RFC 6092),
  • il permet le maintien du principe de la connexion de bout en bout, y compris pour les connexions « entrantes », mais, comme toute technique de traduction, NPT a des problèmes avec les applications qui incluent les adresses IP dans les données,
  • même problème avec les services qui incluent l'adresse IP dans le calcul d'un MAC comme l'option d'authentification de TCP (RFC 5925).

Voilà pour un résumé très rapide des propriétés de NPT v6.

Mais pour quelles raisons peut-on avoir envie de déployer un système de traduction ? La section 1.1 de notre RFC propose de les résumer en un principe : indépendance vis-à-vis de l'adresse. Ce principe comprend plusieurs propriétés :

  • Les adresses internes au réseau local étant distinctes de celles du réseau extérieur, aucune nécessité de renuméroter si on change de FAI (RFC 5887).
  • Le site peut choisir son opérateur, sa connexion, ses opérateurs multiples, même (multi-homing sans BGP),
  • Pas besoin d'obtenir des adresses PI pour avoir des adresses à soi,
  • Et pour le FAI, pas besoin de BCP 38 (RFC 2827), les adresses annoncées étant traduites en ses adresses.

« Adresses internes + traduction » est donc potentiellement un « PI du pauvre ». En IPv4, beaucoup de sites utilisaient le NAT pour atteindre cette indépendance, même lorsqu'elles pouvaient obtenir suffisamment d'adresses IP. Le RFC 4864 décrit d'ailleurs un concept proche nommé « autonomie du réseau ».

NPTv6 est donc un mécanisme qui permet de réaliser cette indépendance du réseau. Meilleur que le NAT44 (pas de manipulation des ports, fonctionne donc avec tous les protocoles de transport, comme SCTP, permet les connexions entrantes, purement « algorithmique » donc sans état), il peut donc être un ajout intéressant à la boîte à outils de l'administrateur de réseaux IPv6.

Pour être tout à fait complet, il faut aussi rappeler ses inconvénients (RFC 2993) :

  • Comme il modifie l'en-tête IP, il est incompatible avec les techniques de sécurisation de cet en-tête comme l'AH d'IPsec (RFC 4302),
  • Comme toute traduction d'adresses, il ne marche pas avec les protocoles qui transmettent des adresses IP dans les données comme SIP ; ceux-ci auront besoin d'un ALG,
  • La configuration du DNS va être pénible car il faudra prévoir une vue externe et une interne (split DNS).

Bref, NPTv6 n'est pas une solution parfaite et c'est pour cela que ce RFC reste au statut Expérimental.

Si on décide de poursuivre cette voie, il faut choisir les adresses à utiliser en interne. Les ULA du RFC 4193 semblent la solution idéale, maximisant l'indépendance.

Voici pour les grands principes. Quelques détails pratiques maintenant. Prenons l'exemple simple de la section 2.1 : un réseau interne, utilisant un préfixe ULA, fd01:203:405:/48, est connecté à l'Internet via un unique FAI, et un routeur qui fait du NPTv6. Le préfixe PA alloué par le FAI et routable publiquement est 2001:0db8:1:/48 (notez que NPT n'impose pas que les deux préfixes aient la même longueur, cf. section 3.7). Lorsqu'un paquet « sort » (va du réseau local vers l'Internet), l'adresse IP source est remplacée par une adresse IP prise dans le préfixe du FAI. Les autres champs de l'en-tête IP ne sont pas modifiés. En sens inverse, lorsqu'un paquet « entre » (vient de l'Internet vers le réseau local), c'est l'adresse de destination qui est touchée, pour être remplacée par une adresse du réseau local.

La partie identifiant la machine sur le réseau local (80 bits dans cet exemple) n'est en général pas conservée telle quelle. Ainsi, si fd01:203:405:1::1234 écrit à 2a00:1450:8007::13, Gmail, le destinataire, verra le paquet venant de 2001:0db8:1:d550::1234 nat66

En effet, la traduction est neutre pour la somme de contrôle. Si on suit l'algorithme standard du RFC 1071, on veut obtenir la même somme de contrôle avant et après traduction. Les protocoles qui utilisent une somme calculée sur une partie de l'en-tête IP (c'est le cas de TCP) ne seront donc pas affectés. Astuce amusante, pour atteindre cet objectif de neutralité, 16 bits de l'adresse sont réservés pour pouvoir y faire les modifications qui annuleront les autres changements faits dans l'adresse. L'algorithme exact de calcul est dans les sections 3.1 et suivantes. Une mise en œuvre en C figure en annexe B. À noter qu'elle ne prétend pas être optimale, faisant par exemple les calculs de somme de contrôle avec du code portable et pas de l'assembleur adapté à une machine particulière.

On peut avoir des cas plus compliqués que ce simple réseau, par exemple du multi-homing, où le réseau local est connecté à deux FAI (section 2.4). Chacun de ces deux FAI alloue un préfixe PA différent. Les liens avec les deux FAI passent par deux routeurs NPT différents, tous les deux configurés avec le même préfixe interne mais différents préfixes externes. Une machine du réseau local ne pourra pas savoir sous quelle adresse elle apparaitra à l'extérieur, sauf à utiliser une technique comme STUN (RFC 8489). La décision de sortir par un FAI ou l'autre peut être prise comme on veut. Par contre, par rapport à du vrai multi-homing, avec adresses PI et BGP, un changement de FAI de sortie entraîne un changement de l'adresse IP vue par l'extérieur et coupe donc toutes les sessions en cours.

Continuons avec les considérations de déploiement et de configuration (section 4). Le plus probable est que NPTv6 sera mis en œuvre dans les routeurs, comme dans l'exemple ci-dessus, et, pour les particuliers et petites organisations dans le CPE. Les obligations du RFC 7084 s'appliquent donc à l'engin qui fait la traduction.

Cela implique entre autres que le traducteur NPT soit capable de faire des virages en épingle à cheveux (renvoyer vers le réseau local un paquet qui était à destination du réseau local, cf. RFC 4787), afin que des machines du réseau local puissent se parler en utilisant leurs adresses publiques. Comme NPT ne tripote pas les ports, la plupart des autres exigences des RFC du groupe BEHAVE ne s'appliquent pas à lui.

Et pour les applications, quelles sont les conséquences (section 5) ? Plusieurs des problèmes classiques de la traduction, qui avaient déjà été décrits dans le RFC 2993 sont toujours présents. Les applications ne verront pas les mêmes adresses, selon qu'elles sont situées d'un côté ou de l'autre du traducteur. Par exemple, si un ordinateur portable se déplace de part et d'autre du traducteur, il verra ses connexions s'interrompre, son adresse IP ayant changé. Mais les problèmes les plus fréquents et les plus sérieux seront pour les protocoles applicatifs qui utilisent des références, c'est-à-dire qui indiquent dans les données à quelle adresse IP envoyer les paquets. Les cas les plus connus sont FTP et SIP. Si un client SIP envoie à un autre son adresse interne, pour recevoir un flux RTP, cette adresse ne sera pas traduite, et le flux ne joindra pas la destination. Que peut-on faire pour limiter les dégâts ?

  • Comme avec le NAT44, les applications peuvent utiliser STUN pour apprendre leur adresse,
  • Dans le futur, un mécanisme de référence général, résistant aux traductions, sera peut-être développé.

Et la sécurité du NPTv6 ? La section 7 résume les points importants. Le principal est que, contrairement au NAT classique, avec état, NPT n'empêche pas les connexions entrantes. C'est une bonne chose mais cela peut dérouter certains administrateurs réseaux qui croyaient que la traduction les protégeait de l'extérieur. Ce n'est pas le cas avec NPTv6 et si on veut une telle protection, il faut installer un pare-feu explicite (alors que le NAT traditionnel mélange les deux rôles de traduction et de protection), comme décrit dans le RFC 6092.

Curieusement, cette idée de traduction d'adresses sans état, selon une cardinalité 1:1, est très ancienne. Si notre RFC 6296 semble être le premier RFC à la décrire, elle avait été à la base du projet GSE, auquel l'annexe A rend hommage. GSE, décrit dans le draft draft-ietf-ipngwg-gseaddr, était un des projets qui avaient été élaborés pour le successeur d'IPv4. Contrairement au projet retenu (le futur IPv6) qui conservait les concepts de base de son prédécesseur, GSE repensait nettement le problème de l'adressage dans l'Internet. Celui-ci était divisé en deux, les réseaux de transit et les réseaux de bordure. Dans GSE, seuls les réseaux de transit avaient des adresses publiques et annoncées dans la table de routage globale. Les réseaux de bordure avaient des adresses stables et uniques mais qui n'étaient pas routées. Les adresses étaient traduites lors du passage du réseau de bordure au réseau de transit et réciproquement. Le but était surtout de limiter la croissance de la table de routage (problème qu'IPv6 avait finalement décidé de ne pas traiter). En décembre 2010, sur l'Internet, il y a 36 000 systèmes autonomes dont 15 000 n'annoncent qu'un seul préfixe (et sont donc probablement des réseaux de bordure). Seuls 5 000 systèmes autonomes apparaissent dans des chemins (en dehors de l'origine) et sont donc des réseaux de transit.

Et les implémentations publiquement disponibles ? (Merci à François Romieu et Samuel Thibault pour leurs informations.) Il y a map66 et aussi nfnat66 (NAT66 pour Netfilter), qui utilise netfilter et est présenté en français dans l'exposé de Guy Leduc et plus en détail dans la thèse de Terry Moës, « IPv6 address translation in a Linux kernel ». Ne m'en demandez pas plus, je n'ai pas testé. (À noter qu'il en existe aussi pour des techniques de traduction IPv6<->IPv6 différentes, par exemple avec état.)

Mais c'est une autre mise en œuvre qui a été intégrée dans le noyau Linux en août 2012 (commit 8a91bb0c304b0853f8c59b1b48c7822c52362cba) et qui a donc été livrée avec la sortie de la version 3.7 en décembre 2012. Regardez les fichiers en net/ipv6/netfilter comme ip6table_nat.c.


Téléchargez le RFC 6296


L'article seul

RFC 6293: Requirements for Internet-Draft Tracking by the IETF Community in the Datatracker

Date de publication du RFC : Juin 2011
Auteur(s) du RFC : P. Hoffman (VPN Consortium)
Pour information
Réalisé dans le cadre du groupe de travail IETF genarea
Première rédaction de cet article le 24 juin 2011
Dernière mise à jour le 6 juillet 2012


Une des particularités de l'IETF est son extrême ouverture. Tout le monde peut suivre le travail en cours, les documents de travail (les Internet Drafts) sont publiquement accessibles, l'état de chaque document dans le processus de publication peut être suivi sur le Web. Bref, sans avoir à se ruiner en déplacements physiques, le participant à l'IETF a accès à tout ce qu'il faut. Mais ce système a aussi ses insuffisances, notamment parce qu'il ne permet pas d'accès personnalisé et que seuls certains participants ont un accès en écriture. Ce RFC est donc le cahier des charges d'un nouveau système de suivi des Internet Drafts, système qui a finalement été déployé début juillet 2012.

Le système de suivi du travail de l'IETF repose sur un ensemble d'outils non-officiels maintenus par des volontaires, http://tools.ietf.org/, et par un site officiel de suivi, le « Datatracker » (http://datatracker.ietf.org/. Le Datatracker permet de s'identifier, pour certaines actions, mais cette possibilité n'était pas ouverte aux participants ordinaires, seulement à ceux chargés d'une tâche comme le pilotage d'un groupe de travail. (Notez que « participant IETF » = « public » puisque l'IETF n'a pas d'adhesion formelle, tout le monde en est membre dès qu'il participe, cf. section 1.3.)

Le Datatracker donne accès à plein d'informations sur les documents en cours (la section 1 résume les possibilités de l'actuel Datatracker). Prenons l'exemple de l'Internet Draft que demandait l'ICANN sur la syntaxe des noms de TLD, draft-liman-tld-names. On peut connaître son état en visitant http://datatracker.ietf.org/doc/draft-liman-tld-names/ : au 23 juin 2011, la version actuelle est la n° 5, datant du 12 avril, et il est en état I-D Exists, qui est l'état normal de tout Internet Draft. Il n'est donc pas en vue d'une publication comme RFC, juste en discussion. Si on veut suivre les évolutions du document, nul besoin de tout relire (comme c'est le cas dans d'autres organisations, où les diff ne sont pas fournies lors de la sortie d'un nouveau document), le Datatracker est serviable. Voici les différences entre les versions 4 et 5 : http://tools.ietf.org/rfcdiff?url1=draft-liman-tld-names-04&difftype=--html&submit=Go!&url2=draft-liman-tld-names-05 (dans ce cas précis, elles étaient purement administratives).

Si je m'intéresse plutôt au document sur le protocole de résolution de noms d'Apple appelé (bien à tort) Multicast DNS, je trouve l'information en http://datatracker.ietf.org/doc/draft-cheshire-dnsext-multicastdns/. Le document (actuellement en version 14) est approuvé par l'IESG mais a besoin d'une nouvelle version. Les opinions des membres de l'IESG sont accessibles en http://datatracker.ietf.org/doc/draft-cheshire-dnsext-multicastdns/ballot/ (Discuss signifiant une objection.).

Ce niveau de transparence est bien au delà de ce que font les autres SDO comme l'UIT ou l'AFNOR où tout le travail est fait derrière des portes closes, pour éviter que le public n'y participe. Mais on peut encore faire mieux.

Par exemple (section 1.1), on pourrait imaginer qu'un utilisateur veuille s'identifier pour retrouver les informations sur la liste des Internet Drafts qu'il suit, liste déterminée manuellement ou via une recherche. Il peut aussi vouloir recevoir une notification si une nouvelle version d'un de ces documents apparait.

La section 2 décrit plus précisement les exigences du nouveau Datatracker :

  • Possibilité de se créer un compte automatiquement (et pas manuellement sur demande, comme aujourd'hui, ce qui n'est pas très 2.0), et ses propres listes de documents à suivre,
  • Possibilité de modifier l'affichage dans le Datatracker (par exemple l'ordre de présentation des documents, la liste des attributs affichés, etc),
  • Gestion de grandes listes (des dizaines de documents suivis),
  • Définition des listes par des attributs comme « Tous les Internet Drafts du groupe de travail XXX », « Tous ls Internet Drafts écrits par Machin », « Tous les Internet Drafts qui citent le RFC yyyy », etc,
  • Publication sous forme de flux Atom, notification par courrier, peut-être demain notification des changements via XMPP.

D'autres idées, dont la mise en œuvre n'est pas requise pour la première phase, figurent dans les annexes A et B. Par exemple, suivi des changements dans les registres IANA (ça, cela me serait très utile).

Le cahier des charges est donc fini, il ne restait plus que le développement et le déploiement, qui a été finalisé le 3 juillet 2012. Tout le monde peut désormais en bénéficier.


Téléchargez le RFC 6293


L'article seul

RFC 6286: AS-wide Unique BGP Identifier for BGP-4

Date de publication du RFC : Juin 2011
Auteur(s) du RFC : E. Chen, J. Yuan (Cisco Systems)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF idr
Première rédaction de cet article le 11 octobre 2011


Un tout petit RFC pour régler un bête problème de définition dans le protocole BGP. L'identifiant d'un routeur BGP devait être une adresse IPv4. Avec l'épuisement de ces adresses, tous les routeurs n'en auront pas forcément une et ce RFC accepte explicitement comme identificateur n'importe quel numéro unique (à l'intérieur d'un AS).

Cet identifiant est défini par la norme BGP (RFC 4271, section 1.1) comme un nombre de 32 bits, qui doit être une des adresses IPv4 du routeur (cela assurait son unicité en réutilisant un nombre déjà alloué ; cette unicité est vérifiée lors de l'établissement de la connexion). La section 2.1 de notre RFC supprime l'obligation d'être une adresse IPv4, et ajoute celle que le numéro soit unique au sein de l'AS (ou, plus exactement, de la confédération, s'il y a plusieurs AS). Cette unicité par AS était nécessaire pour les cas où un routeur fait de l'agrégation de routes qu'il relaie (section 3).

Ce changement ne modifie donc pas le protocole BGP, ni le comportement de chacun des pairs BGP. Simplement, dans le cas d'un réseau purement IPv6, où aucun des routeurs n'avait d'adresse IPv4, ils pourront désormais prendre un nombre quelconque comme identifiant, sans violer de RFC.


Téléchargez le RFC 6286


L'article seul

RFC 6280: An Architecture for Location and Location Privacy in Internet Applications

Date de publication du RFC : Juillet 2011
Auteur(s) du RFC : R. Barnes, M. Lepinski (BBN Technologies), A. Cooper, J. Morris (Center for Democracy & Technology), H. Tschofenig (Nokia Siemens Networks), H. Schulzrinne (Columbia University)
Réalisé dans le cadre du groupe de travail IETF geopriv
Première rédaction de cet article le 24 juillet 2011


Aujourd'hui, de nombreuses applications des réseaux informatiques dépendent de la localisation physique de l'appareil mobile. La récolte de ces données de localisation (« le 31 mai 2011, à 08:04, l'appareil était en 40,756° Nord et 73,982° Ouest, ±150m »), leur transmission à travers le réseau, et leur traitement par le service qui héberge l'application posent de graves questions de protection de la vie privée, surtout quand on lit les conditions d'utilisation de ces services (si on pouvait comprendre le jargon juridique, elles se résumeraient à « nous faisons ce que nous voulons, nous nous occupons de tout, ne vous inquiétez pas »). D'où ce RFC qui essaie de définir une architecture de gestion de la vie privée pour ces informations de localisation.

Un exemple d'une telle application est Pages Jaunes sur Android : elle permet d'obtenir des réponses qui dépendent du lieu, tel que l'a indiqué le téléphone. Ainsi, si on tape « pizzeria », on obtient en haut du classement les pizzerias les plus proches physiquement. Résultat, les Pages Jaunes savent où vous êtes et on imagine facilement les conséquences pour la vie privée de ce genre de suivi (« L'utilisateur est allé quatre fois dans une clinique spécialisée cette semaine. »). Outre les Pages Jaunes, plusieurs intermédiaires connaissent également votre position (l'opérateur du réseau, qui sait par quelle borne vous vous connectez, les tiers qui écoutent, si le trafic n'est pas chiffré, et le téléphone lui-même qui peut garder cette information très longtemps, comme le fait l'iPhone). À noter que cette information est collectée en permanence, sans action explicite de l'utilisateur (section 1.2). Dans les romans policiers, finies les longues filatures sous la pluie pour savoir où passe le suspect. Le cyber-policier moderne ne bouge plus de sa chaise et obtient via le réseau toutes les informations nécessaires, chaque citoyen emportant avec lui volontairement l'outil qui permet de le suivre à la trace.

Le RFC (section 1) ne prétend même pas qu'il va régler ce problème, qui est consubstantiel de la récolte et diffusion d'informations de localisation : il affirme juste qu'il tente de limiter les dégâts.

Il y a deux autres points importants à comprendre sur cette « architecture de protection de la vie privée » : d'abord, ce n'est qu'une architecture, pas un protocole, encore moins un logiciel. Elle définit un cadre et des principes, elle ne fournit pas de solutions clé en main. Ensuite, s'agissant d'un travail de l'IETF, elle ne traite que l'aspect technique. Si on suit ce RFC, et les standards futurs qui le développeront, on peut faire un système relativement protecteur de la vie privée. Mais la technique ne suffit pas : le respect du RFC ne garantit pas la sécurité, c'est une norme technique, pas une politique. Des lois de protection de la vie privée (et qui soient d'application générale, pas annulables par des conditions d'utilisation d'un service commercial), bien appliquées et une vigilance citoyenne permanente sont nécessaires si on veut empêcher la vie privée de devenir une marchandise comme les autres.

Ce RFC 6280, œuvre du groupe de travail Geopriv, qui travaille sur tous les problèmes situés à l'intersection de la localisation et de la vie privée, tourne autour de la notion d'« objet de localisation » (une bonne introduction à Geopriv est le RFC 3693). Cet objet stocke la localisation et les règles d'utilisation de cette information. Lorsque l'objet est transmis, les conditions d'utilisation voyagent avec lui (section 1.1). Ainsi, celui qui reçoit une information de localisation ne peut pas prétendre ignorer les règles qui s'y attachent. Ces règles sont, par exemple, « ne transmets ces données à personne » ou, plus subtil, « ne transmets les informations à mon entreprise que pendant les heures de travail ».

Lier les règles d'usage aux informations de localisation est contraignant mais permet de d'assurer que le destinataire a accès à ces règles. Le RFC cite l'exemple des licences libres comme Creative Commons, qui imposent une telle liaison. Il y a eu de nombreuses polémiques (par exemple au sujet de la GFDL), sur l'opportunité d'imposer l'inclusion du (long) texte de la licence dans chaque document couvert par cette licence mais le but est le même : couper court à toute tentative de jouer l'ignorance. Un autre exemple donné par le RFC est celui des classifications utilisées par les militaires (« Secret », « Confidentiel », etc). Tous les documents sont marqués avec leur niveau de sécurité et tout militaire qui les manipule sait donc exactement ce qu'il peut faire ou ne pas faire avec ce document. (Un exemple détaillé figure dans les règles de classification du ministère de la défense états-unien.)

La solution radicale serait évidemment d'arrêter la collecte et la transmission de ces informations. Mais, outre qu'elles peuvent permettre d'améliorer certains services (comme dans l'exemple des pizzérias plus haut), des systèmes comme le GSM ne peuvent pas fonctionner sans connaître la localisation de l'utilisateur (pas moyen de lui faire suivre un appel entrant si on ne sait pas quelle borne le dessert en ce moment). Comment limiter les dégâts ? Historiquement, les décisions en matière de vie privée étaient prises uniquement par le récepteur des données, qui en faisait à peu près ce qu'il voulait. Le seul choix de la personne concernée était de partager ses données ou pas, et ce choix binaire ne permettait pas d'indiquer ce qu'il acceptait qu'on fasse des données (section 1.3). Comme, évidemment, les intérêts des personnes ne coïncident pas avec ceux des entreprises privées et organisations étatiques qui reçoivent les données, les abus étaient inévitables. Par exemple, un utilisateur envoie volontairement son adresse électronique sur un site Web pour recevoir ensuite des informations, mais il ne pouvait jamais s'opposer à ce que cette adresse soit ensuite revendue à des spammeurs. (Aujourd'hui, il est courant de voir une case à cocher « J'accepte de recevoir du spam, pardon, que mon adresse soit revendue à des tiers » mais il faut noter que c'est le site Web destinataire qui définit les choix possibles, pas le titulaire de l'adresse.) Geopriv pose donc comme principe que l'utilisateur, pas le destinataire, définit les usages acceptables, et les indique avec les données. À noter que ce n'est qu'une indication. Il n'existe pas de moyen technique de s'assurer que ces choix de l'utilisateur seront respectés, une fois les données transmises. Sur un réseau distribué comme l'Internet, il n'y a pas de possibilité de concevoir un mécanisme technique de respect de ces règles. Celui-ci doit être assuré par des moyens autres, comme la loi (loi Informatique & Libertés, par exemple), des régulateurs efficaces et/ou le marché (note personnelle : pour des raisons idéologiques, le marché est mentionné par le RFC comme mécanisme possible de rétroaction sur les entreprises qui violeraient les usages spécifiés par l'émetteur ; l'expérience déjà ancienne de l'Internet en matière de protection de la vie privée montre bien la vanité de cette idée). Le mécanisme technique de Geopriv sert donc juste à s'assurer que le destinataire des données était conscient des règles et donc, s'il les a violées, qu'il était de mauvaise foi (ce qui est important pour d'éventuelles poursuites judiciaires).

Avec la section 3 commence la partie la plus technique du RFC : elle décrit l'architecture utilisée. Les deux objectifs de cette architecture sont :

  • S'assurer que les données de localisation ne soient distribuées qu'aux entités autorisées,
  • S'assurer que ces entités soient au courant des conditions d'usage.

Comme on l'a vu, s'assurer que les entités réceptrices ne peuvent pas techniquement violer les règles est un non-but : il n'est pas réalisable techniquement. Pour atteindre les deux objectifs, il y a deux classes de règles :

  • Les contrôles d'accès qui indiquent les entités autorisées,
  • Les règles d'usage, qui indiquent ce que celles-ci ont le droit de faire.

Un exemple figure en section 3.1, décrivant le « cycle de vie » des données. Alice se déplace. Son mobile apprend sa position (par le réseau de communication, ou bien par GPS) et elle veut partager cette information avec ses amis via un service de présence (un tiers, qu'on suppose de confiance). Avec cette information viennent les règles d'usage qu'Alice a définies, par exemple que les amis ne peuvent pas garder cette information plus de N jours. Si un ami, mettons Bob, veut transmettre l'information sur la localisation d'Alice à des amis à lui, il devra également vérifier si les règles d'usage lui permettent (rappelez-vous que ce RFC définit une architecture de sécurité, pas des moyens techniques de protection ; comme le savent ceux qui ont essayé de mettre en œuvre des DRM, il n'existe aucun moyen technique d'empêcher Bob de tricher et de faire suivre ces données à des gens non autorisés).

Décrire ensuite tout ce qui se passe nécessite un vocabulaire élaboré (section 3.2). On y trouve de nombreux rôle (un même acteur pouvant tenir plusieurs rôles) :

  • Le sujet (target) est la personne dont on veut protéger la vie privée (Alice, dans l'exemple précédent),
  • L'engin (device) est la machine que porte le sujet (par exemple son smartphone) ; techniquement, c'est lui qui est localisé, pas le sujet (pensez au nombre de films où un personnage jette son téléphone pour ne pas être repéré),
  • Le décideur (rule maker) est celui qui définit les règles d'usage ; c'est souvent le sujet, mais cela peut être le responsable sécurité de son entreprise,
  • Le localisateur (location generator) est le matériel ou logiciel qui détermine la localisation ; cela peut être un récepteur GPS ou bien la partie GSM de l'appareil, qui obtient sa localisation à partir du réseau GSM,
  • Les serveurs de localisation (location server), terme impropre : un serveur de localisation est une entité susceptible de transmettre l'information de localisation, en appliquant les règles d'usage. Dans l'exemple plus haut, Alice, le serveur de présence, et Bob connaissaient tous les trois la localisation d'Alice et étaient susceptibles de la transmettre (et donc étaient des serveurs de localisation potentiels),
  • Les destinataires de la localisation (location recipient) sont toutes les entités qui connaissent la localisation du sujet et s'en servent mais ne la transmettent pas forcément. Bob, le serveur de présence, les autres amis qui ne relayaient pas l'information, sont tous des destinataires de localisation.

J'ai simplifié en mettant un seul décideur et un seul localisateur mais il peut y avoir des cas plus complexes.

Pour mettre en œuvre l'architecture de sécurité Geopriv, on a besoin de deux formats de données :

  • Les objets de localisation (LO pour Location Object, cf. RFC 5491), qui stockent une position, exprimée en géodésique (geodetic, c'est-à-dire longitude, latitude, altitude) ou bien en civil (civic, comme 120, rue de la Gare, 75013, Paris..., voir par exemple le RFC 5139),
  • Les règles d'usage (PR pour Privacy Rules, et RFC 4745 pour un exemple de langage pour exprimer ces règles).

En utilisant cette terminologie, la section 4 du RFC décrit le cycle de vie de l'information de localisation. Elle passe par trois étapes :

  • Détermination de la localisation (un fix, dans la terminologie GPS),
  • Distribution de la localisation, par les serveurs de localisation,
  • Utilisation de la localisation, par les destinataires.

Les trois étapes sont ensuite étudiées une à une, chacune posant des problèmes spécifiques de protection de la vie privée.

La section 4.1 parle de la détermination. Elle peut être faite par l'engin lui-même (GPS, observation des étoiles et bien d'autres, y compris pour le cas trivial où l'utilisateur rentre manuellement l'information), par le réseau auquel il se connecte, ou bien via une coopération entre tous les deux. Dans le premier cas, guère de problème de sécurité dans cette étape, l'engin étant tout seul (les satellites GPS ne dialoguent pas avec l'engin, ils ne savent pas qui les utilise). Bien plus délicat est le cas où c'est le réseau qui détermine la position. C'est ce qui se produit en GSM (le réseau sait avec quelle base parle l'engin, et l'intensité du signal, ainsi que sa direction, peuvent donner une idée plus précise de la position de l'engin) mais évidemment aussi en connexion filaire, où le réseau sait exactement où on se trouve. Tout mécanisme du genre GeoIP est également un cas de détermination de la position par le réseau. Il n'y a pas forcément besoin d'un protocole réseau. Mais le point important est qu'un tiers (pas seulement le sujet) connait dès le début la position de l'engin. Enfin, le troisième cas est celui de la détermination assistée par le réseau. Par exemple, un engin va mesurer un certain nombre de choses comme la force du signal radio, l'adresse MAC obtenue, etc, et les envoyer à un localisateur qui en déduira une position précise. Cette fois, il y a un protocole réseau (entre l'engin et le localisateur), qu'il faut protéger, par exemple contre l'écoute.

L'étape de détermination est le premier endroit où on peut appliquer des mesures de protection, comme l'utilisation d'identificateurs qui ne permettent pas un lien simple avec l'utilisateur, et comme le chiffrement pour empêcher l'écoute, dans le cas où la détermination emploie un dialogue sur le réseau.

La deuxième étape est la distribution de l'information de localisation (section 4.2). C'est là que les règles d'usage commencent à jouer un rôle, en limitant la redistribution. Voici quelques exemples de règles :

  • Ne retransmettre cette information qu'aux machines dont le nom se termine en example.com,
  • Ne transmettre de l'adresse que la ville et le pays (pas la rue),
  • Dans la même idée de dégradation délibérée de la précision, ne transmettre de la longitude et latitude que des valeurs arrondies à la minute d'angle la plus proche (environ deux kilomètres)...

Les deux derniers exemples montrent qu'un serveur de localisation a deux armes à sa disposition, ne pas transmettre la localisation du tout, ou bien la transformer pour limiter les risques.

Pour cette étape de distribution, les choses les plus importantes sont de toujours transmettre les règles d'usage avec la localisation, et de respecter ensuite ces règles. Ces règles pouvant dépendre de l'identité de celui à qui on transmet, utiliser des techniques d'authentification fiables est donc impératif. De même, il faut veiller à ce qu'un tiers non-autorisé ne puisse pas accéder aux données qui circulent sur le réseau, donc le chiffrement est fortement souhaité. On est là dans un domaine plus traditionnel pour l'IETF, la conception de protocoles réseaux sûrs.

Enfin, la troisième étape du cycle de vie de l'information de localisation est l'utilisation de l'information (section 4.3). Le destinataire doit respecter les règles d'usage, qu'il a reçu avec l'objet de localisation. Normalement, ce respect est obligatoire et des mesures administratives ou légales doivent être déployées pour s'assurer que ce soit le cas. Cette étape ne comprend pas de transmission de l'information et ne nécessite donc pas de protocole réseau.

La section 6 du RFC fournit des exemples de scénarios concrets d'utilisation de cette information de localisation. Le premier scénario est très simple : un engin détermine sa position et la transmet à une application Web dans une requête HTTP de type POST ou bien une requête SIP de type INVITE. Le serveur fournit le service demandé, sans stocker l'information de localisation. Dans ce cas ultra-simple, pas de place pour les architectures compliquées, les rôles sont bien définis (le RFC oublie toutefois de rappeler que la connexion entre l'engin et le serveur doit être protégée contre l'écoute).

Plus complexe, en section 6.2, le cas où un navigateur Web qui fait appel à des API de détermination de sa position (comme la Geolocation API, dont l'implémentation fait souvent appel à l'aide du réseau d'accès) et exécute du code JavaScript qui va appeler des services d'assistance à la détermination de la position (voyez un bon tutoriel en « Geocoding A User's Location Using Javascript's GeoLocation API »). Notez qu'une partie des risques peut provenir d'une action du navigateur après avoir obtenu sa position. Par exemple, s'il demande à Google Maps une carte des environs, Google Maps, bien que n'étant pas partie lors de la détermination de la position, la connaîtra désormais. Il y a plus de deux acteurs, cette fois (notez que, même sur une machine unique, il peut y avoir plusieurs composants logiciels ne se faisant pas mutuellement confiance) et donc davantage de complexité.

Enfin, le troisième scénario est plus critique puisqu'il concerne un appel d'urgence, domaine très régulé, puisque beaucoup d'opérateurs ont l'obligation légale de fournir automatiquement la localisation de l'appel. Ici, la distribution de l'information se fera typiquement en utilisant LoST (RFC 5222).

Comme tout RFC, notre RFC 6280 inclut une section sur les problèmes de sécurité (section 5). Ici, elle sert surtout de rappel car tout le RFC est consacré à la sécurité. Parmi les rappels : le fait qu'il existe déjà des protocoles fournissant les fonctions de sécurité importantes (IPsec et TLS, par exemple) et que les solutions de localisation devraient les utiliser. Autre rappel : la sécurité de bout en bout est préférable à la sécurité transitive et il est donc recommandé qu'on sécurise l'ensemble du trajet, pas juste chaque étape (pensez au cas de Bob faisant suivre un objet de localisation : l'a-t-il modifié ?). Une bonne étude générale des problèmes de sécurité de Geopriv est dans le RFC 3694.


Téléchargez le RFC 6280


L'article seul

RFC 6274: Security Assessment of the Internet Protocol version 4

Date de publication du RFC : Juillet 2011
Auteur(s) du RFC : F. Gont (UK CPNI)
Pour information
Réalisé dans le cadre du groupe de travail IETF opsec
Première rédaction de cet article le 6 juillet 2011


Le protocole IPv4, qui représente toujours la très grande majorité du trafic réseau sur l'Internet, n'avait jamais fait l'objet d'un rapport synthétique sur sa sécurité. Certes, il existe d'innombrables articles portant sur la sécurité d'IPv4, des avis des CSIRT, de très nombreuses mentions dans les RFC et ailleurs. Mais tout ceci était dispersé dans de nombreux documents, et pas forcément facilement accessible lorsqu'on se mettait à lire les normes. D'où ce RFC 6274 qui rassemble en un seul endroit tout ce qu'il faut savoir sur la sécurité d'IPv4. Pas de révélations dans ce document, les problèmes qui y sont décrits sont très classiques, souvent résolus depuis des années mais, comme ils n'avaient pas forcément été documentés dans un RFC, il y avait un risque sérieux qu'un programmeur, voulant mettre en œuvre IPv4 en partant de zéro, retombe dans des failles anciennes. Ce RFC vise donc à éviter toute régression. Avant sa publication, un programmeur qui ne lisait que les RFC était à peu près sûr de créer des failles de sécurité béantes.

Parfois, c'est même pire : des failles connues ne sont pas résolues dans certaines implémentations, ou bien le sont d'une manière qui rend le remède pire que le mal (beaucoup de programmeurs ne connaissent de la sécurité que de vagues notions et des légendes entendues et jamais contestées).

L'introduction (section 1) note qu'IPv4 avait été conçu dans un environnement très différent de ce qu'il est aujourd'hui. Toutefois, elle ne reprend pas l'idée courante mais fausse comme quoi les failles de sécurité d'IPv4 découleraient d'une vision optimiste et naïve de la nature humaine, d'une époque où seuls des bisounours utilisaient l'Internet et où il n'était donc pas nécessaire de prévoir des mécanismes de sécurité. En réalité, même si on refaisait l'Internet aujourd'hui en partant de zéro, une bonne partie des problèmes se poserait de la même façon : sécuriser un réseau multi-organisations et multi-national n'est pas de la tarte, que ce soit aujourd'hui, ou bien il y a vingt-cinq ans ! Quoi qu'il en soit, l'Internet est aujourd'hui une ressource critique, dont dépendent bien des choses dans le monde. Sa sécurité est donc un enjeu majeur.

À propos de légendes, le RFC prend position sur le récit « Internet a été conçu pour résister à une attaque nucléaire » en estimant que ce n'est pas exact, que la principale motivation n'était pas de fournir un système de communications invulnérable aux militaires, mais de partager l'accès à des mainframes (voir l'article de D. Clark, « The Design Philosophy of the DARPA Internet Protocols », Computer Communication Review Vol. 18, No. 4, 1988).

Les problèmes de sécurité découverts depuis ont parfois affecté une mise en œuvre particulière (c'est une loi générale du logiciel : « il y a des bogues ») et parfois les concepts de base du protocole, rendant bien plus difficile la solution. La bibliographie du RFC donne une idée des problèmes les plus importants.

Comme il n'est pas réaliste de couvrir tous les problèmes de sécurité de l'Internet, ce RFC se focalise (section 1.2) sur ceux d'IP lui-même, excluant les protocoles de transport comme TCP ainsi que les protocoles de routage comme BGP ou ceux de démarrage comme DHCP. Les RFC cruciaux pour cette évaluation de la sécurité sont donc :

La section 2 du RFC rappelle les concepts de base d'IP, inchangés depuis ses débuts (et parfois depuis l'époque d'Arpanet). Reprenant l'article fondateur de Clark cité plus haut, il cite les trois principes essentiels :

  • Pas d'état dans les routeurs, ceux-ci traitent chaque paquet sans tenir compte des paquets précédents,
  • Un service minimum au niveau IP, notamment sans garantie de délivrance (ce qui fait qu'une grande partie du travail doit être fournie par des protocoles situés au dessus, comme TCP),
  • Un service minimum fourni par les couches inférieures, auxquelles IP ne demande pas grand'chose, lui permettant de fonctionner sur n'importe quel réseau.

Maintenant, allons-y, avec deux longues sections, dont je ne transmets ici qu'une partie : la section 3 examine un par un les champs de l'en-tête du paquet IP et les différentes façons dont ils peuvent impacter la sécurité. La section 4 examine les différents mécanismes de traitement de paquets IP et ce qui peut en résulter.

La section 3 commence par rappeler le schéma du RFC 791 décrivant tous les champs qu'on trouve dans l'en-tête d'un paquet IP. En théorie, tous les paquets doivent obéir à certains invariants, le premier cité par le RFC étant que la taille du paquet doit être d'au moins vingt octets (la taille minimale d'un en-tête et donc d'un paquet). Mais, comme l'a observé toute personne qui a analysé du trafic réseau avec des dissecteurs mal écrits, on trouve de tout sur l'Internet et notamment plein de paquets mal formés. Notre RFC 6274 donne donc à chaque fois des conseils de tests de santé à faire sur chaque paquet avant de le traiter. Le premier test est donc longueur(paquet) >= 20. À chaque fois, si le test échoue, le paquet devrait être abandonné et un compteur de problèmes incrémenté. Allons-y maintenant pour les autres tests (oui, cela va être long), dans l'ordre des champs.

L'en-tête a un champ Version qui, pour IPv4, doit valoir... 4 (section 3.1). En théorie, on peut imaginer des techniques de couche 2 où les paquets de différentes versions d'IP soient démultiplexés par ce champ (une telle technique existe dans la section 3.2 du RFC 6214, publié le premier avril 2011). En pratique toutefois, tous les réseaux existants fournissent un autre moyen de démultiplexer (par exemple le champ EtherType dans Ethernet, qui vaut 0x0800 pour IPv4 et 0x86DD pour IPv6) et donc, une fois le paquet reçu par l'implémentation IPv4, le champ Version doit donc forcément valoir 4 et il faut vérifier cela. Oublier ce test permettrait certaines attaques où un méchant mettrait une autre valeur pour exploiter le fait que certains équipements accepteraient le paquet et d'autres (avec un peu de chance, les IDS) l'ignoreraient.

Champ suivant, IHL (Internet Header Length), la longueur de l'en-tête du paquet IP (contrairement à IPv6, celle-ci n'est pas constante, en raison de la présence possible d'options). Comme elle est exprimée en nombre de mots de quatre octets, le test de longueur minimale est cette fois longueur(en-tête) >= 5. Comme l'en-tête est forcément plus petit que le paquet, on doit aussi vérifier longueur(en-tête) * 4 <= longueur(paquet). Ces tests peuvent sembler un peu bêtes mais il y a déjà eu des attaques jouant sur des longueurs bizarres, pour forcer une implémentation à lire des zones mémoire où elle n'aurait pas dû aller. Là encore, en cas d'échec des tests, abandon du paquet et incrémentation du compteur des paquets invalides.

Tout est évidemment plus compliqué lorsqu'un champ a changé de sémantique, ce qui est le cas de l'ancien ToS (Type of Service) devenu DSCP avec le RFC 2474 (section 3.3). Normalement, toutes les mises en œuvre d'IP devraient traiter ce champ selon la nouvelle définition mais cela ne semble pas être le cas. Donc, une application peut mettre une valeur qui semblera inoffensive si elle est interprétée comme ToS mais lui donnera une priorité si cette même valeur est interprétée comme DSCP. Une protection possible est d'effacer ce champ lorsqu'un paquet arrive dans un domaine administratif (la qualité de service différenciée n'a de toute façon de sens qu'à l'intérieur d'un même domaine, au sein d'une même entreprise, par exemple).

Les bonnes intentions faisant parfois les belles failles de sécurité, la section 3.3.2.2 est consacrée à ECN (RFC 3168), une technique de lutte contre la congestion, qui peut dans certains cas être exploitée contre la sécurité (par exemple en faisant croire qu'on gère la congestion par cette technique, même si ce n'est pas vrai, simplement pour diminuer la probabilité de voir ses paquets jetés par les routeurs).

On a déjà parlé de longueur, de celle indiquée par la couche 2, de celle indiquée par le champ IHL pour indiquer la longueur de l'en-tête... Il y a aussi un champ Total Length qui indique la longueur du paquet (en-tête compris). Quels sont les pièges de sécurité liés à ce champ (section 3.4) ? D'abord, ce champ pouvant indiquer des tailles jusqu'à 65535 octets, les mises en œuvre d'IP doivent préparer des tampons d'entrée/sortie assez grands pour cela. Normalement, les correspondants ne doivent pas envoyer de paquets de plus de 576 octets avant qu'on leur ai signalé qu'on pouvait traiter plus (par exemple par le biais de l'option MSS de TCP, ou par l'EDNS du DNS). Mais il existe certains cas où les autres machines envoient des paquets plus grands sans prévenir (cas de NFS) et, de toute façon, un attaquant ne suivra pas forcément les règles.

Plus rigolo, un attaquant peut transmettre un paquet plus grand que la taille indiquée dans le champ Longueur, par exemple dans l'espoir d'obtenir un débordement de tampon. Si la couche 2 lui permet, il peut même envoyer des paquets plus grands que 65535 octets. Ce genre de paquets se trouve réellement dans la nature et peuvent être le résultat d'une programmation maladroite, ou bien d'une tentative d'attaque (comme celle citée en « US-CERT Vulnerability Note VU#310387: Cisco IOS discloses fragments of previous packets when Express Forwarding is enabled »). Le récepteur doit donc être paranoïaque. Allouer un tampon de la taille indiquée par le champ Longueur, puis y copier le paquet sans vérification serait très imprudent. Il faut utiliser au contraire la taille indiquée par la couche 2.

Le champ suivant la longueur, ID, identifie le fragment (section 3.5), pour permettre le réassemblage en cas de fragmentation. Sur certains systèmes, la façon dont est choisie ce nombre peut révéler bien des choses sur l'emetteur (voir « Idle scanning and related IP ID games »). Sur les systèmes anciens, l'ID était unique par paquet, choisi de manière incrémentale et donnait donc au récepteur une indication, par exemple sur le nombre de machines derrière un routeur NAT. Comment peut-on limiter ces risques de fuite d'information ? Une des solutions est de mettre le champ ID à zéro pour tout paquet qui a le bit DF (Don't Fragment). Ces paquets ne pouvant être fragmentés, le fait d'avoir tous le même ID n'est pas gênant. Linux a été le premier à faire cela. Mais certains équipements mal conçus (les affreuses middleboxes) fragmentaient quand même ces paquets, qu'on ne pouvait plus réassembler. Depuis, Linux (et Solaris) mettent un ID fixe, mais différent pour chaque adresse, ce qui limite les fuites d'information. En effet, l'ID n'a pas besoin d'être unique par machine, il suffit qu'il soit unique par tuple {source, destination, protocole}. Le mieux serait donc de générer aléatoirement (pour empêcher les fuites d'information) un ID unique par « session » pour chaque tuple. Attention à bien lire le RFC 4086 avant de choisir son générateur aléatoire. Ce problème de choix entre un identificateur prévisible (qui est donc indiscret) et un identificateur aléatoire (qui risque donc d'être réutilisé plus vite) est très proche de celui du choix du port source décrit dans le RFC 6056.

Le cas est plus complexe pour les protocoles sans connexion comme UDP (utilisé notamment pour le DNS qui, depuis le déploiement de DNSSEC, a plus souvent des paquets fragmentés). Dans certains cas, des paquets corrompus risquent d'être réassemblés et les protections des couches supérieures risquent de ne pas être suffisantes pour détecter cette corruption (pour le DNS, il faut au moins activer la somme de contrôle UDP, ce qui limite les risques).

Passons maintenant au champ Flags de l'en-tête (section 3.6). Il contient trois bits dont deux sont définis : DF (Don't Fragment) et MF (More Fragments). De manière amusante, le bit DF peut être utilisé pour empêcher la détection par un IDS. Si l'attaquant sait que, après l'IDS, la MTU baisse, il peut envoyer des paquets ayant le bit DF dont certains sont trop gros pour cette MTU. L'IDS va les lire mais la machine de destination ne les verra jamais, puisqu'ils ont été jetés par le routeur précédent (qui n'avait pas le droit de les fragmenter). L'IDS et la machine de destination verront alors des données différentes, ce qui peut permettre de rendre indétectable une charge utile malveillante. Si ce cas semble extrêmement tordu (depuis quand met-on des tunnels après les IDS ?), il faut préciser qu'il existe des variantes de cette attaque, basées sur les bogues de certains logiciels (par exemple qui jettent les paquets ayant à la fois MF et DF, alors que ces paquets peuvent atteindre la destination), qui permettent d'obtenir le même résultat.

Juste après, un autre champ lié au réassemblage, le champ Fragment Offset (section 3.7). Si certaines des attaques décrites dans ce RFC peuvent sembler purement théoriques, celles portant sur des jeux avec l'algorithme de réassemblage des fragments sont très courantes en pratique. Ce champ indique la position du fragment dans le datagramme original et les valeurs bizarres de ce champ sont fréquentes dans la nature. Par exemple, un fragment peut prétendre être situé plus loin que le 65535ème octet du paquet original (le champ est assez grand pour cela, on peut aller jusqu'à 131043 octets), ce qui peut mener à des débordements de tampon au cours du réassemblage. Cela a déjà été utilisé par exemple dans l'attaque nommée (bien à tort) ping of death (« CERT Advisory CA-1996-26: Denial-of-Service Attack via ping » et « The Ping of Death Page » en 1996. Cette attaque est très mal nommée parce qu'elle n'a rien à voir avec ping, ni même avec ICMP. un paquet IP de n'importe quel protocole peut convenir. Si vous faites un interview d'un candidat à un poste d'administrateur réseaux, c'est une bonne question à poser : « faut-il filtrer ICMP sur le pare-feu ? ». S'il répond « oui, à cause du ping of death », vous savez qu'il n'y connait pas grand'chose en sécurité des réseaux.

Et le bon vieux champ TTL (Time To Live, section 3.8), pose-t-il aussi des problèmes de sécurité ? Oui. Il peut transmettre de l'information (type de système d'exploitation à la source, puisque la valeur par défaut du TTL peut en dépendre, distance de la source, d'après la diminution observée, etc). Son rôle dans la découverte de la topologie du réseau est bien connu puisqu'elle est utilisée par l'outil traceroute (qui lance des paquets de TTL croissant, pour repérer les routeurs qui reçoivent un paquet de TTL nul et refusent donc de le transmettre).

Il peut, comme dans le cas de DF, être utilisé pour faire en sorte qu'un IDS et la machine de destination ne voient pas la même chose, par exemple en mettant un TTL plus bas aux paquets destinés seulement à l'IDS. S'il y a un routeur après l'IDS, ces paquets ne seront pas vus par la machine cible. L'outil Scrub d'OpenBSD peut aider contre cette attaque.

Mais le TTL a aussi des usages positifs en terme de sécurité. Par exemple, mis à la valeur maximale (255), il peut permettre de s'assurer qu'un paquet vient bien du réseau local, en vérifiant que le TTL est bien 255 à l'arrivée (cette technique est décrite en détail dans le RFC 5082).

Le champ suivant le TTL indique le protocole utilisé par les couches supérieures (UDP, TCP, SCTP, etc). Il n'a rien de dangereux mais certaines attaques dans le passé utilisaient ce champ avec des implémentations boguées (section 3.9).

Ensuite vient la somme de contrôle de l'en-tête. Là encore, on peut s'en servir pour échapper à certains contrôles faits par des équipements qui ne testent pas cette somme. En mettant délibérement une valeur invalide, on crée un paquet qui sera vu par certaines machines et pas par d'autres, trompant ainsi les IDS.

Puis viennent les adresses IP, les deux champs suivants, qui indiquent respectivement les adresses source et destination (section 3.11 et 3.12). Normalement, tout le monde connait leur principale faiblesse en matière de sécurité : elles ne sont pas authentifiées et l'émetteur du paquet (ou un intermédiaire) peut mettre ce qu'il veut, surtout dans la source. Les adresses identifient normalement une interface réseau (la notion d'« adresse IP d'une machine » n'existe pas en IP). Sauf que rien n'empêche de mettre ce qu'on veut. (Un rappel au passage : le logiciel le plus souple et le plus facile d'usage pour fabriquer de faux paquets, en bricolant les champs qu'on veut, est Scapy. Utilisez-le, vous en serez content.) Normalement, un filtrage est réalisé par le réseau d'accès (RFC 2827 et RFC 3704, mais aussi « NISCC Technical Note 01/2006: Egress and Ingress Filtering ») pour empêcher les mensonges les plus éhontés de sortir sur l'Internet mais, en pratique, très peu de fournisseurs d'accès font ce test. (Le Spoofer Project mesure ce pourcentage.) Une autre technique de protection est la surveillance des adresses utilisées sur le réseau local, par exemple avec arpwatch.

On a donc vu d'innombrables attaques où les adresses IP source des attaquants étaient fausses. Le RFC fournit quelques exemples comme « CERT Advisory CA-1996-01: UDP Port Denial-of-Service Attack », « CERT Advisory CA-1996-21: TCP SYN Flooding and IP Spoofing Attacks » ou « CERT Advisory CA-1998-01: Smurf IP Denial-of- Service Attacks ».

Cette absence d'authentification des adresses IP se retrouve à d'autres endroits que l'en-tête IP, par exemple, dans les paquets ICMP qui sont censés transporter une partie du paquet original : rien n'indique que cette information soit fiable (RFC 5927).

Conséquence pratique, il ne faut surtout pas authentifier une machine sur la seule base de l'adresse IP qu'elle présente. Par exemple, dans le cas d'une dDoS, on voit parfois des administrateurs réseaux naïfs croire qu'ils ont découvert l'origine de l'attaque lorsqu'ils ont fait un whois sur l'adresse IP source, sans penser une seconde qu'elle puisse être trompeuse...

À noter que le RFC ne rappelle pas qu'on peut « authentfier » une adresse IP si le protocole de transport impose des aller-retours, ce qui est en général le cas avec TCP (si les numéros de séquence initiaux sont bien choisis au hasard, l'attaquant doit recevoir ou voir passer les paquets de réponse, pour arriver à établir une connexion).

IPv4 a ensuite un champ Options, le dernier du paquet. Il est de taille variable car les options sont... optionnelles (section 3.13). Bien que plusieurs options aient été normalisées, elles sont très peu utilisées en pratique, en partie parce qu'elles ne passent pas partout, en partie parce que leur présence peut ralentir sérieusement le paquet (beaucoup de routeurs traitent le paquet « normal » en ASIC et transmettent les paquets ayant des options au processeur principal, bien plus lent : cela peut être exploité pour DoSer le routeur en envoyant plein de paquets avec options).

Les options étant de taille variable (le curieux lira avec amusement la section 3.1 du RFC 791, qui explique les deux méthodes d'encodage d'une option), il y a une nouvelle possibilité d'attaque par débordement de tampon, si l'indication de la longueur de l'option est fausse. Là encore, quelques tests sont indispensables, les options du cas 2 ont une longueur d'au moins deux octets (option-length >= 2), et cette longueur ne doit pas nous mener en dehors du paquet (option-offset + option-length <= IHL * 4). Si vous êtes étudiant, faites attention : écrire un analyseur de paquets IP est un TP classique et le professeur sadique risque fort d'envoyer à votre analyseur des paquets délibérement mal formés pour vous prendre en défaut.

Autre piège pour le code d'analyse, les types utilisés : certaines options ont des pointeurs, stockés sur un octet, et le RFC 791 ne précise pas si cet octet est signé ou non. Si on ne fait pas attention, on peut se retrouver avec des pointeurs négatifs.

Ça, c'était le problème des options en général. Après, certaines options spécifiques ont leurs propres problèmes de sécurité. LSSR (Loose Source and Record Route, option de numéro 13) permet de contourner le routage et donc certaines règles des pare-feux, permet de joindre des machines normalement injoignables (par exemple si elles ont une adresse IP privée et sont derrière un routeur NAT), etc. Ces risques sont tels, par rapport aux bénéfices de cette option, que notre RFC 6274 recommandent de jeter sans autre forme de procès tous les paquets ayant cette option, dans la configuration par défaut des équipements. Un exemple d'attaque contre OpenBSD est décrit dans « OpenBSD Security Advisory: IP Source Routing Problem ». Mêmes remarques, et même recommandation pour l'option SSSR (Strict Source and Record Source, numéro 137). Cette option a déjà été utilisé pour des attaques (par exemple « Microsoft Security Program: Microsoft Security Bulletin (MS99-038). Patch Available for "Spoofed Route Pointer" Vulnerability" ».

L'option Record Route (section 3.13.2.5) est encore pire puisque le routeur doit alors écrire dans le paquet lui-même. Comme avec les deux précédentes, il est vital de vérifier que les pointeurs ne pointent pas n'importe où. (Le problème touche d'autres protocoles qu'IP ; par exemple, lors du dévelopement de DNSmezzo ou de grong, j'ai pu constater que les pointeurs utilisés dans la compression des paquets DNS sont souvent invalides et ne doivent pas être suivis aveuglément.) En outre, cette option est indiscrète, puisqu'elle permet de réveler les routeurs par lesquels est passé un paquet. La taille très limitée du champ Options limite ce risque (on ne peut pas stocker plus de quelques routeurs) et rend cette option peu utile.

Un grand nombre de ces options peuvent être considérées comme n'étant que d'un intérêt historique (mais le code pour les traiter est parfois toujours là dans la pile IP et peut provoquer des problèmes de sécurité). C'est le cas de Timestamp (numéro 68, section 3.13.2.7), qui indique au routeur de marquer l'heure de passage du paquet dans le paquet. Comme Record Route, elle est indiscrète et devrait donc être ignorée par défaut. Comme Record Route, elle entraine une écriture dans le paquet, à l'endroit indiqué par un pointeur et il faut donc, si on a activé cette option, vérifier le pointeur.

Je passe sur un certain nombre d'options pittoresques pour arriver à DoD Basic security Option (numéro 130). Cette option militaire, normalisée dans le RFC 1108, indique le niveau de sécurité du paquet (« confidentiel », « secret », « très secret », etc). Contrairement à la plupart des options IPv4, elle est largement mise en œuvre et déployée. Par exemple, SELinux, Cisco IOS et Solaris l'ont et beaucoup de réseaux comptent dessus. Elle a même inspiré un équivalent IPv6, décrit dans le RFC 5570.

Après cette longue liste des champs de l'en-tête IP, la section 4 de notre RFC 6274 s'attaque aux mécanismes actifs de traitement des paquets. De nouvelles failles se cachent là. Les principales touchent le processus de fragmentation et réassemblage (section 4.1). Lorsqu'un paquet IPv4 est trop gros pour le lien qu'il va emprunter, l'émetteur, ou bien le routeur intermédiaire, fragmentent ce paquet en paquets plus petits. La machine de destination (pas les routeurs) va devoir réassembler un paquet entier. Historiquement, ce processus est à l'origine de très nombreuses failles de sécurité. En effet, le réassemblage est une opération très complexe et qui était mal normalisée. C'est une opération qui nécessite de maintenir un état (dans un protocole, IP, qui est normalement sans état), le réassembleur ne connait pas les caractéristiques du chemin suivi par les paquets et ne sait donc pas combien de temps il peut attendre des fragments manquants, et les fragments peuvent arriver dans le désordre.

Quelles sont les conséquences de sécurité de la fragmentation ? D'abord, l'allocation mémoire : la machine de destination ne sait pas combien de temps elle doit attendre les fragments manquants. Elle doit donc réserver un espace mémoire pour le paquet et le garder jusqu'à être sûr que les fragments manquants n'arriveront jamais. Le RFC 1122 conseille de rester ainsi pendant 60 à 120 secondes, ce qui est très long si on reçoit beaucoup de paquets et peut mener à un épuisement de la mémoire si un attaquant génère des paquets fragmentés et délibérement incomplets. C'est encore pire si on suit le conseil du RFC 815 qui est d'allouer de la mémoire suffisante pour le plus grand paquet possible (la taille du paquet n'est connue qu'avec le dernier fragment).

Autre problème, le champ ID et sa taille limitée : sur un lien à 1 Gb/s, un flot continu de paquets IP de 1 kb (ce qui peut arriver avec de la vidéo en temps réel), chacun fragmenté en deux, va mener à une réutilisation du champ ID en moyenne au bout de 0,65 secondes seulement. Il y aura donc collision entre les fragments de deux paquets différents et le réassemblage mènera à la corruption (dont on espère qu'elle sera détectée par les protocoles des couches supérieures). Si des paquets sont injectés par un attaquant, il peut ainsi facilement créer une DoS.

Certains des problèmes de sécurité des fragments proviennent d'erreurs ou d'ambiguités dans la spécification. Ainsi, il est possible d'avoir des fragments qui se recouvrent (un fragment va de l'octet 0 à l'octet 959 inclus, un autre fragment de 1200 à 1919 inclus et encore un autre fragment va de 960 à 1279. Pour les octets de 1200 à 1279, doit-on utiliser le deuxième ou le troisième fragment ? Différents mises en œuvre d'IP ont fait des choix différents et ce point a été exploité par des outils qui fragmentent le paquet afin qu'il échappe à l'IDS (en utilisant le fait que l'IDS et la machine de destination n'utiliseront pas la même stratégie.) Un exemple d'un tel outil est Frag.

La section 4.1.2 rassemble un ensemble de conseils sur la fragmentation. S'ils étaient appliqués, IP serait plus sûr :

  • Avoir deux espaces mémoire différents, pour le réassemblage et pour les paquets arrivant entiers, afin d'empêcher qu'une attaque par fragmentation ne bloque le service « normal » (Linux fait ceci),
  • Réduire le temps d'attente (les 60 à 120 secondes officielles sont beaucoup trop),
  • Jeter les fragments qui ont coupé l'en-tête du protocole de niveau supérieur (ces en-têtes sont assez petits pour ne jamais être fragmentés en temps normal, une telle coupure indique presque à coup sûr une tentative d'échapper au pare-feu ou à l'IDS),
  • Et bien d'autres.

Le RFC 1858 et son successeur RFC 3128 fournissent des détails sur ces points.

Autre grande question, la transmission des paquets IP par un routeur (section 4.2). Par définition, un routeur reçoit des paquets qui ne lui sont pas destinés et qu'il doit transmettre. Cela peut soulever des problèmes de sécurité. Par exemple (section 4.2.3) , si un routeur doit faire une requête ARP (RFC 826) pour trouver l'adresse MAC de la machine suivante, et qu'il garde le paquet à transmettre en attendant la fin de la résolution ARP, un attaquant peut épuiser les ressources du routeur en envoyant plein de paquets vers des destinations inexistantes. Il est donc suggéré de jeter immédiatement les paquets lorsqu'une résolution ARP est nécessaire, en espérant que l'émetteur les renverra, s'ils étaient importants.

Enfin, l'adressage IP peut aussi recéler des pièges (section 4.3). Ainsi, un préfixe est réservé à des fins expérimentales, le 240/4 (ancienne « classe E », section 4.3.4). Le RFC, suivant une vieille pratique, recommande de jeter sans hésitation les paquets dont l'adresse source est dans ce bloc. Ce conseil est d'ores et déjà largement suivi, et est la raison pour laquelle on ne peut pas espérer récupérer ces nombreuses adresses IPv4 pour faire face à l'épuisement.

Voilà, et on n'a couvert qu'IP et pas les autres protocoles de la famille. Reste maintenant à faire le même travail pour IPv6. Qui s'y colle ?

Si cette lecture peut donner l'impression qu'IPv4 est une incroyable erreur de sécurité, bourrée de vulnérabilités, il faut aussi se rappeler, comme l'analyse le RFC 5218, que ce sont certains raccourcis pris par IP qui ont permis ce succès. Aujourd'hui, il est certain qu'IPv4 ne serait pas accepté par l'IESG et c'est pourtant le protocole qui a fait décoller l'Internet.

À noter que ce RFC est très largement inspiré du rapport « Security Assessment of the Internet Protocol », du Centre for the Protection of National Infrastructure (CPNI) britannique. D'autre part, la bibliographie du RFC est recommandée, c'est un rappel de toutes les fameuses failles de sécurité d'IP.


Téléchargez le RFC 6274


L'article seul

RFC 6272: Internet Protocols for the Smart Grid

Date de publication du RFC : Juin 2011
Auteur(s) du RFC : F. Baker, D. Meyer (Cisco Systems)
Pour information
Première rédaction de cet article le 22 juin 2011


Le titre de ce RFC ne rend pas complèment compte de son but. Ce document est en fait une présentation complète de la suite de protocoles TCP/IP, celle qui fait tourner l'Internet. Conçu pour des ingénieurs qui viennent d'une autre culture que celle des barbus Unix, récapitulant tout ce qu'il faut savoir sur les protocoles de la famille, ce texte est utilisable comme base d'un cours, ou comme introduction à TCP/IP. Il a été conçu pour le projet Smart Grid.

En effet, ce projet de distribution de l'électricité en faisant appel à des équipements plus proches des ordinateurs que des traditionnels transformateurs et compteurs, équipements qui communiqueraient beaucoup entre eux, cherche une architecture réseau. Un certain nombre de consultants, souvent ignorants de ce qui s'est fait depuis trente ans sur l'Internet, prône le développement en partant de zéro de nouvelles techniques, non prouvées et coûteuses à créer, alors que TCP/IP fournit déjà tout ce qu'il faut. Ce RFC explique TCP/IP pour les débutants, et fournit une liste des protocoles, dont peut être tirée un futur profil Smart Grid (un profil étant un sous-ensemble adapté à une tâche donnée). Voir la section 1 à ce sujet.

Comme je ne connais pas assez Smart Grid, et que le RFC ne contient quasiment rien de spécifique à ce projet (l'annexe A rassemble les informations purement Smart Grid), je vais adopter une autre perspective en utilisant ce RFC comme moyen de présenter les protocoles d'Internet, à un ingénieur qui ne les connaîtrait pas. Ces protocoles sont désignés dans le RFC sous le nom d'IPS, Internet Protocol Suite. À partir d'ici, si vous connaissez déjà l'IPS, vous avez le droit de partir et d'aller voir un film (par exemple Le chat du rabbin) ou de lire un livre (par exemple Le chat du rabbin).

L'IPS est décrite dans les fameux RFC. Outre la normalisation des protocoles, certains RFC sont là pour décrire l'implémentation par exemple les RFC 1122 et RFC 1123 sur les machines terminales et le RFC 1812 sur les routeurs. (Avec une version des spécificités IPv6 dans le RFC 8504.) Une des particularités de l'IPS est qu'elle offre des choix : ainsi, il existe plusieurs protocoles de transport comme TCP (RFC 793) ou SCTP (RFC 9260) et même un « non-protocole », UDP (RFC 768), où l'application doit faire tout le travail de la couche 4. La section 2 de ce RFC va présenter l'architecture de l'IPS, la section 3 une liste de protocoles et la section 4 l'organisation non-technique de l'Internet (relations d'affaires, etc).

Donc, c'est parti, comment tous ces protocoles tiennent-ils ensemble ? L'Internet Protocol Suite suit la classique organisation en couches (section 2.1). Si le principe est celui du modèle OSI, le découpage des couches n'est pas forcément le même, ni la terminologie. Ainsi, l'OSI parle (en anglais) de end system lorsque l'IPS dit host (que je traduis par machine terminale) et l'OSI dit intermediate system où l'IPS dit router.

En partant du haut, de ce qui est le plus proche des utilisateurs, on trouve la couche Applications (section 2.1.1). L'IPS ne fait pas de distinction forte entre les couches 5, 6 et 7, considérant plutôt une seule couche Applications.

Ensuite, toujours en allant vers le bas, l'IPS a une couche de Transport (section 2.1.2). Le terme de transport est très galvaudé. Énormément d'ingénieurs l'utilisent pour dire « les couches du dessous qui ne m'intéressent pas ». Un concepteur d'un réseau optique va parler du transport pour la fibre sous-jacente, alors que le développeur d'une application Web va considérer que le protocole HTTP est le transport, pour son application. Mais dans l'IPS, « transport » a un sens bien précis, c'est la plus basse couche qui va de bout en bout. Des protocoles archi-connus comme TCP (RFC 793) ou très exotiques comme NORM (RFC 5740) mettent en œuvre ce transport. Comme plusieurs flots de données simultanés peuvent exister entre deux adresses IP, le démultiplexage se fait sur la base d'un numéro de port géré par la couche transport. Deux flots différentes auront ainsi des couples {port source, port destination} différents. Les différents protocoles de transport fournissent en outre des services tels que garantie de délivrance des données (ou pas), gestion de messages séparés (ou bien flot d'octets continu, ce que fait TCP), contrôle de la congestion.

Continuons à descendre vers les couches bases, la couche Réseau (section 2.1.3) vient ensuite. Au contraire du choix qui existe en couche Transport, il n'y a qu'un seul protocole de couche Réseau, IP (ou deux, si on considère IPv4 et IPv6 comme différents). IP fournit un service de datagrammes : chaque paquet est indépendant des autres, porte donc les adresses IP de source et de destination, et il n'y a pas besoin d'établir un circuit avant d'envoyer des données. IP fournit également un service de fragmentation, permettant de découper un paquet trop gros avant de le réassembler à la fin.

IP peut fonctionner sur d'innombrables protocoles de couche 2. L'IETF n'en normalise aucun (à l'exception possible de MPLS, RFC 4364, tout dépend comment on place ce protocole dans le modèle en couches). La plupart du temps, ces protocoles des couches basses (section 2.1.4) sont normalisés par l'IEEE : 802.3, 802.11, 802.16, etc. IP peut aussi tourner sur IP, via des tunnels comme GRE (RFC 2784).

La famille TCP/IP a souvent été critiquée pour son manque de sécurité (section 2.2). En fait, toute la sécurité dans l'Internet ne dépend pas de TCP/IP. Le hameçonnage, par exemple, est une question d'éducation et d'interface utilisateur, deux points très importants mais qui ne sont pas du ressort de l'IETF. D'autres problèmes (comme la faille BGP dite « attribut 99 ») ne relèvent pas non plus de la sécurité du protocole puisqu'ils sont causés par une bogue dans un programme mettant en œuvre le protocole.

D'autres questions de sécurité viennent de l'organisation de l'Internet, pas de ses protocoles. Ainsi, il n'existe pas de chef de l'Internet, qui pourrait ordonner que les vieilles versions des logiciels, versions ayant des bogues connues, soient immédiatement retirées du service. On constate qu'elles traînent souvent dans la nature. De même, les nouvelles techniques de sécurité ont souvent du mal à être déployées, puisqu'aucune autorité ne peut imposer leur emploi. Il faut au contraire convaincre chaque administrateur réseaux. (Des exemples de protocole de sécurité dont le déploiement a été faible sont SPFRFC 4408 et IPsecRFC 4301. Un exemple d'un protocole de sécurité qui a mis très longtemps à être déployé est DNSSECRFC 4033.)

Cela ne veut pas dire que l'IETF baisse les bras sur la sécurité. Chaque nouveau protocole doit inclure une analyse de sécurité, et le RFC 3552 guide les auteurs pour cette tâche.

Les problèmes de sécurité de la couche physique se traitent en général par des moyens physiques (enterrer et protéger les câbles, par exemple). Pour les autres couches, le problème est posé en termes de trois services : Confidentialité, Intégrité et Disponibilité. On souhaite que les conversations privées restent privées (Confidentialité), on souhaite que les données soient authentifiées au départ, puis arrivent sans modifications (Intégrité) et on souhaite que l'Internet marche (Disponibilité). Voici deux exemples :

  • Une attaque classique contre TCP est d'envoyer des faux paquets RST (ReSeT), faux car utilisant une adresse IP source fabriquée, pour casser la connexion en cours. Il existe plusieurs protections, comme l'authentification TCP (RFC 5925), ou bien une sécurité au niveau en dessous comme IPsec. (Le RFC laisse entendre que TLS est une autre solution mais il ne protège pas du tout contre ces attaques.)
  • Une autre attaque contre TCP est le SYN flooding où l'attaquant tente d'ouvrir suffisamment de connexions TCP pour épuiser les ressources de l'attaqué (la liste des connexions est typiquement de taille finie). Il existe aussi des protections comme les SYN cookies du RFC 4987.
  • Dans les deux cas précédents, l'attaque portait sur la Disponibilité. Un exemple d'attaque contre la Confidentialité serait un accès non autorisé au réseau.

Dans beaucoup de cas, une première étape vers la sécurisation est la création d'un canal sûr entre la source et la destination (TLS ou IPsec le permettent.) Mais attention, ce n'est pas suffisant de sécuriser la communication, car le pair peut lui-même être malveillant, délibérement ou à son insu.

Enfin, l'infrastructure de l'Internet compte également des protocoles qui sont officiellement dans les applications mais sont en pratique nécessaires au bon fonctionnement. La section 2.3.1 mentionne le DNS, système de correspondance entre un nom de domaine et des données (typiquement des adresses IP). Bien sûr, l'Internet peut fonctionner sans le DNS. Mais, en pratique, cela serait vite insupportable (contrairement à ce qu'on lit parfois, la plupart des sites Web ne sont pas accessibles via leur adresse IP, voir section 5.4 du RFC 7230). Et la section 2.3.2 mentionne les outils de gestion de réseau comme les deux protocoles de gestion SNMP et Netconf (RFC 4741). (Dans le projet français PREMIO, SNMP est utilisé.)

La section 3 du RFC attaque ensuite les protocoles spécifiques. L'idée, là encore, est d'utiliser pour la Smart Grid des protocoles bien conçus, éprouvés, et disposant de mises en œuvre nombreuses et de qualité, souvent en logiciel libre.

Cette section commence avec la sécurité, La section 3.1 se penche d'abord sur l'AAA. Dans le contexte de l'Internet, cela concerne les protocoles qui autorisent l'accès au réseau, Radius (RFC 2865 et Diameter (RFC 6733). Ces protocoles utilisent souvent un mécanisme d'authentification nommé EAP (RFC 4017 ; opinion personnelle, EAP est d'une grande complexité), qui permet à son tour plusieurs méthodes (RFC 5216, RFC 5433).

Une fois qu'on a accès au réseau, reste à protéger les communications. Au niveau 3, une solution générale est IPsec (RFC 4301), qui « cryptographie » tout le trafic IP, fournit intégrité et authentification, aussi bien que confidentialité (IPsec est une architecture, pas un protocole, donc la liste des services peut dépendre du protocole). Pour l'échange des clés cryptographiques, cela peut se faire à la main (sans doute la technique la plus courante aujourd'hui) ou bien via le protocole IKE (RFC 5996). À noter que notre RFC 6272, bien que se voulant pratique, mentionne rarement de choix lorsque plusieurs protocoles existent. Toutefois, pour IPsec, il note que ESP (RFC 4303) est de très loin le plus utilisé et qu'on peut oublier les autres.

La sécurité peut-elle être assurée dans la couche 4 ? Oui, grâce au très connu protocole TLS (RFC 5246). TLS chiffre toute la communication de l'application. Il ne protège pas contre les attaques situées plus bas, mais est bien plus simple à déployer qu'IPsec.

Enfin, la sécurité peut être appliquée au niveau des applications, où on a le maximum de souplesse. La famille TCP/IP a plusieurs mécanismes dans sa boîte à outils pour cela :

  • CMS (RFC 5652) est une syntaxe pour avoir des messages authentifiés et/ou confidentiels, en utilisant la cryptographie. Cette syntaxe peut ensuite être utilisée dans des applications comme les mises à jour de logiciels (RFC 4108) ou bien le courrier électronique (RFC 5751 sur S/MIME, à noter qu'il existe une syntaxe concurrent, celle d'OpenPGP, RFC 4880, non mentionnée par le RFC).
  • Si on préfère le format XML, le RFC 3275 décrit un moyen de signer XML.
  • L'authentification peut utiliser OAuth (RFC 5849).

Toujours dans la boîte à outils, la famille TCP/IP a aussi un protocole de connexion sécurisée à distance, SSH (RFC 4253), qui peut aussi servir de mécanisme pour faire des tunnels sûrs (en concurrent d'IPsec, donc).

Toute solution fondée sur la cryptographie a besoin d'un mécanisme de gestion des clés. L'IETF en a au moins deux, PKIX (RFC 5280), fondé sur X.509, et Kerberos (RFC 4120), le second étant plutôt limité au cas où tout les participants sont dans le même domaine administratif.

Après ces considérations sur la sécurité, place à la description des protocoles de couche 3. L'Internet en a actuellement deux, IPv4 et IPv6 (section 3.2). IPv4 est décrit en détail dans la section 3.2.2. Je passe rapidement, pour arriver à IPv6 en section 3.2.3. IPv6 est normalisé dans le RFC 2460. À noter que, pour le cas de la Smart Grid, dont certains équipements peuvent avoir des capacités et des connexions peu performantes, les RFC comme le RFC 4919 peuvent être également utiles.

Les adresses IPv6 sont décrites dans le RFC 4291. Elles peuvent être distribuées aux machines terminales via le protocole DHCP (RFC 8415) ou bien sans serveur par un système d'auto-configuration (RFC 4862). Deux machines IPv6 dans le même réseau se trouvent par le protocole NDP (RFC 4861).

Le routage des paquets IPv6 se fait d'abord par la distribution des informations entre routeurs, puis par l'utilisation de ces routes lors de la transmission de chaque paquet. La route la plus spécifique (le préfixe le plus long) est utilisée. Pour distribuer les routes, les routeurs peuvent utiliser divers protocoles comme OSPF (RFC 5340 et qui peut router IPv4 comme IPv6, grâce au RFC 5838) et BGP (RFC 2545). OSPF est utilisé à l'intérieur d'un domaine administratif et fait partie des protocoles « à état des liens » dont l'avantage est que chaque routeur a une vue complète du réseau (au lieu de router par « on-dits »). BGP est utilisé entre domaines administratifs et c'est donc lui qui lie les routeurs de l'Internet.

Il y a aussi des protocoles de routage spécifiques aux réseaux de capteurs, les équipements peu puissants dont je parlais plus haut. OSPF, où chaque routeur doit garder en mémoire tous les liens de tout le réseau, ne convient pas forcément pour cette tâche. Parmi les concurrents plus adaptés, on trouve par exemple AODV (RFC 3561) ou d'autres protocoles en cours de définition (voir le cahier des charges dans les RFC 5548, RFC 5673, RFC 5826 et RFC 5867).

Depuis l'épuisement des adresses IPv4, la migration vers IPv6 est nécessaire mais elle n'est pas instantanée et il faut donc gérer la coexistence entre les deux protocoles. Il existe plusieurs mécanismes pour cela mais tous ne sont pas recommandés (cf. RFC 6180). Le plus simple et le plus conseillé est la « double-pile » : le réseau et les machines ont à la fois IPv4 et IPv6, jusqu'à ce qu'on puisse éteindre la dernière adresse v4 (RFC 4213). Si on ne peut pas disposer d'une connectivité IPv6 native, l'approche recommandée est de tunneler le trafic v6 à travers l'Internet, par exemple par les techniques du RFC 5569. Enfin, si une des deux machines participant à la communication est purement v4 ou purement v6, il faut utiliser les techniques de traduction. Celles-ci recélant des pièges inattendus, le mieux est de préférer la traduction faite au niveau des applications (par des relais applicatifs). Sinon, l'IETF a normalisé un cadre général de traduction v4<-> v6 dans le RFC 6144, avec des déclinaisons dans des protocoles comme celui du RFC 6146.

Continuant à monter vers les couches hautes, la section 3.3 présente les protocoles de transport de l'IPS (Internet Protocol Suite). Le plus connu est TCP, responsable sans doute de la très grande majorité du trafic de l'Internet. TCP garantit aux applications qui l'utilisent la délivrance des octets, dans l'ordre et sans perte. Si le RFC qui le normalise date de trente ans, TCP a subi pas mal de travaux et de modifications et il vaut donc mieux commencer par lire le RFC 7414 pour tout savoir de ce protocole. Par exemple, pour la sécurité de TCP, le RFC 4987 est une bonne lecture.

Autre protocole de transport, UDP (RFC 768), un protocole minimal qui n'assure presque aucune fonction : l'application qui l'utilise doit tout prévoir, le contrôle de congestion (ne pas envoyer trop de paquets pour ne pas surcharger le réseau), la détection des pertes (et réessayer si nécessaire), etc. Le RFC 8085 guide les applications à ce sujet.

Il existe d'autres protocoles de transport qui n'ont guère eu de succès comme SCTP (RFC 9260) ou DCCP (RFC 4340), une sorte d'UDP avec contrôle de congestion.

Pour les protocoles d'infrastructure, la section 3.4 mentionne :

  • Le DNS : des noms hiérarchiques (www.example.com est un sous-domaine de example.com, lui-même sous-domaine de .com) et un protocole de résolution de noms en données (RFC 1034). Il existe un mécanisme de sécurisation, décrit par le RFC 4033.
  • DHCP (RFC 2131 en IPv4 et RFC 8415 en IPv6) permet d'attribuer des adresses IP (et de distribuer d'autres informations comme l'adresse du serveur de temps) aux différentes machines d'un réseau local depuis un point central. Il facilite donc beaucoup la vie de l'administrateur réseaux. Sans lui, lorsqu'on voudrait renuméroter les machines, il faudrait se connecter à chaque machine pour changer sa configuration. (Regardez comment on faisait en 1992.)
  • Je viens de parler du serveur de temps. Le protocole NTP (RFC 5905) permet justement de mettre à l'heure les horloges de toutes les machines de l'Internet et s'assurer qu'elles soient d'accord. C'est une tâche plus compliquée qu'elle n'en a l'air.

Et la gestion de réseaux (section 3.5) ? Les deux protocoles concurrents sont SNMP (RFC 3411 et RFC 3418) et Netconf (RFC 4741). Lequel choisir ? Notre RFC 6272 ne fournit pas d'indications à ce sujet... La seule information de comparaison donnée est que SNMP utilise l'encodage ASN.1 alors que Netconf utilise XML.

Une machine qui démarre a souvent besoin d'informations sur son environnement, par exemple les coordonnées d'une imprimante ou bien d'un serveur de courrier. C'est le domaine des protocoles de découverte (section 3.6). C'est depuis longtemps une faiblesse de la famille TCP/IP. Le problème n'est pas complètement résolu de manière standard. Le RFC cite un protocole comme SLP (RFC 2608, qui n'a jamais été très utilisé) ou comme le protocole d'Apple, Bonjour. D'autres protocoles sont en cours de déploiement comme COAP (Constrained Application Protocol, RFC 7252), qui utilise HTTP pour demander à un serveur ces informations, en utilisant les adresses « bien connues » du RFC 8615.

Enfin, le RFC 6272 cite également (section 3.7) un certain nombre d'applications, qui ne font pas partie de l'IPS à proprement parler, mais qui peuvent être utiles à des déploiements sur TCP/IP. Par exemple, la famille TCP/IP a un protocole standard d'établissement de sessions multimédia, SIP (RFC 3261 et beaucoup d'autres). SIP est surtout utilisé pour la téléphonie sur IP mais a d'autres usages. SIP ne fait que la signalisation (appeler, raccrocher, etc) et la description de la session (voix, vidéo, codecs utilisés, est faite avec le format SDP (RFC 4566). En pratique, SIP a pas mal de problèmes sur l'Internet, face à la fermeture croissante du réseau par des mécanismes comme le NAT (le RFC 2993 décrit le problème et le RFC 5626 propose des solutions).

Autre application qui peut servir, XMPP (RFC 6120), un protocole d'échange de données XML en temps réel dont l'utilisation la plus connue est pour la messagerie instantanée (RFC 6121). XMPP est très riche et dispose de nombreuses extensions (par exemple pour du dialogue à plusieurs, dans des « pièces » virtuelles).

Après cette longue présentation des différents protocoles de la famille, le RFC expose l'architecture non-technique de l'Internet, c'est-à-dire son organisation sociale. Rien de nouveau pour les professionnels de l'Internet mais rappelez-vous que ce RFC est conçu pour des gens d'une culture très différente. La section 4 explique donc que l'Internet est un réseau de réseaux (c'est en cela que son ancêtre, l'Arpanet, était très différent : il était mono-réseau). Ces réseaux s'interconnectent entre eux (sinon, un abonné d'un réseau ne pourrait pas joindre un abonné d'un autre, ce qui était courant avec les technologies pré-Internet). Cette interconnexion est le cœur de l'architecture sociale de l'Internet dont le but est que tout le monde puisse parler à tout le monde (note personnelle au passage : cette interconnexion généralisée semble une banalité aujourd'hui. Mais, dans les années 1990, il était fréquent d'entendre des messieurs sérieux expliquer qu'il n'était pas nécessaire qu'une entreprise doive se connecter à d'autres que ses sous-traitants.)

On peut présenter les différents réseaux qui composent l'Internet en disant qu'il y a une différence entre les réseaux de transit et les autres. Les réseaux de transit forment le cœur de l'Internet. Leur seule activité est de connecter les autres réseaux. Ils vendent ce service aux réseaux d'accès et réseaux d'organisations. Les réseaux d'accès sont ceux du FAI typique, qui connecte M. Toutlemonde (particuliers et petites organisations) moyennant un paiement de trente € par mois. L'accès se fait via ADSL, RTC, 3G ou bien d'autres techniques. Les réseaux d'organisation sont ceux des entreprises, associations, collectivités locales ou universités, qui fournissent de l'accès à leurs employés et étudiants.

Si je fais de chez moi (abonné à Free) un traceroute vers ce blog, je passe successivement par le réseau d'accès du groupe Iliad (Free et Proxad), puis par le réseau de transit Cogent, puis j'arrive chez Datotel, le réseau d'entreprise où le serveur est hébergé :

% traceroute www.bortzmeyer.org
traceroute to www.bortzmeyer.org (208.75.84.80), 30 hops max, 60 byte packets
 1  freebox (192.168.2.254)  5.984 ms  7.027 ms  7.068 ms
...
 4  cha75-6k-1-v906.intf.nra.proxad.net (78.254.255.197)  35.671 ms  35.726 ms                  35.766 ms
 5  bzn-crs16-1-be1502.intf.routers.proxad.net (212.27.58.65)  35.806 ms  37.060      ms  37.125 ms
 6  bzn-6k-2-po57.intf.routers.proxad.net (212.27.59.217)  38.222 ms * *
 7  th2-crs16-1-be1005.intf.routers.proxad.net (212.27.56.5)  39.893 ms  23.638                 ms *
 8  te4-8.330.ccr01.par04.atlas.cogentco.com (149.6.164.221)  44.829 ms  45.136                 ms  49.465 ms
 9  te0-1-0-4.mpd21.par01.atlas.cogentco.com (130.117.2.77)  55.562 ms 53.303 ms   54.986 ms
...
16  host46.datotel.com (208.82.151.46)  127.897 ms   127.465 ms  127.109 ms
17  stl-d2-g5-1.datotel.com (208.82.151.26)  128.295 ms  126.546 ms  127.575 ms
18  host125.datotel.com (208.75.82.125)  127.461 ms * *
...

(Les étoiles représentent des cas où un paquet a été perdu.) Notez que le routeur chez moi, la Freebox, avait une adresse privée (RFC 1918).

Le RFC ne parle pas des relations de peering entre réseaux. À ce sujet, un très intéressant document est le rapport de PCH.

À noter que le RFC n'expose que l'architecture sociale, pas la gouvernance de l'Internet, vaste sujet mais fort loin des problèmes opérationnels...

Souvent, les traceroutes sont interrompus subitement et plus rien n'est visible. C'est souvent le résultat d'un pare-feu mis sur le trajet. Notre RFC note que ces équipements sont très fréquents dans l'Internet d'aujourd'hui, mais aussi qu'ils sont très controversés. En effet, leur efficacité n'est pas prouvée, la plupart des attaques provenant de l'intérieur (soit parce qu'une personne située dans l'organisation mène l'attaque, soit parce qu'une machine interne a été infectée par un logiciel malveillant, le pare-feu ne protégeant souvent pas contre les attaques par « charge utile »). Bref, le pare-feu ne doit être utilisé que comme composante d'une solution de sécurité, pas comme l'alpha et l'oméga de la sécurité. Il existe plusieurs RFC ayant un rapport avec les pare-feux comme le RFC 2647 (mesures de performance), RFC 2979 (règles que doivent suivre les pare-feux), RFC 5207 (un exemple des problèmes que peuvent poser les pare-feux pour un nouveau protocole), etc.

Autre source de problèmes lorsqu'on circule dans l'Internet, les NAT. Cette technique a été inventée vers 1993 pour pallier le manque d'adresses IPv4 en traduisant des multiples adresses privées du réseau interne vers la seule adresse IP publique. En IPv6, le NAT est devenu inutile, vue l'abondance d'adresses. Mais comme certaines personnes s'imaginent que le NAT joue aussi un rôle pour la sécurité, en servant de pare-feu, il reste très présent et gêne souvent les communications. Les NAT sont décrits dans les RFC 2663 et RFC 3022, leurs conséquences néfastes pour les communications sont expliquées dans le RFC 3027, des idées pour les développeurs d'applications dans un monde où il y a beaucoup de NAT ont été rassemblées dans le RFC 3235, d'autres techniques de contournement sont dans le RFC 5128, quant à la position officielle de l'IAB sur les NAT, elle est dans le RFC 3424.

Sur le projet Smart Grid, si celui-ci n'a pas encore d'architecture réseau normalisée, il a déjà des documents. On peut consulter « Smart Grid Architecture Committee: Conceptual Model White Paper » (document uniquement en format privateur MS-Word, ce qui donne une idée de l'écart de culture avec l'Internet) et IEC 61850.


Téléchargez le RFC 6272


L'article seul

RFC 6270: The 'tn3270' URI Scheme

Date de publication du RFC : Juin 2011
Auteur(s) du RFC : M. Yevstifeyev
Chemin des normes
Première rédaction de cet article le 6 juin 2011


Ce RFC n'aura pas un grand intérêt pratique, vu le petit nombre de terminaux 3270 encore en service ! Mais il était nécessaire pour compléter la liste des plans (schemes) d'URI, qui le mentionnait sans vraiment le décrire.

En effet, le désormais dépassé RFC 1738 mentionnait la possibilité d'avoir des URL comme tn3270:mainframe.accounting.example mais sans expliquer leur syntaxe ou leur sémantique. 3270 est une référence aux vieux terminaux des mainframes IBM d'il y a très longtemps. Ces terminaux sont décrits dans les RFC 1041, RFC 1576 et RFC 2355.

Le RFC 1738 a été remplacé il y a longtemps, par le RFC 3986, qui décrit la syntaxe générique des URI. Mais ce petit point spécifique du tn3270: n'avait jamais été traité. Notre RFC 6270 comble donc le vide en spécifiant rigoureusement syntaxe et sémantique des URI tn3270:. La sémantique est très proche de celle des URI telnet: du RFC 4248. Le plan tn3270: est donc désormais, en suivant les règles du RFC 4395, enregistré dans le registre des plans d'URI.


Téléchargez le RFC 6270


L'article seul

RFC 6269: Issues with IP Address Sharing

Date de publication du RFC : Juin 2011
Auteur(s) du RFC : M. Ford (Internet Society), M. Boucadair (France Telecom), A. Durand (Juniper Networks), P. Levis (France Telecom), P. Roberts (Internet Society)
Pour information
Réalisé dans le cadre du groupe de travail IETF intarea
Première rédaction de cet article le 29 juin 2011


Pour pas mal de raisons, il est fréquent aujourd'hui qu'une adresse IP soit partagée entre plusieurs machines. Le cas le plus typique est celui des N machines d'une petite entreprise, forcées d'utiliser une seule adresse IP publique, via un routeur NAT. Ce RFC est le premier document qui discute en détail de ce partage d'adresses, et de ses innombrables inconvénients.

Le RFC met surtout l'accent (section 1) sur une cause du partage d'adresses : l'épuisement de la réserve d'adresses IPv4, qui, n'étant pas compensée par un déploiement massif d'IPv6, mène à ce que le partage d'adresses soit très fréquent, et le sera sans doute davantage dans le futur (la plupart des solutions d'attente d'IPv6 utilisent intensivement ce partage). En fait, aujourd'hui, il est rare que M. Michu puisse bénéficier d'une vraie connexion Internet : il partage en général son adresse avec d'autres M. Michu ; par exemple, à la maison, M. Michu n'a aucune chance d'obtenir plus d'une adresse IPv4, même si plusieurs personnes vivent dans ce foyer et utilisent toutes des appareils connectés à l'Internet (ce qui est banal aujourd'hui dans les grandes villes du Nord). Le CPE fait office de routeur NAT et les machines de M. Michu et de sa petite famille sont contraintes de se contenter d'adresses IP privées (RFC 1918). Mais l'avenir (déjà réalisé en Europe sur les connexions ultra-civilisées de la 3G, et, en Asie, dès à présent sur toutes les connexions) nous réserve pire : le partage d'adresses IP, non pas au sein du foyer ou de la petite entreprise, mais entre abonnés, ce qu'on nomme parfois le CGN, pour Carrier-Grade NAT et qu'on pourrait qualifier de « partage d'adresses généralisé ». (L'annexe A résume les différents types de partage d'adresses.) Le « facteur multiplicatif » (annexe B) entre le nombre d'adresses privées et celui d'adresses publiques vaut typiquement entre 3 et 10 pour une maison européenne typique (une seule adresse publique mais plusieurs machines connectées, smartphones, ordinateurs, consoles de jeu, etc). Il pourrait dépasser 1000 avec les CGN (plusieurs adresses IP publiques mais des milliers d'abonnés se partageant ce mince gâteau).

Le RFC insiste sur le fait que le déploiement d'IPv6 est la seule solution correcte aux problèmes engendrés par le partage d'adresses. C'est vrai mais il faut noter que le partage d'adresses a commencé bien avant la famine, qu'il est pratiqué par des entreprises qui disposent de suffisamment d'adresses IPv4 (en général au nom de pseudo-arguments de « sécurité ») et qu'on le trouve pratiqué massivement en Afrique et en Asie alors que le continent africain est celui qui a la plus grande réserve d'adresses IPv4 officielles disponibles. Donc, le non-déploiement d'IPv6 n'est pas la seule raison de l'utilisation du partage d'adresses.

J'ai mentionné le NAT tout à l'heure. Si le partage d'adresses se fait en général (mais pas toujours) via le NAT, l'inverse n'est pas forcément vrai. On peut avoir du NAT sans partage d'adresses, si chaque adresse interne est mise en correspondance avec une et une seule adresse externe. Évidemment, en IPv4, c'est rare, vu le manque d'adresses, mais cela sera peut-être plus fréquent avec IPv6.

À noter que ce RFC ne discute que du problème : il ne propose pas de solution, celles-ci étant renvoyées à des documents ultérieurs (qui ne seront peut-être pas nécessaire si le déploiement d'IPv6 rend inutile ces solutions). Il ne se penche pas non plus sur les problèmes qui sont spécifiques à une technique utilisant le partage d'adresses, essayant au contraire de voir les questions communes à toutes ces techniques. Ainsi, qu'on utilise, pour gérer le passé en attendant le déploiement d'IPv6, NAT64, DS-Lite ou encore d'autres importe peu : toutes ont en commun les même défauts liés au partage d'adresses.

Des problèmes, notamment de sécurité, liés au partage d'adresses avaient déjà été discutés dans les RFC sur le NAT comme les RFC 2663 et RFC 2993 (section 2 de notre RFC). Mais le partage généralisé, entre utilisateurs n'ayant rien en commun, va aggraver ces problèmes. Cette situation se rencontre souvent aujourd'hui en Asie, et dans les hotspots WiFi publics. Mais elle sera hélas sans doute demain le lot de beaucoup d'utilisateurs.

Bien, arrivé à ce stade, vous avez le droit de penser que j'ai beaucoup répété qu'il y avait des problèmes, sans dire lesquels. Patientez encore un peu. L'analyse des problèmes qui commence en section 3 est faite en cherchant d'abord si le problème affecte l'organisation qui déploie le partage d'adresses (et donc ses abonnés ou employés), ou bien des tiers (comme la police par exemple ou bien comme un CDN qui essaie de distribuer du contenu en fonction de l'adresse). Le tout est stocké dans un grand tableau synthétique (figure n° 1) et détaillé dans les sections suivantes. Pour ne prendre que trois exemples de ce tableau, le fait que les requêtes DNS traduisant une adresse en nom perdent de leur signification affecte aussi bien l'utilisateur que les tiers (ceux qui traduisent une adresse IP entrante en nom). Par contre, la perte de traçabilité qui résulte du partage (si on détecte un comportement illégal lié à une adresse IP, on ne retrouve plus facilement la machine en cause) n'affecte que les tiers (les organisations répressives comme la HADOPI). Au contraire, la perte de fiabilité de la connexion (car l'engin qui fait les traductions d'adresses est un nouveau composant dans la connexion, qui peut avoir des bogues ou des pannes, cf. section 18) ne concerne que l'utilisateur, les tiers ne seront pas touchés.

Les sections suivantes du RFC détaillent successivement chacun de ces problèmes (je ne les présente pas dans l'ordre, j'essaie de mettre les plus importantes en premier). La section 5 s'attaque aux problèmes liés à l'allocation de port. Avec le partage d'adresses, plusieurs adresses « internes » sont mises en correspondance avec une seule adresse « externe ». Comment, dans ces conditions, différencier les paquets IP qui arrivent, à destination de cette adresse IP externe ? On utilise le numéro de port TCP ou UDP pour cela et c'est donc le couple {adresse, port} qui identifie la machine et non plus l'adresse seule. Ce numéro de port n'étant stocké que sur 16 bits, cela met une limite stricte à l'ampleur du partage. Si 500 machines partagent une adresse (facteur multiplicatif de 500), cela ne fait qu'un peu plus de 131 ports chacune (et même moins car certains doivent être réservés, cf. RFC 4787), ce qui est vite épuisé sur une machine un tant soit peu active, qui ouvre de nombreuses connexions (une seule page Web peut se traduire par l'ouverture de dizaines de connexions). D'autant plus que ce n'est pas le nombre de connexions actives qui compte, mais celui des connexions TCP dans l'état TIME-WAIT, celui dans lequel les connexions fermées restent pendant quatre minutes (RFC 1337).

Voyons les ports « sortants », ceux alloués pour les connexions initiées de l'intérieur (section 5.1). Les études (Alcock, S., « Research into the Viability of Service-Provider NAT ») semblent indiquer que la distribution de la consommation est très inégale : une minorité d'utilisateurs consomme beaucoup de ports. Cela encourage à répartir les numéros de port à partir d'un pool central, et pas à attribuer de manière fixe des plages de ports à chaque client (cf. annexe A). Mais la seconde solution serait bien plus simple et moins coûteuse. Et la première est vulnérable à une attaque DoS : une seule machine infectée par du malware et qui ouvre des connexions le plus vite possible peut épuiser le pool. Ceci dit, l'allocation statique de plages de ports a aussi ses risques (cf. RFC 6056). Tous ces problèmes existaient avec le partage limité à un foyer ou une entreprise mais sont évidemment plus graves en cas de partage généralisé puisqu'un utilisateur peut être bloqué par un autre utilisateur qu'il ne connait pas.

Et pour les ports des connexions entrantes (section 5.2) ? L'étude citée ci-dessus montre qu'elles sont fréquentes (la majorité des utilisateurs) mais consomment moins de ports. Comment négocier entre la machine de l'utilisateur et le routeur NAT l'allocation d'un port « entrant » ? Aujourd'hui, les méthodes les plus courantes sont l'allocation manuelle (la plupart des CPE permettent de configurer des ports entrants, du genre « toute connexion arrivant pour le port 80 de l'adresse publique doit être traduite vers 192.168.1.13:8080 ») ou bien un protocole comme UPnP. Le CGN complique sérieusement les choses puisqu'il n'est pas dédié à un utilisateur et qu'on doit donc sérieusement étudier sa sécurité avant de permettre à un utilisateur de se réserver les ports 22 ou 80 ! C'est encore pire si le CPE et le CGN doivent coopérer pour rendre le service, puisqu'il n'existe aucun protocole standard pour cela. Actuellement, sur l'abonnement 3G typique en Europe, on n'a pas accès à l'allocation de ports entrants et le smartphone ne peut donc pas héberger de serveur. Cet engin bien plus puissant que les ordinateurs des débuts de l'Internet est donc limité à un rôle de Minitel plus perfectionné.

Il existe des solutions potentielles à ces problèmes mais aucune n'est vraiment satisfaisante. À titre d'exemple, le RFC cite les enregistrements SRV qui pourraient permettre de faire savoir que tel service réside sur tel port de la machine coincée derrière le partage d'adresses. Parmi les limites de cette solution, notons qu'elle ne s'applique pas au protocole le plus demandé, HTTP, qui n'utilise pas les SRV...

Jusqu'à présent, j'ai surtout parlé du problème des applications « serveur », celles qui écoutent des connexions inattendues sur un port bien connu, un serveur SSH, par exemple. On peut se dire que de tel cas sont rares sur la machine de M. Michu, qui n'installe en général pas de serveur SSH, ni même HTTP. Mais il y a toute une catégorie d'applications qui a besoin d'écouter des connexions entrantes sans être pour autant un « serveur » à proprement parler. La section 6 est une bonne occasion de les mentionner. En effet, cette section examine tous les cas où le partage d'adresses gène les applications. Cela concerne bien sûr les serveurs traditionnels, vus en section 5.2, mais aussi, entre autres :

  • Les applications qui indiquent des adresses et des ports dans leur trafic, ce qui concerne typiquement FTP et SIP. Un ALG sera nécessaire pour les gérer.
  • Les applications qui n'utilisent pas du tout de port (ping...) et pour qui il faut donc trouver d'autres moyens de démultiplexage. Une section entière, la 9, détaille les problèmes posés à ICMP, puisque ce protocole n'a pas de notion de port. Outre ping, ce protocole est utilisé, par exemple par les applications pair-à-pair pour mesurer la « distance » avec un pair, ce qui ne marche plus dans le cas d'un partage généralisé.
  • Un cas analogue est celui des applications qui n'utilisent pas TCP ou UDP, mais, par exemple, SCTP ou encore le protocole 41 (encapsulation IPv6 dans IPv4, pour gérer le cas des réseaux qui n'ont toujours pas IPv6). Très rares sont les techniques de partage d'adresses qui gèrent d'autres protocoles que TCP et UDP. Ces techniques contribuent donc à l'ossification de l'Internet (la grande difficulté à déployer de nouveaux protocoles).
  • Les applications qui tiennent pour acquise l'unicité des adresses IP (voir aussi le RFC 6250). Par exemple, une application Web qui lie les cookies à une adresse IP, pour augmenter la sécurité, n'a pas de sens si cette adresse est partagée entre des dizaines d'utilisateurs qui ne se font pas forcément confiance.

Résultat, les applications passent aujourd'hui beaucoup de temps à mettre en œuvre des techniques de contournement, cherchant à récupérer leur connectivité que le NAT contrarie. Il suffit de regarder le code source de n'importe quelle application de téléphonie sur l'Internet pour voir le résultat : le code est plus complexe, et dépend de systèmes difficiles comme ICE (RFC 8445). Avis personnel : il est donc faux de dire que le NAT fait faire des économies. Le NAT est un déplacement de coûts, depuis les administrateurs réseaux vers les développeurs d'applications, contraints à des prodiges d'astuces pour assurer la connectivité.

Un des principaux problèmes que pose fondamentalement le partage d'adresses est la traçabilité (notez que ce n'est pas un problème pour tout le monde). Il est fréquent de suivre les actions d'une machine et de son propriétaire via l'adresse IP. 192.0.2.66 s'est connecté à www.anonymous.org. 203.0.113.13 a envoyé du spam. 198.51.100.254 a participé à une attaque DoS. Évidemment, si les adresses IP sont partagées, cette traçabilité n'existe plus. Aujourd'hui, avec le NAT local classique, on peut au moins relier une adresse IP à un foyer ou une entreprise. Avec du partage d'adresses généralisé, cela ne sera plus le cas (section 12). Actuellement, une requête de la police auprès d'un FAI pour obtenir l'identité d'un abonné dont la machine s'est fait repérer inclus l'adresse IP et l'heure (pour les cas d'adresses IP dynamiques, changeant régulièrement). Le partage généralisé oblige à inclure d'autres informations dans la requête, comme le numéro de port, que peu de serveurs enregistrent aujourd'hui. Attention, identifier un abonné à partir du couple {adresse IP, port} est délicat, car la table de correspondance change bien plus vite que les baux DHCP typiques. La requête doit donc inclure une heure très précise et, pour cela, s'appuyer sur une horloge bien synchronisée. Comme cela risque de ne pas suffire (et cette solution implique que le serveur enregistre le numéro de port source, ce qui est inhabituel aujourd'hui), faudra t-il que le routeur NAT enregistre également l'adresse IP de destination ? Cela étendrait le domaine du flicage très loin...

Et le FAI doit garder des journaux de taille colossale pour pouvoir répondre aux questions comme « Qui utilisait le couple {198.51.100.254, 23152} le 23 mai à 11:28:05 ? », les obligations légales de surveillance imposant en général de conserver ces données pendant six à douze mois. Cela ne sera probablement pas réaliste pour tous les FAI, sauf à créer des obligations légales qui acculeraient bien des opérateurs à la faillite. Noter l'adresse IP de destination aggraverait évidemment le problème.

Comment cela va t-il se passer alors ? Une solution est de baisser les bras et de ne pas divulguer l'identité de l'abonné. Cela peut poser des problèmes légaux au FAI, des lois comme la LCEN en France leur faisant obligation de surveiller leurs abonnés, comme un hôtelier des vieux films policiers surveillait les entrées et sorties de ses clients. Une autre solution est de divulguer les coordonnées de tous les abonnés qui avaient une session active à ce moment là et de laisser la police trier. On imagine le nombre d'innocents qui seront alors harcelés.

À noter que la situation décrite par cette section 12 ne sera pas forcément perçue comme un problème par tout le monde. Ainsi, certains utilisateurs pourraient trouver des avantages à un système qui rend plus compliquée la tâche des surveillants. Si, à cause du partage d'adresses, une société privée de surveillance comme TMG, qui collecte les adresses IP de partageurs de fichiers, a des problèmes, tant mieux, se diront-ils. Le partage d'adresses pourrait alors fournir, sinon l'anonymat, au moins un certain brouillage de pistes. Ce n'est pas faux mais c'est à mettre en rapport avec les inconvénients de ce partage d'adresses.

Le partage d'adresses perturbe une mesure importante pour le bon fonctionnement de l'Internet, celle de la MTU du chemin (section 10). Bien des systèmes mesurent cette MTU du chemin (RFC 1191) pour optimiser le transfert de données. Mais cette PMTU est en général stockée par adresse IP et le partage généralisé peut donc fausser les mesures : deux machines derrière la même adresse IP peuvent ne pas avoir la même PMTU. Cela peut permettre des attaques par déni de service où une des machines derrière l'adresse publique générerait des paquets ICMP packet too big (type 3 et code 4 d'ICMP) indiquant une taille ridiculement basse... qui sera utilisée pour tous les malheureux situés derrière la même adresse.

Il y a d'autres questions de sécurité liées au partage d'adresses. La section 13 les expose successivement. Par exemple, bien des mesures de sécurité sont prises sur la base de l'adresse IP. Un exemple est le logiciel fail2ban qui met automatiquement en liste noire (et donc filtre) les adresses IP qui sont à l'origine de comportements agressifs (comme des connexions SSH répétées). Si cette adresse IP est partagée, des innocents vont aussi se voir bloquer l'accès. Même chose pour les listes noires des expéditeurs de spam.

Des problèmes peuvent également survenir avec des logiciels qui estiment qu'une adresse IP identifie une machine (section 14). Un des exemples est l'optimisation TCP du RFC 2140, qui consiste à partager l'information entre toutes les connexions TCP vers la même machine. Cette optimisation ne fonctionnera plus si la même adresse IP sert à des machines connectées de manière très différente (avec le NAT résidentiel d'aujourd'hui, ce n'est pas trop un problème car toutes les machines de la même maison ont à peu près la même connectivité).

Autre conséquence négative du partage d'adresses : la géolocalisation (section 7). Les adresses IP sont souvent utilisées pour donner une idée (fort imparfaite) de la localisation d'une machine. C'est un système très contestable, déjà aujourd'hui, comme le note le RFC. Mais le partage généralisé d'adresses le rendra encore moins utile, puisque c'est l'adresse du routeur CGN qui sera vue par le serveur, et qu'elle peut n'avoir qu'un très lointain rapport avec le client. Bon, personnellement, je trouve qu'on en arrive à un fort niveau de pinaillage ici : les problèmes posés par le partage d'adresses sont assez graves pour qu'on ne charge pas la barque en mentionnant des conséquences négatives sur un système qui était déjà mal fichu, comme la géolocalisation. Même remarque pour la section 8, qui fait remarquer que le partage généralisé empêchera de compter le nombre d'utilisateurs uniques en comptant le nombre d'adresses IP - ce qui est déjà largement le cas, ou la 11 qui note que le fait d'utiliser le numéro de port pour démultiplexer les paquets arrivant dans le routeur NAT pose un problème avec la fragmentation, puisque seul le premier fragment contient le numéro de port.


Téléchargez le RFC 6269


L'article seul

RFC 6266: Use of the Content-Disposition Header Field in the Hypertext Transfer Protocol (HTTP)

Date de publication du RFC : Juin 2011
Auteur(s) du RFC : J. Reschke (greenbytes)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF httpbis
Première rédaction de cet article le 6 juin 2011


Le protocole HTTP ne sert pas qu'à récupérer des pages HTML qu'on va afficher à l'utilisateur. Une part importante de ses usages est la récupération de fichiers qu'on enregistrera sur le stockage local. Quel nom donner au fichier local ? HTTP dispose depuis longtemps d'un en-tête dans les réponses, Content-Disposition:, qui fournissait des suggestions de noms. Cet en-tête était imparfaitement normalisé et traité un peu à part. Ce nouveau RFC en fait un élément standard et rigoureusement défini de la panoplie HTTP.

Cet en-tête était donc décrit dans les RFC 2616 (section 19.5.1, qui prend des pincettes et affirme que cet en-tête n'est décrit que parce qu'il est largement mis en œuvre mais qu'il ne fait pas vraiment partie de la norme) et RFC 2183. La description était incomplète, notamment question internationalisation.

La grammaire formelle de cet en-tête est désormais décrite en section 4. Voici un exemple :

Content-Disposition: Attachment; filename=example.txt

Cette réponse HTTP demande que le fichier soit traité comme un attachement, à enregistrer, et que le nom suggéré est example.txt. Le premier terme se nomme le type (section 4.2) et à la place du Attachment qu'on a ici, on pourrait avoir Inline qui suggère au client HTTP d'afficher le fichier, plutôt que de l'enregistrer (c'est le comportement par défaut en l'absence de l'en-tête Content-Disposition). Les types et les noms de paramètres (ci-dessous) sont insensibles à la casse.

Après le type et un point-virgule, on trouve des paramètres. Ici, le paramètre filename était indiqué, pour proposer un nom de fichier. À noter que ce paramètre peut être complété par un filename*, doté de possibilités étendues, notamment celle de suggérer des noms comportant des caractères non-Latin1 (cf. RFC 8187, section 6 et annexe C). Ce filename* est plus récent et pas compris de tous les clients HTTP. L'idée est que le serveur moderne envoie les deux, le client ancien ne gardera que filename (qui est « sûr ») et le client nouveau n'utilisera que filename*. Voici un exemple suivant ces recommandations :

     Content-Disposition: attachment;
                          filename="EURO rates";
                          filename*=utf-8''%e2%82%ac%20rates

Ce fichier sera enregistré, par un client récent, sous le nom € rates.

J'ai utilisé à plusieurs reprises des verbes comme « suggérer » ou « proposer » car le client HTTP reste maître du choix du nom. Il est même important qu'il n'accepte pas aveuglément n'importe quel nom donné par le serveur (imaginez une machine Unix où le navigateur Web stockerait le fichier sous le nom /etc/passwd sans réfléchir). Plus précisement, insiste le RFC (sections 4.3 et 7), le client HTTP doit :

  • N'autoriser l'écriture du fichier que dans les dossiers ou répertoires choisis. Le mieux est d'ignorer complètement tout chemin inclus dans le nom (ne garder que le nom de fichier proprement dit).
  • Se méfier de l'extension (dans le premier exemple, .txt). Avec certains systèmes d'exploitation comme Windows, c'est cette extension (et pas le type MIMERFC 2046 - envoyé avec le fichier) qui détermine le comportement associé au fichier. Un nom se terminant en .exe peut donc avoir des conséquences ennuyeuses.
  • Certains caractères sont spéciaux pour le système d'exploitation qui va stocker le fichier (comme le point-virgule ou le tube sur Unix) et il vaut donc mieux les supprimer avant d'enregistrer. Même chose, bien que moins dangereux, pour des noms qui pourraient perturber l'interface utilisateur, comme les espaces pour Unix : ils sont légaux mais pas pratiques à gérer depuis le shell.

Un bon exemple de faille de sécurité provoquée par le non-respect de ces règles figure en en http://securitytracker.com/id?1024583.

La section 4.4 ajoute qu'il faut ignorer les paramètres inconnus (pour permettre l'extensibilité ultérieure). Les en-têtes invalides devraient être ignorés par les clients HTTP. De nombreux détails sur le traitement de Content-Disposition: par les clients figurent dans l'excellente page http://greenbytes.de/tech/tc2231/.

Les clients HTTP, par exemple les navigateurs Web, respectent-ils cette norme ? Actuellement, Firefox, Opera et Konqueror le font, ainsi que Chrome depuis sa version 9 (parait-il : ça ne marche pas chez moi) et Internet Explorer depuis sa version 9. Cela ne signifie pas qu'ils gèrent tout et notamment Firefox 3 semble ignorer le paramètre de nom de fichier international, filename* (bogue #588781). wget semble ignorer l'indication de nom de fichier par défaut. Il faut lui ajouter l'option --content-disposition pour que cela marche. C'est encore pire pour curl dont l'auteur refuse de gérer Content-Disposition: et fait semblant de croire que l'option --remote-name le remplace. lynx a une amusante bogue : il inclus le point-virgule qui suit (s'il y a un deuxième paramètre), dans le nom de fichier.

À noter que le registre des en-têtes (section 8.2) et celui des paramètres de Content-Disposition: (section 8.1) sont utilisés par d'autres protocoles que HTTP (cf. section 4.5).

L'annexe A résume les changements par rapport au RFC 2616, le premier qui mentionnait cet en-tête Content-Disposition: dans le cadre de HTTP. Le principal est l'ajout des capacités d'internationalisation du RFC 8187. Mais il y a aussi quelques détails, comme la suppression de la restriction qui limitait cet en-tête aux ressources de type application/octet-stream. L'annexe B, elle, résume les changements depuis le RFC 2183. Ils consistent essentiellement en l'abandon de paramètres intéressants mais qui, en pratique, n'ont jamais été mis en œuvre par les clients HTTP, comme creation-date ou size.

L'annexe C discute l'approche d'internationalisation utilisée dans ce RFC, en comparant avec les alternatives. Un peu d'histoire : les en-têtes HTTP sont historiquement limités à ISO 8859-1 (RFC 2616, section 2.2 ; j'ai bien dit ISO 8859-1 et pas ASCII ; c'est ainsi que ce blog émettait un en-tête en ISO 8859-1, qui avait planté quelques logiciels qui n'avaient pas bien lu le RFC 2616 ; le RFC 7230, depuis, a supprimé cette possibilité). C'est évidemment une limite unsupportable. La solution standard, depuis belle lurette (RFC 2231, en 1997) est d'encoder les caractères Unicode en « notation pourcent ». Le RFC 8187, plusieurs fois cité ici, est l'application de ce principe à HTTP. Mais les clients HTTP, notamment les navigateurs, ont très souvent essayé des approches non-standard. Pourquoi n'ont-elles pas été reconnues dans notre RFC 6266 ?

Par exemple, certains ont implémenté les encodages du RFC 2047, même si ce RFC précisait bien qu'ils ne devaient pas être utilisés dans les en-têtes. D'autres gèrent l'encodage pourcent (RFC 3986, section 2.1) dans le paramètre filename, ce qui encourage les serveurs à l'utiliser ainsi, semant la confusion chez les navigateurs. Ainsi, si le nom de fichier est caf%C3%A9.html, certaines navigateurs l'enregistreront sous le nom café.html et d'autres sont le nom caf%C3%A9.html. Plus rigolo, certains navigateurs pratiquent l'examen du nom du fichier et appliquent diverses heuristiques pour déterminer son contenu (« Hmmm, on dirait de l'UTF-8 encodé pour-cent... Je vais essayer ça. ») C'est évidemment très fragile. Le tableau « Test Result Summary » en http://greenbytes.de/tech/tc2231/ résume fort bien le comportement actuel des navigateurs Web.

Les programmeurs, enfin, ont tout intérêt à lire l'annexe D, qui rassemble les conseils pour les développeurs de serveurs HTTP et d'applications Web (en pratique, c'est souvent le framework de développement, pas le serveur HTTP, qui génère ces en-têtes). Parmi les conseils :

  • Inclure un paramètre filename si l'ASCII suffit (ce devrait être Latin-1 mais le RFC note qu'il n'est pas prudent de compter dessus, trop de programmeurs n'ont pas lu le RFC 2616 et ne gèrent pas correctement le non-ASCII et, de toute façon, le RFC 7230 a modifié la règle depuis),
  • Inclure un paramètre filename* si l'ASCII ne suffit pas, tout en sachant que bien des clients Web ne le cherchent pas et n'utiliserons que filename ; le RFC suffère donc de mettre les deux, une version dégradée du nom étant présente dans filename (cela est possible en français, voir l'exemple ci-dessous, mais pas tellement en arabe),
  • Utiliser uniquement UTF-8 comme encodage de filename*.

Notez que le moteur de recherche de mon blog produit des en-têtes « Content-Disposition: » en respectant, je l'espère, les conseils de cette annexe D...


% wget --server-response 'http://www.bortzmeyer.org/search?pattern=café chocolat&format=atom' 
...
  Server: Apache/2.2.9 (Debian) mod_wsgi/2.5 Python/2.5.2
  Content-Disposition: Inline; filename=bortzmeyer-search-caf--chocolat.atom; filename*=UTF-8''bortzmeyer-search-caf%C3%A9-or-chocolat.atom
  Content-Type: application/atom+xml; charset="utf-8"
...

(Si vous lisez le code source, c'est dans wsgis/search.py.)


Téléchargez le RFC 6266


L'article seul

RFC 6265: HTTP State Management Mechanism

Date de publication du RFC : Avril 2011
Auteur(s) du RFC : A. Barth (UC Berkeley)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF httpstate
Première rédaction de cet article le 29 avril 2011
Dernière mise à jour le 30 avril 2011


Les cookies, ces célèbres gâteaux du Web ont déjà fait l'objet d'innombrables articles, par exemple pour critiquer les conséquences pour la vie privée d'un mécanisme qui permet de suivre l'utilisateur à la trace (voir par exemple l'introduction de la CNIL). Mais on connait moins leur spécification technique, ou plutôt le fait que, mal spécifiés dès le début, ces gâteaux ont été mis en œuvre de diverses manières et qu'il est très difficile de décrire intégralement leur fonctionnement. C'est la tâche de notre RFC 6265, d'être, normalement, la norme technique complète et faisant autorité sur les cookies, en capturant l'ensemble des points techniques sur les gâteaux en une seule norme. Les textes précédents étaient la description originale de Netscape (on notera avec ironie que cette spécification privée n'est plus accessible que via WebArchive), puis le RFC 2109, puis le RFC 2965, que notre RFC remplace et annule. Les documents précédents étaient loin de spécifier tous les aspects des petits gâteaux.

Le point de départ est que le protocole HTTP, le plus utilisé du Web est sans état. Lors d'une visite à un site Web, l'utilisateur clique successivement sur plusieurs liens, visite plusieurs pages, et chaque téléchargement d'une page est une requête HTTP séparée des autres, sans rien qui permette de les corréler (par exemple pour se souvenir des préférences exprimées par un utilisateur lors de l'arrivée sur la première page). Les gâteaux visent à combler ce manque. La norme définit deux en-têtes HTTP, Set-Cookie qui permet au serveur HTTP de déposer un gâteau sur l'ordinateur de l'utilisateur et Cookie qui permet au client HTTP (typiquement le navigateur) de renvoyer un gâteau préalablement déposé. Lorsque le serveur reçoit le gâteau, il le compare à ceux qu'il a envoyés et reconnait ainsi un utilisateur déjà vu. HTTP devient alors un protocole avec état.

Ce n'est pas que les gâteaux soient une solution géniale : imposés par un acteur du Web particulier, Netscape, ils n'avaient pas fait l'objet d'un examen sérieux par une SDO et ont des tas d'inconvénients techniques et politiques. Néanmoins, comme ils sont largement utilisés dans le Web, il était préférable qu'une documentation sérieuse de leur syntaxe et de leur comportement existe, et c'est le rôle de ce RFC 6265.

La section 1 de ce RFC résume le principe des gâteaux. Un gâteau inclus un certain nombre de métadonnées qui permettent au client HTTP de savoir si et quand il doit retransmettre le cookie. Par exemple, on peut spécifier la période pendant laquelle le gâteau reste valable, les serveurs à qui on doit le renvoyer, etc. Du fait de leur spécification hâtive et non collective, les gâteaux ont bien des faiblesses techniques. Par exemple, l'attribut secure dans les métadonnées ne fournit aucune garantie d'intégrité en dépit de ce que son nom pourrait faire croire. D'autre part, les gâteaux ne sont pas spécifiques à un port donné donc, si plusieurs serveurs tournent sur des ports différents de la même machine, ils peuvent se voler leurs gâteaux mutuellement. Mais, d'une manière générale, ce RFC n'essaie pas de réparer la situation, mais de documenter les gâteaux tels qu'ils sont réellement produits et consommés sur le Web.

Bien, assez râlé, qui doit lire ce RFC ? Il y a deux audiences, les développeurs d'applications côté serveurs (ou, plus exactement, des bibliothèques qui sont utilisées par ces applications) qui produisent et consomment des gâteaux, et les développeurs des logiciels clients, notamment les navigateurs Web. Pour maximiser les chances d'interopérabilité, les serveurs devraient se montrer très prudents et ne produire que des gâteaux parfaitement conformes à la norme (section 4 du RFC, qui décrit le profil restreint), alors que les clients doivent être plus tolérants et accepter la grande variété des gâteaux actuellement fabriqués (section 5, sur le profil libéral), car tous les serveurs ne suivent pas le profil restreint.

Avant de lire le gros du RFC, un petit détour par la norme HTTP, le RFC 7230, peut être utile, puisque notre RFC en reprend le vocabulaire.

La section 3 décrit les généralités sur les gâteaux. Ceux-si sont envoyés par un en-tête Set-Cookie dans la réponse HTTP, puis retournés dans un en-tête Cookie dans la requête suivante. L'état est donc stocké chez le client mais, en pratique, la taille des gâteaux étant limité, le serveur stocke l'essentiel de l'état et le gâteau ne sert que d'index pour retrouver une session particulière. Un serveur peut utiliser Set-Cookie dans n'importe quelle réponse (y compris les erreurs comme 404) et le client doit le gérer (sauf pour les réponses de type 1xx, qui sont seulement « pour information »). Plusieurs gâteaux peuvent être envoyés, chacun dans un en-tête Set-Cookie différent (le client, lui, peut utiliser un seul en-tête Cookie pour envoyer plusieurs gâteaux). Un exemple classique est l'envoi d'un identificateur de session (ici, SID, pour Session ID). Le serveur envoie :

Set-Cookie: SID=31d4d96e407aad42

et à la requête suivante, le client renverra :

Cookie: SID=31d4d96e407aad42

Le serveur peut réduire la portée du gâteau avec les attributs Path et Domain. Ici, par exemple, le gâteau doit être renvoyé pour tous les URL dans example.com :

Set-Cookie: SID=31d4d96e407aad42; Path=/; Domain=example.com

Ici, un serveur prudent utilise en plus les attributs Secure et HttpOnly. En outre, il envoie deux gâteaux, SID et lang (chacun étant un doublet nom-valeur) :

Set-Cookie: SID=31d4d96e407aad42; Path=/; Secure; HttpOnly
Set-Cookie: lang=en-US; Path=/; Domain=example.com

Le client peut les renvoyer en un seul en-tête :

Cookie: SID=31d4d96e407aad42; lang=en-US

Ici, le serveur fixe une date d'expiration au gâteau :

Set-Cookie: lang=en-US; Expires=Wed, 09 Jun 2021 10:18:14 GMT

Après ces exemples tirés du RFC, voici maintenant un exemple réel entre un site Web écrit en PHP et un navigateur. Le trafic a été capturé et formaté avec tshark :

# Le serveur envoie :
Set-Cookie: PHPSESSID=euk3daoldp4s3j90uocetas3a0; path=/\r\n

# Le client répond (d'autres gâteaux avaient été transmis) :
Cookie: __utma=85646793.1868252067.1190397623.1190397623.1190397623.1; \
     PHPSESSID=euk3daoldp4s3j90uocetas3a0; \
     culture=fr\r\n

Autre façon de voir les gâteaux, se servir du client en ligne de commande curl :

% curl -v http://twitter.com/ > /dev/null
...
< Set-Cookie: guest_id=130393513906128799; path=/; expires=Fri, 27 May 2011 20:12:19 GMT
< Set-Cookie: _twitter_sess=BAh7CDoPY3JlYXRlZF9hdGwrCPc8l5gvAToHaWQiJWY3NTg3YTU1YTgwOWE2%250AODcxMTA5M2NiNzNiOWMxODRmIgpmbGFzaElDOidBY3Rpb25Db250cm9sbGVy%250AOjpGbGFzaDo6Rmxhc2hIYXNoewAGOgpAdXNlZHsA--dd45d4b08ccac6e6f832ccb70af983e16a12df43; domain=.twitter.com; path=/; HttpOnly

curl permet même de renvoyer ces gâteaux au serveur :

% curl --cookie _twitter_sess=BAh7CDoPY3JlYXRlZF9hdGwrCPc8l5gvAToHaWQiJWY3NTg3YTU1YTgwOWE2%250AODcxMTA5M2NiNzNiOWMxODRmIgpmbGFzaElDOidBY3Rpb25Db250cm9sbGVy%250AOjpGbGFzaDo6Rmxhc2hIYXNoewAGOgpAdXNlZHsA--dd45d4b08ccac6e6f832ccb70af983e16a12df43\;guest_id=130393513906128799 -v http://twitter.com/ > /dev/null     
...
> Cookie: _twitter_sess=BAh7CDoPY3JlYXRlZF9hdGwrCPc8l5gvAToHaWQiJWY3NTg3YTU1YTgwOWE2%250AODcxMTA5M2NiNzNiOWMxODRmIgpmbGFzaElDOidBY3Rpb25Db250cm9sbGVy%250AOjpGbGFzaDo6Rmxhc2hIYXNoewAGOgpAdXNlZHsA--dd45d4b08ccac6e6f832ccb70af983e16a12df43;guest_id=130393513906128799
...

La section 4 définit rigoureusement les obligations d'un serveur sérieux, qui ne cherche pas à exploiter les possibilités de la norme à fond et qui veut être sûr que tous les clients pourront traiter correctement ses gâteaux. Sa section 4.1.1 définit la syntaxe formelle à suivre, en ABNF. Les valeurs qui ne sont pas réduites à un strict sous-ensemble de caractères sûrs, pour maximiser les chances d'être transmises sans accident, sont encodées en Base64. Les dates s'expriment avec le format du RFC 1123 (mais certains serveurs non compatibles avec ce profil envoient des dates sur deux chiffres...). Certains clients stockent les dates dans un entier de seulement 32 bits donc il est possible que les choses se passent mal à partir de 2038.

Le serveur peut ajouter des attributs aux gâteaux. Ainsi, l'attribut Expires (section 4.1.2.1) permet de spécifier la date limite de consommation du gâteau (« À consommer avant le 29 avril 2011 ») et l'attribut Max-Age indique la durée de vie maximale (le RFC prévient que Max-Age est moins souvent mis en œuvre que Expires par les clients HTTP). Le gâteau peut durer moins longtemps que cela, par exemple parce que le navigateur Web a décidé de faire de la place, ou bien parce que l'utilisateur l'a détruit explicitement (chose que permettent tous les bons navigateurs, vues les conséquences négatives des gâteaux pour la vie privée).

Important pour la sécurité, l'attribut Domain permet d'indiquer le domaine des serveurs à qui le client doit renvoyer le gâteau. Attention, les sous-domaines de ce domaine sont également acceptés. Si le serveur envoie Domain=example.org lors du Set-Cookie, le client renverra le gâteau à, par exemple, www.example.org et mail.example.org. (Et si un serveur distrait met un gâteau avec Domain=com ? Il sera renvoyé à tous les domains en .com ? Cela dépend du navigateur ; beaucoup ignorent cet attribut Domain s'il correspond à un domaine d'enregistrement comme .fr ou .co.uk mais il n'existe pas de moyen officiel d'en connaître la liste donc ces navigateurs dépendent de listes incomplètes comme http://publicsuffix.org. Voir la section 5.3 pour une discussion complète. À noter que Konqueror utilise une méthode encore pire qui n'a jamais été corrigée.)

Le serveur peut restreindre encore plus l'utilisation du gâteau qu'il envoie avec l'attribut Path (section 4.1.2.4). Celui-ci indique quelle section du site Web a besoin du gâteau. Si on met Path=/accounting et que le domaine est www.example.com, seuls les URL commençant par http://www.example.com/accounting recevront le gâteau.

Enfin, deux autres attributs permettent d'améliorer la (faible) sécurité des gâteaux, Secure, qui impose au client de ne renvoyer le gâteau qu'au dessus d'une connexion « sûre » (typiquement HTTPS, pour éviter les attaques par FireSheep) et HttpOnly qui restreint le gâteau à ce protocole.

Une fois que le serveur a créé le gâteau et l'a envoyé avec les attributs qu'il juge utile, il doit être prêt à recevoir des gâteaux retransmis par le client. La section 4.2 décrit l'en-tête Cookie des requêtes HTTP, qui sert à cela. (Voir les exemples plus haut.)

La section 4 décrivait un profil réduit des gâteaux. Un client HTTP sérieux qui veut pouvoir comprendre tous les serveurs existants dans la nature, y compris ceux qui ne s'en tiennent pas à ce profil réduit, doit, lui, lire la section 5, qui décrit l'intégralité du très compliqué comportement des gâteaux. Cette section reprend le plan de la 4, en détaillant toutes les horreurs qu'on peut rencontrer dans le monde réel.

Par exemple, le format des dates (section 5.1.1), utilisées dans des attributs comme Expires, permet à peu près toutes les variations possibles. Écrire un analyseur complet n'est pas trivial, d'autant plus que le RFC ne décrit pas une grammaire indépendante du contexte mais un algorithme à état. (Si un pro de l'analyse syntaxique peut fournir une grammaire plus déclarative de cette syntaxe, je serais intéressé...)

De même, l'analyse du Set-Cookie en section 5 est plus complexe car le client doit accepter des Set-Cookie plus variés, par exemple avec des espaces en plus.

La section 5.3, qui n'a pas d'équivalent dans la section 4, décrit la façon dont les clients, les navigateurs Web, doivent stocker les gâteaux et les renvoyer. Elle rappelle la liste des attributs à stocker avec chaque gâteau (par exemple, s'il doit être renvoyé uniquement sur une connexion sécurisée ou bien si ce n'est pas nécessaire). Elle est très longue et le pauvre auteur de navigateur Web a donc bien du travail.

En parlant du programmeur, justement, la section 6 décrit les questions que pose l'implémentation de cette spécification. Parmi elles, la question de la taille du magasin où sont stockés les gâteaux. Le client Web n'est nullement obligé de fournir un magasin de taille infinie. Néanmoins, le RFC demande que le client accepte au moins quatre kilo-octets par gâteau, cinquante gâteaux par domaine et trois mille gâteaux en tout (ce qui permet déjà une belle indigestion). Conséquence de cette limite : un serveur doit s'attendre à ce qu'un client ne renvoie pas tous les gâteaux prévus. Certains ont pu être abandonnés par manque de place.

On l'a vu, la section 5, qui normalise le comportement du client, est très complexe. La section 4 l'est moins mais l'expérience a largement prouvé que les serveurs émettant des gâteaux avaient du mal à se tenir à un profil strict, et produisaient trop de variations. Une des raisons identifiées par la section 6.2 est le manque d'API. La plupart du temps, les applications font directement un printf "Set-Cookie: foobar=1234567; Expires=Wed, 06 Jun 2012 10:18:14 GMT\n" (ou équivalent) au lieu d'appeler une API plus abstraite dont l'implémentation se chargera de sérialiser proprement les objets complexes comme la date. Avec tant de liberté laissée au programmeur, il n'est pas étonnant qu'il y ait des variations non-standard.

Si le RFC ne propose pas de solution, il insiste sur l'importance pour les programmeurs d'utiliser des bibliothèques bien déboguées et de ne pas se croire capable d'écrire un Set-Cookie correct après cinq minutes de lecture de la norme. Un exemple d'une telle bibliothèque est, en Python, http.cookies. D'encore plus haut niveau, dans le même langage, urllib2 gère les gâteaux toute seule.

Comme le respect de la vie privée est le principal problème des gâteaux, il est normal que cette question ait une section entière, la 7, qui détaille ce point. C'est inhabituel à l'IETF, où la vie privée ne génère en général que peu d'intérêt. Peu de RFC ont une section Privacy considerations. Que dit-elle ? Que les gâteaux sont effectivement une technologie sensible (bien qu'il existe d'autres moyens de suivre un utilisateur mais moins pratiques donc moins dangereux) et que les plus problématiques sont les gâteaux envoyés à un tiers (c'est-à-dire à une autre organisation que celle qui gère visiblement la page, par le biais d'une discrète image insérée, par exemple). Par exemple, un service de statistiques utilisé sur de nombreux sites Web, ou bien un service de placement de publicités, peuvent permettre à leur gérant de croiser les visites faites sur plusieurs sites différents et ceci sans que l'utilisateur n'ait fait de visite explicite aux services de cette indiscrète organisation. Certains navigateurs sont, à juste titre, davantage paranoïaques lorsque le gâteau est envoyé par un tiers, par exemple en les refusant par défaut. D'autres ne traitent pas ces gâteaux différemment des autres. La question étant essentiellement politique, notre RFC 6265 ne définit pas de comportement normalisé, se contentant d'attirer l'attention sur ce point.

Peut-on demander son avis à l'utilisateur ? C'est ce qu'expose la section 7.2, consacrée au contrôle par l'utilisateur. Le RFC recommande que les clients Web fournissent des mécanismes de contrôle des gâteaux permettant de :

  • Gérer les gâteaux stockés dans la magasin local, par exemple examiner les gâteaux en place, détruire tous ceux d'un certain domaine (voici comment faire dans Firefox), etc,
  • Refuser systématiquement les gâteaux,
  • Proposer à l'utilisateur de refuser ou d'accepter chaque gâteau reçu, même si cela nécessite un peu plus de travail lors de la navigation (mais cela a l'avantage de faire prendre conscience de la quantité de gâteaux mis par des tiers, sur des pages Web qui semblaient pourtant innocentes ; cette option existait dans Firefox mais semble avoir disparu du panneau de contrôle des dernières versions de Firefox 3 ; on peut toujurs la régler « à la main » dans about:config network.cookie.lifetimePolicy=1),
  • Traiter les gâteaux comme temporaires (et donc les détruire lorsqu'on quitte le programme), une option parfois nommée safe browsing (cf. « An Analysis of Private Browsing Modes in Modern Browsers ») ; dans Firefox, elle peut se configurer dans Privacy ; History ; Use custom setting for history.

Voici la liste des gâteaux stockés, telle que Firefox permet de l'examiner et de la modifier : firefox-list-cookies.jpg Et la question que pose le même Firefox lorsqu'on l'a configuré avec about:config network.cookie.lifetimePolicy=1 : firefox-ask-cookie.jpg Et le dialogue de configuration dans Firefox 4, montrant l'option qui permet de demander à chaque gâteau si on l'accepte : firefox4-ask-cookie-each-time.png À noter qu'il existe bien d'autres moyens de configurer la politique des gâteaux, si le navigateur ne fait pas ce qu'on veut, par exemple des extensions comme Cookie Monster, WebDeveloper (qui permet de voir tous les gâteaux de la page en cours, avec pour chacun « Éditer » ou « Supprimer ») ou Ghostery pour Firefox. Le navigateur Dillo, quant à lui, à un mécanisme très détaillé.

Même en dehors du cas de la vie privée, les gâteaux posent un certain nombre de problèmes de sécurité (section 8). L'utilisation de HTTPS, quoique évidemment souhaitable, ne protège pas complètement contre ces vulnérabilités.

Premier problème, l'autorité diffuse (ambient authority, section 8.2). Le gâteau utilisé pour l'authentification sépare la désignation (l'URL) de l'autorisation. Le client risque donc d'envoyer le gâteau pour une ressource Web qui était contrôlée par un attaquant, une technique connue sous le nom de CSRF (il existe plusieurs moyens de convaincre un navigateur de se prêter à cette attaque, une étude bien plus détaillée des CSRF, qui a parmi ses auteurs l'auteur de ce RFC, est « Robust Defenses for Cross-Site Request Forgery »). Une solution à ce problème serait de traiter les URL comme une capacité, donnant accès à une ressource. L'URL serait alors le secret à transmettre pour avoir accès (le RFC ne note malheureusement pas que les URL ne restent pas secrets longtemps, par exemple certains navigateurs ou extensions des navigateurs - la Google Toolbar - transmettent les URL consultés à leur maître).

Autre problème des gâteaux, leur envoi en texte clair (section 8.3). Si on n'utilise pas HTTPS, Set-Cookie et Cookie sont transmis en clair avec leur contenu, permettant à un espion de les copier et de les utiliser (c'est cette vulnérabilité qu'exploite un programme comme FireSheep). En outre, un attaquant actif peut modifier ces en-têtes. La solution recommandée est évidemment de chiffrer toute la session, et de mettre l'attribut Secure aux gâteaux envoyés, pour éviter qu'ils ne soient plus tard transmis sur une session non chiffrée. Beaucoup de gros services très populaires ne sont pas accessibles en HTTPS ou bien ne le mettent pas en œuvre par défaut (souvent pour des raisons de performance, facteur crucial pour ces services qui reçoivent beaucoup de visites). Dans le cas de Gmail, c'est l'option « Général : Connexion du navigateur ; Toujours utiliser le protocole https ». Dans celui de Twitter, c'est « Toujours utiliser le HTTPS ». L'EFF mène une campagne pour systématiser cette protection. À noter qu'on peut limiter (mais pas supprimer) la réutilisation du gâteau en liant celui-ci à l'adresse IP du client ; si le gâteau vient d'une autre adresse, il sera refusé. Cette méthode n'est pas si efficace qu'elle en a l'air en raison de la fréquence du partage d'adresses IP (via le NAT). Ainsi, dans un café avec WiFi, un attaquant qui utilise FireSheep n'aura pas de problèmes malgré cette protection car tous les clients sont probablement derrière la même adresse IPv4 (c'est sans doute pour cela que le RFC ne propose pas cette solution).

C'est encore pire si le gâteau contient directement de l'information utile. Par exemple, si le gâteau est lang=en-AU, l'espion qui écoute peut trouver la langue et le pays de l'utilisateur. En général, cette information est plutôt stockée sur le serveur et le gâteau ne contient qu'un identificateur de session, inutile si on n'a pas accès au serveur. Mais cette technique présente d'autres risques (section 8.4), par exemple celui du « choix de session » où l'attaquant se connecte au serveur, puis convainct la victime (par exemple par le biais d'un lien) d'utiliser l'identificateur de session et d'interagir avec le serveur (par exemple en y déposant des informations confidentielles). L'attaquant, qui a conservé l'identificateur de session, pourra alors continuer la session et récupérer ces informations. (Voir un exemple et un article complet.)

Autre problème de sécurité des gâteaux, la confidentialité (section 8.5) : comme les gâteaux ne sont pas spécifiques d'un port ou d'un plan (http, gopher, ftp, etc), un client risque toujours de transmettre les gâteaux d'un serveur à un autre. L'intégrité n'est pas non plus garantie (section 8.6). Si bar.example.com a mis un gâteau de domain de example.com, un autre serveur, foo.example.com peut parfaitement le remplacer. Path n'est pas une protection : il n'empêche pas le remplacement.

Enfin, les gâteaux dépendent du DNS et en héritent les vulnérabilités (section 8.7).

Une très bonne synthèse des failles de sécurité des gâteaux figure dans l'excellent article « HTTP cookies, or how not to design protocols ».

Voilà, c'est tout, il reste à enregistrer les deux en-têtes dans le registre des en-têtes, ce que fait la section 9.

Contrairement aux autres RFC qui remplacent un autre RFC, ce RFC 6265 ne contient pas de description des changements par rapport aux précédents documents. Les clarifications et précisions sont sans doute trop nombreuses pour former une liste intéressante.

Merci à Jean-Baptiste Favre, bohwaz et Ollivier Robert pour leurs remarques et suggestions.


Téléchargez le RFC 6265


L'article seul

RFC 6264: An Incremental Carrier-Grade NAT (CGN) for IPv6 Transition

Date de publication du RFC : Juin 2011
Auteur(s) du RFC : S. Jiang, D. Guo (Huawei), B. Carpenter (University of Auckland)
Pour information
Réalisé dans le cadre du groupe de travail IETF v6ops
Première rédaction de cet article le 14 juin 2011


Verra-t-on un jour la fin des RFC sur les plans de transition d'IPv4 vers IPv6 ? Sans doute pas tant que la transition traîne. En effet, la lenteur imprévue du déploiement d'IPv6 remet en cause les plans initiaux (qui reposaient sur l'idée qu'il resterait des adresses IPv4 pendant toute la phase de transition) et nécessite le développement de nouveaux plans, pour répondre à une situation différente.

Le plan présenté ici est une variante des plans reposant sur l'idée de CGN (Carrier-Grade NAT), ces routeurs NAT installés, non pas dans la box de M. Michu, pour son usage et celui de sa famille, mais installés chez le FAI, pour l'usage partagé de plusieurs clients du FAI. Le CGN a l'avantage de nécessiter zéro logiciel ou configuration chez l'utilisateur (qui n'a probablement pas le temps et l'envie de maîtriser ces mécanismes). Ces solutions reposant uniquement sur le travail du FAI sont donc tentantes pour répondre au problème de la trop lente migration chez les utilisateurs. (Toutefois, mon impression personnelle est que beaucoup de réseaux de M. Michu, plein de gadgets récents, sont plus avancés vers IPv6 que pas mal de réseaux de FAI, conçus il y a des années.)

La nouveauté par rapport aux autres plans reposant sur le CGN est l'introduction de mécanismes pour éviter que ce CGN ne se transforme en impasse, et pour le faire évoluer vers de l'IPv6 natif complet. En effet, dans la plupart des cas, le terme de CGN fait penser à un mécanisme pour retarder la transition, le NAT444, qui permet au FAI paresseux de continuer à utiliser IPv4 même alors qu'il ne peut plus distribuer ne serait-ce qu'une seule adresse IPv4 publique à ses clients. Ce CGN-là ne fait pas progresser vers IPv6 (section 1 du RFC).

D'où cette idée de proposer un plan de migration reposant sur le CGN mais prévoyant dès le début les moyens d'en sortir. Ce RFC ne contient pas de nouveaux protocoles, il ne fait que combiner les protocoles existants.

Dans un certain nombre de FAI, la situation est actuellement la suivante (section 2) :

  • Plus d'adresses IPv4 publiques,
  • Un réseau interne purement IPv4, par manque de proactivité du FAI (qui aurait dû déployer IPv6 depuis longtemps), et qu'on ne peut pas migrer en cinq minutes,
  • La prise de conscience qu'IPv6 est nécessaire, et à relativement court terme.

Dans d'autre cas, FAI ayant fait son travail à l'avance et ayant déployé IPv6 depuis longtemps, ou bien FAI tout récent et préférant l'approche radicale de déployer un réseau purement IPv6, avec NAT64 (RFC 6144, et section 2.6 de notre RFC) pour assurer la liaison avec le vieux protocole, ces hypothèses ne sont plus vraies et l'approche de ce RFC ne s'applique donc pas. Comme toujours avec la transition vers IPv6, il faut analyser son réseau et déterminer la ou les meilleures stratégies de transition : chacune s'applique à un cas bien particulier.

Le dessin n° 1 en section 2.1 résume bien l'approche « CGN progressif » (Incremental Carrier-Grade NAT). En partant de chez M. Michu (ou plutôt M. Li car le cas décrit est plus proche de ce que vivent les FAI asiatiques), on a :

  • Les machines de M. Li, certaines en IPv6 mais pas toutes,
  • Un nouveau composant, le HG (Home Gateway), une box capable d'assurer certaines fonctions comme de tunneler le trafic IPv6 vers le routeur NAT situé plus loin dans le réseau du FAI,
  • Le tunnel IPv6-sur-IPv4 qui commence à la HG et se termine au routeur CGN,
  • Le réseau purement IPv4 du FAI,
  • Le CGN, une très grosse boîte,
  • Des serveurs restés purement v4 sur le réseau du FAI (serveur Web du portail, par exemple),
  • L'accès à l'Internet, en IPv4 et en IPv6.

Les deux composants nouveaux, que n'a pas forcément le FAI aujourd'hui, sont le HG et le CGN. Le HG doit obéir au RFC 7084. Autrement, tous les équipements (routeurs classiques et machines terminales) ne changent pas (cf. section 2.5).

Quelle technique de tunnel choisir entre le HG et le CGN ? La section 2.2 rappelle les possibilités. Les tunnels configurés manuellement du RFC 4213 paraissent peu pratiques. Ceux du RFC 3053 peuvent ne pas être très utilisables par l'utilisateur résidentiel. Cela laisse 6rd (RFC 5969) et peut-être GRE (RFC 2784). Si le FAI a déjà une infrastructure MPLS, il peut aussi considérer RFC 4798, mais cela suppose que MPLS aille jusqu'au HG, ce qui est peu probable. Bref, le RFC recommande 6rd.

La section 2.3 peut alors décrire en détail le fonctionnement de la HG (Home Gateway, la box). Lorsqu'elle reçoit un paquet de l'intérieur :

  • Si c'est un paquet IPv4, elle le fait suivre sur l'infrastructure v4 normale du FAI (peut-être après traduction), jusqu'au CGN qui fera alors une traduction v4-v4 (il aura donc pu y avoir deux traductions),
  • Si c'est un paquet IPv6, elle l'encapsule pour l'envoyer, via le tunnel, jusqu'au CGN (le gros routeur/traducteur situé plus loin dans l'infrastructure du FAI).

Et le CGN (Carrier-Grade NAT, un routeur NAT qui sert plusieurs clients) ? La section 2.4 lui est consacrée. Lorsqu'il reçoit un paquet IPv4 venu d'une HG (rappelons que tout ce RFC est consacré au cas où l'infrastructure du FAI est purement IPv4), deux cas :

  • C'est un paquet v4 normal, et on le transmet après traduction (puisque le FAI n'a pas assez d'adresses IPv4 publiques, le paquet a certainement une adresse source privée) ; comme tout routeur NAT, le CGN mémorise la correspondance port<->adresse,
  • C'est un paquet IPv6 encapsulé dans du v4. Le CGN le décapsule, et le transmet.

Voilà, sur le papier, c'est tout simple. Quelles sont les conséquences pratiques ? La section 2.7 discute divers points. D'abord, comme toute solution à base de NAT, notre schéma a tous les inconvénients du partage d'adresses. Pire, comme le CGN est situé loin de l'utilisateur, et que celui-ci ne peut pas le configurer, des techniques permettant d'avoir des connexions entrantes comme les correspondances statiques ou comme UPnP ne fonctionnent plus. D'autre part, le tunnel v6-sur-v4 entre le HG et le CGN posera les habituels problèmes de MTU (dont le RFC se débarasse avec une pirouette).

L'originalité de l'approche de ce RFC est la possibilité de migrer de cette solution NAT complexe et fragile vers une solution IPv6 propre. Comment ? C'est ce que décrit la section 3, qui prévoit plusieurs étapes, en supposant :

  • On installe un CGN pour faire du NAT444. À court terme, cela réduit la demande en adresses IPv4 publiques. Mais cela n'aide pas en soi à migrer vers IPv6. Le HG doit être mis à jour pour utiliser le CGN.
  • On déploie 6rd (nouvelle mise à jour du logiciel du CGN),
  • On déploie alors tranquillement IPv6 sur le réseau du FAI. Dès que la zone desservie a un routage IPv6, on peut couper 6rd dans le HG, supprimant ainsi le tunnel v6-sur-v4 (IPv4 continuant à être envoyé au CGN). Cette coupure du tunnel peut se faire automatiquement, si le HG a été programmé pour détecter les RA (Router Advertisment) ou réponses DHCP IPv6.
  • Cette dernière possibilité suppose une forme de double-pile (v4 et v6) sur le réseau du FAI pendant un temps. Si celui-ci préfère n'avoir qu'un seul protocole à gérer, l'approche est au contraire de basculer du routage purement v4 du début à un routage purement v6. C'est alors IPv4 qui sera tunnelé, via DS-Lite. Le FAI sera alors arrivé jusqu'au bout, il sera purement IPv6.

Comme indiqué, le passage d'une étape à une autre peut être détecté automatiquement par le HG, la box, qui peut par exemple interroger le CGN pour noter les nouvelles fonctions disponibles. Cela éviterait une action explicite sur la HG.

Il reste à étudier les conséquences de ce schéma en terme de sécurité (section 4). Le NAT en général pose de nombreux problèmes de sécurité (RFC 2663 et RFC 2993). Le partage massif d'adresses, par exemple dans un CGN, crée des failles expliquées dans le projet de RFC draft-ietf-intarea-shared-addressing-issues. Les protocoles spécifiques utilisés ont également leurs propres questions de sécurité, documentées dans leur norme respective (par exemple, pour 6rd, dans la section 12 du RFC 5969).

Toutefois, le fait que ce schéma concerne uniquement des mécanismes utilisés à l'intérieur du réseau d'un FAI, la sécurité est simplifiée. On peut certes sécuriser les tunnels avec le RFC 4891 mais ce n'est peut-être pas nécessaire, à l'intérieur d'un réseau unique et géré.

Par construction, il n'y a pas d'implémentation complète de ce RFC, mais des implémentations de certaines des fonctions. Par exemple, DS-Lite est mis en œuvre dans AFTR.


Téléchargez le RFC 6264


L'article seul

RFC 6256: Using Self-Delimiting Numeric Values in Protocols

Date de publication du RFC : Mai 2011
Auteur(s) du RFC : W. Eddy (MTI Systems), E. Davies (Folly Consulting)
Pour information
Première rédaction de cet article le 26 mai 2011


Comment encoder des valeurs dans un protocole ? Il existe des tas de méthodes mais celle de ce RFC 6256, les « valeurs numériques auto-terminées » (SDNV pour Self-Delimiting Numeric Values) sont encore très peu connues et guère utilisées.

Soit un concepteur de protocoles réseau. Il doit indiquer dans les données qui circulent des valeurs, par exemple un gâteau qui identifie une session ou bien une durée ou une longueur ou bien une clé cryptographique ou des tas de choses encore. Comment transmettre ces valeurs (section 1.1) ? Une technique courante, très utilisée dans les protocoles « binaires » comme IP (RFC 791) ou bien le DNS (RFC 1035) est le champ de taille fixe. On décide que la longueur sera représentée sur 16 bits et les producteurs et les lecteurs de ce champ connaissent cette taille, qu'ils ont lu dans le RFC correspondant. Plus la taille est grande, plus on consomme de ressources réseaux pour la transmettre mais, plus elle est petite, et moins on pourra représenter de valeurs. Dans mon exemple, que fera t-on si les changements dans les techniques ou dans les usages nécessitent de stocker des longueurs supérieurs à 65 536 ? Le problème est fréquent car des protocoles sont souvent utilisés pour des dizaines d'années consécutives, années pendant lesquelles les hypothèses de base ont changé. Le RFC cite ainsi les exemples de la fenêtre TCP (RFC 793, la fenêtre est limitée à 16 bits, soit 65 kilo-octets, ce qui est bien trop peu pour les réseaux à 10 Gb/s d'aujourd'hui, et a nécessité le hack de l'échelle de fenêtre du RFC 1323, désormais en RFC 7323) et du bien connu champ Adresse d'IPv4, qui s'est montré trop petit. Le RFC note bien que les deux décisions avaient semblé raisonnables à l'époque : sur une ligne spécialisé à 64 kb/s, la fenêtre maximale était de huit secondes, ce qui donnait largement aux accusés de réception le temps de revenir. Aujourd'hui, la même taille ne laisse que 50 microsecondes... Même problème pour les adresses IPv4, épuisées par le changement du modèle de l'ordinateur (de « un par entreprise » à « plusieurs par personnes ») et par le succès inespéré de l'Internet. Les SDNV permettent donc d'éviter de prendre des décisions (« 16 bits ? 32 bits ? Allons-y pour 16 bits, ça suffira bien. ») qu'on regrettera ensuite.

Une autre approche, commune à l'IETF, est d'utiliser TLV. C'est le mécanisme le plus souple, mais, pour des valeurs assez petites, il prend plus de place que SDNV.

Le groupe de recherche IRTF DTNRG, qui est occupé notamment à développer des protocoles réseau pour les vaisseaux spatiaux (cf. RFC 4838) a son idée sur la question (la section 4 présente une discussion des alternatives), et cela a donné ce RFC. Par exemple, dans l'espace, vu le RTT, les protocoles qui négocient des paramètres au début de la connexion (comme l'échelle de fenêtre TCP), et qui permettent ainsi d'avoir des champs de taille fixe et de choisir la taille au début de la connexion, ne sont pas envisageables. Mais le problème n'est pas spécifique aux réseaux « DTN » (Delay-Tolerant Networking, les réseaux où l'acheminement d'un bit prend un temps fou, ce qui est le cas dans l'espace où la vitesse de la lumière est une limite gênante, cf. RFC 5325) et on peut retrouver des ancêtres de SDNV dans des encodages ASN.1 ou bien dans certains protocoles UIT. Par contre, en dehors du projet DTN, il ne semble pas que les SDNV aient été utilisés par des protocoles IETF, peut-être parce que leur encodage et décodage est plus lent qu'avec des champs de taille fixe (le protocole WebSocket utilise les SDNV). À noter que notre RFC n'est pas la premier à normaliser SDNV, ceux-ci avaient déjà été décrits dans les RFC 5050 et RFC 5326 mais de manière sommaire. Un description plus complète n'était donc pas du luxe.

SDNV se limite à représenter des entiers positifs ou des chaînes de bits. Pour des types plus complexes, on peut utiliser les encodages d'ASN.1 ou bien MSDTP (décrit dans le RFC 713).

Après ces préliminaires, attaquons-nous à la définition d'un SDNV (section 2). Un SDNV est encodé sous forme d'une série d'octets en n'utilisant que sept bits de chaque octet. Le huitième indique si l'octet est le dernier du SDNV. Ce mécanisme impose un décodage strictement séquentiel, en examinant un octet après l'autre. Quelques exemples :

  • Le nombre 3 est représenté par 00000011. Le premier bit, ici à zéro, indique que ce premier octet est aussi le dernier.
  • Le nombre 130 est représenté par 1000001 00000010. Le premier bit du premier octet indique que cet octet n'est pas le dernier. Le dernier bit du premier octet est celui qui code 128. (On ne peut pas utiliser le premier bit du deuxième octet, réservé pour indiquer la fin de la série des octets.)

L'annexe A contient d'autres exemples et j'en montre certains à la fin de cet article. Il y a quelques détails pratiques comme les zéros initiaux : le premier nombre est-il 3 où 03 ? Le RFC explique que les zéros initiaux ne sont pas significatifs. Pour les nombres, cela ne change évidemment rien (3 = 03) mais si on voulait représenter des chaînes de bits, c'est plus compliqué et SDNV ne fournit pas de solution satisfaisante (le RFC suggère par exemple d'indiquer explicitement la longueur dans un autre champ, ce qui annule l'intérêt de SDNV ; une autre suggestion est de toujours mettre un bit à 1 au début de toute chaîne).

Les SDNV ont parfois été décrits sous le nom de Variable Byte Encoding (cf. le livre de Manning, Raghavan, et Schuetze, « Introduction to Information Retrieval », qui s'intéressait toutefois à la compression plutôt qu'à la souplesse). On peut remarquer qu'aucune valeur encodée en SDNV n'est un préfixe d'une valeur encodée en SDNV (SDNV est prefix-free, autre façon de dire que les données sont auto-terminées).

Comment encode et décode-t-on ces SDNV ? La section 3 décrit quelques algorithmes qui peuvent être utilisés à cette fin. La section 3.1 contient un algorithme d'encodage très simple en O(log(N)) où N est le nombre à encoder. Le décodage est plus sioux : on ne connait en effet pas la valeur du nombre avant de l'avoir décodé et on ne sait donc pas quel type on doit utiliser pour stocker le résultat. Même un type de grande taille, genre uint64_t peut être trop petit. La section 3.2 propose un algorithme de décodage récursif, qui évalue à chaque étape si le résultat est de taille suffisante et alloue une autre variable si nécessaire.

Cette histoire de taille de la variable qui stocke le résultat est un des problèmes pénibles de SDNV. On ne peut pas exiger de chaque implémentation qu'elle mette en œuvre un système d'entiers infinis (le RFC cite GNU MP comme exemple). La section 3.3 propose que chaque protocole qui utilise des SDNV fixe une taille maximale aux entiers stockés (retombant ainsi partiellement dans les problèmes des champs de taille fixe). Ainsi, le protocole Bundle (RFC 5050) fixe cette limite à la valeur maximale pouvant être représentée avec 64 bits. Le décodeur peut donc utiliser un uint64_t sans crainte.

Voilà, les SDNV sont donc très simples dans leur principe. Mais quels sont leurs avantages et leurs inconvénients ? La section 4 discute des alternatives : SDNV actuels, TLV, et l'ancien système de SDNV qui avait été utilisé dans des versions antérieures de certains protocoles DTN. En gros, le système le plus souple est TLV mais c'est aussi le moins efficace, en place et en temps. Un avantage de TLV est que, via le champ Type, la sémantique est connue, alors que les SDNV ne sont que des entiers non typés. Autre avantage : la taille du résultat est connue tout de suite et l'allocation mémoire pour le résultat tombe donc toujours juste (l'ancien SDNV avait un système analogue). Mais l'un des problèmes des TLV est que la représentation des champs Type et Longueur. S'ils sont de taille fixe, les TLV héritent certains des problèmes des champs de taille fixe. Notons qu'on peut combiner les techniques, par exemple utiliser SDNV pour le champ Longueur d'un TLV.

Bien que le RFC n'en discute guère, je me permets d'ajouter ici une comparaison essentiellement personnelle entre champs de taille fixe et SDNV. Les champs de taille fixe :

  • Sont bien plus faciles à encoder/décoder, dans un langage comme C, c'est même trivial. Ce n'est pas seulement un avantage pour le programmeur, c'est aussi une garantie de rapidité.
  • Ont pour principal inconvénient le fait qu'une mauvaise estimation de la taille nécessaire n'est pas corrigeable a posteriori (cas des fenêtres TCP et des adresses IPv4 cités plus haut). Si la capacité du réseau est grande (ce qui n'est typiquement pas le cas dans l'espace), une solution possible est de gaspiller, en utilisant systématiquement des champs très grands, genre 128 bits.
  • Ont une taille connue à l'avance (par définition), ce qui permet au programmeur de réserver la bonne taille (cf. section 3.3)
  • Sont très sensibles aux erreurs de transmission car les modifications sont indécelables. Au contraire, la modification d'un bit dans un SDNV peut entraîner une erreur de format, qui sera détecté au décodage.

Bref, je trouve personnellement que l'utilisation fréquente de champs de taille fixe dans les protocoles Internet n'est pas due au hasard.

Reparlons de décodage avec la question de la sécurité (section 5). Un décodeur SDNV doit faire attention aux valeurs qui dépassent ses limites, non seulement pour ne pas planter, mais aussi parce que cela peut avoir des conséquences de sécurité (débordement de tampon, par exemple). Autre piège, les entiers gérés par SDNV sont toujours positifs. Une implémentation ne doit donc pas les décoder vers un type signé, ce qui risquerait d'introduire des valeurs négatives dans un processus qui ne s'y attend pas. (TLV a le même problème si on place un champ Longueur dans une variable de type signé.)

Place aux implémentations. Le programme Python sdnv.py, qui utilise le code présent dans l'annexe A du RFC, permet de tester encodage et décodage. L'affichage (pas le calcul) nécessite l'excellent module bitstring :

# Encodage

% python sdnv.py -e 3    
3 -> 0b00000011

% python sdnv.py -e 130
130 -> 0b1000000100000010

% python sdnv.py -e 4598
4598 -> 0b1010001101110110

% python sdnv.py -e 46598           
46598 -> 0b100000101110110000000110

# Décodage

% python sdnv.py -d 00000000        
00000000 -> 0

% python sdnv.py -d 00000011
00000011 -> 3

% python sdnv.py -d 1000000100000010 
1000000100000010 -> 130

[Ajout d'un troisième octet, fait de bits nuls, _après_ le SDNV.]
% python sdnv.py -d 100000010000001000000000
100000010000001000000000 (only 2 bytes read) -> 130

À noter que les SDNV disposent d'une page Web officielle. En dehors du code Python du RFC, je n'ai pas vu d'autres implémentations mais on peut probablement en extraire du code DTN.


Téléchargez le RFC 6256


L'article seul

RFC 6255: Delay-Tolerant Networks (DTN) Bundle Protocol IANA Registries

Date de publication du RFC : Mai 2011
Auteur(s) du RFC : M. Blanchet (Viagénie)
Pour information
Première rédaction de cet article le 26 mai 2011


Le groupe de recherche DTN (Delay-Tolerant Networking, cf. RFC 4838) de l'IRTF a déjà produit plusieurs protocoles comme Bundle (RFC 5050) et Licklider (RFC 5326). Ces protocoles n'avaient pas jusqu'alors de registres officiels pour leurs paramètres, manque que notre RFC 6255 vient de combler.

Jusqu'à présent, les paramètres enregistrés étaient stockés sur le site Web du groupe. Ils sont désormais à l'IANA qui en assurera la maintenance: https://www.iana.org/assignments/bundle/bundle.xml.

Ces paramètres sont souvent encodés sous forme de SDNV (Self-Delimiting Numeric Values, RFC 6256 et section 2 de notre RFC). Pour le protocole Bundle (RFC 5050) les paramètres à enregistrer sont décrits en section 3. On peut citer par exemple les options de traitement (processing control flags, section 3.3), dont la liste peut évoluer, la seule contrainte pour l'enregistrement étant la disponibilité d'une spécification stable (pour les politiques d'enregistrement dans les registres IANA, voir le RFC 5226 ; cette politique particulière, « Specification required » est décrite en section 4.1). Ces options ont la forme de bits dans un tableau de taille 64, parmi lesquels le bit 2 indique que le lot (bundle) ne doit pas être fragmenté, le 5 qu'un accusé de réception est demandé, etc.

Autre exemple, les codes de réponse (status report flags, section 3.5) comme « lot accepté » ou « lot transmis ». Comme le tableau de bits est bien plus petit cette fois (huit bits dont seuls trois sont encore libres), les règles d'enregistrement sont plus strictes, un RFC (pas juste n'importe quelle spécification) est exigé.

Les autres protocoles comme Licklider n'ont pas encore leur registre.


Téléchargez le RFC 6255


L'article seul

RFC 6250: Evolution of the IP Model

Date de publication du RFC : Mai 2011
Auteur(s) du RFC : D. Thaler (IAB)
Pour information
Première rédaction de cet article le 20 mai 2011


Qu'offre l'Internet aux développeurs d'application et aux concepteurs de protocole ? Le modèle de service de l'Internet n'a pas toujours été bien documenté, et les préjugés et idées fausses abondent chez les programmeurs (l'essentiel du RFC est d'ailleurs composé de l'exposé des affirmations erronées sur le modèle Internet.) En outre, l'Internet ayant crû de manière analogue à un écosystème, sans suivre strictement un plan pré-établi, ce modèle a largement changé, sans que ce changement n'ait été intégré par les développeurs. D'où ce RFC, qui ambitionne de documenter le modèle de service de l'Internet tel qu'il est en 2011. Ce RFC devrait être lu par tous les développeurs d'applications, afin qu'ils apprennent le service que leur offre réellement l'Internet.

Tout le monde sait que l'Internet offre un service de niveau 3 (le protocole IP). Même si les applications y accèdent en général via un service de niveau 4 (typiquement TCP), bien des caractéristiques de la couche 3 apparaissent aux applications (comme les adresses IP). (Le RFC utilise d'ailleurs parfois le terme « application » pour parler de tout ce qui est au dessus de la couche 3.) Quelles sont exactement les propriétés de ce service ? Par exemple, les caractéristiques de la communication (latence, taux de perte de paquets, etc) mesurées au début sont-elles constantes (réponse : non) ? Quelle est la taille d'une adresse IP (ceux qui répondent « quatre octets » peuvent abandonner l'informatique pour l'élevage des chèvres en Lozère) ? Si 192.0.2.81 se connecte chez moi, pourrais-je me connecter à mon tour à cette machine (réponse : plutôt oui, à l'origine, malheureusement non aujourd'hui) ? Si certaines applications (par exemple une application qui inclus un simple client HTTP pour récupérer un fichier distant) peuvent ignorer sans problème ce genre de questions, pour d'autres (logiciel de transfert de fichiers pair-à-pair, client SIP, etc), ces questions sont cruciales et les développeurs ne connaissent pas forcément les bonnes réponses.

Revenons à l'histoire, comme le fait la section 1 du RFC. Le modèle original d'IP (et qui est encore souvent enseigné comme tel dans pas mal d'établissements d'enseignement) était partiellement documenté en 1978 dans l'IEN28 (les premières publications sur le TCP/IP actuel, les RFC 791 et RFC 793 ne sont venus qu'après). Un des principes était que les applications étaient très différentes mais que toutes tournaient sur IP, qui à son tour tournait sur tous les réseaux physiques possibles (modèle dit « du sablier », IP représentant le goulet d'écoulement du sablier). Ce modèle a nécessité plusieurs clarifications dans les RFC ultérieurs, par exemple le RFC 1122 en 1989 ou le RFC 3819. Résultat, aujourd'hui, il n'y a pas de document unique qui décrive le modèle de service, ce qu'offre IP aux applications.

Il est d'autant plus nécessaire de comprendre ce modèle qu'il est désormais difficile de le changer. Au début de l'Internet, on pouvait changer un concept et obtenir de tous les développeurs de toutes les applications de s'adapter. Aujourd'hui, la taille de l'Internet et son absence de centre rendent une telle opération impossible. L'Internet s'est ossifié.

Bon, en quoi consiste ce fameux « modèle de service » ? Il est décrit par la section 2. Un modèle de service est défini comme la description du service que rend une couche aux couches supérieures, ici le service que rend IP aux applications. Le schéma n° 1 résume cette notion de couches et la place d'IP dans l'architecture de l'Internet. Et le comportement d'IP ? Sa description officielle était dans la section 2.2 du RFC 791 : un service sans connexion (orienté paquets), acceptant des paquets de taille variable, et les délivrant (mais pas toujours) sans garantir leur ordre ou leur absence de duplication. Bref, un service qui « fait au mieux » (best effort dans la langue de Jack London). Les émetteurs n'ont pas besoin de se signaler aux destinataires ou au réseau avant d'émettre et les récepteurs n'ont pas besoin de signaler quoi que ce soit au réseau avant de recevoir.

On l'a dit, l'architecture réelle n'est plus vraiment celle du RFC 791, qui était de toute façon décrite de manière très brève dans ce RFC. D'autres documents ont approfondi la question comme le RFC 1958 ou comme le rapport « New Arch: Future Generation Internet Architecture » de 2004.

En fait, il est plus facile de décrire ce qu'il n'y a pas dans le modèle de service d'IP. La section 3, consacrée aux préjugés erronés, est donc beaucoup plus longue que la section 2. Je ne vais pas la répéter dans son entièreté mais simplement citer quelqu'uns de ces préjugés, en commençant par ceux concernant la connectivité.

Une des suppositions non dites les plus fréquentes dans les applications est que la possibilité d'envoyer un paquet (reachability) est symétrique (section 3.1.1). Un protocole comme FTP (RFC 959), avec sa notion de « voici mon adresse IP, rappelle-moi », repose largement là-dessus. Si la machine A peut envoyer un paquet à la machine B, le contraire est aussi vrai. Ce principe était largement vrai au début de l'Internet (attention, la possibilité d'envoyer était symétrique mais pas le chemin suivi) mais est tout à fait faux aujourd'hui. C'est même plutôt le contraire : la machine typique est coincée derrière un routeur NAT et un pare-feu qui empêchent tout envoi initié par l'extérieur. L'annexe A du RFC 5694 discute plus en détail ce problème et ses conséquences notamment pour les applications pair-à-pair. Bref, la seule chose que laquelle les applications peuvent relativement compter, est qu'une réponse à une requête initiée depuis l'intérieur a des chances d'arriver (c'est le modèle de HTTP). Les requêtes initiées de l'extérieur sont par contre impossibles dans le cas général (RFC 2993).

À noter que, même en l'absence de boîtiers intermédiaires qui bloquent les paquets, certains liens physiques ne sont pas symétriques, notamment en radio, comme l'illustre la section 5.5 du rapport « The mistaken axioms of wireless-network research ».

Autre supposition fréquente mais erronée, la transitivité. L'idée est que, si une machine A peut joindre B, et que b peut joindre C, alors A peut joindre C (section 3.1.2). Exactement comme pour la symétrie, ce principe était vrai au début, et ne l'est plus maintenant, en raison du NAT et des pare-feux, mais aussi de protocoles physiques comme 802.11 qui ne garantissent pas une telle transitivité.

Autre erreur que font certains développeurs d'applications, parce qu'ils confondent le modèle original de l'Internet et la triste réalité d'aujourd'hui, la conviction que les paquets signalant une erreur arriveront à l'émetteur du paquet qui a déclenché l'erreur (section 3.1.3). Ces paquets signalant une erreur sont typiquement portés par le protocole ICMP. Des exemples de leur usage ? La découverte de la MTU du chemin (RFC 1191 et RFC 1981) ou bien traceroute (RFC 1812).

Pourquoi ne peut-on plus compter sur ces messages ? D'abord, bien des routeurs ont été configurés pour limiter le rythme d'envoi, avant de rendre plus difficile leur utilisation dans une attaque DoS (RFC 2923, section 2.1. Ensuite, bien des pare-feux ont été stupidement configurés par des incompétents et bloquent tout l'ICMP (malgré les recommandations des RFC 2979, section 3.1.1, et RFC 4890). Résultat, il a fallu développer des mécanismes alternatifs pour la découverte de la MTU (RFC 4821).

Autre erreur : certaines applications croient qu'elles peuvent utiliser la diffusion IPv4 pour transmettre un message à toutes les machines (section 3.1.5). Autrefois, des adresses comme 10.1.255.255 (les seize derniers bits tous à un) envoyaient en théorie un message à toutes les machines du réseau 10.1.0.0/16, et les routeurs devaient faire suivre ce message au delà du lien local. Comme ce mécanisme facilitait trop les attaques par déni de service, il a été abandonné par le RFC 2644 en 1999. Depuis, la diffusion ne marche plus que sur le lien local. Et encore, car certains liens, dits NBMA, ne la permettent pas. Plus drôle, certains liens comme 802.11 en mode ad hoc autorisent la diffusion mais, en pratique, le message n'atteint pas toutes les machines du lien. Bref, si on veut écrire à toutes les machines d'un groupe, il vaut mieux le faire soi-même, sans compter sur la diffusion.

À ce sujet, la section 3.1.6 note que, contrairement à une croyance courante, un ensemble de paquets unicast n'est pas forcément plus coûteux ou moins rapide qu'un multicast ou qu'un broadcast. Sur les liens filaires traditionnels, un seul paquet multicast sera sans doute plus rapide. Ce n'est plus le cas sur les liens radio où le multicast devra être transmis au débit de base, même s'il existe des machines ayant une interface radio plus rapide, et qui a négocié un débit plus élevé.

Un problème subtil est causé par le cas où l'application compte sur la latence des paquets, par exemple pour faire de la visioconférence. Une application qui mesure cette latence peut avoir tendance à mesurer le premier paquet et à la considérer comme représentatif. Mais c'est souvent à tort (section 3.1.6). En effet, pour le premier paquet d'un flot de données, il y a souvent un temps d'établissement (dû à la résolution ARP, par exemple). Et ce sera pire avec les futurs systèmes de séparation de l'identificateur et du localisateur qui, tous, prévoient une forte latence pour le premier paquet, lorsqu'il faut résoudre l'identificateur en localisateur.

Autre caractéristique d'un chemin suivi par les paquets : le taux de réarrangement, qui mesure le fait que certains paquets arrivent avant des paquets partis plus tôt. Des études comme celle de Bennett, J., Partridge, C., et N. Shectman, « Packet reordering is not pathological network behavior » ou comme les RFC 2991 ou RFC 3819, section 15, montrent que le réarrangement a des conséquences pour les applications. Pour un programme de streaming, par exemple, il oblige à augmenter la taille des tampons. TCP voit ses performances se dégrader si les paquets n'arrivent pas dans l'ordre. Mais le réarrangement est un fait : des tas de raisons peuvent le causer (un routeur qui fait de la répartition de charges entre deux liens, par exemple) et les applications doivent s'y attendre.

Et le taux de pertes des paquets ? Sur quoi peut-on compter ? Beaucoup de gens pensent que les pertes sont rares, et probabilistiques (c'est-à-dire que le destin frappe un paquet au hasard, et qu'en reessayant, ça va marcher). Mais ce n'est pas forcément le cas (section 3.1.9). D'abord, si l'application a un comportement non-uniforme (des grands moments de silence, puis de brusques envois de nombreux paquets), les pertes se concentreront pendant ces envois, qui rempliront les files d'attente. Ensuite, il existe des phénomènes qui mènent à la perte préférentielle du premier paquet, comme ces routeurs de cœur qui, pour éviter une attaque DoS (envoi de paquets vers beaucoup d'adresses qui ne répondent pas), ne gardent pas en mémoire les paquets qui déclenchent une résolution ARP. Le premier paquet vers une nouvelle destination sera donc forcément perdu. Un autre exemple d'un comportement analogue est le Wake-on-LAN, où le paquet qui déclenche l'allumage de la machine n'est en général pas gardé.

L'Internet garantit-il qu'un chemin existe, à un moment donné, vers une destination (section 3.1.10) ? Oui, c'est toujours largement vrai. Mais cela cesse de l'être dans des réseaux exotiques comme les DTN (cf. RFC 4838) où deux machines pourront communiquer sans jamais être allumées en même temps. Avec humour, le RFC mentionne également le cas de réseaux où les paquets sont transportés par des animaux, peut-être une allusion au RFC 1149.

Pourquoi ces suppositions, qui étaient en général vraies autrefois, ont cessé de l'être (section 3.1.11) ? Il y a deux classes de raisons, une située dans les couches 1 et 2, et une autre placée dans la couche 3. Pour la première, le RFC 3819 donnait d'utiles conseils aux concepteurs de réseaux physiques. En gros, il indique une liste de services que doivent rendre les couches basses à IP et, si celles-ci ne le font pas, comment la couche d'adaptation à IP peut compenser. Ainsi, les RFC 3077 et RFC 2491 décrivent des mécanismes pour compenser l'absence d'atteignabilité symétrique et donc restaurer les services auquel s'attend IP. Mais toutes les couches basses ne le font pas : par exemple, il n'existe pas de moyen standard, lorsqu'une machine est connectée en WiFi ad hoc, de compenser le manque de symétrie dans les liens. Un mécanisme, situé sous IP, reste à élaborer.

Autre classe de causes pour lesquelles les suppositions d'autrefois ne sont plus forcément respectées, les raisons situées dans la couche 3 elle-même. Cela peut être une conséquence d'une politique de sécurité (RFC 4948), qui mène au filtrage. Cela peut être aussi à cause du NAT. Plusieurs applications font beaucoup d'efforts pour contourner ces problèmes. Cela semble une bonne application du principe de robustesse (« soyez strict dans ce que vous envoyez mais laxiste dans ce que vous acceptez »), et, en effet, les protocoles qui réussissent à contourner les limites de la couche 3 ont en général plus de succès que les autres (RFC 5218). Mais le principe de robustesse a aussi l'inconvénient de masquer les problèmes, et de diminuer la pression pour les résoudre. Par exemple (qui n'est pas dans le RFC), Skype réussit à passer via des hotspots où seul le port 80 fonctionne en sortie, donc les clients de ces hotspots ne râlent pas contre l'opérateur de ce dernier et celui-ci continue donc à fournir un service de daube. Le RFC suggère, pour sortir de ce dilemme, de fournir un mode spécial pour l'application, activable à la demande, où l'application n'utilisera que des techniques propres et officielles, permettant ainsi de déboguer les réseaux mal fichus, sans que leurs problèmes soient masqués.

Cela, c'était pour la connectivité. Et pour l'adresssage ? La section 3.2 rassemble les suppositions erronées les plus fréquentes sur ce sujet.

D'abord, bien des applications considèrent l'adresse IP comme stable sur une assez longue période (ce qui était vrai autrefois, où les adresses étaient toutes fixes et configurées manuellement). Cette supposition (section 3.2.1) se reflète dans l'API : par exemple, getaddrinfo() ne fournit pas d'indication sur la durée de validité de l'adresse récupérée. Même avec plein de bonne volonté, l'application ne peut pas savoir si l'adresse IP récupérée en échange du nom peut être conservée pour une minute, une heure ou un jour (la plupart des applications appelent getaddrinfo() et ne remettent jamais en cause son résultat, gardant l'adresse IP pendant toute leur durée de vie, un phénomène connu sous le nom d'épinglage - pinning - et qui peut avoir des conséquences pour la sécurité).

Or, aujourd'hui, avec des techniques comme DHCP, les adresses ne sont pas stables et changent, notamment lorsque la machine se déplace. Cela casse des applications comme SSH. Plusieurs protocoles ont été proposés pour conserver un identificateur stable même lorsque le localisateur change (par exemple HIP).

Encore plus répandue, l'idée comme quoi une adresse IP ferait quatre octets (section 3.2.2). Faites le test lors d'un entretien d'embauche : demandez au candidat à écrire un petit programme C qui gère des adresses IP. S'il déclare une variable de type uint32_t, cela montre qu'il ne connait pas IP (si la variable est de type int, cela montre qu'il ne connait pas C...). Cette idée était juste il y a douze ans, mais ne l'est plus depuis que l'Internet est redevenu multi-protocole, avec la coexistence d'IPv4 et IPv6 (dont les adresses font seize octets).

Plus subtile, la question du nombre d'adresses par interface. Pas mal de programmeurs tiennent pour acquis que « l'adresse IP identifie une interface » (ce qui est faux) et écrivent un code qui ne gère pas vraiment le cas d'adresses multiples. Ce préjugé n'a jamais été réellement justifié (le RFC 791 mentionne explicitement la possibilité d'avoir plusieurs adresses IP par interface) mais il l'est encore moins maintenant, où l'existence de plusieurs adresses IP sur une interface est devenue banale (surtout pour IPv6). On note que HIP, cité plus haut, donnerait raison au préjugé, s'il était déployé massivement : l'identificateur serait en effet unique (par machine virtuelle).

En parlant de l'idée d'une adresse IP par machine, si une machine peut avoir plusieurs adresses IP, est-ce qu'une adresse IP peut être utilisée par plusieurs machines ? Cela mène à la notion d'identité d'une machine. Ce concept n'existe pas réellement dans les protocoles TCP/IP mais pas mal d'applications font comme si (section 3.2.4). Par exemple, une ACL sur un pare-feu, bloquant une adresse IP, signifie que l'administrateur du pare-feu considère que l'ennemi peut être identifié par son adresse IP, ce qui n'est pourtant pas toujours le cas.

Parmi les évolutions technologiques qui empêchent ce préjugé d'être exact : l'anycast (RFC 4786), ou bien certaines solutions de haute disponibilité. Des RFC comme le RFC 2101 ou le RFC 2775 discutent de cette question de l'unicité de l'adresse.

Plus ridicule mais néanmoins fréquente, l'idée que l'adresse IP d'une machine identifie sa position géographique (section 3.2.5). C'est clairement faux aujourd'hui (pensez aux tunnels, par exemple).

Plus subtile, l'idée que l'adresse IP a un rapport avec le routage (section 3.2.6). Par exemple, une application qui déduirait de la proximité de deux adresses la proximité des machines. Avec des protocoles comme Mobile IPv6 ou HIP (déjà cité), cette supposition serait complètement fausse. D'une manière générale, tout système de séparation de l'identificateur et du localisateur casserait cette idée. Dans les textes originels (IEN019 ou IEN023),l'adresse IP était présentée comme un localisateur, alors que TCP, par exemple, l'utilise comme identificateur. C'est là la source de cette confusion d'aujourd'hui.

Ces erreurs sur l'adressage sont fréquentes. La section 3.2.10 fournit une perspective plus large, en partant du RFC 1958, dont la section 4.1 avait été le premier texte à insister sur l'importance d'utiliser des noms plutôt que des adresses (celles-ci ayant une sémantique trop floue). Notre RFC 6250 réinsiste fortement sur ce point : c'est bien à tort que des API comme getaddrinfo() exposent les adresses IP aux applications. La plupart du temps, celles-ci ne devraient pas avoir accès à ces adresses, ce qui éliminerait la tentation de les utiliser de manière incorrecte. Ceci dit, le conseil du RFC 1958 n'est pas possible à suivre intégralement aujourd'hui : bien des machines IP (au hasard, mon téléphone portable) n'ont pas de FQDN à elles.

On l'a vu, le terme « applications », dans ce RFC 6250 est utilisé de manière souple, pour décrire tout ce qui se trouve au dessus de la couche 3. la section 3.3 aborde les problèmes spécifiques à une partie de ces « applications », la couche transport (couche 4). Quelles sont les erreurs courantes à propos de cette couche 4 ?

D'abord, un certain nombre d'acteurs de l'Internet croient qu'il est possible d'ajouter de nouveaux protocoles de transport, des concurrents des classiques TCP et UDP (section 3.2.1), tels que ceux enregistrés à l'IANA. C'était certainement le but originel de l'architecture de TCP/IP. Mais, aujourd'hui, ce n'est plus vrai. L'Internet s'est terriblement ossifié et les nouveaux protocoles de transport ont très peu de chances de passer à travers toutes les middleboxes mal fichues qui abondent sur le réseau. Souvent, on doit même tout tunneler au dessus d'HTTP. C'est au point où le RFC suggère même de ne pas hésiter à normaliser cette utilisation de HTTP (quelque chose que, traditionnellement, l'IETF avait toujours refusé de faire, au nom de la qualité technique des normes). XMPP le fait, par exemple, dans son XEP 0124. SIP n'a pas de méthode standard pour cela, et ça lui a parfois été reproché, alors que le système fermé Skype n'hésite pas à détourner HTTP. Un groupe de travail de l'IETF, HyBi, travaille sur un mécanisme générique d'utilisation de HTTP pour contourner ces middleboxes stupides.

Bref, le point le plus étroit du sablier, celui par lequel tout devait passer, et qui était IP dans l'architecture originale, est de plus en plus souvent TCP, voire HTTP. C'est parfois fait au nom de la sécurité (par des gens qui ne connaissent pas forcément ce sujet). L'IETF continue ses efforts pour casser cette dangereuse évolution mais, au cas où ces efforts ne seraient pas couronnés de succès, il faut se préparer à s'adapter.

En parlant de sécurité, quelles sont les idées reçues sur la sécurité (section 3.4) ? Elles sont évidemment nombreuses (et une analyse plus complète figure dans le RFC 3552). Par exemple, bien des applications se comportent encore comme si les paquets n'étaient jamais modifiés en route, à part pour quelques champs bien définis comme le TTL. Le NAT change malheureusement cette situation. On peut parfois restaurer le comportement correct avec des tunnels (RFC 4380) ou avec IPsec en mode transport (RFC 4301).

À défaut d'être respectés dans leur intégrité, les paquets sont-ils au moins privés (section 3.4.2) ? Pas davantage. Il a toujours été possible d'écouter les communications et pourtant on trouve toujours des protocoles et des applications qui s'obstinent à envoyer des mots de passe en clair. Là encore, IPsec, s'il était déployé, pourrait fournir une solution générique, ne nécessitant pas de changer les applications.

Autre erreur que font souvent les débutants en sécurité : croire que, puisqu'un paquet prétend venir de 198.51.100.66, alors c'est vrai (section 3.4.3). La vérité est qu'il est relativement facile de mettre une fausse adresse IP source (la plupart des lecteurs de mon blog le savent depuis longtemps mais on trouve pourtant régulièrement des articles qui parlent d'une attaque par déni de service en disant « elle vient de tel pays » simplement parce que les adresses IP source indiquent ce pays). Il existe des mécanismes techniques qui pourraient permettre d'avoir des adresses sûres, par exemples les adresses cryptographiques du RFC 3972.

En conclusion, que faut-il retenir de ce RFC ? La section 5 fournit les points essentiels :

  • Vu le nombre d'applications qui dépendent de TCP/IP pour des travaux critiques, tout changement dans le modèle de service ne devrait être fait qu'avec les plus extrêmes précautions.
  • Les invariants (les concepts essentiels sur lesquels on peut compter) devraient être mieux documentés, au lieu de dépendre du savoir informel des vieux sages.
  • Chaque couche devrait expliciter clairement le service qu'elle fournit aux couches supérieures, et le service qu'elle attend des couches inférieures.
  • Et il faudra de toute façon recommencer le travail de temps en temps, l'évolution étant inévitable.

Téléchargez le RFC 6250


L'article seul

RFC 6248: RFC 4148 and the IPPM Registry of Metrics are Obsolete

Date de publication du RFC : Avril 2011
Auteur(s) du RFC : A. Morton (AT&T Labs)
Pour information
Réalisé dans le cadre du groupe de travail IETF ippm
Première rédaction de cet article le 15 avril 2011


Le progrès, c'est aussi de savoir reconnaître quand une idée était mauvaise et qu'il vaut mieux l'abandonner. Ce court RFC prend ainsi acte de l'échec du registre des métriques lancé par le RFC 4148 et décide d'y renoncer.

Le groupe de travail IPPM est chargé notamment de développer des métriques (définitions rigoureuses d'une grandeur qu'on peut mesurer) comme le taux de perte des paquets (RFC 7680). Dans le cadre de ce travail, il avait semblé intéressant, avec le RFC 4148 de créer un registre IANA des métriques existantes. En fait, aucun logiciel n'a été développé pour l'utiliser, aucun utilisateur de ce registre n'a pu être identifié après des mois de recherche (fin 2010), et le registre était donc déjà de facto abandonné avant que notre RFC 6248 le reconnaisse et ne le decrète dépassé. Un exemple montrant l'inutilisation du registre ? Le fait qu'il contenait une faute de syntaxe qui a mis huit mois (depuis la parution du RFC 5644) avant d'être signalée ! Cette décision d'abandon explicite est nécessaire pour éviter d'accumuler dans les registres IANA un grand nombre d'informations qui ne sont plus maintenues.

Notre RFC rappelle d'abord quelles étaient les motivations qui avaient mené à la création du registre : la grande variabilité des définitions de métriques, d'autant plus que certaines étaient modifiées et/ou enrichies par des RFC ultérieurs comme le RFC 3432. Stocker ces variations dans un registre semblait une bonne idée sauf que, en pratique, la structure du registre n'avait pas permis de stocker toute l'information.

Le registre ne sera donc plus mis à jour (le dernier RFC à l'avoir fait avait été le RFC 6049) même s'il continue à être distribué par l'IANA mais avec un texte montrant sans ambiguité son statut.


Téléchargez le RFC 6248


L'article seul

RFC 6247: Moving the Undeployed TCP Extensions RFC1072, RFC1106, RFC1110, RFC1145, RFC1146, RFC1379, RFC1644 and RFC1693 to Historic Status

Date de publication du RFC : Mai 2011
Auteur(s) du RFC : L. Eggert (Nokia)
Pour information
Réalisé dans le cadre du groupe de travail IETF tcpm
Première rédaction de cet article le 17 mai 2011


Grand nettoyage à l'IETF, plus précisement au sein du groupe de travail TCP Maintenance and Minor Extensions. Huit RFC sur le protocole TCP sont rangés dans la cave de l'IETF, en étant reclassés comme « Document d'intérêt historique seulement ».

La famille de protocoles TCP/IP est bien vivante. La preuve, il y a régulièrement des protocoles ou des extensions aux protocoles qui apparaissent. Mais, pour que l'évolution fonctionne, il faut aussi que certains disparaissent. C'est ce qui vient d'arriver à huit extensions du protocole TCP, qui avaient été normalisées, avaient parfois suscité beaucoup d'espoirs, mais ont ensuite été des échecs. Peu de déploiements, des sérieux problèmes identifiés a posteriori, et voici ces extensions vouées au statut « Historique ». La plus récente, le RFC 1693, datait de 1994... Ces huit RFC perdent donc tout droit au nom de « norme ». Les raisons de ce reclassement figurent en général dans la section 5 du RFC 4614, qui avait fait un tour d'horizon complet et critique de tous les RFC sur TCP.

Parmi les RFC ainsi rabaissés, notons le RFC 1644, qui normalisait l'extension T/TCP qui semblait à une époque pouvoir fournir un TCP léger et rapide, mais qui a montré de sérieuses failles de sécurité à l'usage.

Conséquence pour l'IANA, certaines options enregistrées dans le registre des options TCP, comme les options 6 et 7, du RFC 1072, sont désormais marquées comme « dépassées ».


Téléchargez le RFC 6247


L'article seul

RFC 6241: Network Configuration Protocol (NETCONF)

Date de publication du RFC : Juin 2011
Auteur(s) du RFC : R. Enns (Juniper Networks), M. Bjorklund (Tail-f Systems), J. Schoenwaelder (Jacobs University), A. Bierman (Brocade)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF netconf
Première rédaction de cet article le 1 juillet 2011


Netconf est un protocole de configuration de matériel réseau (typiquement des routeurs ou des commutateurs). Ce RFC est la nouvelle version publiée par le groupe de travail IETF sur Netconf. (La precédente était le RFC 4741.)

Si on doit gérer un seul routeur, le faire à la main est raisonnable. Mais, si on doit en gérer des dizaines ou des centaines, cela devient impossible sans automatisation. Il existe depuis longtemps de nombreux outils pour gérer un grand nombre d'équipements réseaux, Rancid étant le plus connu. (L'excellent article de Joe Abley, Managing IP Networks with Free Software en donne un bon aperçu. Le RFC 3535 rend compte d'un atelier de l'IAB qui a discuté de ces questions en 2002.) Netconf vise à rendre l'écriture de ces outils plus simple.

Netconf spécifie donc un protocole de RPC permettant à un gérant (manager) de modifier la configuration de l'équipement (device) en lui envoyant du XML.

Le contenu exact de ce document XML n'est pas entièrement spécifié par Netconf car il dépend de l'équipement configuré (la section 1.2 de notre RFC explique ce point). Un langage de description des modèles, Yang (RFC 6020), existe pour décrire les possibilités.

Extrait du RFC, voici un exemple (hypothétique) où on fixe à 1500 octets la MTU de l'interface réseau eth0 :


    <rpc message-id="101"
          xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
       <edit-config>
         <target>
           <running/>
         </target>
         <config>
           <top xmlns="http://example.com/schema/1.2/config">
             <interface>
               <name>eth0</name>
               <mtu>1500</mtu>
             </interface>
           </top>
         </config>
       </edit-config>
     </rpc>

Il est difficile de ne pas penser à l'acronyme NIH en lisant ce RFC. Netconf définit un protocole de RPC alors qu'il existe déjà SOAP et XML-RPC, Netconf définit en section 6, un mécanisme d'extraction de sous-arbres XML alors que XPath existe déjà...

Quels sont les changements depuis le RFC original ? L'annexe F les résume. Pas de grand changement, des bogues signalées contre le RFC 4741 et quelques ajouts : un malformed-message ajouté aux messages d'erreur possibles, une option remove ajoutée aux opérations possibles, l'ajout de la notion de « nom d'utilisateur », le schéma XSD de modélisation des opérations remplacé par un module YANG, etc.

À noter qu'un Wiki, http://trac.tools.ietf.org/wg/netconf/trac/wiki, fournit plein d'informations sur Netconf, notamment sur les mises en œuvre existantes du protocole, dont certaines en logiciel libre. Parmi les autres, les routeurs Juniper peuvent déjà être configurés avec Netconf (et une bibliothèque Java est fournie). Ça marche aussi sur un Cisco.

NOtez qu'il existe aussi une variante REST, RESTCONF, normalisée dans le RFC 8040.


Téléchargez le RFC 6241


L'article seul

RFC 6238: TOTP: Time-Based One-Time Password Algorithm

Date de publication du RFC : Mai 2011
Auteur(s) du RFC : D. M'Raihi (Verisign), S. Machani (Diversinet), M. Pei (Symantec), J. Rydell (Portwise)
Pour information
Première rédaction de cet article le 7 juin 2019


Ce RFC documente le protocole TOTP, utilisé pour bâtir des systèmes d'authentification à deux facteurs. TOTP est une amélioration du protocole HOTP du RFC 4226, remplaçant le simple compteur par l'heure. Ainsi, il n'est plus nécessaire que les deux machines mémorisent la même séquence.

Mais d'abord, qu'est-ce que l'authentification à deux facteurs ? Imaginons que vous vous connectiez à une interface Web, d'un établissement financier comme Paymium ou PayPal, d'un bureau d'enregistrement de noms de domaines, ou de tout autre service important. La méthode la plus courante d'authentification est le couple {identificateur, mot de passe}. Elle est simple, et facilement expliquable aux utilisat·rice·eur·s. Mais elle pose des problèmes de sécurité : le mot de passe choisi est souvent trop faible, et les utilisat·rice·eur·s le communiquent parfois à des tiers, par exemple suite à une attaque par ingéniérie sociale. On dit traditionnellement qu'il existe trois voies d'authentification : ce qu'on est, ce qu'on a, ou bien ce qu'on sait. La biométrie utilise la première voie, et le mot de passe la troisième. TOTP, décrit dans ce RFC, va permettre d'utiliser la deuxième voie. Mais on n'utilise pas TOTP seul. Le principe de l'authentification à deux facteurs est d'avoir… deux facteurs. Par exemple, sur le Web, le cas le plus courant est un mot de passe classique, plus un code produit par TOTP. Les deux facteurs doivent évidemment être indépendants. Si on se connecte à sa banque depuis son ordiphone et que le générateur TOTP est sur le même ordiphone, il n'y a pas réellement d'indépendance (si le téléphone est volé ou piraté, les deux facteurs peuvent être compromis en même temps). Une solution est d'avoir mot de passe sur l'ordinateur et générateur TOTP sur l'ordiphone, ou bien mot de passe sur l'ordiphone et générateur TOTP sur un dispositif auxiliaire, genre YubiKey.

Pour prendre un exemple récent, lors de l'attaque de 2018 contre de nombreux noms de domaine moyen-orientaux, l'absence d'authentification à deux facteurs avait certainement joué, rendant relativement facile le piratage en masse.

Mais comment fonctionne TOTP ? L'idée de base est qu'on part d'un secret partagé entre les deux parties, le client et le serveur, secret qui n'est pas envoyé pour l'authentification (et donc moins vulnérable qu'un mot de passe). Ce secret sert à générer un code à usage limité dans le temps (donc, si vous l'avez envoyé au pirate par erreur, ce n'est pas forcément grave). Dans l'ancien protocole HOTP (RFC 4226), la génération du code était contrôlée par le nombre de connexions au service (et il fallait donc que les deux parties communicantes gardent trace du nombre de connexions, et soient bien synchrones sur ce point), dans le nouveau protocole TOTP, objet de ce RFC, c'est l'heure qui gouverne le code généré (et les deux parties doivent donc avoir des horloges à peu près correctes).

Voici ce que voit l'utilisateur avec le logiciel andOTP sur Android. On voit la liste des comptes de l'utilisateur (j'ai masqué les identifiants de l'utilisateur, bien qu'ils ne soient pas totalement secrets), et le code courant (je l'ai partiellement masqué mais notez que ce n'est pas nécessaire : ils ne sont utilisables que pendant le bon intervalle). andotp.png

Un petit rappel sur HOTP : HOTP, normalisé dans le RFC 4226, le code à usage unique était généré en condensant avec SHA-1 la concaténation d'un secret partagé et d'un compteur, chaque partie incrémentant le compteur lors d'une connexion. Il y a donc un risque de désynchronisation si une partie incrémente le compteur alors que l'autre a eu un hoquet et a raté cette incrémentation (RFC 4226, section 7.4).

TOTP, au contraire, utilise un condensat du secret partagé et de l'heure. Il est en effet plus facile d'avoir deux machines ayant une horloge à peu près correcte que d'avoir deux machines restant en accord sur un compteur partagé. (D'autre part, TOTP peut utiliser SHA-2 et plus seulement SHA-1.)

La section 3 du RFC résume quel était le cahier des charges de TOTP : dépendance vis-à-vis de l'heure (plus précisement du temps Unix), avec un intervalle de validité partagé, dépendance vis-à-vis d'un secret partagé entre les deux parties (et avec personne d'autre), secrets qui doivent être bien gardés par les deux parties.

L'algorithme exact (j'ai beaucoup simplifié ici) est en section 4. Un code TOTP est la condensation avec SHA-2 de la concaténation du secret partagé et de l'heure, plus exactement du nombre de secondes depuis l'epoch, divisée par l'intervalle. Ainsi, pour un même couple client/serveur, deux demandes de code très rapprochées donneront le même code, contrairement à HOTP où les codes n'étaient pas réutilisés. Notez que les valeurs de l'epoch et de l'intervalle ne sont pas spécifiées dans le protocole, elle sont communiquées en dehors du protocole. On ne peut donc pas utiliser TOTP seul et espérer que cela va marcher, il faut ajouter des informations. Cela peut se faire via des cadres de référence comme OATH ou bien dans l'URI fabriqué par le serveur (par exemple otpauth://totp/ACME%20Co:john.doe@example.com?secret=HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ&issuer=ACME%20Co&period=60 pour mettre un intervalle à soixantes secondes, le format exact de ces URI est documenté par Google.)

La section 5, sur la sécurité, est évidement très détaillée. Elle rappelle par exemple que la transmission du secret initial doit être faite sur un canal sécurisé, par exemple avec TLS. D'autre part, ce secret, cette clé, doit être stockée de manière sûre. Si on utilise un ordiphone pour générer les codes, ce qui est fréquent, il faut tenir compte du fait qu'un ordiphone se perd ou se vole facilement. Il ne doit pas divulguer le secret simplement parce qu'un voleur a l'appareil en main. Le RFC recommande que le secret soit chiffré, et de manière à ce que la possession physique de la machine ne permettre pas de le déchiffrer. (Dans andOTP, la base de données est chiffrée avec un mot de passe choisi par l'utilisateur. À l'usage, il est assez pénible de taper ce mot de passe - forcément long et compliqué - très souvent, mais c'est le prix de la sécurité.)

TOTP repose sur l'heure et non seulement les deux horloges ne sont pas parfaitement synchrones mais en outre les délais de transmission du réseau ajoutent une incertitude. On pourrait mettre un intervalle important (la valeur recommandée est de 30 secondes) pour limiter le risque de rejet d'un code mais, d'une part, cela augmente le risque qu'un code volé puisse être réutilisé (il reste valable pendant tout l'intervalle) et d'autre part on peut jouer de malchance, par exemple si un code est généré juste avant la fin d'un intervalle. Le RFC recommande donc d'accepter les codes de l'intervalle précédent l'intervalle courant.

L'annexe A du RFC contient une mise en œuvre de TOTP en Java (avec au moins une bogue).

Pour envoyer, lors de l'enrôlement initial, le secret partagé qui servira de base au calcul, la méthode la plus courante est que le serveur auprès duquel on s'authentifiera la génère, puis l'affiche sous forme d'un QR-code à lire, ou sous une forme texte. Voilà comment ça se passe chez le bureau d'enregistrement Gandi. On active l'authentification à deux facteurs : gandi-activate-2fa.png

Puis on fait lire à son ordiphone le secret (j'ai masqué QR-code et secret en texte, puisqu'ils doivent rester secrets) : gandi-qrcode-2fa.png)

Bien d'autres services sur le Web acceptent l'authentification à deux facteurs. C'est le cas entre autres de GitLab (et donc de l'excellent service Framagit) dans la rubrique « Compte », des places de marché Bitcoin comme Kraken (qui le documente très bien) ou Paymium (qui, stupidement, ne le documente que comme imposant l'utilisation de Google Authenticator, ce qui est faux, ça a marché avec andOTP, remarquez, Mastodon commet presque la même faute), des registres comme le RIPE (qui documente également très bien), etc. En revanche, les banques, comme le Crédit mutuel ou la Banque postale, imposent un outil privateur, sous forme d'une application fermée, exigeant trop de permissions, et contenant des pisteurs. (Alors que le but des normes comme TOTP est justement de permettre le libre choix du logiciel. Mais un tel mépris du client est classique chez les banques.)

Côté client, j'ai choisi andOTP sur mon ordiphone mais il y a aussi Aegis, FreeOTP, Google Authenticator, etc. Si vous êtes fana de la ligne de commande, vous pouvez même directement utiliser l'outil oathtool présenté plus loin, comme décrit dans cet article (avec un astucieux script pour analyser les URI otpauth:). Il y a aussi des mises en œuvre privatrices dans du matériel spécialisé comme la YubiKey (à partir de 35 € à l'heure actuelle.)

TOTP est à l'origine issu du projet OATH (ne pas confondre avec OAuth.) Une de leurs initiatives est le développement d'outils logiciels pour faciliter le déploiement de techniques d'authentification fortes. C'est par exemple le cas de l'outil libre oathtool et des autres logiciels du OATH Toolkit. Voici une utilisation sur une Debian (le paramètre à la fin est la clé, le secret partagé) :

% oathtool --totp=sha256 123456789abcde
839425
  

Si on le lance plusieurs fois de suite, il affichera le même code, jusqu'à la fin de l'intervalle en cours :

% oathtool --totp=sha256 123456789abcde
839425
% oathtool --totp=sha256 123456789abcde
839425
% oathtool --totp=sha256 123456789abcde
839425
% oathtool --totp=sha256 123456789abcde
963302
   

Par défaut, oathtool utilise l'horloge courante. On peut lui indiquer une autre heure (cf. sa documentation mais attention à ne pas copier/coller les exemples, ça ne marchera pas, les tirets ayant été remplacés par des caractères typographiquement plus jolis, menant à un « hex decoding of secret key failed » incompréhensible). Essayons avec les vecteurs de test indiqués dans l'annexe B de notre RFC :

 
% oathtool --totp=sha256 --digits=8 3132333435363738393031323334353637383930313233343536373839303132 
62307269

% oathtool --totp=sha256 --digits=8 --now "1970-01-01 00:00:59 UTC"  3132333435363738393031323334353637383930313233343536373839303132
46119246

(Et, oui, les valeurs de la clé secrète indiquées dans le RFC sont fausses.)

Notez aussi que oathtool fait par défaut du HOTP (ici, au démarrage, puis au bout de cinq connexions) :

% oathtool 123456789abcde           
725666

% oathtool --counter=5 123456789abcde
030068
   

Pour configurer un serveur ssh avec TOTP et l'outil de gestion de configuration Salt, vous pouvez utiliser la recette de Feth Arezki.

Si on veut déveloper des services utilisant TOTP, il existe plein d'autres mises en œuvre comme ROTP pour Ruby, onetimepass ou otpauth pour Python, etc. Pour apprendre à utiliser TOTP depuis Python, j'ai apprécié cette transcription de session.

Il ne faut pas croire que l'authentification à deux facteurs est une solution magique. Comme toujours en sécurité, elle vient avec ses propres inconvénients. (Ils sont très bien expliqués dans l'excellent article « Before You Turn On Two-Factor Authentication… ».) Le risque le plus sérieux est probablement le risque de s'« enfermer dehors » : si on perd l'ordiphone ou la clé physique, ou bien s'il tombe en panne, tout est fichu, on ne peut plus se connecter sur aucun des services où on a activé l'authentification à deux facteurs. Une seule solution : les sauvegardes. Avec andOTP, par exemple, on peut exporter la liste des comptes et leurs secrets dans un fichier en clair (ce qui est évidemment déconseillé), chiffré avec AES et le mot de passe d'andOTP, ou bien chiffré avec PGP, la solution la plus pratique. J'ai installé openKeychain sur mon Android, récupéré ma clé PGP et tout marche, les sauvegardes, une fois exportées, sont copiées sur d'autres machines. Si je déchiffre et regarde en quoi consiste la sauvegarde, on y trouve un fichier JSON contenant les informations dont nous avons déjà parlé (la clé secrète), le type d'algorithme, ici TOTP, l'algorithme de condensation, l'intervalle (period), etc :

   {
    "secret": "K...",
    "label": "framagit.org - framagit.org:stephane+frama@bortzmeyer.org",
    "digits": 6,
    "type": "TOTP",
    "algorithm": "SHA1",
    "thumbnail": "Default",
    "last_used": 1559836187528,
    "period": 30,
    "tags": []
  }
  

Si on veut utiliser ces sauvegardes depuis l'outil en ligne de commande présentée plus haut, il faut prendre note de l'algorithme de condensation (ici SHA-1), du nombre de chiffres (ici 6) et de la clé (qui est encodée en base32) :

% oathtool --totp=sha1 --digits 6 --base32 K...
  

Sinon, je recommande cet article en anglais très détaillé : « Understanding TOTP Two-Factor Authentication: An ELI5 », avec une mise en œuvre en Python.


Téléchargez le RFC 6238


L'article seul

RFC 6235: IP Flow Anonymization Support

Date de publication du RFC : Mai 2011
Auteur(s) du RFC : E. Boschi, B. Trammell (ETH Zurich)
Expérimental
Réalisé dans le cadre du groupe de travail IETF ipfix
Première rédaction de cet article le 14 mai 2011


La question de la protection de la vie privée sur l'Internet est, à juste titre, une question très sensible et qui a déjà agité beaucoup d'électrons sur les blogs et autres sites Web, d'autant plus que de grosses et puissantes entreprises, comme Facebook et Google sont à l'œuvre pour réduire cette vie privée à pas grand'chose. Parmi toutes les problèmes pratiques que pose la protection de la vie privée, ce RFC se limite à celui des fichiers de trafic réseau, contenant des données sensibles et qu'on souhaite anonymiser. Le RFC se concentre sur le format IPFIX mais la plupart des problèmes exposés et des recommandations faites peuvent s'appliquer à d'autres formats comme les journaux de connexion ou comme les fichiers pcap. Un RFC utile, donc, pour tous les techniciens qui se soucient de la vie privée de leurs utilisateurs (et qui n'ont donc pas été embauchés par Facebook).

« Anonymiser » n'est pas un bon terme (mais je reprends celui du RFC). Tout le problème est qu'en effet les données ne sont pas réellement anonymes après cette opération : il est devenu simplement plus difficile de les relier à une personne ou une organisation donnée. Mais ce n'est pas impossible : de nombreux travaux de recherche ont montré qu'on pouvait reconstituer une bonne part des données manquantes dans un fichier « anonymisé ». Un exemple est l'excellent article de Bruce Schneier : « Why 'Anonymous' Data Sometimes Isn't » qui montre très bien à quel niveau de perfectionnement les outils de « désanonymisation » sont parvenus.

Avant d'attaquer le RFC lui-même, commençons par un exemple simple. Supposons qu'on ait enregistré le trafic réseau en un endroit donné et qu'on récupère donc un fichier pcap. On peut le dire avec divers outils comme tcpdump et voici un résultat typique :

% tcpdump -n -v -r MYFILE.pcap
... 
15:00:24.451549 IP (tos 0x0, ttl 64, id 17621, offset 0, flags [DF], proto TCP (6), length 1059)
    192.168.2.1.41949 > 193.159.160.51.80: Flags [P.], cksum 0xd268 (correct), seq 1029:2036, ack 247, win 108, options [nop,nop,TS val 2792071 ecr 1944126014], length 1007

On peut y voir que 192.168.2.1 interrogeait le serveur HTTP 193.159.160.51 (un des serveurs d'Akamai, qui héberge www.wired.com, le site cité précedemment). On sait que c'était de l'HTTP par le port de destination (80) mais on aurait aussi pu le déduire en examinant les données (que tcpdump n'affiche pas, mais qui sont bien dans le fichier pcap et qu'un outil comme Wireshark peut afficher de manière très lisible ; ces mêmes données auraient pu nous dire qu'elle était la page Web exacte qui avait été consultée). Autre exemple, le journal d'un serveur HTTP où on trouvera des choses comme :

2001:db8:33::dead:beef:1 - - [10/May/2011:19:49:57 +0200] "GET /aventures-jules.html HTTP/1.1" 200 5306 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1" www.bortzmeyer.org

qui nous indique que la machine d'adresse IP 2001:db8:33::dead:beef:1 a consulté la page aventures-jules.html de ce serveur. Ces informations sont-elles sensibles ? D'abord et avant tout sont-elles nominatives, ce qui, dans la loi Informatique & Libertés ne se limite pas aux informations comportant le nom d'une personne physique, mais inclut celles qui permettent de retrouver facilement cette personne (comme le « numéro de Sécu »). Ici, l'adresse IP source n'est pas la vraie (les données ci-dessus ont été anonymisées) mais, si elle l'était, elle permettrait assez facilement de retrouver l'auteur de cette visite à Wired et donc il est tout à fait justifié de considérer l'adresse IP comme nominative.

Et c'est embêtant pour les chercheurs et les analystes. Car de telles données de connexion sont très utiles et de nombreux articles scientifiques intéressants ont été produits à partir de données comme celles-ci, collectées dans des grandes opérations comme le DITL. De même, les opérateurs réseaux ont souvent besoin d'analyser ces données pour mieux comprendre ce qui se passe dans leur réseau et pour l'améliorer. Enfin, l'étudiant, le curieux, le programmeur qui met au point un nouvel outil d'analyse ont besoin de telles données (on trouve par exemple plein de fichiers pcap sur pcapr.net). Mais transmettre ces données, les rendre publiques, les envoyer dans un pays qui n'a aucune législation de protection de la vie privée, comme les États-Unis, pose des problèmes éthiques et légaux considérables.

Une façon courante de concilier ces deux demandes est d'anonymiser les données. Par exemple, si on supprime l'adresse IP, on a enlevé la donnée la plus sensible, tout en permettant encore plusieurs analyses (par exemple sur la taille des paquets, sur les ports - donc, souvent, les services - les plus fréquents, etc. Mais en faisant cela, on a interdit certaines analyses, comme par exemple la répartition du trafic (tout le monde consomme t-il pareil, ou bien certains gros consommateurs sont-ils « responsables » de la majorité du trafic ?) Bref, l'anonymisation sera toujours un compromis : plus on retire de données et mieux on a anonymisé. Et plus les données perdent de leur intérêt... Il faudra donc prendre une décision en fonction des risques et des bénéfices. L'IETF n'a évidemment pas le pouvoir de prendre une telle décision mais ce RFC pose au moins les bases techniques nécessaires pour comprendre les choix. Il insiste notamment sur les techniques de désanonymisation, qui font que certaines techniques d'anonymisation ne protègent guère la vie privée.

Pour prendre l'exemple des requêtes DNS, si on peut croire que l'adresse IP source (qui est celle du résolveur, par celle du client final) n'est pas une information bien sensible, il ne faut pas oublier que le contenu de la requête (le QNAME, pour Query NAME) peut en dire beaucoup. Par exemple, certains réseaux sociaux utilisent un sous-domaine qui a le nom de l'utilisateur.

Passons au RFC maintenant. Il a deux parts, une première générale sur les techniques d'anonymisation, leurs forces et leurs faiblesses et une seconde spécifique au format IPFIX (RFC 7011). La première partie intéresse tous les programmeurs et récolteurs de données. Le fait d'avoir un format standard, IPFIX, pour les échanges d'information sur les flots de données (pcap - un standard de fait - est limité aux paquets individuels, une information de plus bas niveau) est évidemment un avantage pour tous ceux qui font circuler de l'information mais cela augmente aussi les risques de divulgation. D'où l'importance particulière de ce problème pour IPFIX.

Commençons par une définition rigoureuse de l'anonymisation (qu'il faudrait normalement écrire entre guillemets à chaque fois, tellement on est loin du vrai anonymat). La section 1 la définit comme la suppression ou la transformation d'une information qui, sans cette suppression ou cette transformation, pourrait permettre d'identifier la personne ou de l'organisation à l'origine d'une communication. Il ne faut pas utiliser l'anonymisation seule (elle a des tas de limites, notamment en raison de la puissance des techniques de désanonymisation) mais elle peut être un outil utile dans un arsenal de mesures de protection de la vie privée.

La section 1.4 rappelle d'ailleurs que ce RFC a le statut « Expérimental » car il considère que toutes les techniques d'anonymisation sont encore peu fiables (voir Burkhart, M., Schatzmann, D., Trammell, B., et E. Boschi, « The Role of Network Trace Anonymization Under Attack »).

La première partie de ce RFC revient sur ces techniques, d'une manière indépendante du format des données (pcap, IPFIX, etc). D'abord, la section 3 classifie les techniques d'anonymisation. Toutes ont en commun de chercher à empêcher la traçabilité, tout en préservant les informations utiles à l'analyse. Elles fonctionnent par mise en correspondance de l'espace des vrais valeurs vers un autre espace, « anonyme », suivant une fonction bien définie. La mise en correspondance est récupérable si on peut inverser cette fonction (ce qu'on ne souhaite évidemment pas, pour l'anonymisation) et commensurable (ou mesurable) si les deux espaces ont la même taille (préservant ainsi toutes les analyses qui cherchent à compter, par exemple le nombre d'adresses IP distinctes). Ainsi, une fonction de généralisation qui ne garderait que les N premiers bits de l'adresse IP (pour empêcher l'identification d'un individu) ne serait pas commensurable (plusieurs adresses IP seraient mises en correspondance avec un préfixe unique). Lorsque la fonction est commensurable, la technique d'anonymisation est appelée une substitution (je change chaque adresse IP par une autre). Notez que la substitution est vulnérable aux attaques par force brute, même si l'attaquant ignore la fonction utilisée, s'il peut injecter le trafic qu'il veut et observer les résultats (une variante des attaques « par dictionnaire »).

L'anonymisation la plus radicale est de retirer complètement un champ des données (méthode du feutre noir, le black-marker, dit le RFC, du nom de l'outil des censeurs du courrier d'autrefois). Ni récupérable, ni commensurable, elle offre le maximum de sécurité mais peut faire perdre des informations précieuses.

Voyons maintenant chaque champ un à un. La section 4, qui détaille les techniques adaptées à chaque champ, commence évidemment par les adresses IP car c'est le champ le plus « nominatif ». Lorsqu'on parle d'anonymisation, on pense tout de suite à celle des adresses IP, et à juste titre (section 4.1). Le problème de leur anonymisation n'est pas simple. Par exemple, une adresse IP est structurée. Même si on supprime les N derniers bits, ceux qui restent, le préfixe, identifient encore un FAI ou une entreprise et donne donc des informations. Il y a quatre moyens d'anonymiser une adresse IP (sans compter évidemment le feutre noir) :

  • La troncation, qui supprime les N derniers bits de l'adresse (pour le programmeur, la troncation est un AND avec un nombre de M-N uns et N zéros). C'est ce que permet un logiciel comme Squid avec sa directive client_netmask, qui permet de préserver la vie privée des utilisateurs du cache en ne gardant dans le journal que le préfixe de leur adresse IP. La troncation est une généralisation (elle ne conserve pas le nombre d'adresses IP.)
  • La troncation inverse consiste au contraire à supprimer les N premiers bits. Ainsi, l'organisme (FAI ou entreprise) est masqué. C'est aussi une généralisation et deux machines sans lien entre elles (par exemple 192.0.2.57 et 203.0.113.57) vont être confondues (ici, si on supprime les 24 premiers bits). Attention, si le réseau sur lequel a été fait la collecte est connu, il n'est pas difficile de retrouver le préfixe des adresses de ce réseau.
  • La permutation consiste à remplacer chaque adresse IP par une autre. Elle conserve donc le nombre d'adresses IP (mais pas la structure des adresses : deux machines du même réseau local peuvent se retrouver très « loin » l'une de l'autre). La façon la plus fréquente de la réaliser est via une fonction de hachage de l'adresse IP. Attention, si cette fonction est connue, une attaque par force brute (tester toutes les adresses) devient possible, surtout en IPv4. Il est donc recommandé d'introduire un élément secret (par exemple un mot de passe concaténé à chaque adresse avant le hachage).
  • La pseudonymisation qui préserve le préfixe est le quatrième moyen. Elle garde les N premiers bits et fait une permutation sur les M derniers. Cela permet de garder l'information sur la « proximité » de deux adresses. Comme à chaque fois, garder de l'information permet de faire certaines études... mais augmente le risque de désanonymisation.

Les adresses MAC identifient également une machine. Elles ne sont pas toujours présentes dans les données collectées (si le point de capture est sur le réseau d'un gros opérateur, les adresses MAC de la source et de la destination ne sont pas disponibles) mais on peut les trouver dans des captures faites localement. Elles peuvent aussi apparaître comme partie d'un identificateur de couches hautes, par exemple dans certaines adresses IPv6 (cf. section 2.5.1 du RFC 4291, et RFC 8981 pour une solution). Donc, il faut également anonymiser ces adresses (section 4.2). Comme les adresses IP, elles ont une structure, mais plus simple (les 24 ou 40 premiers bits indiquent le constructeur). Comme pour les adresses IP, on peut utiliser la troncation (on ne garde typiquement que les bits qui identifient le constructeur), la troncation inverse, la permutation et la pseudonymisation structurée.

Les numéros de port et de protocole de couche 4 n'identifient pas une entité du monde réel (comme une personne) mais peuvent servir à classer les machines (par exemple, le choix des ports sources permet souvent d'identifier le système d'exploitation, cf. RFC 6056). Ils méritent donc parfois une anonymisation (section 4.5) par exemple par permutation. Le RFC ne le mentionne pas, mais il n'est pas sûr qu'une technique d'anonymisation, qu'elle qu'elle soit, puisse fonctionner avec la distribution typique des protocoles : le plus répandu sera forcément TCP (numéro 6).

Les traces de trafic réseau contiennent souvent des nombres (collectivement appelés compteurs) qui peuvent révéler des choses sur leurs émetteurs (section 4.4). On peut donc les anonymiser en diminuant leur précision ou en les quantifiant, c'est-à-dire en les répartissant dans un petit nombre d'intervalles (les corbeilles ou bin dans le texte original du RFC) et en ne gardant qu'une valeur par intervalle.

Plus étonnant, les estampilles temporelles que contiennent les traces (date de passage du paquet, dates de début et de fin du flot) peuvent être également indiscrètes (voir Murdoch, S. et P. Zielinski, « Sampled Traffic Analysis by Internet-Exchange-Level Adversaries »). Par exemple, le séquencement des paquets peut permettre d'identifier une activité (une communication téléphonique n'aura pas du tout la même répartition temporelle des paquets qu'un téléchargement donc, même sans DPI, on pourra identifier le type de trafic). On peut donc essayer d'anonymiser les indications temporelles mais la plupart des méthodes disponibles, à part bien sûr le feutre noir, sont assez faibles contre la désanonymisation (section 4.3). On peut diminuer la résolution des temps (comme on a fait pour les compteurs, par exemple arrondir à la seconde la plus proche), on peut utiliser l'énumération (méthode qui remplace chaque estampille temporelle par un chiffre croissant : elle préserve l'ordre des événements, qui peut être important mais pas les écarts, ce qui interdit de mesurer des grandeurs comme la gigue), etc.

Une fois qu'on a anonymisé les données, il faut indiquer au destinataire comment on l'a fait, pour qu'il puisse faire ses analyses (section 5). Par exemple, si les adresses IP ont été tronquées, le destinataire ne doit pas tenter d'étudier des distributions de trafic par machine, puisque plusieurs machines sont désormais regroupées dans le même préfixe. Il faudra donc indiquer si l'anonymisation était stable ou pas (la stabilité est la propriété de mise en correspondance d'une valeur de départ avec la même valeur d'arrivée ; une anonymisation instable, au contraire, peut diriger vers une autre valeur d'arrivée après un certain temps). Typiquement, un jeu de données est stable, sauf indication contraire, mais deux jeux de données peuvent ne pas l'être entre eux, donc il vaut toujours mieux l'indiquer explicitement.

S'il y a eu troncation, il faut évidemment indiquer la longueur qui a été conservée. S'il y a eu quantification, il faut donner la liste des valeurs et leurs intervalles. S'il y a eu permutation, il ne faut pas donner la fonction utilisée (ou alors, si une clé a été ajoutée, donner la fonction mais sans la clé), afin d'éviter les attaques par dictionnaire (traduire des valeurs et regarder le résultat obtenu).

L'anonymisation soulève d'autres questions de sécurité, décrites en section 9. Elle enfonce le clou que l'anonymisation n'est jamais parfaite (sauf à effacer toutes les données). Elle rappelle que l'anonymisation ne remplace pas la confidentialité. Si des données sensibles sont exportées vers un tiers de confiance, le chiffrement sur le trajet reste nécessaire, même si les données sont anonymisées.

Ici commencent maintenant les questions spécifiques à IPFIX. Si vous ne pratiquez pas ce format, vous pouvez décider d'arrêter là. Sinon, la section 1.1 offre un utile rappel des RFC 5470, RFC 5101 et RFC 7012. IPFIX permet d'envoyer des tuples TLV dont la sémantique est décrite dans un gabarit (Template). Plusieurs gabarits standards figurent dans le registre décrit par le RFC 7012.

La section 6 décrit comment représenter les données anonymisées et les méta-informations (celles de la section 5 sur le mécanisme d'anonymisation) dans un flow IPFIX. Les données effacées par le feutre noir représentent le cas le plus simple : on ne les met pas du tout dans le flot. Pour les autres, il faut ajouter au flot un Anonymization Options Template qui décrira les fonctions d'anonymisation. Les détails de ce gabarit figurent en section 6.1 et 6.2. Par exemple, un champ anonymizationTechnique va indiquer l'absence d'anonymisation s'il vaut 1, la troncation (ou la dégradation de la précision, qui est à peu près la même chose) s'il vaut 2, l'énumération s'il vaut 4, etc (des exemples plus complets figurent en section 8).

Ces considérations d'encodage ont été inscrites dans les registres IANA d'IPFIX. anonymizationTechnique, par exemple, est identifié par le nombre 286.

L'anonymisation est typiquement effectuée dans un relais IPFIX (Mediator), en général situé à la frontière administrative du domaine (on n'anonymise pas si les données restent dans l'organisation d'origine). Attention : outre les données proprement dites, le flot contient souvent des méta-informations sur le processus de collecte qui peuvent si on ne prend pas soin de les modifier, casser en partie ou totalement l'anonymisation. Ainsi (section 7.2.3), le temps auquel a été fait l'observation peut permettre de retrouver les estampilles temporelles, même brouillées. L'identité du réseau où a été fait la mesure permet de retrouver une partie de l'adresse IP, même en cas de troncation inverse (cette identité a la même taille qu'une adresse IPv4 et il peut donc être tentant d'utiliser une adresse du réseau local comme identité).

Plus rigolo, la section 7.2.5 recommande de se méfier des adresses IP « spéciales » (RFC 6890). Ces adresses sont en effet souvent utilisées à des fins bien connues, qui font qu'on peut les retrouver, même anonymisées, en examinant leur activité. Cela fournit alors un point de départ au travail du désanonymisateur. Le RFC recommande donc d'exclure ces adresses des données exportées.

Les mises en œuvre d'IPFIX permettent-elles aujourd'hui cette anonymisation ? Je ne crois pas mais, en dehors du monde IPFIX, il existe un grand nombre d'outils d'anonymisation. Citons :


Téléchargez le RFC 6235


L'article seul

RFC 6234: US Secure Hash Algorithms (SHA and SHA based HMAC and HKDF)

Date de publication du RFC : Mai 2011
Auteur(s) du RFC : Donald Eastlake (Huawei), Tony Hansen (AT&T Labs)
Pour information
Première rédaction de cet article le 7 mai 2011


Ce long RFC (127 pages, dont la majorité est composé de code source C) est la mise à disposition de la communauté IETF du code de FIPS 180-2, décrivant les algorithmes de cryptographie de la famille SHA-2. Il remplace le RFC 4634.

Cette famille de fonctions de hachage cryptographiques normalisée par le NIST (et donc standard officiel aux États-Unis) a vocation à remplacer l'ancien SHA-1 (RFC 3174). Elle comprend SHA-224 (également décrit dans le RFC 3874), SHA-256, SHA-384 et SHA-512. Tous ont le même principe (section 1) : un document de longueur quelconque est transformé en un condensat cryptographique de longueur fixe (le nom de l'algorithme indique le nombre de bits du condensat), de telle manière qu'il doit extrêmement difficile de fabriquer un document ayant le même condensat qu'un document donné (ou même de fabriquer deux documents ayant le même condensat).

Notre RFC décrit également leur utilisation en HMAC (cf. RFC 2104), et en HKDF (HMAC-based Key Derivation Function, cf. RFC 5869). L'essentiel du RFC est tiré directement de la norme officielle et les assertions sur la sécurité de SHA-2 viennent donc directement du NIST et pas des éditeurs du RFC.

Les sections 2 à 7 du RFC résument le fonctionnement de ces algorithmes, et la section 8 est le code source C les mettant en œuvre.

La licence de ce code source figure dans le fichier sha.h, listé en section 8.1.1. C'est une licence BSD-3 (sans la clause de publicité), qui permet tout usage, commercial ou non, ainsi que toute modification et redistribution. Elle est donc adaptée au logiciel libre.

Comme copier/coller le code source depuis le RFC en éliminant les en-têtes et pieds de page n'est pas pratique, on peut récupérer une archive « propre » en http://www.pothole.com/~dee3/source/sha.tar. Il y en a plein d'autres mises en œuvre de SHA décrites en http://en.wikipedia.org/wiki/SHA-2#Implementations.

Les changements depuis le RFC 4634 sont résumés dans l'annexe. Le principal est l'ajout de HKDF (HMAC-based Key Derivation Function). Il y a aussi pas mal d'errata dans le code, détectés par le meilleur relecteur des RFC, Alfred Hoenes, et désormais réparés. La licence est nouvelle (BSD-3 désormais) et a nécessité de remplacer le code de getopt.


Téléchargez le RFC 6234


L'article seul

RFC 6227: Design Goals for Scalable Internet Routing

Date de publication du RFC : Mai 2011
Auteur(s) du RFC : T. Li (Cisco)
Pour information
Réalisé dans le cadre du groupe de recherche IRTF RRG
Première rédaction de cet article le 7 mai 2011


Le problème fondamental du routage dans l'Internet est connu depuis longtemps : le système actuel a du mal à fournir certains services (multi-homing, mobilité, ingénierie de trafic, etc) d'une manière qui passe à l'échelle, c'est-à-dire qui puisse grandir au rythme de la croissance de l'Internet. Un groupe de travail IRTF, le Routing Research Group travaille donc sur ce sujet et ce RFC 6227 est le cahier des charges produit.

Il est très court : il est plus facile de spécifier le problème que de décrire les solutions. Le problème (les services difficiles à fournir tout en passant à l'échelle) a déjà été présenté par le RFC 4984. Reste à concevoir les solutions et, pour cela, à décrire les exigences auxquelles doit se plier la future architecture, et leurs priorités respectives. Logiquement, le cahier des charges s'écrit au début et est publié longtemps avant que le travail ne se termine mais, ici, cela n'a pas été le cas. Les conclusions du travail sur la nouvelle architecture sont déjà sorties (RFC 6115). Simplement, le cahier des charges avait bien été écrit au début mais il a été modifié et raffiné au fur et à mesure de l'avancement du travail et d'une meilleure compréhension du problème, pour n'être publié officiellement que maintenant.

Chaque exigence listée dans ce RFC a une priorité : requise, fortement souhaitée ou souhaitée, et les exigences avec leurs priorités sont résumées dans un tableau dans la section 3.11. D'autre part, les principes traditionnels de l'Internet, tels qu'explicités dans le RFC 1958 s'appliquent toujours (notamment le principe de bout-en-bout qui indique que les deux machines terminales qui communiquent doivent faire l'essentiel du travail, puisque ce sont elles qui doivent décider, par exemple des priorités de trafic).

La « liste au Père Noël » est en section 3. D'abord, compte-tenu de la croissance continue de la table de routage globale (cf. les rapports sur la croissance de la table BGP), il est fortement souhaité (section 3.1) que le nouvelle architecture permettre de séparer la croissance de l'Internet et celle de la table de routage. Actuellement, un nouvel utilisateur qui veut être « multi-homé » proprement ajoute une entrée BGP dans la table de routage globale, qui risque donc de devenir proportionnelle au nombre de tels utilisateurs. Ce n'est clairement pas souhaitable. Notez que le RFC est ambitieux : on ne parle pas de faire croître la table de routage moins vite que le nombre d'utilisateurs, mais de ne pas la faire croître du tout lorsque ce nombre d'utilisateurs augmente.

Autre exigence, concernant l'ingénierie de trafic, c'est-à-dire la possibilité d'envoyer le trafic sur tel ou tel chemin selon des critères qui ne sont pas ceux du système de routage classique, par exemple pour forcer le passage par un lien moins coûteux. Une méthode courante aujourd'hui est d'injecter dans la table de routage globale des préfixes d'adresses IP plus spécifiques. Cela augmente la taille de ladite table. Il est donc fortement souhaité qu'une meilleure solution soit trouvée (section 3.2).

Même chose pour le multi-homing, déjà cité : il est fortement souhaité qu'il puisse aussi passer à l'échelle (section 3.3).

Une bonne partie des problèmes de l'architecture actuelle de l'Internet vient de la confusion de deux rôles dans l'adresse IP : localisateur (indique un point d'attachement dans l'Internet) et identificateur (nomme une machine ou une interface). Il est depuis longtemps reconnu (cela se trouvait déjà dans l'IEN1) que cette confusion est dommageable. Il est donc souhaité qu'on sépare ces deux rôles (section 3.4).

Un certain nombre de gens (note au passage : je n'en fais pas partie) considèrent qu'il est essentiel qu'une machine terminale, voire un réseau entier, puisse se déplacer dans l'Internet, changer de fournisseur, etc, sans remettre en cause son adresse IP et les sessions existantes. Par exemple, une connexion SSH devrait rester intacte si mon smartphone passe du Wi-Fi chez moi avec Free, au 3G chez Bouygues, voire si je passe de Free à la maison à Paris à un accès Verizon en Californie. Comme ces deux scénarios entraînent un changement de l'adresse IP, la connexion SSH cassera. Les mécanismes existants pour permettre ces changements d'attachement sans casser les connexions en cours sont la mobilité IP (RFC 5944), avec introduction d'une machine relais, le home agent, ou bien l'injection de préfixes dans la table de routage lorsque la machine se déplace. Les deux solutions sont imparfaites (la seconde impacte sérieusement la table de routage globale) et on désire donc une meilleure solution pour la mobilité (section 3.5). Le mieux serait qu'elle sépare complètement la mobilité du routage.

Autre problème du système de routage : comme il est très difficile de rénuméroter un grand réseau (cf. RFC 5887), beaucoup d'organisations font tout pour garder des adresses IP à elles, ce qui impacte le système de routage (l'agrégation des préfixes devient plus difficile). Le RFC note bien qu'une rénumérotation complètement automatique est utopique, il estime néanmoins (section 3.6) qu'on peut abaisser sérieusement le coût de renumérotation (cf. RFC 4192) et que c'est fortement souhaitable.

Autre souhait fort : que le nouvelle architecture soit conçue de manière modulaire, de manière à ce qu'on puisse en utiliser seulement une partie et à ce que les différents composants de la solution ne soient pas excessivement couplés (par exemple, si la solution introduit un tunnel, la détermination de la PMTU devrait se faire par les moyens standard, sans introduire un nouveau mécanisme pour les machines terminales).

Ce n'est pas tout que les paquets arrivent : encore faut-il qu'ils arrivent vite. La qualité du chemin trouvé par le système de routage compte donc beaucoup. Il est donc fortement souhaité (section 3.8) que ce dernier trouve une route rapidement (convergence efficace), n'en change tout le temps (routes stables) et que les routes trouvées soient proches de l'idéal (faible élongation - stretch - cette dernière étant définie comme le rapport entre la longueur du chemin effectif et la longueur du chemin le plus court possible, cf. « A Trade-Off between Space and Efficiency for Routing Tables » de Peleg et Upfal).

Autre préoccupation importante, la sécurité (section 3.9). Il est requis que la nouvelle architecture ait une sécurité au moins équivalente à l'ancienne. C'est un des deux seuls points où l'exigence est requise. Les cyniques diront que celle-ci n'est pas trop difficile à atteindre, vu le niveau de sécurité existant.

Enfin, une dernière exigence, elle aussi requise, en section 3.10 : la déployabilité. Il ne sert à rien de concevoir une splendide architecture si celle-ci reste dans les cartons. Or, des expériences malheureuses comme celle d'IPv6 ont montré que déployer des nouvautés dans l'Internet était très difficile. Il faut notamment que le nouveau système soit déployable de manière incrémentale : les premiers adoptants doivent pouvoir l'installer, et même en tirer des bénéfices immédiats. Sinon, chacun attendra que l'autre fasse le premier pas et on n'avancera pas. (Il n'est évidemment pas question de repartir de zéro, vus les investissements réalisés.)

Voilà, il n'y a maintenant plus qu'à trouver des solutions correspondant à ce cahier des charges : le RFC 6115 résume les résultats de cette quête.


Téléchargez le RFC 6227


L'article seul

RFC 6220: Defining the Role and Function of IETF Protocol Parameter Registry Operators

Date de publication du RFC : Avril 2011
Auteur(s) du RFC : Danny McPherson (IAB), Olaf M. Kolkman (IAB), John Klensin (IAB), Geoff Huston (IAB)
Pour information
Première rédaction de cet article le 15 avril 2011
Dernière mise à jour le 6 mai 2011


Voici un RFC officiel de l'IAB pour mettre solennellement par écrit le rôle de l'opérateur des registres des protocoles utilisé par l'IETF. Des tas de protocoles normalisés par cet organisme ont besoin de garder une trace des noms ou numéros réservés (par exemple les numéros de port de TCP ou UDP, les numéros d'options DHCP, etc) et le rôle de l'opérateur du registre qui garde ces réservations (aujourd'hui, essentiellement l'IANA) n'avait apparemment jamais été formalisé. À noter que, depuis, ce RFC a été remplacé par le RFC 8722.

L'IETF n'assure en effet pas ce rôle d'opérateur du registre elle-même. Elle se focalise sur la production de normes (les RFC) et délègue la gestion du registre. Pourquoi les valeurs en question ne sont-elles pas directement mises dans les RFC ? Parce qu'elles évoluent plus vite que la norme elle-même. Ainsi, l'enregistrement d'un nouveau type d'enregistrement DNS est un processus bien plus souple que de modifier un RFC et la liste de tels types ne peut donc pas être figée dans un RFC (ceux-ci ne sont jamais modifiés, seulement remplacés, et cela n'arrive pas souvent).

Mais on ne peut pas non plus laisser chacun définir ses propres paramètres, car cela empêcherait toute interprétation commune. D'où cette idée d'un registre des paramètres. Les règles d'enregistrement dans ce registre, la politique suivie, sont décrites pour chaque norme dans la section IANA considerations du RFC, en utilisant le vocabulaire et les concepts du RFC 5226 (pour les types d'enregistrements DNS, cités plus haut, c'est dans le RFC 6895).

Plusieurs autres SDO suivent ce même principe de séparation entre la normalisation et l'enregistrement (en revanche, les groupes fermés d'industriels qui tentent d'imposer leur standard ne séparent pas en général ces deux fonctions). Par exemple, l'ISO définit, pour la plupart de ses normes, une Registration Authority ou bien une Maintenance Agency qui va tenir le registre. (Exemples : l'opérateur du registre de ISO 15924 est le consortium Unicode et celui du registre de ISO 639 est SIL. Contre-exemple : l'opérateur du registre de ISO 3166 est l'ISO elle-même.) Pourquoi cette séparation ? Les raisons sont multiples mais l'une des principales est la volonté de séparer la politique de base (définie dans la norme) et l'enregistrement effectif, pour gérer tout conflit d'intérêts éventuel. Un opérateur de registre séparé peut être plus indépendant, afin de ne pas retarder ou bloquer l'enregistrement d'un paramètre pour des raisons commerciales ou politiques. Notons aussi que bien d'autres fonctions liées à l'IETF sont également assurées à l'extérieur, comme la publication des RFC (cf. RFC 6335).

Contre-exemple, celui du W3C, qui utilise très peu de registres et pas d'opérateur de registre officiel séparé. En pratique, c'est l'IANA qui gère plusieurs registres Web, comme celui des URI bien connus (RFC 8615), celui des types de fichiers (comme application/pdf ou image/png), celui des en-têtes (utilisés notamment par HTTP), etc. En dehors de l'IANA, le W3C a quelques registres gérés en interne comme celui de Xpointer. Pour le reste, la politique du W3C est plutôt qu'un registre est un point de passage obligé et que de tels points ne sont pas souhaitables.

Dans le cas de l'IETF, les documents existants sont le RFC 2026, qui décrit le processus de normalisation mais pas celui d'enregistrement. Ce dernier est traditionnellement connu sous le nom de « fonction IANA » (d'où la section IANA considerations des RFC) même si, en pratique, ce n'est pas toujours l'IANA qui l'effectue. (Les registres de l'IANA sont en https://www.iana.org/protocols/.)

La section 2 du RFC expose donc le rôle et les responsabilités du(des) opérateur(s) de registres de paramètres. Celui(ceux)-ci, désormais nommés avec majuscules IETF Protocol Parameter Registry Operator, seront formellement choisis désormais par l'IAOC (RFC 4071). J'ai mis le pluriel car l'IANA n'assure pas actuellement la totalité du rôle : il existe d'autres opérateurs de registres, en général sur des tâches très secondaires comme par exemple le RIPE-NCC pour l'enregistrement en e164.arpa (ENUM, cf. RFC 6116 et lettre de l'IAB). Dans le futur, on pourrait imaginer un rôle moins exclusif pour l'IANA.

La section 2.1 est la (longue) liste des devoirs qu'implique le rôle d'opérateur de registre. Il y a bien sûr le tenue du registre à proprement parler mais ce n'est pas tout. En voici une partie :

  • Donner des avis sur les futurs RFC (concrètement, relire les sections IANA considerations à l'avance, pour voir si elles ne poseraient pas de problèmes insurmontables au registre).
  • Suivre les RFC : l'opérateur du registre n'est pas censé déterminer la politique mais l'appliquer. Si un RFC dit que l'enregistrement dans tel registre se fait sans contrainte, l'opérateur du registre ne peut pas refuser un enregistrement, par exemple. Chaque registre a une politique d'enregistrement, expliquée dans le RFC correspondant (les règles générales figurent dans le RFC 5226).
  • Bien indiquer dans chaque registre les références notamment le numéro du RFC qui normalise ce registre et pour chaque paramètre enregistré dans le registre, indiquer la source de ce paramètre et la date d'enregistrement.
  • En cas de désaccord ou de problème, se tourner vers l'IESG, seule habilitée à trancher.
  • Diffuser gratuitement les registres qui sont tous publics par défaut (contrairement à ce qui se passe chez l'ultra-dinosaure ISO). Un exemple est le registre de DHCP, en https://www.iana.org/assignments/bootp-dhcp-parameters/.
  • Maintenir les listes de diffusion spécifiées pour certains registres, par exemple lorsque l'enregistrement nécessite un examen par un expert, sous l'œil du public.
  • Produire des rapports réguliers à destination de l'IAB, suivant le RFC 2860 mais aussi suivant l'accord supplémentaire qui l'a complété, et à destination de toute l'IETF. Aujourd'hui, cela se fait sous la forme de l'exposé IANA qu'il y a à chaque plénière de l'IETF. Ces rapports incluent des points comme les performances de l'opérateur du registre (délai de traitement, par exemple).
  • Ne pas oublier que les droits de propriété intellectuelle sur ces registres sont gérés par l'IETF Trust (RFC 4748).

Après cette description des devoirs de l'opérateur du registre, la section 2 continue avec les devoirs des autres acteurs. En section 2.2, ceux de l'IAB, qui supervise l'opérateur du registre : l'IAB procède à la délégation formelle du registre, après que l'IAOC ait identifié les candidats. L'IAB décide, l'IAOC gère la relation avec l'opérateur.

En section 2.3, le rôle de l'IESG : celui-ci s'occupe de la partie technique, vérifier que les RFC comportent une bonne section IANA considerations, identifier les experts techniques si le RFC précise que l'enregistrement est précédé d'une évaluation technique (exemple : le RFC 5646, où l'enregistrement d'une langue dans le registre des langues est précédé d'une telle évaluation par un linguiste), répondre aux questions de l'opérateur du registre si celui-ci a un problème pratique.

En section 2.4, le rôle de l'IETF Trust (RFC 4748). Il gère la propriété intellectuelle de l'IETF donc est « propriétaire » du contenu des registres. Enfin, en section 2.5, le rôle de l'IAOC, bras administratif de l'IETF, qui est de gérer au quotidien les relations avec l'opérateur du registre.

Voilà, l'essentiel était là mais la section 3 rajoute quelques détails.


Téléchargez le RFC 6220


L'article seul

RFC 6206: The Trickle Algorithm

Date de publication du RFC : Mars 2011
Auteur(s) du RFC : P. Levis (Stanford University), T. Clausen (LIX, Ecole Polytechnique), J. Hui (Arch Rock Corporation), O. Gnawali (Stanford University), J. Ko (Johns Hopkins University)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF roll
Première rédaction de cet article le 29 mars 2011
Dernière mise à jour le 30 mars 2011


Dans le cadre des travaux sur l'Internet des objets, le groupe de travail ROLL de l'IETF s'occupe de définir des mécanismes de routage pour des réseaux d'engins aux capacités limitées, et connectés par des liens radio à faible portée et souvent brouillés. (Par exemple, cela peut décrire la situation de capteurs dans une usine.) Une brique de base pour beaucoup de protocoles utilisés dans ce contexte est un algorithme pour coordonner un état entre toutes les machines (cet état pouvant être par exemple la table de routage, mais aussi une configuration commune). Trickle (terme désignant un mince filet d'eau, par exemple celui coulant du robinet en cas de fuite) est l'algorithme utilisé et ce RFC est sa première normalisation. Il est notamment utilisé dans le protocole RPL du RFC 6550.

Vu le contexte très spécial, les protocoles classiques de distribution d'information ne convenaient pas forcément à ce type de réseau, où il est crucial d'économiser l'énergie, et de fonctionner malgré des liaisons physiques sommaires. Trickle atteint ces objectifs en ne diffusant l'information que lorsque elle a changé. L'idée de base est de permettre à deux nœuds de déterminer très rapidement s'ils ont la même version de l'information distribuée et, sinon, de se synchroniser. S'ils sont synchronisés, il n'y a plus beaucoup de communication. Lorsque de la nouvelle information apparait, le trafic reprend. Trickle repose entièrement sur les mécanismes de diffusion du réseau local et n'est donc pas routé. Le tout est simple et tient dans 50 à 200 lignes de code C (je n'ai pas trouvé de distribution officielle de référence de ce code miracle mais l'implémentation dans Contiki fait effectivement cette taille).

Trickle est un algorithme générique : conçu à l'origine pour distribuer du code (pour mettre à jour le programme sur les autres machines), il a pu être adapté pour distribuer n'importe quel type d'information, par exemple une table de routage. Pour un nouveau type d'information, il suffit de définir ce que veut dire « être synchrone » ou pas et la partie générique de Trickle fait le reste.

Assez de publicité, place à l'algorithme (sections 3 e 4 du RFC). Le travail de chaque nœud est de transmettre les données qu'il connait jusqu'à ce que, en entendant les autres nœuds, il se rende compte que ses transmissions sont inutiles (cela veut dire qu'un nœud Trickle isolé continuera à parler tout seul). Pour prendre l'exemple du protocole CTP (Collection Tree Protocol), quelques paquets par heure suffisent.

La transmission se fait à une adresse multicast locale. Par exemple, au dessus d'IPv6, Trickle va écrire à une adresse multicast locale au lien alors qu'en IPv4, il utiliser 255.255.255.255.

Lorsqu'un nœud reçoit les messages d'un autre, il y a deux cas :

  • Le message montre que celui dont on vient de recevoir des nouvelles a la même version de l'information,
  • Le message montre qu'un des deux nœuds, le récepteur ou l'émetteur, est en retard. Notons que Trickle ne fait pas trop de différence entre ces deux sous-cas : ils entraineront tous les deux une transmission de données.

L'un des principaux paramètres d'un algorithme spécifique utilisant Trickle est un moyen de déterminer cette notion de « être à jour ». Par exemple, supposons que l'information ait un numéro (comme le numéro de série des zones DNS). Alors, « être à jour » signifie avoir le même numéro que l'autre et « être en retard » avoir un numéro inférieur.

Pour décider ensuite de l'action exacte à entreprendre, les nœuds Trickle ont besoin de quelques paramètres :

  • la taille minimum de l'intervalle, Imin,
  • la taille maximum de l'intervalle, Imax,
  • la constante de redondance k.

et de quelques variables :

  • la taille actuelle de l'intervalle, I,
  • le moment de la transmission, t,
  • le compteur c.

Le nœud suit les règles suivantes :

  • Choisir I entre Imin et Imax. Commencer le premier intervalle.
  • Au début de l'intervalle, mettre c à zéro et t à une valeur située dans la deuxième moitié de l'intervalle.
  • À chaque message reçu pour lequel on est à jour, incrémenter c.
  • Au temps t, si c est inférieur à k, on transmet les données. (C'est la seule étape de l'algorithme où on transmet quelque chose.) c < k peut se traduire par « j'ai trop de voisins qui ne sont pas à jour par rapport à l'ensemble de mes voisins ». C'est par cette comparaison de c (nombre de voisins à jour) à k que Trickle s'adapte automatiquement à la densité du réseau (s'il y a plein de voisins à jour, pas la peine de se fatiguer à transmettre, un autre le fera).
  • À la fin de l'intervalle, doubler la taille de l'intervalle (en s'arrêtant à Imax).
  • Si on entend un message qui montre que quelqu'un (le nœud qui exécute cet algorithme ou bien son voisin) n'est pas à jour, on réduit l'intervalle à Imin. L'idée est de rendre l'algorithme plus dynamique lorsqu'il y a des nœuds qui sont en retard.

On note que Trickle ne réagit pas immédiatement en détectant un retard : il se contente de démarrer un nouvel intervalle. C'est fait exprès pour éviter une tempête de mises à jour, par exemple lorsqu'un nouveau nœud rejoint le réseau après une absence. Trickle privilégie donc l'économie de ressources, et ne cherche pas à être temps-réel.

Ça, c'était l'algorithme. Simple, non ? Maintenant, si vous êtes concepteur de protocoles et que vous voulez utiliser Trickle, que vous reste-t-il à faire ? La section 5 liste vos tâches :

  • Préciser des valeurs par défaut pour les paramètres Imin, Imax, k, etc. Notamment, Imin dépend de la latence du réseau utilisé.
  • Définir ce que signifie « être à jour » et « être en retard ».
  • Et quelques détails. Regardez le RFC 6550 pour un exemple de protocole de routage utilisant Trickle.

Il ne faut quand même pas oublier quelques considérations pratiques (section 6). D'abord, le bon fonctionnement de Trickle dépend d'un accord de tous les nœuds sur les paramètres à utiliser. En cas de différence, le résultat peut être sous-optimal voire faux dans certains cas. Par exemple, un nœud qui aurait une constante de redondance k supérieure aux autres pourrait se retrouver à émettre à chaque intervalle, vidant sa batterie. De même, un désaccord sur Imax pourrait mener certains nœuds à ne jamais transmettre, laissant les autres faire tout le travail. En outre, toutes les valeurs ne sont pas forcément raisonnables. Par exemple, la constante de redondance k mise à l'infini est théoriquement possible (Trickle travaillerait alors en mode bavard, n'économisant pas les transmissions) mais très déconseillée. Il faut donc trouver un moyen de distribuer la bonne configuration à toutes les machines.

Le pire problème serait évidemment une fonction de définition de la cohérence différente selon les nœuds, cela pourrait mener à une impossibilité de converger vers un état commun. C'est pour cela que le RFC demande qu'elle soit strictement définie pour un protocole donné, et non configurable.

L'auteur de protocole, ou le programmeur, pourraient vouloir « améliorer » Trickle en ajustant l'algorithme. Attention, avertit le RFC, cet algorithme a été soigneusement étudié et testé et la probabilité d'arriver à l'améliorer est faible. Il est conseillé de ne pas le toucher gratuitement. Trickle est extrêmement simple et la plupart des améliorations mèneraient à un code plus compliqué. Or, pour le genre de machines pour lesquelles Trickle est prévu, économiser en transmissions de paquets pour finir par faire davantage de calculs ne serait pas forcément optimal.

Enfin, question sécurité, c'est simple, Trickle n'en a pas (section 9). Un méchant peut facilement pousser tous les nœuds à transmettre, épuisant leurs ressources. Et il peut assez facilement empêcher le groupe de converger vers un état stable. Les protocoles qui utilisent Trickle doivent donc définir leurs propres mécanismes de sécurité.

Pour approfondir Trickle, notamment sur ses performances ou son implémentation, les articles recommandés sont « Trickle: a self-regulating algorithm for code propagation and maintenance in wireless sensor networks » et « The emergence of a networking primitive in wireless sensor networks ».

Plusieurs utilisations de Trickle sont mentionnées en section 6.8, avec références. Trickle est par exemple utilisé dans Contiki : http://www.sics.se/~adam/contiki/contiki-2.0-doc/a00543.html. Damien Wyart s'est attelé à la tâche de trouver d'autres mises en œuvre et voici ses résultats (je le cite).

« Dans les travaux qui parlent de Trickle, on voit souvent cité Maté, une sorte d'environnement qui permet de mettre en réseau des mini-machines virtuelles (si j'ai bien compris), et certains documents indiquent que Maté contient une implantation de Trickle. Maté est distribué principalement sous forme de RPM, ce qui n'aide pas sur Debian... Il ne semble plus évoluer depuis 2005 (mais l'auteur principal continue à travailler sur TinyOS et peut sans doute être contacté pour obtenir plus de détails sur les implantations de Trickle. De plus, Maté est intimement lié à TinyOS qui a depuis, semble-t-il, beaucoup évolué. »

« Par recoupements (c'est assez rare d'avoir à autant jouer les détectives entre fichiers RPM, confusion sur les versions et vieux dépôts CVS --- TinyOS a maintenant un SVN chez Google Code), je suis arrivé principalement au fichier http://tinyos.cvs.sourceforge.net/viewvc/tinyos/tinyos-1.x/tos/lib/VM/components/MVirus.nc?view=log. Sur une copie locale des deux sous-arborescences tinyos-1.x/tools/java/net/tinyos/script et tinyos-1.x/tos/lib/VM (citées dans http://www.eecs.berkeley.edu/~pal/mate-web/downloads.html), j'arrive à ceci (avec le bien pratique concurrent de grep, ack) :

 dw@brouette:/storage/sandbox/tinyos-1.x$ ack -ai trickle
 tos/lib/VM/components/MVirus.nc
 118:  MateTrickleTimer versionTimer;
 119:  MateTrickleTimer capsuleTimer;
 153:  void newCounter(MateTrickleTimer* timer) {

 tos/lib/VM/doc/tex/mate-manual.tex
 615:that has newer code will broadcast it to local neighbors. The Trickle
 635:Trickle's suppression operates on each type of packet (version,
 645:\subsubsection{Trickle: The Code Propagation Algorithm}
 647:The Trickle algoithm uses broadcast-based suppressions to quickly
 651:completes, Trickle doubles the size of an interval, up to
 662:Trickle maintains a redundancy constant $k$ and a counter

 tos/lib/VM/types/Mate.h
 168:typedef struct MateTrickleTimer {
 173:} MateTrickleTimer;

 tools/java/net/tinyos/script/VMFileGenerator.java
 524:    writer.println(" * MVirus uses the Trickle algorithm for code propagation and maintenance.");
 528:    writer.println(" * \"Trickle: A Self-Regulating Algorithm for Code Propagation and Maintenance");
 549:    writer.println("     the timer interval for Trickle suppression, and the redundancy constant");

Cela donne donc des pistes, la partie principale semblant bien être le fichier MVirus.nc. »


Téléchargez le RFC 6206


L'article seul

RFC 6204: Basic Requirements for IPv6 Customer Edge Routers

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


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 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 a depuis été remplacé par le RFC 7084.

Le gros débat qui avait eu lieu à l'IETF lors de la conception de ce RFC portait sur une règle exprimée dans les premières versions de l'Internet-Draft qui avait précédé le RFC : cette règle disait qu'un CPE IPv6 devait, par défaut, bloquer les connexions entrantes. L'argument principal était que les CPE IPv4 font tous cela. Mais ils le font parce qu'en IPv4, la pénurie d'adresses oblige à des bricolages comme le NAT, et empêchent de toute façon les connexions entrantes. IPv6 permettant enfin de récupérer une adresse IP unique mondialement, et donc d'avoir à nouveau une connectivité de bout en bout, cette règle évoquait plus un « Minitel 2.0 » que l'Internet du futur.

Elle a donc été retirée de ce RFC, qui laisse ouverte la question de la sécurité, la déléguant à un autre document, le RFC 6092. En coupant les connexions entrantes, on bloque certaines attaques (par forcément les plus fréquentes : aujourd'hui, la plupart des attaques se font par le contenu des données transférées - importation de malware - et pas directement sur IP) mais on empêche les utilisateurs de profiter des services comme la téléphonie sur IP ou le pair-à-pair, qui dépendent souvent de cette possibilité de connexions entrantes.

Donc, en dehors de ce point, que contient ce RFC ? La section 1 résume les points importants : le RFC se focalise 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 ».

D'abord, 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 2010. 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 6204 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.

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. Citons, parmi elles, l'obligation de d'abord se comporter en bon routeur, ce qui implique par exemple de mettre en œuvre ICMP (RFC 4443) correctement. Du côté du WAN, le CPE devra lui-même utiliser les protocoles standard de découverte d'un routeur (RFC 4861) pour trouver où envoyer les paquets, devra demander son préfixe avec DHCP (RFC 8415), devra bien sûr encapsuler IPv6 correctement (RFC 2464 pour Ethernet), etc. Du côté du LAN, il 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 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. Il doit évidemment pouvoir distribuer ce préfixe sur le réseau local avec SLAAC (Stateless Address Autoconfiguration, RFC 4862) ou avec DHCP (RFC 3315, ce protocole devient donc désormais obligatoire). Il doit fournir des options comme l'annonce des serveurs DNS (RFC 3646).

La sécurité, on l'a vu, est l'aspect délicat de ces machines, puisque le M. Michu qui les utilise pour connecter sa maison, ne connait pas le problème et n'a pas envie d'apprendre. Sur ce point controversé, la section 4.4 se contente de renvoyer à un autre RFC, le RFC 6092 en disant que ce serait bien de mettre en œuvre ses recommandations. Délibérement, la question de la configuration par défaut souhaitable (permettre les connexions entrantes ou pas) est laissée de côté.

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. Des tests chez Free sur une Freebox v5 semblent indiquer que tout est correct (pas de filtrage bizarre, et merci à Ludovic Martin pour ses essais.)


Téléchargez le RFC 6204


L'article seul

RFC 6203: IMAP4 Extension for Fuzzy Search

Date de publication du RFC : Mars 2011
Auteur(s) du RFC : T. Sirainen
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF morg
Première rédaction de cet article le 27 mars 2011


Où s'arrêtera la liste des extensions au protocole IMAP d'accès aux boîtes aux lettres ? En tout cas, elle ne cesse de grossir. Ce RFC propose une extension aux fonctions de recherche d'IMAP pour permettre des recherches floues, par exemple pour que « hipothèse » puisse trouver « hypothèse ».

Beaucoup de systèmes de recherche disposent de mécanisme analogue, par exemple le moteur de recherche Google, lorsqu'on lui soumet la requête erronée citée plus haut propose « Essayez avec cette orthographe : hypothèse 2 premiers résultats affichés ». Mais IMAP n'avait qu'un service de recherche exact, via la commande SEARCH (RFC 3501, section 6.4.4). Notre RFC 6203 l'étend en permettant, via l'ajout du mot-clé FUZZY, des recherches floues. Il est important de noter que ce RFC ne spécifie qu'une syntaxe : la sémantique exacte d'une recherche est laissée à chaque mise en œuvre, et on peut penser qu'elle évoluera avec les progrès de la recherche floue. Ainsi, pour prendre un exemple, est-ce que « Penelope » trouvera les textes sur Pénélope ? Le RFC ne le spécifie pas, laissant chaque serveur IMAP ajouter les algorithmes de recherche floue qu'il préfère.

La syntaxe exacte figure en section 3. Un mot-clé, FUZZY, enregistré dans le registre IANA d'IMAP, préfixe le critère de recherche, comme dans, par exemple :

   C: MYTAG1 SEARCH FUZZY (SUBJECT "balade dames jadisse")
   S: * SEARCH 1 5 10
   S: MYTAG1 OK Search completed.

Et on trouvera peut-être (selon l'implémentation) un message dont le sujet était « La ballade des dames du temps jadis » (et merci à ma fille pour une intéressante discussion sur balade / ballade). Je répète que c'est le serveur qui décidera du niveau de flou acceptable, le RFC ne fournit pas de guide à ce sujet.

Le mot-clé FUZZY s'applique au critère qu'il préfixe, pas à toute la recherche. Donc :

   C: MYTAG2 SEARCH FUZZY (SUBJECT "balade dames jadisse") FROM francois@villon.fr
   S: * SEARCH 1 4
   S: MYTAG2 OK Search completed.

fera une recherche floue sur le sujet mais une recherche exacte sur l'auteur.

Les recherches floues vont évidemment renvoyer davantage de résultats que les recherches exactes et le tri de ces résultats, par pertinence, est donc essentiel. La section 4 décrit donc le mécanisme de pertinence. Le RFC recommande très fortement aux serveurs IMAP qui mettent en œuvre FUZZY d'affecter une grandeur entre 0 et 100 à chaque résultat, indiquant la pertinence. Si le serveur accepte également l'extension ESEARCH (RFC 4731), celle-ci peut servir à récupérer les valeurs de pertinence, avec la nouvelle option de RETURN, RELEVANCY :

   C: MYTAG3 SEARCH RETURN (RELEVANCY ALL) FUZZY TEXT "Bnjour"
   S: * ESEARCH (TAG "MYTAG3") ALL 1,5,10 RELEVANCY (4 99 42)
   S: MYTAG3 OK Search completed.

Les exemples ci-dessus utilisaient la recherche floue avec des chaînes de caractère. Mais la norme ne se limite pas à ces chaînes, comme le précise la section 5. Un serveur peut donc décider de permettre des recherches floues pour d'autres types de données et le RFC donne des indications sur les types pour lesquels c'est utile :

  • Les dates, pour permettre des recherches comme « il y a une semaine, à peu près », la pertinence décroissant lorsqu'on s'éloigne de la date indiquée,
  • Les tailles, pour chercher des messages d'« environ un Mo »,
  • Alors qu'en revanche les recherches par UID (RFC 3501, section 2.3.1.1) n'ont sans doute aucune raison d'être floues.

Le concept de pertinence s'applique aussi à la commande SORT (section 6). On peut donc trier les messages selon la pertinence :

   C: MYTAG4 SORT (RELEVANCY) UTF-8 FUZZY SUBJECT "Bjour"
   S: * SORT 5 10 1
   S: MYTAG4 OK Sort completed.

Si vous être programmeur et que vous ajoutez cette capacité de flou à un serveur IMAP existant, lisez bien la section 8 sur la sécurité. En effet, les recherches floues peuvent consommer bien plus de ressources du serveur et faciliter ainsi des attaques par déni de service.

D'autre part (comme, là encore, avec les moteurs de recherche du Web), les recherches floues peuvent être plus susceptibles d'empoisonnement par des méchants qui glisseraient dans les messages de quoi apparaître en tête du classement.

Et quelles sont les implémentations existantes de cette extension ? Il y en a apparemment au moins deux mais j'ai été trop paresseux pour chercher lesquelles, comptant sur les lecteurs pour me les signaler.


Téléchargez le RFC 6203


L'article seul

RFC 6195: Domain Name System (DNS) IANA Considerations

Date de publication du RFC : Mars 2011
Auteur(s) du RFC : Donald E. Eastlake 3rd (Motorola)
Première rédaction de cet article le 29 mars 2011


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 5395, qui avait libéralisé l'enregistrement de nouveaux paramètres. Et il a lui-même été remplacé par la suite par le RFC 6895.

Un certain nombre de paramètres, 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, etc). Cet espace n'étant pas de taille infinie, il faut y enregistrer de nouveaux paramètres avec prudence, selon les règles qui étaient expliquées dans le RFC 2929, qui a été sérieusement réformé par le RFC 5395 avant de l'être, beaucoup plus légèrement, par notre RFC 6195.

En effet, les règles du RFC 2929 étaient bien trop strictes à l'usage. Notamment, le processus d'enregistrement d'un nouveau type d'enregistrement était tellement pénible que beaucoup de protocoles (comme SPF à ses débuts) préféraient utiliser le fourre-tout TXT pour y mettre leurs enregistrements. Ce goulet d'étranglement était souvent cité comme un exemple typique des blocages liés à l'IETF.

Le RFC 5395 avait donc assoupli les règles d'enregistrement des types de ressources DNS (les autres règles sont peu changées). Avant, il y avait deux solutions (voir le RFC 5226 pour plus d'explications), IETF Review (ex-IETF Consensus), un processus long et incertain imposant un RFC sur le chemin des normes, approuvé par l'IESG, ou Specification required, qui impose l'écriture d'une norme (pas forcément un RFC) « stable et permanente ».

Le nouveau système est plus léger (section 3.1.1) : il suffit désormais de remplir un formulaire décrivant le nouveau type d'enregistrement (un gabarit figure en annexe A), de le soumettre sur la liste dnsext@ietf.org et d'attendre le jugement d'un expert, désigné parmi les noms fournis par l'IESG, qui décidera, sur la base du formulaire soumis, d'allouer ou pas la requête. Un tel processus est utilisé pour d'autres enregistrements à l'IANA, par exemple pour les nouvelles étiquettes de langue.

Le nouveau processus a été testé pour la première fois pour le type d'enregistrement ZS (Zone Status) qui a été accepté, sous un autre nom, NINFO, et figure désormais sous le numéro 56 dans le registre IANA. Autre exemple, plus récent, le type URI, permettant de stocker des URI dans le DNS, enregistré en février 2011, sous le numéro 256. Mais tous les types ne réussissent pas forcément leur entrée dans le registre. CAA, qui sert à indiquer l'autorité de certification du domaine, est toujours en discussion.

Quels sont les changements entre le RFC 5395, qui avait marqué l'entrée dans la nouvelle ère, et notre RFC 6195 ? Ils sont minimes (voir annexe B). Le principal est le changement de nom de la liste de diffusion où se discutent les demandes. Autrement, ce sont surtout des petites corrections éditoriales. À son tour, le successeur de notre RFC, le RFC 6895 n'a apporté que de petits changements.

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. Ainsi, le bit RD (Recursion Desired) 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. 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.

Les codes de réponse (rcodes), comme NXDOMAIN (nom inexistant) ou BADTIME (signature trop ancienne ou trop récente, cf. RFC 8945) sont tirés d'un espace plus vaste et la procédure est donc un peu plus libérale (section 2.3).


Téléchargez le RFC 6195


L'article seul

RFC 6186: Use of SRV Records for Locating Email Submission/Access services

Date de publication du RFC : Mars 2011
Auteur(s) du RFC : C. Daboo (Apple)
Chemin des normes
Première rédaction de cet article le 31 mars 2011


Les enregistrements DNS de type SRV ont été normalisés dans le RFC 2782 il y a dix ans, pour permettre de trouver la ou les machines rendant un service (par exemple de messagerie instantanée avec XMPP), en ne connaissant que le nom de domaine délégué, par exemple example.org ou apple.example. Ils ont été adoptés par la plupart des protocoles Internet, avec deux exceptions importantes : le Web ne les utilise toujours pas, ce qui mène à des bricolages contestables comme de mettre une adresse IP sur un nom de domaine délégué. Et le courrier électronique n'utilise pas non plus SRV car, pour trouver le serveur d'un domaine, il compte sur une technique plus ancienne, proche du SRV mais spécifique au courrier, le MX (les MX ne présentent aucun avantage spécifique et, si tout était à refaire de zéro, on utiliserait certainement les SRV aussi pour cela). Les enregistrements MX ne concernent toutefois que la transmission de courrier de MTA à MTA. Pour les autres logiciels de courrier, comment font-ils ?

Depuis ce RFC 6186, ils utilisent SRV à leur tour. Ainsi, un MUA qui cherche à quel serveur transmettre le courrier n'aura plus besoin d'être configuré explicitement (options Mail submission server, Mail retrieval server, ou quelque chose de ce genre). Il suffira d'indiquer l'adresse électronique de l'utilisateur (mettons jeanne@example.org) et le MUA pourra extraire le domaine (example.org) et chercher des enregistrements SRV qui lui indiqueront où trouver ces serveurs. (Une autre méthode ancienne était d'utiliser des conventions comme de mettre le serveur IMAP en imap.example.org mais elle est moins souple, les SRV permettent en effet d'indiquer plusieurs serveurs, de préciser leurs priorités, etc.)

Bien, commençons par l'introduction. Une liste (sans doute non limitative) des services de courrier est donnée par la section 1 :

Le premier cité de ces RFC, le RFC 5321 (section 5) normalise l'utilisation des enregistrements MX pour trouver le serveur de courrier suivant. Mais il ne dit rien des autres services. Par exemple, un MUA ne peut pas trouver dans les MX le serveur de soumission. Résultat, les MUA dépendent d'une configuration manuelle des serveurs à utiliser, parfois augmentée d'une série d'heuristiques (du genre, essayer l'IMAP sur le serveur de soumission, au cas où ce serait le même...). Ce système est complexe pour les utilisateurs (« Indiquez le numéro de port de votre serveur IMAP ; si vous ne le connaissez pas, écrivez à jenerepondsjamaisintelligemment@support.votre-fai.net »...)

Les différents noms SRV utilisés sont normalisés en section 3 :

  • submission (section 3.1) sert pour la soumission initiale de message, telle que décrite dans le RFC 6409. Ainsi, pour le domaine example.org, on pourrait voir un enregistrement _submission._tcp.example.org. SRV 0 1 9587 mail.example.NET. indiquant que les messages doivent être soumis à mail.example.NET, sur le port non-standard 9587. À noter que cet enregistrement couvre les connexions avec ou sans TLS, ce qui est une autre source de confusion lors de la configuration. (Depuis, la sortie du RFC 8314, avec son _submissions._tcp, a clarifié les choses.)
  • imap (section 3.2) et imaps servent pour trouver le serveur IMAP. Donc, par exemple, avec cette fois le port standard, _imap._tcp.example.org. SRV 0 1 143 imap.example.NET..
  • pop3 et pop3s servent à localiser le serveur POP3. Leur absence peut donc indiquer que ce vieux protocole n'est pas disponible pour un domaine.

Les enregistrements SRV indiqués ici utilisent évidemment la sémantique standard du RFC 2782. Ainsi, l'ensemble suivant :

$ORIGIN example.org.
 _imap._tcp     SRV 0 1 143 imap.example.net.
                SRV 10 1 143 imap.plan-B.example.

signifie, en raison du champ Priorité (mis à zéro pour le premier enregistrement et à 10 pour le second), que le client IMAP doit tenter d'abord de se connecter à imap.example.net et ne doit essayer imap.plan-B.example que si le premier est injoignable. Tout cela est ancien et bien connu. Mais le courrier présente un défi spécifique, l'existence de deux protocoles de récupération, IMAP et POP. Que doit faire le MUA si les deux sont annoncés dans le DNS ? La section 3.4 tranche : le MUA qui gère les deux protocoles devrait récupérer les enregistrements pour POP et IMAP et utiliser ensuite le champ Priorité, non seulement à l'intérieur d'un ensemble (POP ou IMAP) mais même pour choisir entre les deux protocoles. Ainsi, ces données :

$ORIGIN example.org.
_imap._tcp     SRV 10 1 143 imap.example.net.

_pop3._tcp      SRV 50 1 143 pop.example.net.

indiquent sans ambiguité que l'administrateur système voudrait qu'on utilise de préférence IMAP (champ Priorité plus petit, donc plus prioritaire).

Bien, maintenant, dans le futur (car, aujourd'hui, il n'y a à ma connaissance aucune mise en œuvre de ce RFC dans un logiciel), comment se comportera un MUA lorsque ce RFC sera déployé ? La section 4 expose le mode d'emploi. Il leur suffira d'interroger l'utilisateur sur son adresse électronique et tout le reste pourra être trouvé dans le DNS, en prenant la partie à droite du @ et en cherchant les SRV pour les différents services. Regardez par exemple le domaine bortzmeyer.fr comment c'est fait (enregistrements _submission._tcp, _imap._tcp et _imaps._tcp). Si la recherche des SRV ne donne rien, le MUA pourra alors, comme aujourd'hui, demander à l'utilisateur ces informations.

Notez toutefois que beaucoup d'hébergeurs DNS ne permettent pas, via le panneau de contrôle qu'ils proposent à leurs clients, d'ajouter un enregistrement SRV. Même lorsque cette possibilité existe, elle est souvent boguée comme chez Gandi où le formulaire ne permet pas d'indiquer proprement poids, priorité ou port (astuce : il faut les taper dans le champ Valeur, dans le bon ordre).

La partie de cette section concernant TLS est plus faible (mais a été changée dans le RFC 8314, bien plus détaillé). Si on trouve un serveur IMAP, par exemple, le RFC demande de tenter la commande STARTTLS pour voir si elle marche. Les enregistrements SRV de notre RFC ne permettent pas d'indiquer que la gestion de TLS est obligatoire (chose que l'on peut configurer dans beaucoup de MUA) et, si TLS échoue, le MUA doit donc compter sur une configuration manuelle par l'utilisateur (du genre « Toujours utiliser TLS »). La section 6 détaille ce choix.

Notons aussi que l'utilisation des SRV peut compliquer la vérification de l'identité du serveur distant (si le domaine est mapetiteentreprise.example et que l'enregistrement SRV indique que le serveur IMAP est mail.grosfournisseur.example, l'identité du serveur dans le certificat ne sera pas mapetiteentreprise.example). La procédure du RFC 6125 doit impérativement être utilisée.

Lors de la connexion au serveur IMAP ou au serveur SMTP de soumission, il faut en général s'authentifier, ce qui implique qu'on puisse indiquer un nom d'utilisateur. Notre section 4 impose au MUA d'utiliser d'abord l'adresse électronique entière, puis la partie à gauche du @. Si ces deux tentatives échouent, il reste à demander à l'utilisateur (le nom pour la procédure d'authentification n'est en effet pas forcément dans l'adresse de courrier).

Les informations sur les serveurs peuvent être conservées pour éviter de demander au DNS à chaque fois. Mais, si la connexion a marché à un moment mais échoue par la suite, le MUA doit ré-interroger le DNS pour voir si les serveurs n'ont pas changé.

La section 4 conseillait les auteurs de MUA. La section 5 aide les fournisseurs de courrier. Le principal conseil est de permettre comme nom de connexion l'adresse électronique complète, vu que c'est la première chose que tenteront les MUA.

La section 6 est celle de la sécurité. En l'absence de signatures DNSSEC, la récupération des enregistrements SRV n'est pas sûre. Si un attaquant a réussi à empoisonner le cache du résolveur DNS, il peut rediriger le courrier vers n'importe quel serveur de son choix. Notez bien que c'est un des cas où l'argument des sceptiques sur DNSSEC « Il suffit d'utiliser TLS » ne tient pas. Sans DNSSEC pour sécuriser le SRV (le lien entre un nom de domaine et les noms des serveurs), TLS ne protégerait rien puisque les serveurs d'un attaquant peuvent parfaitement avoir un certificat valide et correspondant à leur nom.

La section 6 conseille, au cas où DNSSEC ne soit pas utilisé (ce qui est aujourd'hui le cas le plus fréquent), de vérifier que les serveurs sont dans le même domaine que le domaine de l'adresse de courrier et, sinon, de demander confirmation à l'utilisateur, procédure lourde qui annulerait une partie de l'intérêt de ce RFC (et qui n'est pas suivie dans l'exemple de bortzmeyer.fr donné plus haut).


Téléchargez le RFC 6186


L'article seul

RFC 6182: Architectural Guidelines for Multipath TCP Development

Date de publication du RFC : Mars 2011
Auteur(s) du RFC : A. Ford (Roke Manor Research), C. Raiciu, M. Handley (University College London), S. Barre (Université catholique de Louvain), J. Iyengar (Franklin and Marshall College)
Pour information
Réalisé dans le cadre du groupe de travail IETF mptcp
Première rédaction de cet article le 23 mars 2011


Plusieurs efforts ont déjà été déployés pour avoir un protocole de transport qui puisse utiliser plusieurs chemins simultanés, pour le cas où deux machines disposent de plusieurs moyens de se joindre. Le projet « Multipath TCP » dont voici le premier RFC se distingue par le fait que son trafic apparaîtra comme du TCP habituel, aussi bien aux applications qu'aux équipements intermédiaires situés sur le réseau.

L'idée de base de tous ces efforts est : il arrive qu'entre deux machines A et B, il existe plusieurs chemins possibles, par exemple si A et B sont tous les deux connectés à au moins deux FAI (cf. section 1.3). Utiliser simultanément ces deux chemins permettrait d'augmenter la capacité disponible (et donc le débit effectif) et d'augmenter la résilience (en cas de panne d'un chemin pendant la connexion, on utiliserait automatiquement l'autre). TCP ne permet pas cela, puisqu'il est lié à des adresses IP source et destination qui ne changent pas. Des protocoles de couche 4 comme SCTP (RFC 4960) ont déjà exploré cette voie. Mais ils souffrent d'un double problème : il faut parfois adapter les applications, qui s'attendent à la sémantique de TCP, et il faut être sûr que le chemin complet soit de l'IP propre. Or, cela est rare dans l'Internet aujourd'hui, que des incompétents ont truffé de boîtiers intermédiaires non transparents et qui rendent le déploiement de tout nouveau protocole très difficile.

Pourtant, pouvoir mettre en commun la capacité de plusieurs chemins est tellement tentant que d'autres projets ont vu le jour. C'est ainsi que le groupe de travail mptcp de l'IETF a été créé pour mettre au point une architecture, Multipath TCP et un protocole mettant en œuvre cette architecture, MPTCP (le RFC normalisant ce protocole étant encore en cours d'élaboration).

Comme son nom l'indique, l'idée de base est de ne pas trop s'éloigner du TCP actuel, afin d'assurer une compatibilité à la fois avec les applications actuelles et avec le réseau actuel, les deux points sur lesquels SCTP a largement achoppé. SCTP est donc plus propre, plus conforme à l'architecture originale de l'Internet mais Multipath TCP est peut-être plus réaliste. (Notre RFC 6182 ne cite pas SHIM6RFC 5533 - mais celui-ci possède pas mal de points communs avec SCTP, notamment un très faible déploiement dans l'Internet actuel.)

La section 2 précise les buts de l'architecture Multipath TCP. Du point de vue des fonctions, on voudrait :

  • Augmenter le débit, par l'utilisation simultanée de davantage de ressources réseaux. Plus formellement, l'utilisation de Multipath TCP doit mener à un débit au moins égal à celui du meilleur des chemins.
  • Augmenter la résistance aux pannes. La résistance totale de Multipath TCP doit être au moins aussi bonne que celle du chemin le plus fiable.

Notons que SCTP n'avait que le second but (SCTP ne permet pas actuellement d'envoyer des paquets sur différents chemins, cf. section 2.4). Naturellement, il faut en outre que le tout se fasse automatiquement : une machine MPTCP doit pouvoir trouver seule si son partenaire est également MPTCP et basculer automatiquement vers le nouveau protocole.

Mais, tout aussi importants que les fonctions sont les critères de compatibilité avec l'Internet d'aujourd'hui :

  • Compatibilité avec les applications : l'API doit rester la même et les services rendus à l'application doivent être les mêmes (délivrance des octets dans l'ordre, et sans perte). Ainsi, on doit pouvoir passer à Multipath TCP uniquement en mettant à jour le système d'exploitation, sans réécrire les applications. Il est souhaitable que l'API soit étendue pour permettre une utilisation (optionnelle) des fonctions spécifiques de Multipath TCP. Enfin, petite exception à cette compatibilité, une application qui s'attendrait à un débit très régulier peut être surprise par Multipath TCP, qui aura probablement des débits et des latences moins constants. La section 6 donne des détails sur les relations entre Multipath TCP et les applications.
  • Compatibilité avec le réseau : Multipath TCP devra fonctionner avec l'Internet tel qu'il est aujourd'hui. Or, comme l'illustrent très bien les figures 2 et 3 du RFC, l'architecture de l'Internet a changé, de fait. Elle était censée offrir un lien IP transparent, de façon à ce que la première couche « de bout en bout » soit la couche 4. En fait, l'Internet d'aujourd'hui est truffé de middleboxes qui ont souvent un rôle actif dans la couche 4 (terminaison de connexions, par exemple, ou bien filtrage des protocoles de couche 4 inconnus) et donc, de fait, la première couche de bout en bout aujourd'hui est la couche 7. La section 7 revient en détail sur cette interaction entre Multipath TCP et les middleboxes.
  • Compatibilité avec les utilisateurs existants : Multipath TCP ne doit pas « voler » de la capacité réseau aux utilisateurs du TCP normal (mais pas non plus être trop poli et les laisser tout prendre).

La deuxième exigence de compatibilité, celle avec le réseau, va donc être difficile à assurer. Mais elle est nécessaire pour le succès de Multipath TCP, les innombrables middleboxes programmées avec les pieds et configurées n'importe comment étant un puissant frein au déploiement de tout protocole de transport qui ne serait pas TCP ou UDP.

Multipath TCP a également des contraintes en terme de sécurité : la section 2.3 impose qu'il n'aggrave pas la situation par rapport à TCP.

Une fois les buts exposés, comment les atteindre ? la section 3 décrit l'architecture de Multipath TCP. En gros, Multipath TCP part des idées exposées dans « Breaking Up the Transport Logjam » de Ford & Iyengar : séparation de la couche transport en deux, une demi-couche haute « sémantique » (service aux applications, fonctionnant de bout en bout) et une demi-couche basse « flot et terminaison » (pas forcément de bout en bout, si des middleboxes sont présentes).

La section 4 de notre RFC descend ensuite dans le concret. On passe de l'architecture, Multipath TCP, au protocole, MPTCP. Le principe de base de MPTCP est de répartir chaque connexion TCP en plusieurs « sous-connexions », chacune d'entre elles apparaissant à un observateur extérieur comme une connexion TCP complète et normale (et aura donc de bonnes chances de passer à travers les NAT et autres horreurs). Les méta-informations spécifiques à MPTCP seront transportées à part. MPTCP aura les tâches suivantes :

  • Gérer les chemins : cela veut surtout dire les découvrir, essentiellement via la présence de plusieurs adresses IP sur une même machine. On pourra aussi utiliser ECMP (RFC 2992).
  • Gérer les paquets : les octets transmis par l'application doivent être répartis entre les différents chemins. Cela implique la remise dans l'ordre à la destination, puisque des paquets ont pu voyager par des chemins différents.
  • Gérer chaque sous-connexion : c'est relativement facile, chacune est une connexion TCP habituelle.
  • Contrôler qu'il n'y a pas de congestion.

La section 5 rappelle les choix techniques importants de MPTCP et leurs raisons. Ainsi de la façon de numéroter les octets. La section 5.1 explique qu'il y avait deux façons :

  • Un seul espace de numérotation, pour toute la connexion MPTCP. Cela aurait facilité le réassemblage des octets issus de chaque sous-connexion mais cela aurait rendu les sous-connexions bizarres, puisque les séquences auraient été incomplètes. Des engins comme les IDS auraient alors pu décider de couper ces connexions bizarres.
  • La solution choisie a donc été d'avoir un espace de numérotation par sous-connexion, de façon à ce que chacune de celles-ci ressemble vraiment parfaitement à une connexion TCP traditionnelle. Cela implique par contre de conserver (et de transmettre au pair) la correspondance entre les numéros de séquence de la sous-connexion et ceux de la connexion complète.

Autre choix délicat, les retransmissions en cas de perte. Chaque sous-connexion étant du TCP normal, elle a un système d'accusé de réception. Mais si des données sont perdues, par exemple lors du réassemblage des sous-connexions, on ne peut pas utiliser les mécanismes TCP normaux pour demander une réémission puisque ces données ont déjà fait l'objet d'un accusé de réception. Il y a donc également un système d'accusés de réception et de réémission au niveau de la connexion MPTCP globale.

Plusieurs des fonctions de MPTCP nécessitent donc un mécanisme de signalisation entre les deux pairs, par exemple au démarrage lorsqu'il faut signaler au pair TCP qu'on sait faire du MPTCP. La section 5.4 explore l'espace des choix : les options TCP (RFC 793, section 3.1) ont été retenues pour cette signalisation, de préférence à un encodage TLV dans les données. Les options sont la solution standard de TCP et la seule propre. Elle présentent toutefois une limitation, leur faible taille, et un risque : certaines middleboxes massacrent les options (section 7 et voir aussi par exemple l'excellente étude de Google Probing the viability of TCP extensions).

Et comment va t-on identifier une connexion MPTCP ? Traditionnellement, l'identificateur d'une connexion TCP était un quadruplet {adresse IP source, adresse IP destination, port source, port destination}. La connexion MPTCP, reposant sur plusieurs connexions TCP, ne peut pas utiliser un de ces identificateurs (puisqu'il risque de ne plus rien signifier si la connexion TCP associée casse). MPTCP devra donc développer un nouvel identificateur (section 5.6). Cela limitera d'ailleurs la compatibilité de MPTCP avec les anciennes applications, qui n'utiliseront comme identificateur celui de la première connexion TCP. Si celle-ci défaille ultérieurement, la connexion MPTCP entière pourra avoir un problème.

L'Internet étant ce qu'il est, tout nouveau protocole apporte un lot de nouveaux problèmes de sécurité (section 5.8). Le cas de la sécurité de Multipath TCP est traité plus en détail dans un futur RFC « Threat Analysis for TCP Extensions for Multi-path Operation with Multiple Addresses ». En attendant, les propriétés de sécurité essentielles attendues sont :

  • Permettre de vérifier que les pairs qui négocient une sous-connexion TCP sont bien les mêmes que ceux qui avaient négocié la première sous-connexion de la connexion MPTCP.
  • Avant d'ajouter une adresse à la liste, permettre de vérifier que le pair peut recevoir du trafic à cette adresse, pour éviter qu'un pair MPTCP ne vous fasse attaquer un tiers innocent.
  • Protéger contre le rejeu.

Atteindre ces objectifs ne va pas être facile pour MPTCP : le choix d'utiliser les options TCP limite sévèrement la quantité d'information qu'on peut transmettre et le choix de permettre qu'une middlebox s'interpose oblige à compter avec le fait que certains paquets seront modifiés en transit.

Revenons aux applications (section 6). Il y aura un certain nombre de points de détail qu'elles vont devoir gérer. Par exemple, si l'application se lie explicitement à une adresse particulière de la machine, MPTCP ne doit pas être utilisé (puisque l'application a marqué une préférence pour une adresse donnée).

L'interaction avec les équipements intermédiaires fait l'objet d'une étude plus approfondie en section 7. MPTCP ne sera pas déployé dans un réseau idéal, un réseau qui ne fournirait que de la délivrance de datagrammes IP. Au contraire, il opérera au milieu d'une jungle de middleboxes toutes plus mal programmées les unes que les autres : routeurs NAT, pare-feux, IDS, PEP, etc. Toutes ont en commun d'optimiser les applications d'aujourd'hui au détriment de celles de demain. En effet, violant la transparence du réseau, elles rendent très difficiles de déployer de nouvelles techniques qui font des choses inattendues. La section 7 donne une liste détaillées des différentes catégories de middleboxes et de leur influence possible. Ansi, certains pare-feux mélangent les numéros de séquence TCP (pour protéger les systèmes bogués qui ne choisissent pas le numéro initial au hasard). Si un tel équipement se trouve sur le trajet, l'émetteur TCP ne sait même pas quel numéro de séquence sera vu par le récepteur ! Quant aux IDS, ne connaissant pas MPTCP, ils trouveront peut-être suspect cet établissement de multiples connexions. À moins qu'ils ne comprennent pas que ces connexions sont reliées, ratant ainsi certaines informations transportées. (Imaginons une attaque transmise par MPTCP, où les différentes parties de l'attaque arrivent par des chemins séparés...).

Comme indiqué, MPTCP n'est pas encore complètement spécifié. Seule l'architecture générale est choisie. Il n'est donc pas étonnant qu'on n'en trouve pas encore d'implémentations officielle, que ce soit dans Linux ou dans FreeBSD. Néanmoins, le travail est déjà en cours sur Linux à l'Université de Louvain qu'on peut tester selon les instructions en http://mptcp.info.ucl.ac.be/.


Téléchargez le RFC 6182


L'article seul

RFC 6180: Guidelines for Using IPv6 Transition Mechanisms during IPv6 Deployment

Date de publication du RFC : Mai 2011
Auteur(s) du RFC : J. Arkko (Ericsson), F. Baker (Cisco Systems)
Pour information
Première rédaction de cet article le 28 mai 2011


IPv6 fait souvent peur aux administrateurs réseaux par le nombre de techniques de coexistence entre IPv4 et IPv6. Ces techniques sont variées, et inévitables, puisque la transition a pris un retard considérable, ce qui mène à devoir déployer IPv6 alors que les adresses IPv4 sont déjà épuisées. Ce RFC 6180 vise à simplifier la tâche dudit administrateur système en le guidant parmi les techniques existantes.

Il ne s'agit donc pas de normaliser le Nième protocole de transition et/ou de coexistence entre IPv6 et IPv4, plutôt de faire le point sur les protocoles existants, dont le nombre a de quoi effrayer. Mais il ne faut pas paniquer : selon le cas dans lequel on se situe, toutes ces techniques ne sont pas forcément pertinentes et il n'est donc pas nécessaire de les maîtriser toutes.

D'abord, notre RFC 6180 rappelle qu'il n'y a pas le choix : la réserve IPv4 de l'IANA a été épuisée en février 2011 et celle des RIR le sera fin 2011-début 2012. IPv6 est donc la seule solution réaliste. Le point sur la transition est fait dans le RFC 5211 et elle a commencé il y a longtemps, dans les organisations les mieux gérées. Un des points qui la freine est que l'administrateur réseaux normal, celui qui ne suit pas heure par heure les travaux de l'IETF, voit un grand nombre de techniques de coexistence IPv4/IPv6 (le Wikipédia anglophone a excellente page de synthèse sur ces techniques) et se demande « Dois-je donc déployer 6to4 et 6rd et DS-lite et NAT64 et donc maîtriser toutes ces techniques ? ». La réponse est non : selon son réseau, notre malheureux administrateur n'aura à gérer qu'une partie de ces méthodes.

Déjà, il faut comprendre ce que ces termes barbares veulent dire : la section 2 rappelle la terminologie, et les RFC à lire.

La section 3 décrit ensuite les principes suivis dans le RFC : le premier est de garder en tête le but, qui est de pouvoir continuer la croissance de l'Internet sans être gêné par des problèmes comme le manque d'adresses. Pour cela, le but final de la transition doit être le déploiement complet d'IPv6 natif dans tout l'Internet. Lorsque cela sera réalisé, toutes les techniques de transition et de coexistence pourront être abandonnées, simplifiant ainsi beaucoup la situation. Mais pour atteindre ce but lointain, il n'y a pas qu'une seule bonne méthode. Par contre, ces méthodes ont quelques points en commun. Il est par exemple essentiel de s'y prendre à l'avance : les adresses IPv4 sont déjà épuisées et une organisation qui n'aurait encore rien fait du tout, question IPv6, va avoir des problèmes. Donc, aujourd'hui, En tout cas, il n'existe pas de raison valable de retarder le déploiement d'IPv6. Ceux qui n'ont pas encore commencé devraient s'y mettre immédiatement.

Mais cela implique une longue période de coexistence avec IPv4. Pas pour tout le monde : il existe des réseaux un peu particuliers, des déploiements récents, contrôlés par une seule organisation, dans un environnement fermé (une usine, par exemple) et qui n'ont pas besoin d'échanger avec le reste du monde. Ceux-ci peuvent faire de l'IPv6 pur et ne pas lire ce RFC. Mais tous les autres doivent se poser la question « Qu'est-ce que je fais avec mes deux protocoles ? ».

Et cela va durer longtemps. Même si on peut espérer qu'un jour on éteigne la dernière machine IPv4, cela ne se produira pas avant de nombreuses années. Même si un réseau est entièrement IPv6, il faudra bien qu'il puisse communiquer avec des machines v4 à l'extérieur. (Le RFC ne mentionne pas le fait qu'actuellement, l'effort de la coexistence repose entièrement sur ceux qui veulent déployer IPv6. Une date importante sera celle où l'effort changera de camp et où ce sera ceux qui veulent continuer à utiliser IPv4 qui devront travailler pour cela. Cette date surviendra longtemps avant la disparition de la dernière machine IPv4.)

Ceux qui déploient IPv6 doivent donc choisir un modèle de déploiement. Le RFC 5218 rappelait, en s'inspirant de l'expérience de plusieurs protocoles, ce qui marche et ce qui ne marche pas. Certains de ces rappels semblent évidents (ne pas casser ce qui marche aujourd'hui, permettre un déploiement incrémental, puisqu'il n'y a aucune chance de faire basculer tout l'Internet d'un coup) mais sont toujours bons à garder en mémoire.

Voilà, après ces préliminaires, place aux techniques elle-mêmes, en section 4. Le début de cette section précise qu'elle n'est pas exhaustive : il existe d'autres mécanismes de coexistence/transition mais ils sont considérés comme relativement marginaux. Les techniques sont exposées dans l'ordre d'importance décroissante et les premières sont donc les plus recommandées.

Premier mécanisme de coexistence, et le plus recommandé, la double pile. Chaque machine a deux mises en œuvre des protocoles réseau, une pour IPv4 et une pour IPv6 et peut parler ces deux protocoles au choix. Ce modèle s'applique aussi bien sur la machine terminale (où les applications sont donc « bilingues ») que sur les routeurs du FAI (qui font tourner des protocoles de routage pour les deux familles, cf. RFC 6036 pour le point de vue du FAI). C'était le mécanisme de transition originellement envisagé. Le choix de la version d'IP dépend de la machine qui initie la connexion (RFC 6724), et de ce que la machine réceptrice a annoncé (par exemple dans le DNS). Ce mécanisme est simple et évite les problèmes qu'ont, par exemple, les tunnels, comme les problèmes de MTU. Comme le rappelle le RFC 4213, c'est la méthode recommandée.

Cela n'empêche pas ce modèle d'avoir des failles. D'abord, si l'adoption de ce modèle est une décision individuelle de chaque réseau, son utilisation nécessite que les deux réseaux qui communiquent aient adopté ce système. Si un client double-pile veut se connecter à un serveur en IPv6, celui-ci doit avoir une connectivité IPv6 (ce qui dépend de son FAI), doit avoir une application IPv6isée et doit avoir annoncé un AAAA dans le DNS. Autrement, on a IPv6, mais on n'observe guère de trafic. Inversement, lorsqu'un gros fournisseur de contenu active IPv6 (comme l'a fait YouTube en février 2010), le trafic IPv6 fait soudain un bond.

Une deuxième limite de l'approche double-pile est que certaines applications ne réagissent pas proprement lorsqu'un des protocoles fonctionne mais pas l'autre. De nos jours, c'est en général l'IPv6 qui a un problème et la double-pile peut alors entraîner une dégradation du service, l'application perdant bêtement du temps à tenter de joindre le pair en IPv6 au lieu de basculer tout de suite vers IPv4. Le code naïf de connexion d'un client vers un serveur est en effet (en pseudo-code) :

for Address in Addresses loop
    try
       connect_to(Address)
       exit loop
    except Timeout
       # Try the next one
    end try
end loop   

Cette approche purement séquentielle peut être pénible si les adresses IPv6 sont en tête de la liste Addresses et si le délai de garde est long. Car chaque connexion fera patienter l'utilisateur plusieurs secondes. (La durée exacte avant le Timeout dépend de la nature de la non-connectivité IPv6 - le routeur envoie-t-il un message ICMP ou pas, de ce que transmet la couche 4 à l'application, etc.) C'est pour cette raison que de nombreux gérants de gros services Internet hésitent à activer IPv6 (par exemple, ce dernier est disponible pour le service, mais n'est pas annoncé dans le DNS), de peur de pourrir la vie d'une partie, même faible, de leurs utilisateurs. C'est ainsi que www.google.com n'a d'enregistrement AAAA que pour certains réseaux, que Google estime suffisamment fiables en IPv6. Ce mécanisme de « liste blanche » où Google décide qui va pouvoir se connecter à eux en IPv6 est contestable mais n'oublions pas que les autres « gros » sites Internet ne font rien du tout.

Rendre les applications plus robustes vis-à-vis de ce problème pourrait aider (voir par exemple la technique proposée par l'ISC ou bien le très bon guide de programmation IPv6 d'Étienne Duble), surtout si ces mécanisme de connexion intelligents (tenter en parallèle les connexions v4 et v6) sont emballés dans des bibliothèques standard. Par exemple, la plupart des applications pair-à-pair gèrent relativement bien ce problème, habituées qu'elles sont à vivre dans un monde de connectivité incertaine et intermittente.

Ces défauts sont à garder en tête mais il n'en demeure pas moins que la double-pile reste la meilleure méthode, d'autant plus que de nombreux réseaux ont aujourd'hui IPv6 (le RFC cite les NREN comme Renater ou Internet2, complètement IPv6 depuis longtemps).

Une conséquence amusante de la double-pile est qu'elle nécessite une adresse IPv4 par machine. Cela ne semblait pas un problème au moment où ce mécanisme a été conçu, puisqu'il semblait possible de passer tout le monde en IPv6 avant l'épuisement des adresses v4. Comme cela ne s'est pas fait, on se retrouve aujourd'hui dans une situation où il n'y a plus d'adresses IPv4. La double pile est donc en général utilisée avec une adresse IPv6 publique et une IPv4 privée, NATée plus loin.

La double pile, c'est très bien mais que faire si on n'a pas de connectivité IPv6, et qu'on veut relier son réseau IPv6 au reste de l'Internet v6 ? La section 4.2 expose la solution des tunnels. L'intérêt des tunnels est qu'ils ne nécessitent aucune action sur les routeurs situés sur le trajet. On n'a pas à attendre que son FAI se bouge le postérieur et déploie IPv6. C'est une technique connue et éprouvée, qui est d'ailleurs utilisée pour bien d'autres choses qu'IPv6. L'inconvénient des tunnels est la complexité supplémentaire, et le fait qu'ils réduisent la MTU entraînant tout un tas de problèmes avec les sites qui bloquent stupidement l'ICMP.

Il existe plusieurs types de tunnels : les tunnels manuels du RFC 4213, des tunnels automatiques comme 6to4 (RFC 3056), les serveurs de tunnel présentés dans les RFC 3053 et RFC 5572, et bien d'autres, résumés dans le RFC 5565.

Lorsque le tunnel fait partie d'une solution gérée par un administrateur réseaux compétent, il ne pose pas de problème en soi. Mais certaines solutions techniques (comme 6to4) sont prévues pour être « non gérées » et elles ont toujours posé beaucoup de problèmes. Ainsi, elles peuvent donner aux applications l'impression qu'une connectivité IPv6 fonctionne alors qu'en fait les paquets ne reviennent pas. Beaucoup d'applications tentent alors de se connecter en IPv6 et mettent longtemps avant de s'apercevoir que cela ne marchera pas et qu'il vaut mieux se rabattre sur IPv4. 6to4 a donc beaucoup contribué à la réputation d'IPv6 comme technologie fragile et source d'ennuis. (La solution 6rd - RFC 5969, quoique dérivée de 6to4, n'a pas ces défauts.)

Pour l'instant, IPv6 est peu déployé et ce sont les gens qui veulent utiliser ce protocole qui doivent faire des efforts pour se connecter. Désormais que les adresses IPv4 sont épuisées, on commencera bientôt à voir des déploiements purement IPv6 et il faudra alors faire des efforts pour maintenir les vieux systèmes v4. Les sections 4.3 et 4.4 couvrent ces cas. En 4.3, la question est celle d'un nouvel entrant dans le monde des opérateurs qui n'a pas eu d'adresses IPv4 pour son beau réseau tout neuf et qui a donc déployé un cœur purement v6 ce qui, après tout, simplifie sa configuration. Mais ses clients, et les partenaires auxquels ses clients essaient de se connecter, sont restés en v4. Comment leur donner la connectivité qu'ils désirent ? Il va falloir cette fois tunneler IPv4 sur IPv6. Le modèle recommandé est DS-lite (Dual Stack Lite), dont le RFC n'est pas encore publié. Le principe est que le client recevra uniquement des adresses IPv4 privées, que le CPE fourni par le fournisseur d'accès encapsule les paquets IPv4 qu'émettrait un client, les tunnele jusqu'à un équipement CGN qui décapsulera, puis procédera au NAT44 classique. Le nouveau FAI aura donc quand même besoin de quelques adresses IPv4 publiques. Il existe déjà une mise en œuvre en logiciel libre de la fonction CGN, AFTR.

Autre cas, légèrement différent, est celui où le réseau local connecté à l'Internet n'a pas d'équipement IPv4 du tout. Tout beau, tout neuf, toutes ses machines (et les applications qu'elles portent) sont purement IPv6. Ce n'est pas aujourd'hui très réaliste avec des machines et des applications ordinaires mais cela pourrait arriver avec de nouveaux déploiements dans des environnements modernes. Le problème, décrit en section 4.4, est alors de se connecter quand même à d'éventuels partenaires restés v4. Une des solutions est le passage par un relais (j'en ai fait l'expérience lors d'un atelier de formation et Apache fait un très bon relais pour HTTP, permettant aux machines purement IPv6 de voir tout le ouèbe v4). Une autre solution est NAT64 (RFC 6144).

Puisqu'un certain nombre de trolls ont deversé du FUD sur la sécurité d'IPv6, la section 7, consacrée à ce sujet, est une bonne lecture. Elle rappelle que IPv6 a en gros le même niveau de sécurité qu'IPv4, c'est-à-dire pas grand'chose et que ce sont les implémentations et les déploiements qui apportent des risques, plus que les spécifications. Par contre, chaque technique de transition a ses propres risques de sécurité, en plus de ceux d'IPv6 ou d'IPv4 mais notre RFC ne les détaille pas, renvoyant aux normes décrivant ces techniques.

Conclusion ? La section 5, après cette longue énumération de bricolages variés recentre le débat : l'essentiel est d'activer IPv6. Une fois ce principe posé, cette section rappelle des points mentionnés au début comme le fait qu'il ne faut pas appliquer aveuglément la même technique à tous les réseaux. Ainsi, un réseau tout neuf ne fera sans doute pas les mêmes choix qu'un réseau existant depuis vingt et ayant accumulé plein de technologies historiques.

La section 6 propose une bibliographie pour ceux qui veulent approfondir le sujet : plein de RFC dont les RFC 4213, RFC 4038, RFC 6036, etc. D'autre part, j'avais fait un exposé au GUILDE à Grenoble sur ces sujets (IPv6 et la transition), exposé dont les transparents sont disponibles.


Téléchargez le RFC 6180


L'article seul

RFC 6179: The Internet Routing Overlay Network (IRON)

Date de publication du RFC : Mars 2011
Auteur(s) du RFC : F. Templin (Boeing Research & Technology
Expérimental
Réalisé dans le cadre du groupe de recherche IRTF RRG
Première rédaction de cet article le 21 mars 2011


Sous la houlette du groupe de travail RRG (Routing Research Group) de l'IRTF, un gros effort est en cours pour définir une nouvelle architecture de routage pour l'Internet. Cette future architecture doit permettre de poursuivre la croissance de l'Internet sans se heurter aux limites quantitatives des routeurs, et en autorisant des configurations qui sont actuellement peu pratiques comme le multi-homing. Cet effort a été synthétisé dans les recommandations du RFC 6115. La plupart des propositions d'architecture résumées dans le RFC 6115 seront sans doute publiées, chacune dans son RFC. Notre RFC 6179 ouvre la voie en décrivant le système IRON (Internet Routing Overlay Network).

IRON fait partie de la famille des architectures Map-and-Encap où les réseaux ont un identificateur indépendant de leur position dans le réseau et où les routeurs doivent utiliser un mécanisme de mapping, de correspondance entre l'identificateur connu et le localisateur cherché, avant d'encapsuler les paquets, pour qu'ils puissent atteindre leur destination via un tunnel. L'originalité d'IRON est de combiner mapping et routage pour distribuer l'information nécessaire aux routeurs. Comme les autres architectures Map-and-Encap (par exemple LISP), IRON ne nécessite pas de changement dans les machines terminales, ni dans la plupart des routeurs, mais seulement dans les routeurs d'entrée et de sortie des tunnels.

Comme IRON utilise une terminologie très spéciale, qu'on ne trouve pas dans les autres protocoles, cela vaut la peine, si on veut lire ce RFC, de bien apprendre la section 2, qui décrit le vocabulaire. IRON est donc un système d'overlay, c'est-à-dire de réseau virtuel fonctionnant au dessus d'un réseau « physique », l'Internet. Il part de RANGER RFC 5720 en le généralisant à tout l'Internet. En partant du bas (la description du RFC, c'est peut-être symptomatique, part du haut), chaque organisation connectée à IRON (un EUN pour End User Network) aurait un préfixe à elle, un identificateur, nommé le EP (EUN Prefix). Ces préfixes viennent de préfixes plus larges, les VP (Virtual Prefix), qui sont alloués par de nouvelles organisations, les VPC (Virtual Prefix Companies). Ces organisations n'ont pas d'équivalent dans l'Internet actuel : les VPC pourraient être des FAI mais ce n'est pas obligatoire. Le RFC ne donne aucun détail sur les points non-techniques de cette architecture (par exemple, comment une VPC gagnera sa vie ? Si on change de VPC, pourra t-on garder son préfixe ?) considérant que ces questions sont hors-sujet pour une spécification technique.

Les routeurs IRON se connectent entre eux par des liens NBMA qui sont simplement des tunnels au dessus de l'Internet existant.

Toujours dans le vocabulaire original (IRON n'utilise pas les termes d'ITR - Ingress Tunnel Router - et ETR - Egress Tunnel Router - probablement parce que son architecture ne colle pas bien à ce modèle), IRON repose sur trois types de routeurs (appelés collectivement agents) :

  • Le client est le routeur chez l'EUN, l'organisation terminale (entreprise, association, université, etc). Il connait les EP de l'organisation et se connecte au « réseau » IRON (éventuellement via du NAT). La section 3.1 détaille ces clients.
  • Le serveur appartient à la VPC et il reçoit les « connexions » des EUN qui hébergent les clients. La section 3.2 le décrit complètement.
  • Le relais appartient également à la VPC et assure l'interconnexion avec l'Internet actuel, pour les correspondants qui ne sont pas dans IRON. Il va donc parler BGP avec les routeurs actuels et utiliser les protocoles IRON avec les autres relais. Il est présenté complètement en section 3.3.

Les détails de l'architecture sont ensuite détaillés en sections 3 à 6. Les agents IRON (les trois sortes de routeurs présentées plus haut) forment des tunnels entre eux, en utilisant la technique VET (Virtual Enterprise Traversal, RFC 5558) et encapsulent selon le format SEAL (Subnetwork Encapsulation and Adaptation Layer, RFC 5320). Curieusement, l'auteur prend soin de préciser que SEAL permet de tunneler d'autres protocoles qu'IP et il cite CLNP, ce qui donne une idée de l'âge des idées qui sont derrière SEAL...

SEAL dispose d'un protocole d'échange d'informations sur les routes, les MTU, etc, SCMP (SEAL Control Message Protocol) et c'est lui qui permet à l'overlay IRON de fonctionner.

Chaque VPC représente donc un morceau d'un patchwork global. Les morceaux sont connectés entre eux via l'Internet public. Le client final, lui, doit se connecter à l'Internet puis acquérir une connectivité IRON auprès d'une VPC, et s'équiper d'un routeur client qui va relier son EUN (son réseau local) à la VPC.

Pour amorcer la pompe (section 5), chaque relais est configuré avec la liste des VP qu'il va servir, la liste des serveurs (les routeurs des VPC), et avec celle de ses voisins BGP. Avec ces derniers, il établit des liens comme aujourd'hui et annonce sur ces liens les VP. Avec les serveurs, le relais découvre la correspondance entre les EP, les identificateurs des réseaux IRON et les serveurs. (Rappelons que les identificateurs, EP et VP, ont la même forme que des adresses IP et peuvent donc être annoncés comme tels aux routeurs BGP actuels.)

Les serveurs, eux, sont nourris avec la liste des relais, auxquels ils vont transmettre les VP qu'il servent. Ils attendent ensuite les connexions des clients, apprenant ainsi petit à petit les EP connectés, que les serveurs transmettront aux relais.

Les clients, eux, auront besoin de connaître les serveurs de leur VPC, ainsi que leurs EP, et un moyen de s'authentifier.

Une fois tout ceci fait, les routeurs n'ont plus qu'à router les paquets comme aujourd'hui (section 6, qui décrit les différents cas, notamment selon que le destinataire du paquet est dans IRON ou pas ; par exemple, le cas du multi-homing est en section 6.5.2, qui précise qu'un client peut avoir plusieurs localisateurs pour un même EP).

Et d'une manière plus générale, comment cela va se passer en pratique ? La section 7 se lance dans certains détails concrets. Par exemple, comme le routage à l'intérieur d'IRON est souvent sous-optimal, mais qu'un mécanisme d'optimisation des routes permet de les raccourcir par la suite, le premier paquet de chaque flot aura sans doute un temps de trajet bien supérieur à celui de ses copains.

Et, comme toute solution utilisant des tunnels, IRON aura sans doute à faire face à des problèmes de MTU, que cette section mentionne, mais jette un peu rapidement à la poubelle.

Toujours pour ceux qui s'intéressent aux problèmes concrets, l'annexe B est une très bonne étude des propriétés de passage à l'échelle d'IRON.

IRON ne semble pas avoir été testé, même en laboratoire, même tout simplement dans un simulateur. Et mon avis personnel ? Je dois avouer n'avoir pas tout compris et avoir la sensation inquiétante que ce n'est pas uniquement une limite de mon cerveau, mais que l'architecture d'IRON reste encore insuffisamment spécifiée.


Téléchargez le RFC 6179


L'article seul

RFC 6177: IPv6 Address Assignment to End Sites

Date de publication du RFC : Mars 2011
Auteur(s) du RFC : Thomas Narten (IBM), Geoff Huston (APNIC), Lea Roberts (Stanford University)
Réalisé dans le cadre du groupe de travail IETF v6ops
Première rédaction de cet article le 27 mars 2011


Ce RFC vient remplacer le RFC 3177 et modifier assez sérieusement les recommandations en matière d'allocation d'adresses IPv6 aux sites situés aux extrémités du réseau (entreprises, universités, particuliers, à l'exclusion des FAI et des opérateurs). Le RFC 3177 recommandait, en gros, de donner un préfixe de même longueur, un /48, à tout le monde. Ce nouveau RFC 6177 met un sérieux bémol à cette recommandation.

Le RFC 3177 avait été publié en 2001 et mis en œuvre par les RIR dans leurs politiques d'allocation d'adresses (celle du RIPE-NCC est en http://www.ripe.net/ripe/docs/ipv6policy.html). À partir de 2005, plusieurs critiques se sont fait jour (voir par exemple la proposition 2005-08), menant à une révision de ces politiques et à ce nouveau RFC 6177. Les critiques portaient aussi bien sur la technique (un /48 n'est-il pas excessif ?) que sur la politique (est-ce vraiment le rôle de l'IAB et de l'IETF de recommander des politiques d'allocation ?). Résultat, le « /48 pour tous » n'est plus la politique officielle.

La section 1 de notre nouveau RFC rappele les principaux changements par rapport au RFC 3177 :

  • La possibilité de distribuer des /128 (une seule adresse IPv6) est retirée, un site comprend forcément plusieurs machines,
  • Les valeurs numériques explicitement indiquées par le RFC 3177, /48, /64 et /128, ne sont plus mentionnées, de crainte qu'elles ne deviennent « sacrées » et soient, par exemple, codées en dur dans certaines mises en œuvre d'IPv6, ce qui n'avait pas été prévu,
  • Et, la plus spectaculaire, le retrait de la recommandation d'un /48 pour tous les sites. Il n'y a désormais plus de recommandation officielle de l'IETF, la taille des allocations devant être décidée par les RIR. (On notera que c'est un changement de gouvernance : les RIR, émanation des opérateurs réseau, sont moins favorables que l'IETF aux demandes des utilisateurs.) À titre d'exemple, voici la politique d'APNIC.

Mais alors, que reste-t-il du RFC 3177 ? Le principe comme quoi un site ne devrait pas avoir à geindre et à supplier pour avoir suffisamment d'adresses. En IPv4, la rareté des adresses justifiait les obstacles mis devant les utilisateurs mais, en IPv6, cet argument ne joue plus. Les sites devraient donc toujours avoir les adresses dont ils ont besoin, et ne jamais être contraints à utiliser des techniques comme le NAT pour économiser des adresses, ces économies étant tout à fait inutiles avec IPv6.

La question de l'allocation d'un /48 aux sites d'extrémité est discutée dans la section 2. La recommandation du RFC 3177 était fondée sur trois motivations :

  • Garantir que ces sites auraient suffisamment d'adresses et donc décourager fortement les pratiques malthusiennes de certains FAI comme par exemple, celle de ne donner qu'une seule adresse IPv4, ce qui est compréhensible vue la pénurie mais gêne les sites qui ont plusieurs machines, ce qui est pourtant banal aujourd'hui, même chez le particulier. La plupart du temps, obtenir autant d'adresses IPv4 qu'on a de machines nécessite de passer à un abonnement beaucoup plus cher, sans que cela soit justifié par le coût de ces adresses.
  • La seconde motivation, et qui était souvent oublié par les adversaires du « /48 pour tous », était de faciliter le changement de FAI. Si certains FAI fournissent un /56 à un site et d'autres un /60, le passage du premier au second nécessitera de refaire les plans d'adressage (puisqu'il y a moins de sous-réseaux disponibles) alors que, si tout le monde propose un /48, le changement de fournisseur ne nécessite qu'un changement de préfixe (ce qui est en général très simple avec IPv6). Même chose pour l'administration du DNS, les zones dans ip6.arpa seront plus simples à gérer si on change juste de préfixe, sans avoir à réorganiser ses sous-réseaux. L'idée d'une même taille d'allocation pour tous (de la grande université au particulier) est donc une mesure de protection du client, de garantie qu'il n'y aura pas d'obstacle artificiel à un changement de fournisseur.
  • La troisième motivation de la recommandation du RFC 3177 était de faciliter la croissance des réseaux. Ceux-ci peuvent souvent dépasser les prévisions (une école connecte le bureau du directeur, puis une salle de classe, puis finalement on connecte tout) et les plans d'adressage prudents d'IPv4, conçus pour ne demander que le nombre d'adresses strictement nécessaire, ont souvent gêné la croissance d'un réseau.

Mais, alors, quels sont les problèmes perçus avec cette recommandation du « /48 pour tous » ? D'abord, certains trouvent qu'elle mène au gaspillage. (Je pense personnellement que c'est un argument subjectif, sans base scientifique : il existe 280 billions de /48 disponibles, ce qui fait qu'on n'épuisera pas IPv6 en en donnant un à chacun.) Les partisans de cet argument disent souvent qu'on pourrait ne donner qu'un /64 aux particuliers (ce que fait aujourd'hui un FAI comme Free), oubliant qu'une maison bien dotée en appareils numériques peut avoir besoin de plusieurs réseaux, pas seulement d'adresses, et que, avec l'auto-configuration des adresses IPv6, il faut un /64 par réseau. Notre RFC 6177 demande donc qu'on donne à tous davantage qu'un /64 (un /56 est cité comme possibilité).

Notons que notre RFC 6177 ne traite pas explicitement le cas des hébergeurs de serveurs dédiés comme Gandi ou OVH. Par exemple, Gandi ne permet apparemment qu'une seule adresse IPv6 par machine, rendant ainsi difficile d'y faire tourner plusieurs serveurs. (Pour OVH, l'information est en ligne, avec l'orthographe habituelle de ce fournisseur.)

Le RFC 3177 contenait d'autres points (section 3). Par exemple, il rappelait explicitement que la règle d'un /48 pour tous limitait le pouvoir des intermédiaires : sans avoir à demander, sans remplir de paperasserie, l'utilisateur avait droit à une quantité d'adresses suffisante. C'est hélas quelque chose qui sera différent désormais, l'utilisateur devra à nouveau affronter un bureau insensible pour avoir la quantité d'adresses nécessaire.


Téléchargez le RFC 6177


L'article seul

RFC 6175: Requirements to Extend the Datatracker for IETF WG Chairs and Authors

Date de publication du RFC : Mars 2011
Auteur(s) du RFC : E. Juskevicius (TrekAhead)
Pour information
Première rédaction de cet article le 11 mars 2011


Comme toute organisation qui manipule de grandes quantités de documents, et des processus formalisés complexes, l'IETF a besoin de logiciels qui mettent en œuvre ces processus. Le principal outil est le Datatracker et ce RFC 6175 est le cahier des charges pour une nouvelle extension du Datatracker.

Le Datatracker sert entre autres à suivre l'état des Internet-Drafts. Il était traditionnellement très détaillé pour la phase d'évaluation à l'IESG de ces documents, et nettement moins précis pour les autres phases. Ce service était très réclamé depuis longtemps. Ce cahier des charges demande donc que le Datatracker soit mis à jour pour gérer les états décrits par le RFC 6174.

Quelques rappels, en section 2, pour les gens qui ne suivent pas l'évolution du vocabulaire IETF. Tous les Internet-Drafts ne sont pas forcément liés à un groupe de travail de l'IETF. Ceux qui le sont, parce qu'un groupe a décidé de les adopter, sont qualifiés de WG draft. Leur nom est du type draft-ietf-wgname-.... Ces drafts, et ceux qui sont candidats à l'adoption mais n'ont pas encore été adoptés, sont ensemble les associated with a WG. Dans le cas où ils ne sont pas encore adoptés, leur nom inclus l'acronyme du groupe de travail mais ne commence pas par draft-ietf. Enfin, tous les autres Internet-Drafts sont qualifiés d' « individuels ».

Les exigences générales sur le « nouveau » Datatracker figurent en section 3. Chacune est numérotée. La première, R-001, est que le Datatracker doit permettre aux présidents des groupes de travail de l'IETF de saisir directement l'état des I-D, en suivant les états décrits dans le RFC 6174. Parmi les autres exigences (consultez le RFC pour une liste complète), le fait que tout changement doit être estampillé, lié à une personne précise (R-007) et que la date et l'heure de ce changement soient affichées. Le Datatracker doit étendre la machine à états existante (illustrée en https://datatracker.ietf.org/images/state_diagram.gif), pas la remplacer (R-011). Et les présidents d'un groupe de travail doivent pouvoir agir sur l'état d'un I-D, indépendemment de son statut à l'IESG (R-012).

La section 4 est consacrée aux questions d'autorisation. En lecture, le Datatracker est accessible à tous (R-013), l'IETF tirant une grande fierté de son ouverture au public (contrairement à la majorité des SDO, qui travaillent derrière des portes closes). Mais en écriture, les personnes qui peuvent modifier l'état d'un I-D doivent d'abord s'authentifier auprès du Datatracker (et inutile de dire que l'IETF n'utilise pas Facebook Connect). La section 11 note d'ailleurs les conséquences que cela peut avoir en matière de sécurité.

Les présidents des groupes de travail doivent avoir la possibilité (section 4.2) de modifier l'état de tous les Internet-Drafts de leur groupe, en restant dans la liste d'états pré-définie (cf. RFC 6174 et voir aussi la section 5.1), peuvent désigner jusqu'à trois délégués pour les aider, etc. Une autre population intéressante est celle des pasteurs (sheperds, cf. RFC 4858). Ceux-ci (section 4.4) sont chargés de suivre un document particulier et doivent donc pouvoir déposer le write-up, le formulaire rempli qui indique à l'IESG les points importants du document (voir aussi la section 5.3). Au sommet de cette série de personnes privilégiées, se trouvent évidemment les directeurs de secteurs (Area Directors), qui couvrent chacun plusieurs groupes de travail et doivent également pouvoir mettre à jour l'état des documents (section 4.5).

Certains états des documents posent des problèmes particuliers et la section 6 les énumère. Ainsi, un document peut être garé (parked document, section 6.4) lorsqu'il a perdu son auteur. Le directeur de secteur a alors des pouvoirs supplémentaires, comme de le transférer à un autre groupe de travail. Plus triste, un document peut aussi mourir (dead document, section 6.5) lorsque tout travail le concernant a été abandonné. Là encore, le directeur peut le transférer.

Jusqu'ici, on a parlé des changements manuels, comme lorsque le président d'un groupe de travail met à jour l'état d'un I-D (Internet-Draft). Y a-t-il aussi des changements automatiques ? Oui, et la section 7 liste les cas où le Datatracker doit agir seul. Par exemple, si une nouvelle version d'un document a un nom qui commence par draft-ietf, le document devient automatiquement document d'un groupe de travail (avant, c'était juste une convention : désormais, cela fait partie des règles mises en œuvre automatiquement).

Quelles sont les informations qui doivent être affichées par le Datatracker ? Les sections 8 et 9 les définissent. Par exemple, le Datatracker doit garder trace de l'historique complet du document puisqu'il doit pouvoir le montrer à quiconque a les droits d'écriture (la foule anonyme n'a droit qu'à l'affichage de l'état actuel).


Téléchargez le RFC 6175


L'article seul

RFC 6174: Definition of IETF Working Group Document States

Date de publication du RFC : Mars 2011
Auteur(s) du RFC : E. Juskevicius (TrekAhead)
Pour information
Première rédaction de cet article le 11 mars 2011


Le processus de production de normes au sein de l'IETF était historiquement informel et peu documenté. Petit à petit, il s'est formalisé (voire ossifié) et a même reçu l'aide de logiciels permettant de suivre l'avancement des travaux. Ce RFC de processus décrit des nouveaux états que peut avoir un document en cours de discussion à l'IETF.

Une des particularités de l'IETF est son ouverture. Tout le monde doit pouvoir suivre l'état d'avancement des travaux, via l'Internet. C'est ce que permet par exemple le Datatracker de l'IETF qui donne accès à l'état (en février 2011) du document sur la syntaxe des TLD (apparemment abandonné, et tant mieux), à celui de la documentation de l'AS 112 (adopté par un groupe, mais perdu dans les sables bureaucratiques depuis très longtemps), à celui sur l'enregistrement DNS CERT (pas adopté par un groupe de travail), ou à celui sur le protocole LISP (en plein développement par un groupe de travail).

Les informations affichées par le Datatracker n'étaient pas toutes documentées et certaines, non actuellement affichées, pourraient être nécessaires. Ce RFC 6174 documente donc les états possibles des documents.

Le Datatracker gère bien d'autres choses que les documents, puisqu'il donne aussi accès aux revendications d'appropriation intellectuelle, et à d'autres aspects de la vie de l'IETF. Concernant le document, la version du Datatracker en service fin 2010 ne permettait de suivre que les documents présentés à l'IESG pour évaluation. Avant cela, il ne savait pratiquement d'un document que le fait qu'il soit Active (en cours de discussion) ou Expired (les Internet-Drafts ont une durée de validité de six mois). Or le processus (décrit dans le RFC 8729 est bien plus riche.

Comme le rappelle la section 2 de notre RFC, un Internet-Draft peut être complètement individuel ou bien être un Working Group I-D si un groupe de travail IETF a décidé de l'adopter et de travailler sur ce document. Dans ce cas, sa vie au sein du groupe passe par plusieurs stades qui étaient ignorés du Datatracker.

La section 3 résume en effet l'état du Datatracker fin 2010. Si ce dernier connaissait tous les détails de l'évaluation à l'IESG, la vie du document avant son passage devant cet aréopage était nettement moins détaillé, le Datatracker ne prenant en compte que la disponibilité du document. La section 3.1 donne une liste complète. Celle-ci inclut, comme vu plus haut, Active et Expired, mais aussi des états comme Replaces et Replaced-by qui indique le remplacement d'un Internet-Draft par un autre, équivalent. Cela se produit typiquement lors de l'adoption d'un draft par un groupe de travail. Si le document était nommé draft-authorname-topic-nn, il devient alors draft-ietf-wgname-topic-00. À noter qu'il n'existe pas de moyen automatique pour identifier ce remplacement (les Internet-Drafts n'ont pas de métadonnées structurées), le président du groupe de travail doit l'indiquer explicitement.

Une fois le document terminé par le groupe de travail, il passe à l'IESG pour évaluation. Cette phase est celle qui a suscité le plus de formalisation et celle-ci est décrite dans la section 3.2 (avec l'intégralité des états dans l'annexe A). Un Internet-Draft peut ainsi être, entre autres :

  • Publication requested, le premier stade, suivant les procédures de la section 7.5 du RFC 2418.
  • AD evaluation qui indique qu'un AD (un Area Director, la personne coresponsable d'une zone de travail de l'IESG comme le routage, la sécurité, les applications) est en train d'évaluer le document.
  • IESG evaluation qui indique que le document est désormais évalué par toute l'IESG, c'est-à-dire par tous les AD. Chacun peut émettre une objection bloquante, connue sous le nom (fort mal choisi) de DISCUSS.

Quels sont les nouveux états possibles pour un document, créé par ce RFC 6174 ? La section 4 les détaille et s'appuie pour cela sur une machine à états (figure 1). Ils sont déjà mis en œuvre dans le Datatracker et se trouvent simplement documentés ici, par exemple (ce n'est pas une liste complète) :

  • Call for adoption quand un document est encore individuel mais que son auteur a demandé qu'un groupe de travail l'adopte comme document de travail officiel du groupe,
  • Adopted, une fois que c'est fait ; le document prendra alors un nom du genre draft-ietf-workingroupname-topic-00,
  • Working Group document une fois que le travail du groupe a effectivement commencé,
  • Working Group Last Call ; le sigle WGLC apparît souvent dans les listes IETF car cet état est une partie importante (quoique optionnelle, cf. RFC 2418) du folklore de cette organisation. C'est le dernier moment où le groupe peut donner son avis avant que le document, transmis à l'IESG, ne lui échappe.
  • Working Group consensus, waiting for write-up, qui indique que le document fait l'objet d'un large consensus dans le groupe, et qu'il a juste besoin d'un write-up, le formulaire qui accompagne tout envoi à l'IESG et qui explique à celle-ci les points importants (comme l'existence de mises en œuvre, l'état effectif du consensus, les menaces d'appel, etc, voir RFC 4858),
  • Submitted to IESG, lorsque le travail du groupe est fini,

Outre ces états, qui sont mutuellement exclusifs, le document peut porter un certain nombre d'étiquettes indiquant des points importants du processus, parmi lesquelles :

  • Awaiting Expert Review/Resolution of Issues Raised qui indique qu'un examen du document par un expert du domaine est en cours (de tels examens existent, par exemple, pour toutes les MIB, qui sont vérifiées par un spécialiste ès-MIB),
  • Waiting for Referencing Document, le document dépend d'un autre document, pas encore prêt,
  • Revised I-D Needed - Issue raised by WGLC, lorsque le dernier appel à commentaires dans le groupe de travail a suscité des problèmes suffisamment sérieux pour justifier un nouvel ID (Internet-Draft).

Enfin, un autre champ est spécifié, en section 5. Tout document doit avoir un « niveau de normalisation visé » qui indique si le groupe de travail veut voir le futur RFC sur le chemin des normes, ou simplement « Pour information » ou encore purement « Expérimental ». (Ces niveaux sont expliqués dans le RFC 2026.)

La mise en œuvre de ces nouveaux états dans le Datatracker se fera suivant le cahier des charges contenu dans le RFC 6175.

Une lecture intéressante sur le sujet de la vie des Internet-Drafts est « Guidelines to Authors of Internet-Drafts ».


Téléchargez le RFC 6174


L'article seul

RFC 6168: Requirements for Management of Name Servers for the DNS

Date de publication du RFC : Mai 2011
Auteur(s) du RFC : W. Hardaker (Sparta)
Pour information
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 4 mai 2011


Traditionnellement, les serveurs DNS étaient gérés par des mécanismes spécifiques au logiciel utilisé. BIND a son rndc, Unbound son unbound-control (voir des exemples à la fin), d'autres logiciels utilisent d'autres méthodes et on n'avait pas de moyen facile de gérer un ensemble hétérogène de serveurs. En outre, ces programmes n'étaient pas prévus pour des autorisations précises (modifier telle zone mais pas telle autre) et cela rendait difficile de déléguer la gestion d'une partie du service à un tiers. L'IETF est donc lancée depuis quelques années dans un effort pour mettre en place un mécanisme standard de gestion à distance des serveurs DNS et ce RFC 6168 en est le cahier des charges formel.

Car c'est un vieux projet ! Une des étapes avait été la publication, il y a plus de quatre ans, du brouillon « Requirments for the Nameserver Communication protocol ». Il y a eu ensuite un groupe de travail restreint, nommé DCOMA, dont j'ai fait partie. Le projet a avancé à une allure de tortue mais, au moins, il a désormais un cahier des charges figé. Avant même le document cité plus haut, un effort de normalisation avait mené à deux MIB, décrites dans les RFC 1611 et RFC 1612, qui n'avaient jamais été réellement déployées et ont été officiellement abandonnées par le RFC 3197.

L'annexe A rassemble quelques études de cas, pour illustrer à quoi pourrait servir un tel protocole. Par exemple, en A.1 se trouve le cas de zones locales non-standard comme un .prive ou .local. Si des TLD locaux sont une mauvaise idée, ils n'en sont pas moins très utilisés et des domaines purement locaux peuvent avoir un sens dans certains cas. Actuellement, pour qu'un tel système fonctionne, il faut mettre des directives stub ou forward dans tous les résolveurs de l'organisation, et garder ces résolveurs (qui peuvent être de marques différentes) synchronisés. D'une façon générale, gérer un pool de résolveurs DNS qui doivent avoir la même configuration (par exemple les mêmes clés DNSSEC, cf. annexe A.3) est une tâche courante pour un FAI et plutôt pénible. Le futur protocole de contrôle pourrait faciliter l'automatisation de cette tâche.

A.2 propose un autre cas, dans l'optique de résilience maximale d'une zone DNS : le RFC 2182 recommande à juste titre qu'une zone DNS soit servie par plusieurs serveurs de noms, ne partageant pas de SPOF. Une solution fréquente est l'hébergement réciproque des zones d'un partenaire. Par exemple (au 12 avril 2011), l'AFNIC héberge un serveur secondaire de .nl et SIDN (Stichting Internet Domeinregistratie Nederland) a un serveur secondaire de .fr. La configuration correspondante est actuellement maintenue à la main, ou par des logiciels ad hoc. Ainsi, si un TLD dont le serveur secondaire est à l'AFNIC, veut tout à coup autoriser le transfert de zones, ou au contraire le restreindre à certaines adresses IP, il doit envoyer un message et attendre qu'un technicien de l'AFNIC ait changé la configuration. De même, si deux hébergeurs DNS assurent réciproquement un service de secours en hébergeant les zones de l'autre, la création d'une nouvelle zone doit actuellement être automatisée par des moyens spécifiques du logiciel utilisé. À noter que ce cas nécessite des autorisations à grain fin, comme rappelé en section 4.4.

Ce cahier des charges concerne à la fois les serveurs faisant autorité (par exemple ceux de .FR) que les récurseurs (par exemple les résolveurs de votre FAI). La section 2.2 donne des détails sur les types de serveurs qui seront gérés (les maîtres, les esclaves, et les récurseurs). Les stub resolvers (la bibliothèque de résolution de noms sur votre machine) sont exclus du champ d'application de ce projet. De même, le futur protocole qui mettre en œuvre ces exigences ne s'occupera que de la configuration des serveurs, pas des données servies (pour lesquelles il existe déjà des protocoles standard de transmission, cf. RFC 2136 et RFC 5936).

Le RFC est écrit sous forme d'une suite d'exigences, chacune dans sa propre section. Donc, le numéro de section identifie l'exigence. Voyons les principales.

L'exigence 2.1.1 concerne la taille : parmi les serveurs faisant autorité, il y en a avec peu de zones mais beaucoup de données dans ces zones (les serveurs des TLD par exemple) et d'autres avec beaucoup de toutes petites zones (un hébergeur DNS qui accueille des centaines de milliers de mapetiteentreprise.com). La solution doit convenir pour toutes les tailles.

La solution pourra permettre la découverte automatique des serveurs de noms existant sur le réseau mais ce n'est pas obligatoire (exigence 2.1.2).

Elle devra fonctionner pour des serveurs dont la configuration change souvent (nombreuses zones ajoutées et retirées par heure, par exemple, exigence 2.1.3).

Pour contrôler quelque chose, il faut un modèle décrivant la chose en question. L'exigence 2.1.5 impose donc la création d'un modèle de données d'un serveur de noms. Enfin, 2.1.6 impose que la nouvelle solution n'interfère pas le service principal, le DNS lui-même.

La section 3 décrit les classes d'opérations de gestion à implémenter :

  • Contrôle (arrêter, redémarrer),
  • Configuration (ajouter une zone, ajouter une clé de confiance DNSSEC, etc),
  • Surveillance de l'état du serveur (pour intégrer dans des solutions comme Nagios),
  • Déclenchement d'alarmes.

Le futur protocole devra gérer toutes ces classes.

Quelles sont les opérations à faire sur un serveur de noms ? La section 3.1 liste les plus importantes :

  • Démarrer et arrêter le serveur,
  • Recharger la configuration,
  • Recharger une zone (ou toutes les zones),

À noter que l'opération « démarrer le serveur » est la seule qui ne puisse pas être mise en œuvre dans le serveur lui-même.

Comme certaines de ces opérations peuvent être très longues (la seule lecture du fichier de zone d'un gros TLD peut prendre du temps), la même section demande en outre que le futur protocole ait un mécanisme de notification asynchrone (« fais ça et préviens-moi quand c'est fini »).

Et question configuration, que doit-on pouvoir configurer ? La section 3.2 donne une liste :

  • Les zones à servir (pour un serveur maître) ; à noter qu'il existe déjà des protocoles standard pour transmettre les données contenues dans ces zones (RFC 5936, RFC 1995 et RFC 2136),
  • La liste des zones à servir ; on doit pouvoir ajouter et retirer des noms à cette liste (« tu fais maintenant autorité pour foobar.example et ton maître est 2001:db8:2011:04:11::53 »), ce qui n'est pas possible de manière standard actuellement,
  • Les clés de confiance utilisées dans des protocoles comme DNSSEC,
  • Les clés utilisées par TSIG (RFC 8945),
  • Les autorisations : qui a le droit de faire des mises à jour dynamiques (RFC 2136), qui a le droit de transférer le contenu de la zone, qui a le droit de faire des requêtes récursives, etc.

Le protocole, on l'a vu, doit également permettre la surveillance du bon fonctionnement du serveur. Des exemples de données utiles sont (section 3.3) :

  • État du serveur (« fonctionnement normal », « en cours d'arrêt », etc),
  • Statistiques de base, comme le nombre de requêtes traitées, le nombre d'erreurs, etc,
  • Liste des zones actuellement servies,
  • Alertes de sécurité.

Le serveur doit pouvoir transmettre ces informations à la demande du logiciel de surveillance, mais aussi pouvoir sonner des alarmes sans qu'on lui ait rien demandé (section 3.4) :

  • Changement d'état du serveur (« ça y est, je suis prêt » ou au contraire « plus de mémoire, j'arrête tout »),
  • Problème de sécurité (tentative de transfert d'une zone refusée, par exemple).

Un tel protocole, riche en fonctions, peut attirer l'attention des méchants : arrêter à distance un serveur de noms, sans avoir besoin de se connecter sur la machine, est tentant. D'où la section 4 qui pose les exigences de sécurité du protocole (voir aussi section 6). La plus importante est l'exigence d'une authentification mutuelle : le serveur de noms doit pouvoir authentifier le logiciel de gestion et réciproquement. Il est également nécessaire que le protocole soit confidentiel : des informations secrètes (comme les clés TSIG) seront parfois transmises par ce canal. Et, une fois l'authentification faite, le protocole doit permettre d'exprimer des autorisations détaillées : tel client peut ajouter des zones mais pas redémarrer le serveur, tel client peut lire toutes les informations mais n'en modifier aucune, etc.

La section 5 est ensuite un pot-pourri d'exigences supplémentaires pour le futur protocole de contrôle des serveurs de noms. On y trouve les grands classiques comme l'extensibilité dans le temps (futures fonctions) et dans l'espace, via des extensions spécifiques à un vendeur (un logiciel donné peut toujours avoir des fonctions très spéciales, trop spéciales pour être normalisées, mais qu'il serait intéressant de contrôler via le protocole).

Pour avoir une idée plus précise des fonctions d'un tel protocole, on peut regarder ce qui existe aujourd'hui. Comme exemple de serveur faisant autorité, essayons BIND. Son outil de contrôle à distance se nomme rndc. Il y a plusieurs moyens de le configurer (la plupart des paquetages binaires de BIND font tout cela automatiquement), ici, je vais générer une clé d'authentification et un fichier de configuration à la main. La clé est une clé secrète partagée, on la génère avec dnssec-keygen :

% dnssec-keygen -a hmac-md5 -n HOST -b 128 samplekey

Le fichier produit, ici Ksamplekey.+157+06915.private, contient le secret :

% cat Ksamplekey.+157+06915.private
...
Key: 7fCXQYhOXW+jkpEx9DuBdQ==
...

On va alors créer le fichier de configuration de rndc. Comme il contient un secret (la clé), il faudra s'assurer que ce fichier ait les bonnes protections :

options {
      default-server  localhost;
      default-key     samplekey;
};

server localhost {
      key             samplekey;
      addresses   { ::1 port 9153; };
};

key samplekey {
      algorithm       hmac-md5;
      secret          "7fCXQYhOXW+jkpEx9DuBdQ==";
};

Et il faut configurer le serveur de noms, dans son named.conf. Ici, le protocole de contrôle n'acceptera que localhost (::1) sur le port 9153 (la valeur par défaut est 953) :

key samplekey {
      algorithm       hmac-md5;
      secret          "7fCXQYhOXW+jkpEx9DuBdQ==";
};

controls {
     inet ::1 port 9153
             allow {::1;}
             keys {samplekey;};
};

Je me répète, attention à la sécurité. Car, s'il peut lire la clé, un utilisateur pourra arrêter BIND, supprimer des zones, etc.

Voyons maintenant des exemples d'utilisation :

% rndc status
version: 9.8.0
number of zones: 2
...
server is up and running

Cette commande était bien inoffensive. Mais on peut en faire d'autres comme :

  • Recharger une zone (rndc reload $MAZONE),
  • Arrêter le serveur (rndc stop),
  • Ajouter une nouvelle zone à servir (rndc addzone example.com '{ type master; file "example.com"; };'),
  • Et bien d'autres...

À la lumière du cahier des charges, que manque t-il à BIND ? Les grandes lignes y sont mais il manque pas mal de détails comme les notifications asynchrones, les changements d'ACL et peut-être la finesse des autorisations. rndc addzone nécessite une option spéciale dans named.conf mais elle s'applique à toutes les zones et, de toute façon, on ne peut pas la lier à certaines clés seulement. Une fois qu'on a un accès au serveur, c'est un accès total.

Comme exemple de serveur récursif, prenons Unbound. La configuration se fait dans le unbound.conf à peu près comme ceci (même adresse et port qu'avec BIND plus haut) :

remote-control:
	control-enable: yes
	control-interface: ::1
	control-port: 9153
	server-key-file: "unbound_server.key"
	server-cert-file: "unbound_server.pem"
	control-key-file: "unbound_control.key"
	control-cert-file: "unbound_control.pem"

Les certificats X.509 utilisés pour l'authentification peuvent facilement être créés avec unbound-control-setup. Le programme de contrôle du serveur utilise le même fichier de configuration unbound.conf (contrairement à BIND) :

% unbound-control status
version: 1.4.5
verbosity: 4
threads: 1
modules: 2 [ validator iterator ]
uptime: 206 seconds
unbound (pid 5315) is running...

et on peut faire plein de choses avec ce programme comme arrêter le serveur (unbound-control stop), afficher d'utiles statistiques (nombre de requêtes, nombre de succès et d'échecs de cache, etc, avec unbound-control stats), activer ou désactiver le relayage vers un autre serveur (unbound-control forward 2001:db8:42::53), vider le cache pour une zone donnée (unbound-control flush_zone example.com, notez qu'unbound_control a d'autres commandes de vidage, plus ou moins subtiles), etc.

Par rapport aux exigences de notre RFC 6168, on note que unbound-control ne permet pas de changer les clés de confiance utilisées par le serveur. Il ne peut pas non plus afficher les zones définies localement sur le récurseur (mais il permet d'en ajouter). Et la finesse des autorisations est insuffisante (la possibilité de créer des zones locales est ouverte à tous ceux qui ont un accès.) Autrement, il a une bonne partie de ce qu'il faut pour un récurseur.

Maintenant que le cahier des charges est fait, quelles sont les solutions pour le mettre en œuvre ? Historiquement, le protocole officiel de gestion des machines, à l'IETF, était SNMP. Comme on l'a vu, il y a même eu une tentative de s'en servir avec les serveurs DNS, tentative qui n'est pas allé loin. Aujourd'hui, la mode est plutôt à un autre protocole de gestion, Netconf (RFC 6241). Il existe une proposition, documentée dans l'Internet-Draft draft-dickinson-dnsop-nameserver-control, qui utilisera dans le futur Netconf (une version précédente de cette proposition incluait le protocole, et même une implémentation, mais la version actuelle se concentre sur le modèle de données). Voir la présentation au CENTR à Amsterdam en mai 2011.

Aux diverses réunions IETF sur le sujet, une alternative ne nécessitant pas un nouveau protocole avait souvent été proposée : se servir d'outils de gestion de configuration comme Chef ou Puppet. La principale limite de ces outils est qu'ils ne conviennent qu'à l'intérieur d'une même organisation et ne règlent pas facilement des problèmes multi-organisations.


Téléchargez le RFC 6168


L'article seul

RFC 6164: Using 127-Bit IPv6 Prefixes on Inter-Router Links

Date de publication du RFC : Avril 2011
Auteur(s) du RFC : M. Kohno (Juniper Networks, Keio University), B. Nitzan (Juniper Networks), R. Bush, Y. Matsuzaki (Internet Initiative Japan), L. Colitti (Google), T. Narten (IBM Corporation)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF 6man
Première rédaction de cet article le 23 avril 2011


Quelles adresses IP utiliser sur un lien point-à-point, lorsque les deux machines qui se parlent sont seules sur le lien ? Ce nouveau RFC recommande l'utilisation d'un préfixe de longueur /127 pour IPv6, ne permettant que deux adresses IP.

Cette recommandation existait déjà pour IPv4, dans le RFC 3021, qui recommande un /31. Pour IPv6, la norme, en l'occurrence le RFC 4291 préconisait au contraire un préfixe /64 pour tous les liens. Les adresses sous ce préfixe pouvaient alors être construites selon le format dérivé du EUI-64. Certains opérateurs avaient déjà ignoré cette norme et utilisaient des préfixes de longueur /127 (ne laissant qu'un seul bit pour identifier la machine), malgré l'avis du RFC 3627, qui mettait en avant le risque de confusion avec l'adresse anycast des routeurs. Notre RFC 6164 leur donne raison et officialise les préfixes /127.

Lorsqu'il n'y a que deux machines sur un lien (par exemple une liaison point-à-point, que ce soit parce qu'elle utilise un technologie purement point-à-point ou bien simplement parce qu'elle a été configurée ainsi), on peut aussi utiliser les adresses locales au lien (fe80::/10). Mais, comme le rappelle la section 2 de notre RFC, celles-ci ne sont pas toujours suffisantes : surveillance du réseau à distance, traceroute et BGP sont des exemples de bonnes raisons pour utiliser des adresses globales.

Quelles étaient les raisons pour se méfier des préfixes de longueur 127 ? La section 4 résume la principale : confusion possible avec l'adresse des routeurs du lien, définie en section 2.6.1 du RFC 4291. Or, non seulement l'expérience des opérateurs qui ont violé le RFC 3627 a été positive (pas de problèmes notés) mais on peut trouver des très bonnes raisons pour utiliser des préfixes plus spécifiques qu'un /64. La section 5 cite :

  • Risque de boucle de routage sur un préfixe plus général qu'un /127, si le lien n'utilise pas le NDP (c'est le cas de SONET).
  • Risque d'attaque par déni de service en épuisant le cache des voisins. Imaginons nos deux routeurs sur un Ethernet et étant configurés dans un préfixe /64. Tout paquet IP à destination d'une adresse de ce préfixe va faire l'objet d'une tentative de résolution par NDP (RFC 4861), et, pendant ce temps, le routeur devra garder une entrée dans sa table des voisins, avant de renoncer. Évidemment, aucune machine n'a une table des voisins de 2^64 entrées. Un méchant qui générerait des paquets à destination de toutes les adresses du préfixe /64 pourrait remplir cette table plus vite que l'expiration du délai de garde ne la vide. Notez que cette attaque n'est pas spécifique aux liens point-à-point mais ceux-ci sont souvent des liens vitaux, entre routeurs « importants ». Cette attaque peut être traitée en limitant le nombre de résolutions NDP en cours mais cela ne la résout pas complètement, alors que l'usage d'un /127 la supprime.
  • Sensation de gaspillage des adresses si on bloque un /64 pour seulement deux machines. Vue la taille de l'espace d'adressage d'IPv6, c'est le moins convaincant des arguments.

Synthétisant tout cela, la section 6 de notre RFC conclut qu'il faut utiliser les /127. Le logiciel des routeurs doit accepter de tels préfixes. Les opérateurs doivent faire attention à ne pas utiliser certaines adresses, celles-ci ayant une signification particulière : adresses où les 64 bits les plus à droite sont nuls, ou bien adresses dont ces mêmes bits ont une des 128 plus grandes valeurs (réservées par le RFC 2526).

Pour un exemple des discussions récurrentes /64 vs. /127, voir « Point-to-point Links and /64s ». Le RFC 3627 a été officiellement déclaré « d'intérêt historique seulement » par le RFC 6547. À noter que ce RFC 6164 ne met pas à jour formellement le RFC 5375, qui continuait avec les anciennes recommandations.


Téléchargez le RFC 6164


L'article seul

RFC 6156: Traversal Using Relays around NAT (TURN) Extension fo IPv6

Date de publication du RFC : Avril 2010
Auteur(s) du RFC : G. Camarillo, O. Novo (Ericsson), S. Perreault (Viagenie)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF behave
Première rédaction de cet article le 28 avril 2011


Le protocole TURN, qui permet à deux machines coincées derrière des routeurs NAT de communiquer en utilisant un relais tiers, a été normalisé dans le RFC 5766, dans une version minimale, uniquement pour IPv4 et seulement pour UDP, les services « incontestables », qui étaient pressés d'avoir une solution. Depuis, des extensions à TURN sont développées pour d'autres services. C'est ainsi que ce RFC 6156 permet d'utiliser TURN pour établir des liaisons en IPv6. Cette extension à TURN a depuis été intégrée dans la norme de base, le RFC 8656, remplaçant ce RFC.

Cette extension permet de communiquer avec une machine IPv4 depuis une machine IPv6, avec une machine IPv6 depuis une autre machine IPv6 et enfin avec une machine IPv6 depuis une machine IPv4 (section 1 du RFC). C'est donc une véritable solution de communication entre les deux protocoles, travaillant dans la couche 7 (contrairement aux techniques comme le NAT qui travaillent dans la couche 3). Le serveur TURN relais la totalité des données entre les deux clients TURN.

On peut se demander si un tel service est bien nécessaire. Après tout, TURN avait été inventé pour le cas du NAT, qui lui-même était motivé par le faible nombre d'adresses IPv4 disponibles. En IPv6, le problème de la pénurie ne se pose pas et TURN semble inutile. Toutefois, comme le note le RFC 5902, il risque d'y avoir quand même des réseaux IPv6 NATés, peut-être avec des adresses ULA à l'intérieur, et TURN peut donc trouver sa place ici. Autre utilité : TURN peut aider les machines purement v4 (la majorité d'aujourd'hui) et les machines purement v6 (qui se répandront sans doute) à communiquer entre elles. Enfin, TURN peut aussi être utile pour un administrateur de pare-feu à état pour permettre aux utilisateurs d'ouvrir des ports afin de recevoir des connexions entrantes. TURN a été conçu pour qu'il soit très restreint dans ce qu'il accepte, de façon à ce que les administrateurs de pare-feux puissent lui faire confiance.

La nouvelle extension fonctionne avec un nouvel attribut TURN, REQUESTED-ADDRESS-FAMILY, valeur 0x0017 (section 3). L'attribut XOR-RELAYED-ADDRESS (RFC 5766, section 14.5, et section 4.2 de notre RFC) de la réponse contiendra une adresse de la famille demandée (v4 ou v6). La famille d'adresse du client est déterminée, elle, en regardant l'adresse utilisée pour contacter le serveur. À noter que chaque demande d'allocation TURN ne peut gérer qu'une seule adresse IP. Le client qui voudrait communiquer avec une adresse IPv4 et une v6 devra faire deux demandes d'allocation. Si le serveur ne veut ou ne peut pas gérer une famille donnée, il répondra 440 (Address Family not Supported).

La section 4 contient ensuite les détails concrets comme le format du nouvel attribut (section 4.1.1). Celui-ci a le numéro 0x0017, ce qui le met dans les plages des attributs dont la compréhension par le serveur est impérative. Un vieux serveur qui ne met pas en œuvre notre RFC ne peut donc pas ignorer cet attribut.

Un problème qui a toujours été très chaud dans le groupe Behave est celui de la traduction des paquets. Comme on dit en italien, « Traduttore, Traditore » (traducteur = traître). Lorsqu'un serveur TURN relaie des paquets, doit-il respecter toutes les options de l'en-tête IP ? La question est évidemment encore plus difficile pour une traduction entre IPv4 et IPv6. La section 8 fournit les règles. Par exemple, lors de la traduction de IPv4 vers IPv6 (section 8.1), que doit valoir le champ Traffic Class (RFC 2460, section 7) d'un paquet IPv6 sortant ? Le comportement souhaité est celui spécifié dans la section 3 du RFC 7915 (RFC qui décrit le mécanisme de traduction de IPv4 vers IPv6, notamment pour l'utilisation dans NAT64). Le comportement possible est d'utiliser la valeur par défaut de ce champ. Le Flow label (RFC 2460, section 6), lui, devrait être mis à zéro (il n'a pas d'équivalent IPv4). Et pour les en-têtes d'extensions IPv6 (RFC 2460, section 4) ? Aucun ne doit être utilisé, dans tous les cas (sauf la fragmentation).

Et si on relaie entre deux machines IPv6 ? Ce sont quasiment les mêmes règles, comme indiqué par la section 8.2. Par exemple, bien qu'il existe un Flow label des deux côtés, on considère que TURN, relais de la couche 7, ne devrait pas essayer de le copier : il y a deux flots différents de part et d'autre du serveur TURN.

Cette extension de TURN pose t-elle des problèmes de sécurité ? Potentiellement oui, répond la section 9. En effet, elle donne aux machines des capacités nouvelles. Ainsi, une machine purement IPv6 obtient, si elle a le droit d'accéder à un serveur TURN mettant en œuvre ce RFC 6156, la possibilité de parler aux machines purement IPv4, possibilité qu'elle n'avait pas avant. Comme il est recommandé de ne faire fonctionner TURN qu'avec une authentification préalable des clients, ce n'est sans doute pas une question sérieuse en pratique.

La section 10 décrit l'enregistrement à l'IANA des nouveaux paramètres (attribut REQUESTED-ADDRESS-FAMILY et codes d'erreur 440 et 443) dans le registre des paramètres STUN (rappelez-vous que TURN est défini comme une extension de STUN).

Question mise en œuvre, il en existe une côté serveur, non distribuée mais accessible vie le réseau (voir http://numb.viagenie.ca/), une libre qui a IPv6 depuis la version 0.5, mais apparemment rien encore côté client.

Merci à Simon Perreault pour sa relecture et ses remarques.


Téléchargez le RFC 6156


L'article seul

RFC 6151: Updated Security Considerations for the MD5 Message-Digest and the HMAC-MD5 Algorithms

Date de publication du RFC : Mars 2011
Auteur(s) du RFC : S. Turner (IECA), L. Chen (NIST)
Pour information
Première rédaction de cet article le 7 mars 2011


Ce RFC marque un peu l'enterrement officiel de MD5 dans les protocoles IETF. Cet algorithme de cryptographie, très répandu et très utilisé, décrit dans le RFC 1321, a connu de nombreuses attaques cryptanalytiques réussies et, pour plusieurs de ces usages, ne doit plus être considéré comme offrant une protection raisonnable. Une bonne partie de la sécurité de l'Internet reposait historiquement sur des protocoles utilisant MD5 et c'est donc un chapitre important qui se clot.

Peut-on dire aujourd'hui que MD5 est « cassé » et n'offre plus aucune protection ? La réponse doit en fait être plus nuancée et cela explique que ce très court RFC ait fait l'objet d'une aussi longue discussion à l'IETF, pour ne sortir que maintenant. En effet, si on voit souvent des affirmations hâtives de la part des ignorants, prétendant sans nuance que MD5 a été cassé, la réalité est plus complexe.

La section 1 rappelle en effet l'état de l'art. MD5 est utilisé pour deux choses :

Dans le premier cas, MD5 n'offre en effet plus une sécurité acceptable face à un attaquant (il reste utilisable lorsque le seul but est de détecter des erreurs produites par un processus aveugle, par exemple des parasites sur la ligne). Pour le second cas, c'est moins évident.

C'est qu'il existe plusieurs types d'attaques contre les fonctions de hachage cryptographiques comme MD5 (voir le RFC 4270). Par exemple, une attaque par collision consiste en la production de deux messages ayant le même condensat. Ce sont ces attaques auxquelles MD5 est le plus vulnérable. Si un document est signé via un condensat MD5, il est aujourd'hui simple de créer deux documents ayant le même condensat MD5, ce qui annule une bonne partie de l'intérêt des signatures.

Mais MD5 résiste bien mieux à d'autres attaques comme celles par pré-image, où un attaquant cherche à fabriquer un message ayant le même condensat qu'un message donné. C'est une tâche nettement plus complexe que la collision, où l'attaquant contrôle les deux messages. Donc, chaque protocole ou application qui utilise MD5 doit analyser si son usage de cette fonction est acceptable ou pas, compte-tenu de l'état de l'art en cryptographie.

Pour voir la différence entre ces deux problèmes, reprenons la commande md5sum. Soit un fichier toto.txt. md5sum calcule le condensat :

% md5sum /tmp/toto.txt 
0365023af92c568e90ea49398ffec434  /tmp/toto.txt

Une attaque par pré-image consisterait en la création d'un nouveau fichier ayant le même condensat 0365023af92c568e90ea49398ffec434 que toto.txt. Cela reste une tâche non-triviale. Une attaque par collision permet au contraire à l'attaquant de choisir le condensat à produire. Avec l'aide du paradoxe de l'anniversaire, c'est bien plus facile. Mais cela ne marche que si l'attaquant a le choix des données, ce qui est partiellement vrai pour les signatures mais pas pour HMAC. (Voir une bonne explication des différentes possibilités d'attaque, assez trapue mais originale, en « Meaningful Collisions (for SHA-1) ».)

La section 2 liste les attaques publiées contre MD5. Attention, en cryptanalyse, toutes les attaques réussies ne sont pas publiées, certains préférant les garder pour eux. Il faut donc toujours prévoir une marge en se disant que, si une attaque publiée permet de casser un algorithme de cryptographie en un mois, les attaques non publiées peuvent sans doute le faire en quelques jours, voire quelques heures.

Donc, les attaques par collision réussies contre MD5 ont été publiées pour la première fois en 1993. Les progrès ont été importants en 2004 avec « Cryptanalysis of HMAC/NMAC-MD5 and MD5-MAC » de Wang, Feng, Lai et Yu. En 2006, une attaque publiée descend à une seule minute de temps d'exécution sur un portable normal. En 2007, ce genre d'attaques a pu casser des certificats X.509. Il est donc clair que MD5 ne doit plus être utilisé pour la signature numérique. (En cherchant, vous trouverez probablement un certain nombre de sites Web qui ont toujours un certificat utilisant MD5.)

Au contraire, comme le note la section 2.2, les meilleures « attaques » pré-image publiées n'ont pas encore abouti. Quelles sont les conséquences pour HMAC (section 2.3) ? S'il y a eu plusieurs tentatives de casser HMAC-MD5 (tel qu'il est utilisé, par exemple, dans TSIG, RFC 8945), aucune de celles publiées n'a réussi. Il n'y a donc pas d'urgence à supprimer MD5 lorsqu'il est utilisé ainsi, néanmoins des remplaçants sont prêts (cf. RFC 4231) et peuvent être intégrés dans les nouvelles versions des protocoles (RFC 6039). Notez que les faiblesses de MD5 ne sont évidemment pas spécifiques aux protocoles Internet, voir par exemple la documentation de GnuPG.


Téléchargez le RFC 6151


L'article seul

RFC 6147: DNS64: DNS extensions for Network Address Translation from IPv6 Clients to IPv4 Servers

Date de publication du RFC : Avril 2011
Auteur(s) du RFC : M. Bagnulo (UC3M), A. Sullivan (Shinkuro), P. Matthews (Alcatel-Lucent), I. van Beijnum (IMDEA Networks)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF behave
Première rédaction de cet article le 28 avril 2011


Ce nouveau RFC est un composant indispensable de la nouvelle technique de traduction entre des machines IPv4 et IPv6 (dont une description générale se trouve dans le RFC 6144). Les machines purement IPv6 ne pouvant pas initier une communication avec des machines n'ayant qu'une adresse IPv4, il est nécessaire de les « tromper » en fabriquant dynamiquement des adresses IPv6. Les machines IPv6 tenteront alors de s'y connecter, leurs requêtes seront reçues par le traducteur d'adresses, qui pourra alors les convertir en IPv4 (cf. RFC 7915 et RFC 6146).

DNS64 n'est donc pas utilisable seul. Il doit se combiner à une machine, typiquement un routeur, qui fait la traduction d'adresses, dite NAT64. La configuration typique des utilisateurs de DNS64 sera un réseau local purement IPv6 (puisque le stock d'adresses IPv4 est épuisé), dont le routeur fait de la traduction NAT64, et qui est muni d'un résolveur DNS capable de fabriquer des adresses IPv6 à partir des adresses v4 des machines externes. En effet, le but du système NAT64 est de ne pas avoir à modifier les machines, seulement les équipements d'infrastructure (routeur et résolveur DNS). Les machines purement v6, ignorantes de la traduction qui se fait entre leur réseau et le monde extérieur, ne pourraient pas se connecter si elle ne connaissaient de leur pair qu'une adresse IPv4. NAT64 et son indispensable compagnon DNS64 rejoignent donc la boîte à outils des techniques permettant de faire coexister IPv4 et IPv6 (cf. RFC 6144).

Comment est-ce que le serveur DNS64 synthétise cette adresse IPv6 ? Supposons qu'une machine IPv6 du réseau local veuille se connecter à www.example.com et que celui-ci n'ait qu'une adresse v4, mettons 203.0.113.18. Le navigateur Web tournant sur le client va faire une requête DNS de type AAAA (adresse IPv6 ; puisqu'il n'a pas d'IPv4, les requêtes de type A n'auraient aucun intérêt). Le serveur DNS la reçoit, la relaie et récupère une réponse vide (le nom existe mais n'a pas d'enregistrement AAAA). Il tente alors une requête A, reçoit 203.0.113.18 en réponse et génère l'adresse v6 de manière purement algorithmique, sans état, en utilisant l'adresse v4 et les paramètres avec lesquels le serveur a été configuré (typiquement, un préfixe v6). Rappelez-vous donc bien que le serveur DNS64 et le traducteur doivent être configurés de manière cohérente (dans la plupart des cas, ils seront sans doute dans la même boîte mais, conceptuellement, ce sont deux services séparés.)

Pour le lecteur pressé qui veut juste une introduction à la norme, la section 2 est la meilleure lecture. Voici un exemple où une machine purement IPv6 tente de contacter Twitter, service purement IPv4 :

% telnet twitter.com 80
Trying 64:ff9b::80f2:f0f4...
Connected to twitter.com.
Escape character is '^]'.

C'est le serveur DNS64 qui a généré l'adresse 64:ff9b::80f2:f0f4 et c'est le traducteur qui changera les paquets IPv6 en IPv4 à l'aller et en sens inverse au retour. Twitter et le client purement IPv6 n'y verront que du feu. Pour le préfixe à utiliser, le serveur DNS64 et le traducteur ont le choix (cf. RFC 6052) entre un préfixe bien connu, réservé à la traduction d'adresse (celui utilisé dans l'exemple, qui avait été testé lors d'une réunion IETF à Pékin) ou bien un préfixe appartenant à l'opérateur réseau (NSP, pour Network-Specific Prefix). La seule contrainte est qu'il doit être configuré de manière identique dans le serveur DNS64 et dans le traducteur.

La norme elle-même fait l'objet de la section 5. Elle décrit avec précision le fonctionnement que j'ai résumé plus haut. Quelques petits points intéressants :

  • On ne synthétise d'enregistrements que s'il n'y avait pas déjà un AAAA (section 5.1.1).
  • Les erreurs (autres que NXDOMAIN - No Such Domain) doivent être traitées comme si le AAAA étai absent (section 5.1.2). Donc, par exemple, SERVFAIL (Server Failure) doit être traité comme un NOERROR,ANSWER=0, pour tenir compte des serveurs assez pourris pour ne pas répondre correctement aux requêtes AAAA (cf. RFC 4074). C'est une violation des normes du DNS, rendue nécessaire par le nombre de serveurs DNS (ou de middlewares placés devant eux) programmés avec les pieds.
  • La règle précédente, interdisant la synthèse d'enregistrements AAAA s'il en existe déjà, a quelques exceptions (section 5.1.4). Ainsi, les adresses IPv6 non utilisables globalement comme celles en ::ffff:0:0/96 doivent être ignorés et le AAAA de synthèse produit.
  • Si le AAAA n'existe pas ou est inutilisable (section 5.1.6), le serveur DNS64 demande un enregistrement A (adresse IPv4). S'il n'en trouve pas, il répond au client « Désolé, aucune réponse ». S'il en trouve un, il fabrique l'enregistrement AAAA correspondant (typiquement en concaténant le préfixe IPv6 avec l'adresse IPv4) et le renvoie (la réponse de type A, elle, n'est pas transmise). La section 5.1.7 donne les détails de cette synthèse.
  • Les deux requêtes, pour un enregistrement de type AAAA et pour un enregistrement de type A, peuvent être faites en parallèle (section 5.1.8). Certes, ce sera un gaspillage si l'enregistrement AAAA existe (puisque le A sera alors inutile) mais cela permettra de diminuer le temps total d'attente si le AAAA n'existe pas.

J'ai dit plus haut que l'adresse IPv6 de synthèse était fabriquée par concaténation du préfixe IPv6 (configuré à la main dans le serveur DNS64) et de l'adresse IPv4. Mais, en fait, le RFC n'impose pas l'utilisation d'un tel algorithme. La méthode utilisée n'a pas besoin d'être normalisée (elle n'est pas vue à l'extérieur) et doit seulement être la même sur le serveur DNS64 et sur le traducteur. La section 5.2 précise plus rigoureusement les exigences auxsquelles doit obéir cet algorithme. Le point le plus important est qu'il doit être réversible : en échange de l'adresse IPv6 de synthèse, le traducteur doit pouvoir retrouver l'adresse IPv4 originelle. Pour faciliter la vie des administrateurs réseau, un algorithme doit être obligatoirement présent dans les programmes (mais ce n'est pas forcément celui que l'administrateur choisira), celui décrit en section 2 du RFC 6052.

Et que doit faire le serveur DNS64 s'il reçoit des requêtes d'un autre type que A ou AAAA ? La section 5.3 couvre ce cas. En gros, il doit les traiter normalement sauf les requêtes de type PTR (résolution d'une adresse en nom). Dans ce cas, le serveur doit extraire l'adresse du nom en ip6.arpa (section 2.5 du RFC 3596), regarder si cette adresse correspond à un des préfixes qu'il gère et, si oui, le serveur DNS64 a deux possibilités :

  • Répondre immédiatement, avec autorité, en utilisant un nom adapté (qui peut être le même pour toutes les adresses, mettons locally-generated-ipv6-address-with-dns64.example.net). L'avantage est que les clients DNS verront bien que l'adresse avait été synthétisée, l'inconvénient est qu'on n'utilisera pas les informations qui pouvaient se trouver dans le DNS,
  • Synthétiser les enregistrements PTR à partir de données trouvées dans le DNS, comme il synthétise des enregistrements AAAA à partir des A récupérés dans le DNS. Dans ce cas, le serveur DNS64 traduit l'adresse IPv6 en IPv4, crée un nom dans in-addr.arpa, fait une requête PTR et renvoie le résultat au client.

La section 6, sur le déploiement, est consacrée aux problèmes pratiques qui pourront survenir lorsqu'on utilisera réellement DNS64. Par exemple, si une machine est multi-homée, il est possible que seulement certaines de ses connexions à l'Internet passent par un traducteur v4-v6. Il faudrait donc idéalement interroger des résolveurs DNS différents selon l'interface de sortie, et considérer les résultats comme locaux à l'interface.

Autre problème pratique, le cas d'une machine à double-pile qui utiliserait DNS64, passant ainsi par le traducteur même lorsque ce n'est pas nécessaire (section 6.3.2 et 6.3.3). Comme la configuration par défaut des systèmes d'exploitation est de préférer IPv6 à IPv4, le cas risque de se produire souvent. Il n'existe pas de moyen simple de le détecter puisque, pour le client, un serveur DNS64 semble un serveur comme un autre. Une machine double-pile (IPv4 et IPv6) ne devrait donc pas utiliser de résolveur DNS64. Mais il peut y avoir des cas où c'est nécessaire, par exemple si la machine double-pile n'a une connectivité IPv4 que partielle. Dans ces conditions, le serveur DNS64 doit exclure les préfixes IPv4 locaux de la synthèse. On peut donc prévoir quelques problèmes de débogage amusants...

La section 7 décrit des exemples de déploiement, en utilisant les scénarios du RFC 6144. Par exemple, la section 7.1 cite le cas qui sera sans doute le plus fréquent au début, une machine H1 réseau purement IPv6 (parce que arrivé après l'épuisement des adresses IPv4) qui essaie de se connecter à un serveur H2 situé dans l'Internet v4 traditionnel. Le traducteur T et le serveur DNS sont configurés avec le préfixe bien connu 64:ff9b::/96. H1 va commencer par faire une requête AAAA pour h2.example.com. Le résolveur DNS ne trouve pas de AAAA pour ce nom, mais il récupère un enregistrement de type A, 192.0.2.1. Il fabrique alors le AAAA 64:ff9b::c000:201 (qui peut aussi légitimement s'écrire 64:ff9b::192.0.2.1). H1 va alors envoyer un paquet TCP SYN à 64:ff9b::c000:201. Le routeur/traducteur le voit passer, note le préfixe NAT64 avec lequel il a été configuré et le traduit en un paquet TCP/IPv4.

Autre exemple, en section 7.3. C'est à peu près l'inverse : une machine dans un Internet passé presque entièrement en IPv6 essaie de se connecter à un des derniers serveurs v4 existants. À noter que DNS64 n'est pas indispensable dans ce cas : on peut simplement affecter algorithmiquement une adresse IPv6 à toutes les adresses IPv4, les publier sur des serveurs DNS normaux, et donc n'utiliser que le traducteur. Toutefois, cette section cite quelques cas où DNS64 peut être utile, par exemple si les adresses IPv4 sont affectées dynamiquement.

Fondamentalement, un serveur DNS64 est un menteur : il fabrique des réponses qui n'existent pas (Twitter, utilisé dans l'exemple plus haut, n'a pas d'adresse IPv6 à ce jour...). Il a donc des problèmes avec DNSSEC, qui a justement été conçu pour détecter les mensonges. Toute la section 3 est consacrée à discuter ce problème. Bien sûr, le résolveur DNS64 ment pour la bonne cause. Mais DNSSEC est au delà du bien et du mal, il se moque des motivations, il ne regarde que le résultat. Plusieurs cas peuvent se poser (le RFC en identifie sept !) selon les options indiquées dans la requête DNS et selon la configuration DNSSEC utilisée. Rappelons que les deux options importantes pour DNSSEC dans une requête DNS sont le bit DO (DNSSEC OK, RFC 4035, section 3.2.1) qui indique si le client DNS comprend les enregistrements DNSSEC et le bit CD (Checking Disabled, RFC 4035, section 3.2.2) qui indique au résolveur que le client fera la validation lui-même et qu'il faut lui envoyer toute l'information, même si elle s'avère fausse.

Les différents cas sont donc (je ne les ai pas tous mentionnés, voir le RFC pour les détails) :

  • Un serveur DNS64 reçoit une requête où DO est à zéro (ce que font aujourd'hui la plupart des bibliothèques de résolution de noms, les stub resolvers). Aucun problème dans ce cas, le client ne comprend pas DNSSEC, le serveur DNS64 peut inventer tous les mensonges qu'il veut.
  • Un serveur DNS64 avec gestion de DNSSEC reçoit une requête avec DO et CD mis à zéro (c'est typiquement le cas - rare - d'un client qui veut valider lui-même). Dans ce cas, il doit passer au client toute l'information obtenue. DNS64 ne marchera pas ici, le client n'acceptera pas le AAAA synthétisé comme étant valide. La seule solution est que le client mette en œuvre DNS64 lui-même.
  • Un serveur DNS64 qui valide avec DNSSEC reçoit une requête avec DO à un et CD à zéro (ce sera sans doute le cas le plus courant dans le futur). Aucun problème, le serveur DNS64 valide les données récupérées et répond SERVFAIL (Server Failure) si cette validation échoue. Le AAAA synthétisé n'est pas validé avec DNSSEC mais le client ne le saura pas. Si le bit DO était mis à un, le serveur DNS64 a juste à mettre le bit AD (Authentic Data) à un dans sa réponse (un mensonge pour la bonne cause ; après tout, si le client DNS n'a pas mis CD à un, c'est qu'il fait complètement confiance au résolveur).

La section 5.5 donne les détails sur le fonctionnement de DNSSEC dans DNS64. La section 6.2 rappelle les problèmes pratiques de déploiement de DNS64 si on utilise déjà DNSSEC.

DNS64 pose t-il des problèmes de sécurité ? Pas beaucoup, dit la section 8. Comme indiqué (paragraphes précédents), il peut interférer avec DNSSEC. Et, surtout, il impose une coordination entre le serveur DNS64 et le traducteur. Si un attaquant peut modifier la valeur du préfixe du serveur DNS64, il peut envoyer les paquets où il veut. Donc, attention, la sécurité du serveur DNS64 est exactement aussi importante que celle du traducteur.

Enfin, l'annexe A explique des motivations pour générer un AAAA alors qu'il existe déjà. Il se peut que la meilleure route passe plutôt par le traducteur et donc, dans certains cas, un serveur DNS64 peut offrir à son administrateur la possibilité de permettre la synthèse d'enregistrements AAAA même quand un vrai existe.

BIND met en œuvre DNS64 depuis les versions 9.7.3 et 9.8.0. Voici un exemple de configuration de DNS64 avec une 9.8.0 :

acl me {
    ::1/128; 127.0.0.0/8;
};
acl rfc1918 { 
    10/8; 192.168/16; 172.16/12; 
};

options {
       ...
       dns64 64:ff9b::/96 { // The well-known prefix
              clients { me; };
              mapped { !rfc1918; any; }; // Never synthetize AAAA records
                     // for private addresses
              exclude { 64:ff9b::/96; ::ffff:0000:0000/96; }; // If the retrieved
              // AAAA record is in that range, do not send it back to the user,
              // synthetize a AAAA.
              //
              // suffix ::42; // Trailing bits. Require some free space (here, 
              // 96 + 32 bits leave no room for trailing bits).
        };

Le premier préfixe est celui des AAAA synthétisés (ici, le préfixe bien connu). La directive clients réduit le service DNS64 à certaines machines seulement (celles qui sont connectées via un traducteur NAT64, relisez les sections 6.3.2 et 6.3.3 du RFC). La directive mapped met en œuvre la règle d'exclusion des préfixes IPv4 locaux (ici, ceux du RFC 1918). La directive exclude implémente la règle d'exclusion des préfixes IPv6 qui ne devraient même pas être mis dans le DNS global. S'il existe un AAAA, mais qu'il pointe vers un des ces préfixes, il sera remplacé par un AAAA synthétique. Enfin, la directive suffix permet d'ajouter quelques bits à la fin du AAAA de synthèse (mais, ici, avec 96 bits pour le préfixe IPv6 et 32 pour l'adresse IPv4, il n'y a plus de place).

Voici l'effet du serveur ayant la configuration ci-dessus (il écoute sur le port 9053) :

[Adresse IPv6 déjà dans le DNS global.]
% dig +short -p 9053 @::1 AAAA www.ietf.org 
2001:1890:1112:1::20

[Pas d'adresse IPv6 dans le DNS global mais trois adresses IPv4.]
% dig +short -p 9053 @::1 AAAA facebook.com
64:ff9b::453f:bd0b
64:ff9b::453f:bd10
64:ff9b::453f:b50c

[Les requêtes PTR marchent bien, BIND synthétise un CNAME, une des
deux techniques permises par le RFC.]
% dig  -p 9053 @::1 -x 64:ff9b::453f:bd10      
...
;; QUESTION SECTION:
;0.1.d.b.f.3.5.4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.b.9.f.f.4.6.0.0.ip6.arpa. IN PTR

;; ANSWER SECTION:
0.1.d.b.f.3.5.4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.b.9.f.f.4.6.0.0.ip6.arpa. 600 IN CNAME 16.189.63.69.in-addr.arpa.
16.189.63.69.in-addr.arpa. 7172 IN      PTR     www-11-01-ash2.facebook.com.
...

[Ici, le nom a une adresse IPv4 mais privée. L'ACL 'rfc1918' va donc
la bloquer.]
% dig +short -p 9053 @::1 A ciel.administratif.prive.nic.fr                  
10.1.84.200

% dig  -p 9053 @::1 AAAA ciel.administratif.prive.nic.fr                         
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 0
                              ^^^^^^^^^

Pour comparer, voici une configuration BIND avec un préfixe du FAI (NSP pour Network-Specific Prefix). Plus court que le précédent, il dégage de la place pour le suffixe :

       dns64 2001:db8:666::/48 { // A Network-Specific Prefix (NSP).
              clients { me; };
              suffix ::42; // Trailing bits.
        };

Et voici les résultats :

% dig +short -p 9053 @::1 AAAA facebook.com
2001:db8:666:453f:bd:1000:0:42
2001:db8:666:453f:b5:c00:0:42
2001:db8:666:453f:bd:b00:0:42

Si vous voulez manipuler les adresses vous-même, voici un joli script awk dû à gbfo, pour traduire les adresses IPv6 en la v4 correspondant :

% echo 64:ff9b::453f:bd0b | \
        awk -F: '{h=strtonum("0x" $(NF-1));l=strtonum("0x" $NF);printf("%d.%d.%d.%d\n",h/256,h%256,l/256,l%256);}' 
69.63.189.11

Question mises en œuvre de DNS64, outre le cas de BIND, déjà présenté, il existait une rustine pour Unbound, chez Viagénie (avec un très ennuyeux système de formulaire à remplir pour l'obtenir). Cette rustine porte sur une version ancienne du protocole, mais Unbound a désormais DNS64 en série. Il y a aussi au même endroit un serveur DNS64 autonome, écrit en Perl. Ce dernier est très court et peut donc être un bon moyen de comprendre le protocole, pour ceux qui aiment lire le code source. Enfin, Cisco a désormais DNS64 sur ses produits.

Voici un exemple de configuration Unbound pour un serveur DNS64 :

server:
   module-config: "dns64 validator iterator"
   dns64-prefix: 64:ff9b::0/96

Et mon opinion personnelle sur DNS64 ? Je dirais que, certes, c'est un hack, mais qu'on a vu pire et que ça traite un vrai problème. DNS64 semble bien pensé, rien n'est oublié et le RFC parle bien de tous les problèmes, notamment avec DNSSEC.

Pour un récit très détaillé, avec plein de technique, d'un test de NAT64 avec DNS64, voir l'article de Jérôme Durand « J'ai testé pour vous : Stateful NAT64 avec DNS64 ».

Notez qu'il existe des résolveurs DNS publics ayant DNS64 (évidemment uniquement avec le préfixe bien connu), comme celui de Hurricane Electric, nat64.he.net / 2001:470:64::1 ou celui de Google, google-public-dns64-b.google.com / 2001:4860:4860::6464.


Téléchargez le RFC 6147


L'article seul

RFC 6146: Stateful NAT64: Network Address and Protocol Translation from IPv6 Clients to IPv4 Servers

Date de publication du RFC : Avril 2011
Auteur(s) du RFC : M. Bagnulo (UC3M), P. Matthews (Alcatel-Lucent), I. van Beijnum (IMDEA Networks)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF behave
Première rédaction de cet article le 28 avril 2011


Dans la grande série des techniques de coexistence entre IPv4 et IPv6, voici une normalisation de NAT64, une technique de traduction entre IPv6 et IPv4, permettant à une machine purement IPv6 de se connecter à une machine purement IPv4. Ce RFC fait partie de la série introduite par le document d'architecture générale RFC 6144.

Aujourd'hui, l'état de l'Internet est que la majorité des serveurs sont accessibles uniquement en IPv4. Or, les dernières adresses IPv4 disponibles à l'IANA ont été distribuées le 3 février 2011. Demain, les nouvelles machines recevront donc de plus en plus uniquement des adresses IPv6. Comment se connecteront-elles à ces serveurs purement v4 ? Une des solutions est de traduire automatiquement les paquets IPv6 du client en IPv4 pour les envoyer au serveur, et de faire la traduction inverse au retour. Cela se nomme NAT64 et notre RFC normalise la version « à état » de cette méthode. « À état » car le traducteur garde un souvenir des flux de données en cours et peut donc, pour la traduction, tenir compte d'un état, des paquets précédents (la version sans état est dans le RFC 7915).

Notez le titre de ce RFC : ses ambitions sont limitées, il ne s'agit pas, comme l'essayait le défunt NAT-PT (RFC 2766) de fournir une solution générale à tous les problèmes de communication v4-v6 mais seulement de permettre à des clients IPv6 de se connecter à des serveurs IPv4.

NAT64 ressemble beaucoup à l'actuel NAT44 (celui que tout le monde est obligé d'utiliser à l'hôtel, chez lui s'il a plusieurs machines, cf. RFC 3022) dans la mesure où il permet :

  • Aucune modification au client ou au serveur, tout est fait dans le routeur du réseau IPv6-pur,
  • Les communications client-serveur, comme le titre de notre RFC le précise,
  • Certaines communications pair-à-pair, en utilisant des techniques comme ICE (RFC 5245),
  • Des communications lancées depuis l'extérieur, si on a configuré statiquement le traducteur pour reconnaître certaines adresses.

Il s'en distingue par le fait qu'on ne se contente pas de traduire les adresses, il faut traduire tout l'en-tête du paquet, et par le fait que, pour que les applications tournant sur la machine purement IPv6 trouvent une adresse IPv6, un serveur DNS spécial, DNS64 (RFC 6147) est nécessaire. Vu la nécessité de faire plus de travail qu'en NAT44, la spécification ne fonctionne que pour certains protocoles des couches supérieures, pour l'instant uniquement ICMP, UDP et TCP. Ne comptez donc pas faire, par exemple, du SCTP.

Notre RFC s'appuie sur plusieurs autres documents, celui d'architecture (RFC 6144), celui sur la traduction des adresses (RFC 6052), et celui sur l'algorithme de traduction (RFC 7915).

Les équipements qui font faire le travail sont donc :

  • Le traducteur, qui sera typiquement embarqué dans le routeur (CPE, box, ou bien plus loin dans le réseau de l'opérateur),
  • Le résolveur DNS64, qui pourra être inclus dans le même routeur ou bien fourni séparement.

Normalement, les traducteurs qui suivront ce RFC seront conformes aux recommandations qu'avait édicté le groupe de travail Behave, dans sa première version, à savoir les RFC 4787, RFC 5382, RFC 5508... et ils permettront les techniques de passage au travers des NAT comme ICE (RFC 5245).

La norme elle-même commence en section 3 mais une gentille introduction, utilisable si vous ne connaissez pas grand'chose aux NAT, figure en section 1.2. Essayons de la résumer sommairement en prenant pas mal de raccourcis : le traducteur a donc deux interfaces, une vers le réseau IPv6-pur et une vers un réseau IPv4 (et peut-être aussi IPv6 mais, dans ce cas, pas besoin de traduction). Le traducteur doit donc avoir une adresse IPv4 publique. Lorsqu'il reçoit un paquet IPv6 dont l'adresse de destination indique qu'il doit être traduit, il le transforme en IPv4 (l'adresse IPv4 est encapsulée dans l'adresse IPv6), et l'envoie par l'interface IPv4. Au retour, c'est un peu plus dur car l'adresse IPv4 de destination est celle du traducteur et, pour retrouver l'adresse IPv6 du vrai destinataire, il doit consulter une table où il a stocké les clients IPv6 qui parlaient à l'extérieur. Comme en NAT44, le numéro de port est utilisé pour reconnaitre les clients locaux. La combinaison d'une adresse IP et d'un port est appelée « adresse de transport ». On le voit, cela ne marche bien que si c'est le réseau IPv6 qui initie la communication (mais diverses astuces permettent des communications un peu plus pair-à-pair).

Le NAT64 devrait donc être appelé NAPT (Network Address AND PORT Translation) car, dans l'écrasante majorité des cas, le traducteur n'aura pas assez d'adresses IPv4 pour tous les clients IPv6 qu'il sert (si on avait assez d'adresses v4, il n'y aurait guère de raison de migrer vers v6).

Comment le client IPv6 a-t-il trouvé l'adresse IPv6 de destination, puisque le serveur n'a qu'une adresse IPv4 ? C'est le rôle du serveur DNS64 qui ment (pour la bonne cause) en fabriquant un enregistrement DNS de type AAAA (adresse IPv6) à partir de l'enregistrement réel A (adresse IPv4). Les étapes complètes effectuées par le client sont décrites en section 1.2.2.

On a vu que cette opération nécessitait de réserver une partie de l'espace d'adressage IPv6 pour représenter les adresses IPv4. Cette partie peut être localement définie (après tout, seuls le traducteur et le résolveur DNS64 auront besoin de la connaître) ou bien on peut utiliser le préfixe standard 64:FF9B::/96. Ici, on voit un serveur DNS64 et un traducteur coopérer pour permettre à une machine purement IPv6 de communiquer avec www.example.com, qui n'a qu'une adresse IPv4 : nat64.

Du fait que le traducteur a un état, tous les paquets IPv4 venus de l'extérieur ne sont pas acceptés. Seuls peuvent être transmis ceux qui correspondent à une correspondance existante, en suivant les règles des RFC 4787 et RFC 5382 (Endpoint-Independent Filtering et Address-Dependent Filtering ; suivre ces règles est important pour que les applications pair-à-pair fonctionnent).

Voilà pour l'introduction. Maintenant, pour lire la spécification elle-même, il faut d'abord bien apprendre la terminologie, en section 2. Quelques termes qui ne sont sans doute pas familiers à tous :

  • Un quintuplet est l'identificateur d'une session TCP ou UDP. Il est composé de {adresse IP source, port source, adresse IP destination, port destination, protocole de couche 4}.
  • La BIB (Binding Information Base) est la liste des communications actuellement en cours, pour un protocole de transport donné. Une liaison (binding) est faite entre une adresse de transport IPv4 et une IPv6, afin de déterminer à qui « appartient » un paquet entrant dans le traducteur. Les liaisons peuvent être établies automatiquement, lorsque le premier paquet passe, ou bien manuellement. Voir la section 3.1.
  • Un virage en épingle à cheveux désigne le cas où deux machines situées du même côté du traducteur communiquent via le traducteur, qui doit alors renvoyer le paquet par là d'où il est venu (cf. section 3.8).
  • Une adresse de transport est le doublet formé d'une adresse IP et d'un port. Comme le traducteur aura moins d'adresses IPv4 que de clients, l'ajout du port est nécessaire pour différencier les sessions, lorsqu'un paquet IPv4 arrive.

Vous avez bien retenu tout le vocabulaire ? Alors, vous pouvez lire la norme elle-même, à partir de la section 3. Quelques points importants à retenir :

  • NAT64 doit garder une table des sessions TCP et UDP en cours, pour pouvoir déterminer leur fin (et donc la suppression des liaisons associées).
  • Chaque entrée de la BIB peut être associée à plusieurs sessions et il ne faut donc la supprimer que lorsque la dernière session est finie.
  • La fragmentation pose des défis particuliers. Un traducteur NAT64 conforme à la norme doit gérer les fragments, même s'ils arrivent dans le désordre. Il doit donc faire du réassemblage (en limitant toutefois les ressources allouées à cette tâche, pour se protéger contre les attaques DoS ; voir les RFC 1858, RFC 3128 et RFC 4963). Le traducteur a aussi le droit d'ajouter quelques contraintes comme le fait que tout l'en-tête TCP doit être dans le premier fragment.
  • Comme le NAT64 avec état n'est défini que pour TCP, UDP et ICMP, le traducteur doit jeter les paquets des autres protocoles (en prévenant la source, via un paquet ICMP).
  • Le traducteur ayant une connaissance des sessions actives, il peut jouer un rôle de filtre en bloquant les paquets ne correspondant pas à une telle session.
  • Déterminer qu'une session est finie n'est pas forcément évident. Ainsi, si la fin d'une session TCP est facile à observer (échange des paquets FIN par les deux parties), que faire pour une « session » UDP puisqu'il n'y a pas de connexion et donc pas de fin explicite ? La solution est d'utiliser une minuterie, remise à zéro par chaque paquet, et qui se déclenche après un certain temps d'inactivité, coupant la session UDP.
  • Pour TCP, la section 3.5.2 décrit en détail les événements de la machine à états de TCP que le traducteur doit observer pour découvrir début et fin de la session. Elle est très longue et détaillée, j'espère que les programmeurs des routeurs bas de gamme à 60 dollars prendront le temps de la lire !
  • Les règles de conversion des adresses IPv4 en IPv6 et réciproquement sont celles du RFC 6052.

Vous avez noté qu'à plusieurs reprises, j'ai utilisé des termes vagues comme « un certain temps ». Les valeurs numériques recommandées pour les diverses constantes sont en section 4. Ainsi, avant de fermer une session UDP, le traducteur doit attendre (par défaut) au moins cinq minutes (cf. RFC 4787), le traducteur doit attendre les fragments manquants au moins deux secondes, etc.

Cette technique du NAT64 améliore-t-elle ou aggrave-t-elle les problèmes de sécurité ? D'abord, cette section note que toute solution de sécurité de bout en bout qui protège l'en-tête IP contre les modifications (par exemple l'AH d'IPsec) va être cassée par NAT64, qui modifie précisément l'en-tête. Si le NAT64 est obligatoire, IPsec peut, par exemple, utiliser l'encapsulation UDP (RFC 3948). La section 5 insiste d'autre part sur le fait qu'un traducteur n'est pas un pare-feu et que le filtrage réalisé par effet de bord de la gestion d'état n'est pas forcément adapté à la sécurité.

D'autre part, NAT64 a ses propres vulnérabilités. Les principales sont le risque d'attaques par déni de service. Par exemple, un attaquant situé à l'intérieur (côté IPv6) peut utiliser toutes les adresses (en général une seule) et ports disponibles et empêcher ainsi l'accès des autres utilisateurs. Une autre attaque possible est d'envoyer régulièrement des paquets de façon à maintenir une liaison active et d'empêcher le traducteur de relâcher des ressources. Une protection possible serait de ne remettre à zéro la minuterie que si le paquet qui passe vient de l'intérieur (supposé plus fiable).

Quelles implémentations existent aujourd'hui ? Viagénie en à une en logiciel libre, voir http://ecdysis.viagenie.ca/. Le terme de ecdysis désigne la mue des arthropodes puisque NAT64 permet à IP de muer vers un nouveau protocole... Voici un exemple d'installation et d'usage : c'est un module noyau, donc il faut installer les paquetages qui permettent la compilation de modules noyau. Sur une Debian version « squeeze » avec le noyau Linux 2.6.32-5 :

% sudo aptitude install linux-headers-2.6.32-5-686 linux-kbuild-2.6.32
...

% make
/bin/sh: [[: not found
make -C /lib/modules/2.6.32-5-686/build M=/home/stephane/tmp/ecdysis-nf-nat64-20101117 modules
make[1]: Entering directory `/usr/src/linux-headers-2.6.32-5-686'
  CC [M]  /home/stephane/tmp/ecdysis-nf-nat64-20101117/nf_nat64_main.o
  CC [M]  /home/stephane/tmp/ecdysis-nf-nat64-20101117/nf_nat64_session.o
  CC [M]  /home/stephane/tmp/ecdysis-nf-nat64-20101117/nf_nat64_config.o
  LD [M]  /home/stephane/tmp/ecdysis-nf-nat64-20101117/nf_nat64.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /home/stephane/tmp/ecdysis-nf-nat64-20101117/nf_nat64.mod.o
  LD [M]  /home/stephane/tmp/ecdysis-nf-nat64-20101117/nf_nat64.ko
make[1]: Leaving directory `/usr/src/linux-headers-2.6.32-5-686'

% sudo make install
...

# On peut éditer le script avant pour changer les paramètres...
% sudo ./nat64-config.sh

Ensuite, on peut vérifier que tout s'est bien passé en regardant la table de routage :

% netstat -r -n  -Ainet6
Kernel IPv6 routing table
Destination                    Next Hop                   Flag Met Ref Use If
64:ff9b::/96                   ::                         U    1024 0     0 nat64
...

Parfait, les paquets pour le préfixe NAT64 sont bien routés à part. Tentons notre chance :

% telnet 64:ff9b::453f:bd0b
Trying 64:ff9b::453f:bd0b...

Et on voit bien les paquets IPv6 sur l'interface nat64 :

21:18:58.910669 IP6 2a01:e35:8bd9:8bb0:304b:5a4b:3b8c:7b1c.37033 > \
         64:ff9b::453f:bd0b.23: Flags [S], seq 3580860303, win 5760, \
           options [mss 1440,sackOK,TS val 23731660 ecr 0,nop,wscale 6], length 0

Et les IPv4 sur l'interface normale :

21:19:09.263613 IP 192.168.2.1.37038 > \
         69.63.189.11.23: Flags [S], seq 4043093045, win 5760, \
           options [mss 1440,sackOK,TS val 23734248 ecr 0,nop,wscale 6], length 0

Un déploiement expérimental de NAT64 est celui du réseau de la recherche lituanien. Voir leur site Web.

Pour un récit très détaillé, avec plein de technique, d'un test de NAT64 avec DNS64, voir l'article de Jérôme Durand « J'ai testé pour vous : Stateful NAT64 avec DNS64 ».


Téléchargez le RFC 6146


L'article seul

RFC 6145: IP/ICMP Translation Algorithm

Date de publication du RFC : Avril 2011
Auteur(s) du RFC : X. Li, C. Bao (CERNET Center/Tsinghua University), F. Baker (Cisco Systems)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF behave
Première rédaction de cet article le 28 avril 2011


Parmi les nombreuses techniques de coexistence d'IPv4 et IPv6, le groupe de travail Behave, dans sa version 2 (la 1 avait été consacrée aux techniques permettant de supporter le NAT) développe un mécanisme de traduction permettant à une machine IPv6 de communiquer avec une machine v4 et réciproquement. Une des pièces de ce mécanisme est l'algorithme de traduction, présenté dans ce RFC 6145.

Ce nouveau mécanisme de traduction entre IPv4 et IPv6 s'inscrit dans le cadre décrit dans le RFC 6144. Il vise à remplacer « NAT-PT » (RFC 2765 et RFC 2766), officiellement retiré, après n'avoir eu aucun succès. Ce RFC a lui-même été remplacé par la suite par le RFC 7915.

Plus spécifiquement, notre RFC 6145 est la version sans état du traducteur, c'est-à-dire que le traducteur peut traiter chaque paquet indépendemment des autres. Le traducteur n'a pas de table des flots en cours. S'il redémarre et perd toute mémoire, pas de problème, il peut immédiatement reprendre son travail. Cette technique permet notamment le passage à l'échelle : un traducteur d'adresses peut gérer un très grand nombre de clients sans épuiser sa mémoire. Mais elle a quelques inconvénients comme le fait que les fragments ICMP ne seront pas traduits. Il existe donc également une version avec état du nouveau mécanisme, normalisée dans le RFC 6146. La section 1.3 discute plus en détail ces deux possibilités, avec ou sans état.

Donc, le NAT64 (son nom non officiel) vise à traduire des adresses IP entre deux réseaux, l'un v4 et l'autre v6. Comme notre RFC 6145 ne traite que le cas sans état, les adresses doivent être converties de manière purement algorithmique, sans référence à leur histoire (cf. RFC 6052 pour ces algorithmes).

Dit comme ça, cela a l'air simple mais la traduction entre deux protocoles différents porte pas mal de pièges. Ainsi, les en-têtes de paquet n'ont pas la même taille en v4 (20 octets ou plus) et en v6 (40 octets, fixe), ce qui fait que des problèmes de MTU peuvent se poser (section 1.4). Le traducteur doit se comporter comme un routeur, donc fragmenter les paquets trop gros (en IPv4) ou retourner un message ICMP « Packet too big ».

La section 4 du RFC décrit en détail les opérations que doit faire le traducteur depuis IPv4 vers IPv6 (rappelez-vous que la traduction des adresses v4 en v6 est essentiellement dans le RFC 6052, section 2). Il y a des détails que ne connaissent pas les routeurs NAT44, qui se contentent de changer adresses et ports. En effet, ici, il faut traduire tout l'en-tête. Je ne vais pas résumer complètement cette section, juste pointer quelques pièges possibles. Ainsi, les en-têtes n'étant pas les mêmes en v4 et en v6, notre RFC doit spécifier quoi en faire. Certains cas sont évidents (comme le champ Longueur), d'autres moins. Ainsi, le champ TOS de IPv4 doit être copié verbatim dans le champ Traffic Class de IPv6. Mais le traducteur doit aussi offrir une option pour ignorer le TOS et mettre systématiquement zéro comme Traffic Class. Le champ TTL de IPv4 doit être copié dans Hop limit mais après avoir été décrémenté (rappelez-vous que le traducteur est un routeur).

La vraie difficulté n'est pas tellement dans la traduction d'IP que dans celle d'ICMP. En effet, le paquet ICMP contient le début du paquet IP qui a motivé son envoi, et ce début de paquet doit être traduit, également, sans quoi le destinataire du paquet ICMP n'y comprendra rien (par exemple, sans traduction ICMP, il recevrait en IPv6 un paquet ICMP dont le contenu est un paquet IPv4...). Notre RFC détaille donc les traductions à faire pour tous les modèles de paquets ICMP.

Le traducteur doit aussi veiller au champ Type d'ICMP, dont les valeurs sont différentes entre IPv4 et IPv6 (par exemple, Echo Reply est 0 en v4 et 129 en v6). Certains types n'ont pas d'équivalent (comme les types Timestamp ou Address Mask d'ICMPv4, absents d'ICMPv6) et le paquet ICMP doit donc être abandonné.

Enfin, le traducteur doit aussi prendre en charge les en-têtes de la couche 4 car la traduction des adresses peut ne pas être neutre pour la somme de contrôle (section 4.5) et il peut donc être nécessaire de recalculer cette dernière.

Et en sens inverse ? La section 5 décrit la traduction d'IPv6 vers IPv4. On retrouve TOS et Traffic Class, les problèmes de MTU et de fragmentation, et la traduction des messages ICMP.

Les problèmes de MTU et de fragmentation sont des cauchemars habituels sur l'Internet, notamment en raison d'équipements intermédiaires (typiquement des pare-feux) programmés avec les pieds par des anonymes, ou bien configurés n'importe comment, et qui bloquent les paquets ICMP, voire les modifient, en ignorant complètement le RFC 4890. Les traducteurs v4<->v6 auront donc ce problème, comme tant d'autres techniques utiles. La section 6 doit donc se pencher sur le traitement des paquets ICMP Packet too big qui signalent normalement que la MTU est plus réduite que ne le croit l'émetteur et qu'il faut fragmenter. Comme ces paquets sont parfois interceptés, voire modifiés, par des machines gérées par des incompétents, le traducteur doit donc parfois faire des efforts spécifiques (par exemple en modifiant la valeur de la MTU dans certains messages Packet too big).

Rien n'étant parfait en ce bas monde, les traducteurs NAT64 vont aussi introduire de nouvelles questions de sécurité. La section 8 tente de prévoir lesquelles mais reste optimiste en considérant que la plupart des problèmes existent déjà dans IPv4 ou dans IPv6. Ainsi, comme avec le NAT traditionnel, l'authentification des paquets par IPsec (RFC 4302) ne marchera pas.

Pour les gens qui aiment bien les exposés concrets, avec des 0 et des 1, l'annexe A explique en grand détail le processus de traduction avec un réseau simple d'exemple, connectant le réseau traditionnel 198.51.100.0/24 et le réseau nouveau 2001:db8::/32, via un traducteur. Deux machines, H4 et H6, Alice et Bob du NAT64, vont tenter de communiquer. Le traducteur utilise le préfixe 2001:db8:100::/40 pour représenter les adresses IPv4 et 192.0.2.0/24 pour représenter les adresses IPv6. Ainsi, H6, qui a l'adresse 2001:db8:1c0:2:21:: est représenté en v4 par 192.0.2.33. H4 a l'adresse 198.51.100.2. behave-xlate-stateless Une fois le routage correctement configuré pour passer par le traducteur, suivez le RFC pour voir le trajet des paquets et les opérations qu'ils subissent, dans le cas où c'est H6 qui initie la connexion, et dans le cas inverse.

Au moins deux mises en œuvre existent déjà, faite par Ecdysis/Viagénie (avec état) et Tayga (sans état, mais nettement plus simple, d'après ses utilisateurs). Pour compenser l'absence de traduction avec état chez Tayga, on peut, sur Linux, le coupler avec SNAT/MASQUERADE (merci à Guillaume Leclanché pour sa suggestion).

Quels sont les changements entre ce mécanisme et celui du RFC 2765 ? Ils sont résumés en section 2. Outre une complète réorganisation des documents, il s'agit surtout de détailler bien davantage les opérations à effectuer. Depuis, notre RFC 6145 a été mis à jour dans le RFC 7915.

Pour réfléchir à la grande question « avec état ou sans état », un article « pro-état » : « Stateless NAT64 is useless ».


Téléchargez le RFC 6145


L'article seul

RFC 6144: Framework for IPv4/IPv6 Translation

Date de publication du RFC : Avril 2011
Auteur(s) du RFC : F. Baker (Cisco), X. Li, C. Bao (CERNET Center/Tsinghua University), K. Yin (Cisco)
Pour information
Réalisé dans le cadre du groupe de travail IETF behave
Première rédaction de cet article le 28 avril 2011


Le groupe de travail Behave de l'IETF a travaillé pendant longtemps sur les mécanismes permettant de communiquer malgré la présence d'un routeur NAT sur le trajet. Ayant terminé ce travail avec succès, il a été muni d'une nouvelle charte pour travailler sur la transition IPv4 -> IPv6, notamment sur un mécanisme de traduction pour permettre à des machines purement v4 de parler à des machines purement v6 et réciproquement. Le groupe « Behave 2 », en ayant fini avec NAT44 s'est donc attaqué à cette tâche et ce RFC est le deuxième de cette nouvelle série (le premier avait été le RFC 6052), qui décrit NAT64.

Il ne décrit pas une technique ou un protocole mais fournit seulement le cadre général dans lequel vont s'inscrire les autres RFC du nouveau groupe Behave comme le RFC 6145 sur le protocole de traduction ou le RFC 6147 sur l'aide que lui apporte le DNS. La liste de ces documents est en section 3.3.

En effet, l'IETF avait déjà normalisé une technique de traduction d'adresses entre IPv4 et IPv6, le NAT-PT (RFC 2766), technique qui avait été abandonnée officiellement par le RFC 4966. La traduction d'adresses entre v4 et v6 n'était pas forcément considérée mauvaise en soi mais NAT-PT était vu comme une mauvaise solution, pour les raisons expliquées dans le RFC 4966.

Mais il est vrai que la traduction d'adresses a toujours été mal vue à l'IETF et que NAT-PT a du faire face à une forte opposition. Le modèle de transition d'IPv4 vers IPv6 promu par l'IETF (RFC 4213) a toujours été d'activer IPv6 au fur et à mesure, de laisser coexister IPv4 et IPv6 sur le réseau et les machines pendant un moment (stratégie de la « double pile ») puis, une fois qu'IPv6 était généralisé, de supprimer IPv4 petit à petit. Cette méthode était encore raisonnable en 2005, lorsque le RFC 4213 a été publié, mais, aujourd'hui, après des années de ratiocination, alors que l'épuisement des adresses IPv4 est effectif, elle n'est plus réaliste : nous n'avons tout simplement plus le temps de procéder à une telle migration ordonnée (cf. section 1.4). Des machines purement v6 vont apparaître, tout simplement parce qu'il n'y aura plus d'adresses v4, alors que les machines purement v4 existant aujourd'hui n'auront pas encore commencé à migrer. Les mécanismes de traduction d'adresses d'une famille à l'autre prennent donc tout leur intérêt (section 1 du RFC). Le RFC 5211 propose donc un autre plan de transition, faisant sa place à ces mécanismes.

La section 1.1 explique pourquoi considérer les mécanismes de traduction d'adresses, à côté des deux techniques du RFC 4213 (la double-pile mais aussi les tunnels). Si la traduction d'adresses est souvent utilisé pour de mauvaises raisons (par exemple parce qu'elle assurerait la sécurité des machines), elle présente aussi des avantages, notamment le fait qu'elle soit, avec les ALG (cf. section 3.1.5), la seule à permettre la communication entre des machines purement v4 et des machines purement v6. Elle a donc sa place dans les stratégies de transition à moyen terme.

La section 1.3 fixe les objectifs de la traduction d'adresses. Il ne s'agit pas de résoudre tous les problèmes (NAT-PT avait souffert d'objectifs irréalistes) mais d'attraper les fruits les plus bas. Il y a (en simplifiant beaucoup), deux types d'application : les client/serveur comme SSH, où le serveur attend les connexions d'un client, et les pair-à-pair comme SIP, où tout le monde initie et accepte des nouvelles connexions. Celles-ci de subdivisent à leur tour en pair-à-pair « d'infrastructure » (SIP, SMTP, ...) où les connexions sont typiquement d'assez courte durée et pair-à-pair « d'échange » comme avec BitTorrent, où on choisit ses pairs (le plus fiable, le plus rapide) et où on maintient de longues sessions avec eux. Quelles sont les conséquences pratiques de cette typologie ? Les applications client/serveur nécessitent des connexions d'un client v4 vers un serveur v6 (ou réciproquement), idéalement sans que les équipements de traduction d'adresses aient à garder un état. Les applications pair-à-pair nécessitent aussi de telles connexions, et dans les deux sens cette fois, mais elles seront sans doute moins nombreuses que celles d'un client vers un serveur, et les solutions avec état seront donc moins problématiques. Enfin, dans le cas de machines purement clientes (des Minitel), il n'est pas nécessaire d'ouvrir des connexions vers elles. Dans tous les cas, s'il faut garder un état pour la traduction, il est très nettement préférable qu'il soit entièrement dans les équipements réseaux (typiquement le routeur) et que la traduction ne nécessite aucune aide de la part de la machine aux extrémités. NAT-PT exigeait de l'état dans deux endroits (le traducteur lui-même et le serveur DNS) et que ces états soient coordonnés. Un routeur NAT IPv4 actuel a un état mais qui est entièrement dans le routeur et qui ne nécessite aucune participation d'une autre machine.

Enfin, un problème de vocabulaire quasiment philosophique. Faut-il parler de « transition » vers IPv6 sachant que ce mot connote une idée d'achèvement (un jour, il n'y aura plus d'IPv4) alors que rien n'est moins sûr et que, de toute façon, cela prendra de nombreuses années ? Certains préfèrent dire que des mécanismes comme la traduction d'adresses sont des mécanismes de « coexistence » plutôt que de « transition » (section 1.4).

La section 2 du RFC s'attache ensuite à décrire les scénarios où les mécanismes de transition pourront être utiles. Par exemple, en 2.1, le scénario est celui d'un FAI récemment apparu dans un endroit où il est très difficile d'obtenir des adresses IPv4 (par exemple en Asie ou en Afrique) et qui est donc entièrement en IPv6. behave-nat64-scenario1 Ses clients veulent quand même se connecter à des services IPv4. Des techniques comme celles du RFC 7915 peuvent alors être utilisées (rappelez-vous que notre RFC 6144 ne décrit qu'un cadre, pas des techniques spécifiques). Le scénario de la section 2.4 représente le problème inverse : un réseau ancien et jamais mis à jour, entièrement en IPv4, et qui veut accéder aux services uniquement v6. behave-nat64-scenario4 Bien plus difficile à résoudre (le petit nombre d'adresse IPv4 ne permet pas de faire une traduction d'adresses efficace, on doit consommer également les ports et ils ne sont que 65536 par adresse IP), ce problème est considéré comme « hors-sujet ». On ne peut pas résoudre tous les malheurs du monde et ce réseau devra utiliser d'autres techniques (probablement des ALG, même si le RFC ne les cite pas ici).

Le cadre complet de ces solutions à base de traduction d'adresses est en section 3. La section 3.1 liste les composants du cadre :

  • La traduction d'adresses (section 3.1.1), comment une adresse v6 est traduite en v4 et réciproquement, ce qui implique un préfixe v6 et une méthode de dérivation des adresses v4 à partir de v6 et réciproquement. Le RFC 6052 donne les détails. Pour les traductions sans état, le même algorithme sert dans les deux sens (v4 vers v6 et l'inverse). Pour celles avec état, l'algorithme ne sert que dans un sens et la table des états est utilisée en sens inverse.
  • La modification des paquets IP rendue nécessaire par la traduction d'adresses (par exemple dans ICMP puisqu'un paquet ICMP d'erreur contient une partie du paquet original, avec des adresses IP). La section 3.1.2 renvoie au RFC 6145 qui couvre le cas sans état.
  • Le maintien d'un état pour les traductions avec état (section 3.1.3), traitée dans le RFC 6146.
  • L'aide que doit apporter le DNS à ces opérations (section 3.1.4), normalisée dans le RFC 6147, qui prévoit la génération automatique d'enregistrements AAAA lorsque seul un enregistrement A existe.
  • Les ALG (Application Layer Gateways, section 3.1.5) qui sont nécessaires pour certaines applications comme FTP (le RFC sur FTP64 n'est pas encore paru) qui inclus les adresses IP dans ses données.

Une fois les composants de la solution listés (on voit qu'il faut beaucoup de choses pour faire fonctionner l'Internet malgré le retard pris à migrer vers IPv6), la section 3.2 expose leurs modes de fonctionnement. La traduction sans état (section 3.2.1) passe mieux à l'échelle et maintient la transparence du réseau de bout en bout. Mais elle ne peut pas être utilisée pour tous les scénarios. La traduction avec état (section 3.2.2) peut alors prendre le relais.

Il n'existe pas de solution magique à tous les problèmes. Le déploiement bien trop lent d'IPv6 a laissé une situation peu satisfaisante, et qui ne pourra pas être complètement résolu par de nouveaux protocoles. La section 5 rappelle donc que certaines questions n'ont pas de solution présente. Mais le groupe Behave a dû travailler dans l'urgence, pour fournir des solutions avant l'épuisement d'IPv4 et s'est donc focalisé sur les problèmes les plus « faciles ». Peut-être dans de futurs RFC ?

À noter qu'un FAI britannique a déjà un tel service déployé sur son réseau.


Téléchargez le RFC 6144


L'article seul

RFC 6143: The Remote Framebuffer Protocol

Date de publication du RFC : Mars 2011
Auteur(s) du RFC : T. Richardson, J. Levine (RealVNC)
Pour information
Première rédaction de cet article le 8 mars 2011


Il est assez fréquent à l'IETF qu'un protocole ne soit documenté dans un RFC que longtemps après son déploiement. C'est le cas de RFB (Remote Framebuffer Protocol), le protocole utilisé dans le système VNC, système qui permet de transmettre via un réseau TCP/IP l'interface graphique d'une machine. VNC permet, par exemple, d'avoir sur son ordinateur le bureau d'une machine distante, se s'y loguer, etc, comme si on était physiquement devant. C'est donc un concurrent de X11 avec XDMCP ou bien de NX mais avec l'avantage sur ce dernier d'avoir désormais une spécification publique, et de nombreuses mises en œuvre. Je compte une quarantaine de clients, de serveurs et de bibliothèques VNC sur mon Ubuntu.

RFB se veut un protocole simple, bien plus simple que X11, basé sur l'idée d'un serveur, tournant sur la machine distante, qui écrit dans une mémoire graphique (le framebuffer) qui est en fait située sur la machine de bureau (le client ; notez que « client » et « serveur » ont des sens différents de celui de X11). Le système VNC, qui utilise ce protocole, est très largement utilisé pour l'accès distant à une machine, exactement dans les mêmes conditions que si on était présent devant cette machine (système de fenêtrage, accès à la souris, etc).

RFB travaille au niveau de la mémoire graphique et est donc compatible avec tous les systèmes de fenêtrage comme X11 ou comme celui de Windows. Le protocole se veut simple, surtout côté client, pour pouvoir être mis en œuvre sur de petites machines. Il existe même un widget VNC/RFB pour GTK, pour ceux qui veulent mettre un client VNC dans leurs programmes.

Le client est sans état et peut donc redémarrer à tout moment et reprendre la session là où il l'avait laissée. C'est le serveur qui maintient l'état de l'interface utilisateur. Cela permet par exemple de changer de client en cours de session.

RFB, je l'ai dit, a été implémenté avant d'être spécifié et a connu plusieurs versions. Ce RFC essaie donc de documenter l'état actuel du protocole.

Si les détails prennent parfois de la place, les principes sont simples et les premières sections du RFC sont donc courtes. La section 2 décrit les connexions entre le client et le serveur. Le mode normal de fonctionnement de VNC est que le serveur tourne pendant une longue période, gardant en mémoire l'état de la mémoire graphique, le ou les clients se connectant à loisir, pendant parfois seulement de courtes périodes. Cela ressemble donc, adapté au graphique, au principe de screen. Le client peut être n'importe où sur l'Internet et se connecte par défaut au port 5900.

Loin de la richesse du protocole de X11, RFB ne fournit qu'une seule primitive : « afficher un rectangle à la position X,Y indiquée » (section 3). Cela peut sembler très inefficace mais divers encodages subtils permettent de rendre ce protocole supportable. Les mises à jour (nouveaux rectangles à afficher) ne sont jamais envoyées par le serveur mais demandées par le client (message FramebufferUpdateRequest, section 7.5.3). Le protocole est donc adaptatif : un client lent ne demandera pas souvent des mises à jour et aura donc moins de travail. Si une même région de la mémoire graphique voit plusieurs modifications successives, le client lent peut donc parfaitement sauter les étapes intermédiaires.

Afficher des rectangles, c'est très joli mais un environnement graphique digne de ce nom doit aussi permettre à l'utilisateur de dire quelque chose, par exemple de taper au clavier ou de cliquer avec la souris. La section 4 résume le protocole d'entrée de RFB : ce dernier ne connait que clavier et souris (multi-boutons). Tout autre périphérique d'entrée doit donc être modélisé comme clavier ou comme souris.

Et les pixels, comment sont-ils modélisés ? La section 5 décrit le modèle. Il repose sur une négociation entre client et serveur, à l'ouverture de la connexion, où le client est roi. C'est lui qui choisit la représentation des pixels sur le réseau, et il peut donc choisir ce qui lui fait le moins de travail, tout reposant alors sur le serveur. Les deux formats les plus classiques sont le « couleurs réelles » où chaque pixel est un nombre sur 24 bits, chaque groupe de 8 bits indiquant l'intensité de rouge, de vert ou de bleu, ou bien le « table des couleurs » où chaque pixel est un nombre sur 8 bits indiquant une entrée d'une table où sont stockées les 256 couleurs possibles.

Plusieurs encodages sont ensuite possibles dans RFB, six étant définis par notre RFC 6143, permettant plus ou moins de compression.

En parlant de négociation, comme RFB existe depuis un certain temps et a connu plusieurs versions, la section 6 décrit la notion de version du protocole. Notre RFC 6143 normalise la version 3.8. Les versions précédentes résumées dans l'annexe A. Si une version 4.x apparaîtra peut-être un jour, la version actuelle, la 3.8, est extensible sans avoir besoin de changer de version. On peut ainsi introduire :

  • De nouveaux encodages en plus des six indiqués plus haut,
  • Des nouvelles fonctions du protocole (appelées « pseudo-encodages » car, dans le processus de négociation initial, elles sont représentées comme des encodages),
  • Des nouveaux mécanismes de sécurité.

Le protocole RFB lui-même figure dans la section 7. Elle est très longue, bien plus que les autres sections, mais pas forcément plus difficile, elle liste juste tous les messages possibles. RFB peut fonctionner sur n'importe quel protocole de transport fiable (comme TCP). La communication commence par une phase de négociation entre le client et le serveur, puis l'initialisation, puis l'envoi des messages de mise à jour de la mémoire graphique. La description des messages utilise quelques types de base comme U8 (entier de huits bits non signé), S16 (entier de seize bits signé, toujours en gros boutien), etc.

La section 7.1 décrit le protocole de négociation. Ainsi, le serveur commence par envoyer un message où il indique la version (message ProtocolVersion, ici, le serveur à l'autre bout est x11vnc) :

% nc ec2-xxx.eu-west-1.compute.amazonaws.com 5900
RFB 003.008

La sécurité se négocie ensuite (section 7.2). La phase d'initialisation est décrite en section 7.3. Par exemple, le message ServerInit contiendra la hauteur et la largeur de la mémoire graphique en nombre de pixels (tous les deux en UA16), ainsi que le format de représentation des pixels (décrit en section 7.4).

La représentation des caractères tapés au clavier du client (message KeyEvent, section 7.5.4) est complexe. La valeur utilisée est un keysym de X11 (même si ni le client, ni le serveur n'utilisent X11). Si vous avez une machine Unix où X11 est installé, le fichier /usr/include/X11/keysymdef.h vous donnera une idée des valeurs possibles. Cela aurait été plus simple si un point de code Unicode était envoyé... Mais il n'y a que pour ASCII que le keysym correspond au point de code. Le RFC va même jusqu'à préciser qu'il vaut mieux utiliser le keysymI traditionnel, même s'il y en a un pour le caractère Unicode. l faut dire que le protocole RFB ne transmet pas que des caractères mais aussi des états des touches (comme le fait que la touche Majuscule est pressée) et des touches non affectées à un caractère particulier (comme F1, F2, etc). Les règles d'interprétation des keysyms sont d'une grande complexité. Le lecteur curieux doit se munir d'aspirine avant de lire lui-même cette section.

Plus facile, le cas du « pointeur » (la souris) en section 7.5.5. Les événements sont simplement « bouton pressé » et « bouton relaché », les attributs étant la position X,Y et le numéro du bouton (huit boutons sont prévus, afin de pouvoir modéliser des dispositifs d'entrée plus complexes comme les roulettes).

Jusqu'à présent, je n'ai parlé que des messages envoyés par le client RFB au serveur. En sens inverse, le principal message est FramebufferUpdate (section 7.6.1) qui indique un changement dans la mémoire graphique. Il contient un certain nombre de rectangles et, pour chacun d'eux, sa position X,Y, sa hauteur et sa largeur, et le type d'encodage utilisé.

Les encodages sont définis en section 7.7. Les six standards à l'heure actuelle sont :

  • Raw : comme son nom l'indique, aucun effort, on envoie juste les pixels l'un après l'autre (largeur, puis hauteur).
  • CopyRect : le serveur indique les coordonnées d'un rectangle existant dans la mémoire du client. Cela sert, par exemple, lorsqu'une fenêtre est déplacée sur l'écran.
  • RRE encoding : officiellement abandonné.
  • Hextile encoding : officiellement abandonné.
  • TRLE encoding : Tiled Run-Length Encoding utilise un ensemble de techniques de compression dont le run-length encoding appliquée à des « tuiles » de 16x16 pixels.
  • ZRLE encoding : Zlib Run-Length Encoding utilise la compression Zlib (RFC 1950 et RFC 1951).

La normalisation du Remote Framebuffer Protocol a nécessité quelques nouveaux registres IANA, décrits en section 8 : celui des types de sécurité, celui des messages RFB, et celui des encodages, qui permettra d'étendre la liste de six encodages présentée plus haut.

Quelle est la sécurité de RFB ? Par défaut, inexistante : comme le note justement la section 9, l'authentification est faible et la confidentialité et l'intégrité sont nulles. RFB est traditionnellement utilisé avec une protection fournie par, par exemple, un VPN chiffré, seule façon de l'utiliser de manière sûre.

L'annexe A du RFC résume les différences entre cette version du protocole (la 3.8) et les précédentes. Ces différences sont concentrées dans la phase de négociation.

À l'heure d'aujourd'hui, je n'ai pas trouvé de connaissance de ce protocole dans tcpdump mais Wireshark, par contre, le décode, sous son ancien nom de VNC (qui est désormais uniquement le nom d'un logiciel). C'est aussi le nom à utiliser sur pcapr : http://www.pcapr.net/browse?proto=vnc&order=date.


Téléchargez le RFC 6143


L'article seul

RFC 6137: The Network Trouble Ticket Data Model

Date de publication du RFC : Février 2011
Auteur(s) du RFC : Dimitris Zisiadis (CERTH), Spyros Kopsidas (CERTH), Matina Tsavli (CERTH), Leandros Tassiulas (CERTH), Chrysostomos Tziouvaras (GRNET), Guillaume Cessieux (CNRS), Xavier Jeannin (CNRS)
Expérimental
Première rédaction de cet article le 19 février 2011


Les centres qui gèrent les réseaux qui composent l'Internet, les NOC, ont régulièrement besoin d'échanger de l'information. Celle-ci, concernant les incidents, les nouveautés, les problèmes, circule souvent en quantités impressionnantes et est donc une bonne candidate pour l'automatisation. Ce RFC expérimental propose donc un format standard, basé sur XML, pour représenter l'information qui circule entre NOC, notamment ceux qui gèrent en commun une grande grille, ce qui est le cas d'EGEE, où travaillent les auteurs. Il est important pour de grosses infrastructures réseau comme les grilles de calculs, qui s'étendent sur plusieurs domaines administratifs, de pouvoir interpréter correctement les tickets avec un minimum de dépendance vis-à-vis de l'origine du ticket. L'effort de normalisation prend tout son sens dans ce contexte. Un ticket pourra donc être lu et compris sans avoir besoin de connaître les particularités et la terminologie du domaine d'origine.

Le but (section 1) n'est pas de remplacer les outils de gestion de tickets de chaque NOC mais d'avoir un format d'échange standard, suivant les souhaits du RFC 1297. Les tickets ainsi formatés pourront automatiquement être émis par un NOC, reçus par un autre, être analysés, etc. Ces outils de gestion de tickets seront ensuite utilisés pour analyser le problème, suivre son évolution et, d'une manière générale, assurer un bon fonctionnement du réseau.

On comprend mieux la taille du problème quant on voit que la grille de calcul EGEE qui utilise les NREN (vingt participants) pour sa connectivité, reçoit 800 tickets et 2500 messages par mois.

Notre RFC décrit un modèle de données en UML, puis un format concret de représentation en XML. Un problème classique que rencontrent toutes les tentatives de normalisation dans ce domaine est qu'il faut à la fois décrire de manière formelle l'incident, en énumérant de manière limitative les choix possibles, pour permettre son traitement automatique, tout en gardant des possibilités d'exprimer des problèmes nouveaux, ce qui impose de garder la possibilité de mettre du texte libre, non formaté.

Voyons d'abord les types de données utilisés (section 2). On y trouve plusieurs énumérés comme TT_TYPE qui indique si le ticket concerne un problème opérationnel, administratif, ou bien n'est là que pour information, TYPE qui indique si l'événement était prévu ou accidentel, TT_STATUS qui donne l'état du ticket (ouvert, résolu, annulé, fermé..., avec un diagramme de transition apparemment obligatoire). On trouve aussi bien sûr des chaînes de caractères (qui seront simplement le type W3C XML Schema xs:string) et des heures (au format du RFC 3339, alias xs:dateTime).

Armée de ces définitions, la section 3 détaille la longue liste des attributs d'un ticket. On y trouvera même un diagramme de classe UML en art ASCII... Parmi ces attributs, les grands classiques, comme l'identificateur unique du ticket (formé par la concaténation de l'identificateur du NOC et d'un identificateur local, ce qui permet d'allouer ces identificateurs uniques de manières décentralisée), l'état du ticket, sa date de création, l'identificateur du NOC qui est à l'origine du ticket (le RFC n'explique pas comment ses identificateurs, qui doivent être uniques, sont attribués et conservés), une description courte qui est sélectionnée à partir d'une liste pré-définie (pour permettre le traitement automatique) et une description longue qui est en texte libre (la langue utilisée peut être représenté dans le fichier XML par un attribut lang - pour des raisons que j'ignore, l'attribut standard XML xml:lang n'a pas été utilisé), les identificateurs de tickets ayant un rapport avec celui-ci, etc. Pour chaque attribut est indiqué s'il est obligatoire ou non.

La section 4 décrit l'approche utilisée pour l'internationalisation puisque les tickets seront échangés entre NOC de pays et de langues différents. Les champs formels (comme la description courte) n'ont pas besoin d'être adaptés (le logiciel de chaque NOC pourra les présenter comme il le voudra), les textes libres (comme la description longue de l'incident) peuvent être dans n'importe quelle langue (des systèmes de traduction automatique sont prévus pour EGEE dans le futur).

Si vous êtes impatients de voir à quoi ressemblent ces fameux tickets en XML, sautez directement à la section 5, qui présente les exemples. Voici un joli ticket indiquant une panne chez Forth en Grèce :


   <?xml version="1.0" encoding="UTF-8"?>
   <!-- This example describes a link failure that was detected -->
   <NTTDM-Document version="1.00" lang="el"
                   xmlns="urn:ietf:params:xml:ns:nttdm-1.0">
   <Ticket>
    <Original_ID>5985</Original_ID>
    <Partner_ID>01</Partner_ID>
    <TT_ID>01_5985</TT_ID>
    <TT_Title>Forth Link Failure</TT_Title>
    <TT_Type>Operational</TT_Type>
    <TT_Status>Closed</TT_Status>
    <TT_Open_Datetime>2008-12-16T10:01:15+02:00</TT_Open_Datetime>
    <TT_Short_Description>Core Line Fault</TT_Short_Description>
    <TT_Long_Description>Forth Link Failure</TT_Long_Description>
    <Type>Unscheduled</Type>
    <TT_Impact_Assessment>No connectivity</TT_Impact_Assessment>
    <Start_Datetime>2008-12-16T09:55:00+02:00</Start_Datetime>
    <TT_Last_Update_Time>2008-12-16T15:00:34+02:00</TT_Last_Update_Time>
    <Location>HERAKLION</Location>
    <History>Optical transmitter was changed</History>
    <TT_Close_Datetime>2008-12-16T15:05:00+02:00</TT_Close_Datetime>    
    <End_Datetime>2008-12-16T15:01:21+02:00</End_Datetime>
    <Network_Node>
     <Node>FORTH</Node>
    </Network_Node>
    <Network_Link_Circuit>
     <Link_Circuit>FORTH-2</Link_Circuit>
    </Network_Link_Circuit>
    <Open_Engineer>Dimitris Zisiadis</Open_Engineer>
    <Close_Engineer>Guillaume Cessieux</Close_Engineer>
    <Contact_Engineers>
     <Engineer>Spyros Kopsidas</Engineer>
     <Engineer>Chrysostomos Tziouvaras</Engineer>
    </Contact_Engineers>
    <TT_Priority>High</TT_Priority>
   </Ticket>
   </NTTDM-Document> 

On notera que l'exemple est imparfait : l'étiquette de langue el indique du grec mais le texte est entièrement en anglais.

Enfin, la section 6 contient le schéma complet, en langage W3C XML schema et la section 7 quelques avertissements de sécurité. Comme le contenu des tickets peut être sensible, il peut être utile de chiffrer et d'authentifier les tickets mais le RFC ne suggère pas de technique standard pour cela.

Merci à Xavier Jeannin pour sa relecture.


Téléchargez le RFC 6137


L'article seul

RFC 6129: The 'application/tei+xml' mediatype

Date de publication du RFC : Février 2011
Auteur(s) du RFC : L. Romary (TEI Consortium and INRIA), S. Lundberg (The Royal Library, Copenhagen)
Pour information
Première rédaction de cet article le 12 février 2011


Petit à petit, de nombreux formats XML obtiennent un type MIME, comme indiqué dans le RFC 7303 et RFC 6839. Ces types permettent d'identifier un contenu de manière précise sur le réseau, et ont la forme application/XXX+xml où XXX indique le format précis. Ici, notre RFC concerne le type application/tei+xml, pour le format TEI, un format de documents très utilisé dans le monde des bibliothèques et dans les sciences humaines en général (le secteur de l'étude des documents anciens est un utilisateur très visible de TEI, mais ce n'est pas le seul).

En effet, TEI (Text Encoding and Interchange) est un format utilisé depuis longtemps, par les musées, les bibliothèques, et des chercheurs, par exemple pour encoder un manuscrit qu'on a réussi à déchiffrer. Nous sommes donc ici à l'intersection du monde des geeks et de celui d'Umberto Eco. Si vous voulez voir des exemples de documents TEI, on en trouve un peu partout, par exemple une version d'« Alice au pays des merveilles » issue du Projet Gutenberg et TEIsée. L'original est en http://www.gnutenberg.de/pgtei/0.5/examples/alice/alice.tei mais j'en ai fait une version légèrement modifiée pour en retirer ce qui était spécifique de Gutenberg.

Comme tout bon fichier XML, les documents TEI ont un namespace XML, ici http://www.tei-c.org/ns/1.0. Plusieurs éléments XML peuvent être utilisés pour être la racine d'un document TEI, mais les plus communs sont <TEI> et <teiCorpus>. On les trouve souvent sur l'Internet avec des extensions de fichier .tei et .teiCorpus. (À noter qu'une recherche Google des fichiers se terminant par .tei ne donne pas le résultat attendu en raison du nombre de chinois nommés Tei...)

Notre RFC est très court. TEI lui-même est spécifié dans des documents du consortium TEI (le format est du Relax NG et disponible en format XML ou en format compact) et ce RFC ne fait que spécifier le type MIME et donner quelques conseils. Armé de ces schémas, on peut valider avec rnv :

% rnv tei_all.rnc alice.tei
alice.tei

Par contre, la validation avec xmllint échoue en raison d'une boucle sans fin.

Enfin, le consortium TEI fournit divers outils permettant, par exemple, la traduction vers LaTeX ou HTML. À noter que le journal de ce consortium est sur revues.org.

À noter que la traditionnelle section sur la sécurité couvre des points inhabituels dans un RFC. Par exemple, les documents encodés en TEI peuvent être tellement anciens qu'ils sont montés dans le domaine public mais parfois ils sont au contraire encore plombés par des règles d'appropriation intellectuelle. Le format TEI permet de spécifier ces règles, avec une grande granularité (élément availability). Ces spécifications peuvent être utilisées pour mettre en œuvre un système de menottes numériques ou, plus simplement, pour permettre l'application du droit moral de l'auteur (citer correctement les auteurs de chaque partie d'un document TEI).

D'autre part, TEI a déjà été utilisé pour encoder des documents ayant un rôle légal, et qui peuvent être encore applicables des siècles plus tard. Il peut donc être nécessaire de prendre des précautions pour vérifier l'authenticité et l'intégrité de ces documents (TEI lui-même ne le fait pas).

Enfin, les documents encodés peuvent être confidentiels et, là encore, cette confidentialité peut devoir être respectée sur de longues périodes (des dizaines d'années, si des personnes physiques sont mentionnées). Regardez donc bien les règles pour les archives de votre pays avant de distribuer des documents TEI.

Merci à Laurent Romary et Sebastian Rahtz pour leurs relectures et pour m'avoir envoyé un autre exemple de document TEI, un encodage du « Conte de Noël » de Dickens. Le fichier carol.zip contient le source TEI et on peut en tirer automatiquement une version EPUB, qui est dans le fichier 3256.epub.


Téléchargez le RFC 6129


L'article seul

RFC 6126: The Babel Routing Protocol

Date de publication du RFC : Avril 2011
Auteur(s) du RFC : J. Chroboczek (PPS, University of Paris 7)
Expérimental
Première rédaction de cet article le 6 avril 2011


La recherche sur les protocoles de routage ne désarme pas, motivée à la fois par les avancées de la science et par les nouvelles demandes (par exemple pour les réseaux ad hoc). Ainsi Babel est un nouveau protocole de routage, de la famille des protocoles à vecteurs de distance, qui vise notammment à réduire drastiquement les probabilités de boucle. (Depuis, Babel a été normalisé dans le RFC 8966.)

Il y a en effet deux familles de protocole de routage, ceux à vecteurs de distance comme l'ancêtre RIP et ceux à états des liens comme OSPF (RFC 2328). Ce dernier est aujourd'hui bien plus utilisé que RIP, et à juste titre. Mais les problèmes de RIP n'ont pas forcément la même ampleur chez tous les membres de sa famille, et les protocoles à vecteurs de distance n'ont pas dit leur dernier mot.

Babel s'inspire de protocoles de routage plus récents comme DSDV. Il vise à être utilisable, à la fois sur les réseaux classiques, où le routage se fait sur la base du préfixe IP et sur les réseaux ad hoc, où il n'y a typiquement pas de regroupement par préfixe, où le routage se fait sur des adresses IP « à plat » (on peut dire que, dans un réseau ad hoc, chaque nœud est un routeur).

L'un des principaux inconvénients du bon vieux protocole RIP est sa capacité à former des boucles lorsque le réseau change de topologie. Ainsi, si un lien entre les routeurs A et B casse, A va envoyer les paquets à un autre routeur C, qui va probablement les renvoyer à A et ainsi de suite (le champ « TTL » pour IPv4 et « Hop limit » dans IPv6 a précisement pour but d'éviter qu'un paquet ne tourne sans fin). Babel, lui, évitera les boucles la plupart du temps mais, en revanche, il ne trouvera pas immédiatement la route optimale entre deux points. La section 1.1 du RFC spécifie plus rigoureusement les propriétés de Babel.

Autre particularité de Babel, les associations entre deux machines pourront se faire même si elles utilisent des paramètres différents (par exemple pour la valeur de l'intervalle de temps entre deux « Hello » ; cf. l'annexe B pour une discussion du choix de ces paramètres). Le RFC annonce ainsi que Babel est particulièrement adapté aux environnements « sans-fil » où certaines machines, devant économiser leur batterie, devront choisir des intervalles plus grands.

Je l'ai dit, rien n'est parfait en ce bas monde, et Babel a des limites, décrites en section 1.2. D'abord, Babel envoie périodiquement toutes les informations dont il dispose, ce qui, dans un réseau stable, mène à un trafic total plus important que, par exemple, OSPF (qui n'envoie que les changements). Ensuite, Babel a des mécanismes d'attente lorsqu'un préfixe disparait, qui s'appliquent aux préfixes plus généraux. Ainsi, lorsque deux préfixes deviennent agrégés, l'agrégat n'est pas joignable immédiatement. Notre RFC a le statut « Expérimental » et l'usage découvrira peut-être d'autres faiblesses.

Comment Babel atteint-il ses merveilleux objectifs ? La section 2 détaille les principes de base du protocole, la 3 l'échange de paquets et la 4 l'encodage d'iceux. Commençons par les principes. Babel est fondé sur le bon vieil algorithme de Bellman-Ford, tout comme RIP. Tout lien entre deux points A et B a un coût (qui n'est pas forcément un coût monétaire, c'est un nombre qui a la signification qu'on veut, cf. section 3.5.2). Le coût est additif (la somme des coûts d'un chemin complet faisant la métrique du chemin, section 2.1 et annexe A), ce qui veut dire que Métrique(A -> C) - pour une route passant par B - = Coût(A -> B) + Coût(B -> C). L'algorithme va essayer de calculer la route ayant la métrique le plus faible.

Un nœud Babel garde trace de ses voisins nœuds en envoyant périodiquement des messages Hello et en les prévenant qu'ils ont été entendus par des messages IHU (I Heard You). Le contenu des messages Hello et IHU permet de déterminer le coût.

Pour chaque source (d'un préfixe, pas d'un paquet), le nœud garde trace de la métrique vers cette source (lorsqu'un paquet tentera d'atteindre le préfixe annoncé) et du routeur suivant (next hop). Au début, évidemment la métrique est infinie et le routeur suivant indéterminé. Le nœud envoie à ses voisins les routes qu'il connait. Si celle-ci est meilleure que celle que connait le voisin, ce dernier l'adopte (si la distance était infinie - route inconnue, toute route sera meilleure).

L'algorithme « naïf » ci-dessus est ensuite amélioré de plusieurs façons : envoi immédiat de nouvelles routes (sans attendre l'émission périodique), mémorisation, non seulement de la meilleure route mais aussi de routes alternatives, pour pouvoir réagir plus vite en cas de coupure, etc.

La section 2.3 rappelle un problème archi-connu de l'algorithme de Bellman-Ford : la facilité avec laquelle des boucles se forment. Dans le cas d'un réseau simple comme celui-ci babel-simple-topo A annonce une route de métrique 1 vers S, B utilise donc A comme routeur suivant, avec une métrique de 2. Si le lien entre S (S = source de l'annonce) et A casse babel-simple-topo-cut comme B continue à publier une route de métrique 2 vers S, A se met à envoyer les paquets à B. Mais B les renvoie à A, créant ainsi une boucle. Les annonces ultérieures ne résolvent pas le problème : A annonce une route de métrique 3, passant par B, B l'enregistre et annonce une route de métrique 4 passant par A, etc. RIP résout le problème en ayant une limite arbitraire à la métrique, limite qui finit par être atteinte et stoppe la boucle (méthode dite du « comptage à l'infini »).

Cette méthode oblige à avoir une limite très basse pour la métrique. Babel a une autre approche : les mises à jour ne sont pas forcément acceptées, Babel teste pour voir si elles créent une boucle (section 2.4). Toute annonce est donc examinée au regard d'une condition, dite « de faisabilité ». Plusieurs conditions sont possibles. Par exemple, BGP utilise la condition « Mon propre numéro d'AS n'apparaît pas dans l'annonce. ». (Cela n'empêche pas les micro-boucles, boucles de courte durée en cas de coupure, cf. RFC 5715.) Une autre condition, utilisée par DSDV et AODV, repose sur l'observation qu'une boucle ne se forme que lorsqu'une annonce a une métrique supérieure à la métrique de la route qui a été retirée. En n'acceptant que les annonces qui diminuent la métrique, on peut donc éviter les boucles. Babel utilise une règle un peu plus complexe, empruntée à EIGRP, qui tient compte de l'histoire des annonces faites par le routeur.

Comme il n'y a pas de miracles en routage, cette idée de ne pas accepter n'importe quelle annonce de route a une contrepartie : la famine. Celle-ci peut se produire lorsqu'il existe une route mais qu'aucun routeur ne l'accepte (section 2.5). EIGRP résout le problème en « rédémarrant » tout le réseau (resynchronisation globale des routeurs). Babel, lui, emprunte à DSDV une solution moins radicale, en numérotant les annonces, de manière strictement croissante, lorsqu'un routeur détecte un changement dans ses liens. Une route pourra alors acceptée si elle est plus récente (si elle a un numéro de séquence plus élevé).

À noter que tout se complique s'il existe plusieurs routeurs qui annoncent originellement la même route (section 2.7 ; un exemple typique est la route par défaut, annoncée par tous les routeurs ayant une connexion extérieure). Babel gère ce problème en associant à chaque préfixe l'identité du routeur qui s'est annoncé comme origine et considère par la suite ces annonces comme distinctes, même si le préfixe est le même. Conséquence : Babel ne peut plus garantir qu'il n'y aura pas de boucle (Babel essaie de construire un graphe acyclique mais l'union de plusieurs graphes acycliques n'est pas forcément acyclique). Par contre, il pourra détecter ces boucles a posteriori et les éliminer plus rapidement qu'avec du comptage vers l'infini.

Voilà pour les principes. Et le protocole ? La section 3 le décrit. Chaque routeur a une identité sur huit octets (le plus simple est de prendre l'adresse MAC d'une des interfaces). Les messages sont envoyés dans des paquets UDP et encodés en TLV. Le paquet peut être adressé à une destination unicast ou bien multicast.

Un routeur Babel doit se souvenir d'un certain nombre de choses (section 3.2) :

  • Le numéro de séquence, qui croît strictement,
  • La liste des interfaces réseau où parler le protocole,
  • La liste des voisins qu'on a entendus,
  • La liste des sources (routeurs qui ont été à l'origine de l'annonce d'un préfixe). Elle sert pour calculer les critères d'acceptation (ou de rejet) d'une route. Babel consomme donc plus de mémoire que RIP, qui ne connait que son environnement immédiat, alors qu'un routeur Babel connaît tous les routeurs du réseau.
  • Et bien sûr la table des routes, celle qui, au bout du compte, sera utilisée pour la transmission des paquets.

Les messages Babel ne bénéficient pas d'une garantie de délivrance (c'est de l'UDP, après tout), mais un routeur Babel peut demander à ses voisins d'accuser réception (section 3.3). La décision de le demander ou pas découle de la politique locale de chaque routeur. Si un routeur ne demande pas d'accusé de réception, l'envoi périodique des routes permettra de s'assurer que, au bout d'un certain temps, tous les routeurs auront toute l'information. Les accusés de réception peuvent toutefois être utiles en cas de mises à jour urgentes dont on veut être sûr qu'elles ont été reçues. (L'implémentation actuelle de Babel ne les utilise pas.)

Comment un nœud Babel trouve t-il ses voisins ? La section 3.4 décrit ce mécanisme. Les voisins sont détectés par les messages Hello qu'ils émettent. Les messages IHU (I Heard You) envoyés en sens inverse permettent notamment de s'assurer que le lien est bien bidirectionnel.

Les détails de la maintenance de la table de routage figurent en section 3.5. Chaque mise à jour envoyée par un nœud Babel est un quintuplet {préfixe IP, longueur du préfixe, ID du routeur, numéro de séquence, métrique}. Chacune de ces mises à jour est évaluée en regard des conditions de faisabilité : une distance de faisabilité est un doublet {numéro de séquence, métrique} et ces distances sont ordonnées en comparant d'abord le numéro de séquence (numéro plus élevée => distance de faisabilité meilleure) et ensuite la métrique (où le critère est inverse). Une mise à jour n'est acceptée que si sa distance de faisabilité est meilleure.

Si la table des routes contient plusieurs routes vers un préfixe donné, laquelle choisir et donc réannoncer aux voisins (section 3.6) ? La politique de sélection n'est pas partie intégrante de Babel. Plusieurs mises en œuvre de ce protocole pourraient faire des choix différents. Les seules contraintes à cette politique sont qu'il ne faut jamais réannoncer les routes avec une métrique infinie (ce sont les retraits, lorsqu'une route n'est plus accessible), ou les routes infaisables (selon le critère de faisabilité cité plus haut). Si les différents routeurs ont des politiques différentes, cela peut mener à des oscillations (routes changeant en permanence) mais il n'existe pas à l'heure actuelle de critères scientifiques pour choisir une bonne politique. On pourrait imaginer que le routeur ne garde que la route avec la métrique le plus faible, ou bien qu'il privilégie la stabilité en gardant la première route sélectionnée, ou encore qu'il prenne en compte des critères comme la stabilité du routeur voisin dans le temps. En attendant les recherches sur ce point, la stratégie conseillée est de privilégier la route de plus faible métrique, en ajoutant un petit délai pour éviter de changer trop souvent.

Une fois le routeur décidé, il doit envoyer les mises à jour à ses voisins (section 3.7). Ces mises à jour sont transportées dans des paquets multicast (mais peuvent l'être en unicast). Les changements récents sont transmis immédiatement, mais un nœud Babel transmet de toute façon la totalité de ses routes à intervalles réguliers. Petite optimisation : les mises à jour ne sont pas transmises sur l'interface réseau d'où la route venait, mais uniquement si on est sûr que ladite interface mène à un réseau symétrique (un Ethernet filaire est symétrique mais un lien WiFi ad hoc ne l'est pas forcément).

Un routeur Babel peut toujours demander explicitement des annonces de routes à un voisin (section 3.8). Il peut aussi demander une incrémentation du numéro de séquence, au cas où il n'existe plus aucune route pour un préfixe donné (problème de la famine, section 3.8.2.1).

La section 4 spécifie l'encodage des messages Babel sur le réseau. C'est un paquet UDP, envoyé à une adresse multicast (FF02:0:0:0:0:0:1:6 ou 224.0.0.111) ou bien unicast, avec un TTL de 1 (puisque les messages Babel n'ont jamais besoin d'être routés), et un port source et destination de 6696. En IPv6, les adresses IP de source et de destination unicast sont link-local et en IPv4 des adresses du réseau local.

Les données envoyées dans le message sont typées et la section 4.1 liste les types possibles, par exemple interval, un entier de 16 bits qui sert à représenter des durées en centisecondes (rappelez-vous que, dans Babel, un routeur informe ses voisins de ses paramètres temporels, par exemple de la fréquence à laquelle il envoie des Hello). Plus complexe est le type address, puisque Babel permet d'encoder les adresses par différents moyens (par exemple, pour une adresse IPv6 link-local, le préfixe fe80::/64 peut être omis).

Ensuite, ces données sont mises dans des TLV, eux-même placés derrière l'en-tête Babel, qui indique un nombre magique (42...) pour identifier un paquet Babel, un numéro de version (aujourd'hui 2) et la longueur du message. (La fonction babel_print_v1 dans le patch de tcpdump est un bon moyen de découvrir les différents types et leur rôle.) Chaque TLV, comme son nom l'indique, comprend un type (entier sur huit bits), une longueur et une valeur, le corps, qui peut comprendre plusieurs champs (dépendant du type). Parmi les types existants :

  • 0 et 1, qui doivent être ignorés (ils servent si on a besoin d'aligner les TLV),
  • 2, qui indique une demande d'accusé de réception, comme le Echo Request d'ICMP (celui qui est utilisé par la commande ping). Le récepteur doit répondre par un message contenant un TLV de type 3.
  • 4, qui désigne un message Hello. Le corps contient notamment le numéro de séquence actuel du routeur. Le type 5 désigne une réponse au Hello, le IHU, et ajoute des informations comme le coût de la liaison entre les deux routeurs ou comme la liste des voisins entendus (les amateurs d'OSPF noteront que, dans ce protocole, la liste des voisins détectés apparaît dans le Hello, ce qui augmente sa taille).
  • 6 sert pour transmettre l'ID du routeur.
  • 7 et 8 servent pour les routes elles-mêmes. 7 désigne le routeur suivant qui sera utilisé (next hop) pour les routes portées dans les TLV de type 8. Chaque TLV Update (type 8) contient notamment un préfixe (avec sa longueur), un numéro de séquence, et une métrique.
  • 9 est une demande explicite de route (lorsqu'un routeur n'a plus de route vers un préfixe donné ou simplement lorsqu'il est pressé et ne veut pas attendre le prochain message). 10 est la demande d'un nouveau numéro de séquence.

Quelle est la sécurité de Babel ? La section 6 dit franchement qu'elle est à peu près inexistante. Un méchant peut annoncer les préfixes qu'il veut, avec une faible métrique pour être sûr d'être sélectionné, afin d'attirer tout le trafic. Des extensions futures à Babel (par exemple telles que spécifiées dans le projet draft-ietf-ospf-auth-trailer-ospfv3) permettront peut-être de signer les messages mais ce n'est pas encore fait. (Notons que, en matière de routage, la signature ne résout pas tout : c'est une chose d'authentifier un voisin, une autre de vérifier qu'il est autorisé à annoncer ce préfixe.)

En IPv6, une protection modérée est fournie par le fait que les adresses source et destination sont locales au lien. Comme les routeurs IPv6 ne sont pas censés faire suivre les paquets ayant ces adresses, cela garantit que le paquet vient bien du réseau local.

Vous pourrez trouver plus d'informations sur Babel en lisant le RFC, ou bien sur la page Web officielle.

Qu'en est-il des mises enœuvre de ce protocole ? Il existe une implémentation d'exemple, assez éprouvée pour être disponible en paquetage dans plusieurs systèmes, comme babeld dans Debian ou dans OpenWrt, plateforme très souvent utilisée pour des routeurs libres (cf. https://dev.openwrt.org/browser/packages/net/babel). Si vous voulez écrire votre implémentation, l'annexe C contient plusieurs conseils utiles, accompagnés de calculs, par exemple sur la consommation mémoire et réseau. Le RFC proclame que Babel est un protocole relativement simple et, par exemple, l'implémentation de référence contient environ 7300 lignes de C.

Néanmoins, cela peut être trop, une fois compilé, pour des objets (le RFC cite les fours à micro-ondes...) et l'annexe C décrit donc des sous-ensembles raisonnables de Babel. Par exemple, une mise en œuvre passive pourrait apprendre des routes, sans rien annoncer. Plus utile, une mise en œuvre « parasite » n'annonce que la route vers elle-même et ne retransmet pas les routes apprises. Ne routant les paquets, elle ne risquerait pas de créer des boucles et pourrait donc omettre certaines données, comme la liste des sources. (Le RFC liste par contre ce que la mise en œuvre parasite doit faire.)

Toujours côté programmes, il existe un patch à tcpdump pour afficher les paquets Babel et un en cours pour Wireshark. On commence à voir des traces Babel sur pcapr.net.

Si vous voulez approfondir la question des protocoles de routage, une excellente comparaison a été faite par David Murray, Michael Dixon et Terry Koziniec dans « An Experimental Comparison of Routing Protocols in Multi Hop Ad Hoc Networks » où ils comparent Babel (qui l'emporte largement), OLSR (RFC 7181) et Batman (ce dernier est dans le noyau Linux officiel). Notez aussi que l'IETF a un protocole standard pour ce problème, RPL, décrit dans le RFC 6550.

Merci beaucoup à Juliusz Chroboczek pour sa relecture et ses nombreux avis.


Téléchargez le RFC 6126


L'article seul

RFC 6125: Representation and Verification of Domain-Based Application Service Identity within Internet Public Key Infrastructure Using X.509 (PKIX) Certificates in the Context of Transport Layer Security (TLS)

Date de publication du RFC : Mars 2011
Auteur(s) du RFC : P. Saint-Andre (Cisco), J. Hodges (PayPal)
Chemin des normes
Première rédaction de cet article le 1 avril 2011


Un RFC long et complexe pour un problème difficile. En résumant violemment, il s'agit de savoir quelle identité utiliser lorsqu'un client TLS s'assure de l'authenticité du serveur auquel il se connecte. Par exemple, si un MTA veut transmettre du courrier à bill@example.com, que doit contenir le certificat X.509 du MX d'example.com pour que l'authentification réussisse ? example.com ? D'autres noms, plus spécifiques à ce service, sont-ils possibles ? Ce cas particulier est mentionné dans la section 4.1 du RFC 3207 mais très peu détaillé, et renvoyé à des décisions locales. Comme de nombreux autres protocoles ont des problèmes de ce genre, l'idée avait germé de faire un RFC générique, définissant un cadre et des principes, RFC que les protocoles n'auraient plus qu'à citer. C'est notre RFC 6125 (depuis remplacé par le RFC 9525).

Traditionnellement, l'identité du pair avec lequel on se connecte était indiqué dans le champ Subject du certificat X.509. openssl permet de l'afficher :

% openssl s_client -starttls smtp -connect mail.bortzmeyer.org:25
...
Certificate chain
 0 s:/C=FR/ST=Ile-de-France/L=Paris/O=Moi/OU=Maison/CN=mail.bortzmeyer.org/emailAddress=postmaster@b
ortzmeyer.org
...

Le champ Sujet est formé de doublets attribut-valeur (par exemple, l'attribut C veut dire Country, ici la France) notamment CN (Common Name), le plus utilisé. Mais l'identité pouvait aussi figurer dans une extension X.509, Subject Alternative Name (section 4.2.1.6 du RFC 5280). Cette extension est rare en pratique, bien que normalisée depuis de nombreuses années. Je ne sais pas comment l'afficher avec openssl. La seule solution que je connaissais était de copier/coller le certificat affiché par openssl s_client -connect www.example.com:443 puis de faire un openssl x509 -text -noout -in /le/certificat.pem, ici avec le serveur HTTPS www.digicert.com :

Certificate:
...
        Subject: businessCategory=V1.0, Clause 5.(b)/1.3.6.1.4.1.311.60.2.1.3=US/1.3.6.1.4.1.311.60.2.1.2=Utah/serialNumber=5299537-0142,
              	C=US, ST=Utah, L=Lindon, O=DigiCert, Inc., 
                CN=www.digicert.com
...
        X509v3 extensions:
...
            X509v3 Subject Alternative Name: 
                DNS:www.digicert.com, DNS:www.origin.digicert.com, 
                       DNS:content.digicert.com, DNS:digicert.com
...

On peut aussi combiner les deux commandes (openssl s_client -connect www.digicert.com:443 | openssl x509 -text) voire n'afficher que la partie qui nous intéresse (openssl s_client -connect www.digicert.com:443 | openssl x509 -text | perl -n0777e 'print $1 if /(.*Subject Alternative Name:.*\n.*\n)/', merci à minimalist pour son aide). Mais les navigateurs Web permettent en général de montrer tout le certificat, y compris cette extension. Regardez par exemple sur https://www.cisco.com/ ou bien https://www.digicert.com/. Un Subject Alternative Name peut contenir un dNSName (un nom de domaine), mais aussi un uniformResourceIdentifier (un URI) et, par des extensions de l'extension (RFC 4985), un SRVName (un nom de service, tel que présent en partie gauche d'un enregistrement SRV).

Quel nom utiliser lorsque plusieurs sont présents ? C'est tout le but de ce RFC : lorsqu'un client TLS se connecte à un serveur TLS, et qu'une authentification X.509 prend place, le client a une idée sur l'identité du serveur (reference identity, identité de référence, dit le RFC) et le serveur présente un certificat contenant un certain nombre d'identités (presented identity, identité affichée). Comment comparer ? Aujourd'hui, la situation est plutôt confuse et deux approches sont largement utilisées :

  • Utiliser uniquement le CN (Common Name) du champ Sujet (subject field), puisque tout le monde doit le connaître, c'est le champ traditionnel,
  • Répéter l'identité du serveur à plusieurs endroits dans le certificat en se disant que le vérificateur en trouvera au moins un.

Une partie de la difficulté est que le déploiement d'une méthode propre et standard nécessite la copération de plusieurs acteurs. Ce nouveau RFC 6125 est surtout destiné à l'usage interne de l'IETF, aux concepteurs de protocoles (section 1.2). Mais les autres acteurs impliqués, par exemple ceux qui écrivent les logiciels ou bien qui gèrent une CA ont tout intérêt à le lire également. Ils ne s'amuseront pas forcément (ce RFC est long, complexe et très abstrait, la section 1.3 donne quelques pistes pour le lire sans trop souffrir) mais ils apprendront des choses utiles. Avant de se mettre à la lecture, il fraut s'assurer d'avoir lu et bien compris le RFC 5280, dont les règles demeurent actives. Il faut également garder en mémoire les RFC spécifiques d'un protocole applicatif particulier comme le RFC 2595 pour IMAP, RFC 2818 pour HTTP, RFC 2830 pour LDAP, RFC 3207 pour SMTP, RFC 6120 pour XMPP, et plusieurs autres encore (liste en section 1.6)...

Pour le lecteur pressé, la section 1.5 résume les recommandations essentielles de ce RFC 6125 :

  • Abandonner progressivement l'utilisation de noms de domaine dans le champ CN (Common Name) du sujet du certificat. Aujourd'hui, c'est un vœu pieux, à en juger par les certificats HTTPS existants. Ceux-ci, soucieux de compatibilité, mettent presque tous le nom de la machine dans ce champ CN.
  • Privilégier l'utilisation des champs de l'extension Subject Alternative Name du RFC 5280.
  • Encore mieux, utiliser de préférence, dans cette extension, les champs typés comme celui qui permet d'indiquer l'URI du service ou celle qui permet d'indiquer le nom SRV (RFC 4985) car ils sont plus spécifiques et évitent de faire des certificats « attrape-tout ». (Personnellement, je n'ai jamais vu dans la nature des certificats d'un serveur HTTPS ou IMAP utilisant ces champs.)
  • Pour le même souci de spécificité, abandonner petit à petit les certificats incluant un joker (*.example.com), un conseil qui plaira aux CA, car il augmentera leur chiffre d'affaires.

Plusieurs points sont exclus de ce RFC (section 1.7) :

  • Les identités des clients finaux (comme l'adresse de courrier électronique représentée par l'identificateur rfc822Name), qui peuvent servir en cas de présentation d'un certificat client. Notre RFC ne considère que l'authentification du serveur.
  • Les identificateurs qui ne sont pas des noms de domaines (par exemple les adresses IP, théoriquement possibles mais, en pratique, très peu utilisées).
  • Les protocoles non-TLS, même si certains d'entre eux, comme IPsec, peuvent eux aussi utiliser X.509.
  • Les certificats non-X.509 comme ceux d'OpenPGP (RFC 4880 et RFC 6091).

Une fois éliminé ces « non-sujets », le lecteur doit ensuite passer un peu de temps sur la section de terminologie en 1.8, car X.509 utilise beaucoup de vocabulaire. Il faut également connaître le vocabulaire standard de la sécurité, exposé dans le RFC 4949. Parmi les sigles dont on aura le plus besoin ici :

  • CN-ID: un RDN (Relative Distinguished Name dans le champ sujet du certificat, qui contient une paire clé-valeur de type CN (Common Name) et qui ait la forme d'un nom de domaine. Par exemple, dans le certificat actuel de www.gmail.com (après redirection vers mail.google.com), le champ sujet est CN = mail.google.com, O = Google Inc, L = Mountain View, ST = California, C = US et le CN-ID est mail.google.com. C'est de très loin le type le plus fréquent aujourd'hui.
  • DNS-ID: un identificateur de type dNSName mis dans l'entrée subjectAltName du RFC 5280. Par exemple, dans le certificat actuel de www.digicert.com, le DNS-ID est www.digicert.com (le même que le CN-ID, ce qui est le cas de la quasi-totalité des certificats qu'on trouve sur l'Internet public).
  • SRV-ID et URI-ID: des identificateurs trouvés également dans l'entrée subjectAltName du RFC 5280 (plus le RFC 4985 pour le SRV-ID), de types respectifs SRVName et uniformResourceIdentifier. On ne les trouve quasiment jamais dans les certificats disponibles sur l'Internet public.

Puisqu'on parle de ce qu'on trouve en pratique ou pas, je précise que mes avis là-dessus sont surtout tirés de quelques explorations faites sans méthode. Ce qui serait cool, ce serait d'avoir un Google des certificats X.509. Un robot récolterait les certificats, les analyserait et un moteur de recherches permettrait de trouver « Des certificats avec Subject Alternative Name » ou bien « Des certificats avec un condensat MD5 » ou aussi « Des certificats expirant après 2014 » ou encore « Des certificats Comodo émis par la Iranian Cyber Army :-) » Il existe deux projets allant dans cette direction : SSLiverse, qui a la récolte mais pas le moteur de recherche. L'archive fait 12 Go et est disponible en torrent. Il ne reste plus qu'à fouiller dedans (ce qui peut s'avérer assez long), la liste de diffusion du projet devient utile dans ce cas (merci à Étienne Maynier pour ses conseils et informations). L'autre projet est Shodan qui, lui, dispose non seulement d'une telle base, mais d'une partie des fonctions de recherche souhaitées (mais pas celle qui me fallait, pour trouver les certificats avec Subject Alternative Name).

Maintenant, passons aux noms. Un certificat contient les noms de services comme www.example.org. Certains noms sont directs : ils ont été tapés par un être humain ou sélectionnés à partir d'une page Web. D'autres, indirects, ont été obtenus, par exemple via une résolution DNS. Ainsi, pour envoyer du courrier à sandra@example.com, une résolution DNS de type MX permettra de trouver le relais de courrier de example.com, mettons smtp.example.net. (On peut noter que, en l'absence de résolution sécurisée, par exemple par DNSSEC, c'est le premier nom qu'il faut chercher dans le certificat, le second peut être le résultat d'un empoisonnement DNS.)

Les noms peuvent également être restreints ou pas. Un nom restreint ne peut être utilisé que pour un seul service. Par exemple, une CA peut émettre un certificat qui ne sera utilisable que pour de l'IMAP.

On voit donc qu'un CN-ID ou un DNS-ID sont directs et non restreints, qu'un SRV-ID peut être direct ou indirect (mais il est indirect la plupart du temps) mais est restreint (le nom de l'enregistrement SRV indique un certain type de service), qu'un URI-ID est direct et restreint.

Et le nom de domaine lui-même, a-t-il plusieurs catégories possibles ? Oui, dit la section 2.2 qui sépare les noms en :

  • Traditionnels. Ce sont les noms historiques comme www.mabanque.example.
  • Internationalisés. Ce sont les noms de domaine en Unicode définis par le RFC 5890.

Au tout début de X.509, les noms étaient censés être tirés d'un grand Annuaire officiel X.500 mais ce projet s'est cassé la figure, comme la plupart des autres éléphants blancs de l'UIT et il ne reste que des certificats isolés (section 2.3). Pour assurer l'unicité des noms, la méthode la plus courante sur l'Internet a donc rapidement été de mettre un nom de domaine dans le CN (Common Name) du sujet du certificat, par exemple C=CA,O=Example Internetworking,CN=mail.example.net. Mais ce n'est qu'une convention : le CN n'est pas typé, il peut contenir n'importe quoi, par exemple un nom lisible par un humain comme CN=A Free Chat Service,O=Example Org,C=GB et, dans ce cas, la vérification automatique de ce nom par rapport à ce qu'attendait l'utilisateur n'est pas évidente. Voici pourquoi notre RFC 6125 recommande l'utilisation des champs typés de subjectAltName au lieu du CN (recommandation très peu suivie dans l'Internet d'aujourd'hui).

Ces (longs) préliminaires étant achevés, la section 3 commence enfin la partie pratique du RFC, destinée aux auteurs de protocoles. Ceux-ci doivent d'abord faire une petite liste des caractéristiques pertinentes de leur protocole : utilise-t-il les enregistrements SRV ? Utilise-t-il des URI ? A-t-il besoin de jokers dans les noms de domaine ? Armé de cette connaissance, le concepteur de protocoles peut passer à la section 4 qui définit les règles de production d'identité (les règles pour les autorités de certification, donc).

Il est donc recommandé de mettre dans les certificats un subjectAltName DNS-ID. Si le protocole utilise les SRV, il est recommandé de mettre un SRV-ID (même conseil évident pour les URI). J'aimerais bien savoir combien de CA permettent de mettre un tel identificateur. Je parierais bien qu'il n'y en a aucune. Le RFC conseille également de ne pas inclure de nom de domaine dans le CN, pour encourager la migration (notons que le premier exemple donné, en section suivante, ne suit pas ce conseil...).

Voyons quelques exemples concrets :

  • Pour un serveur HTTP, protocole qui n'utilise pas les SRV et n'a pas prévu de mettre des URI dans les certificats (cf. RFC 2818), le certificat pour www.example.com doit inclure un DNS-ID www.example.com et peut inclure un CN-ID www.example.com pour la compatibilité avec les vieilles implémentations.
  • Pour un serveur IMAP, qui sert user@example.net et se nomme mail.example.net, comme le protocole peut utiliser les SRV (cf. RFC 6186), il faudra mettre le SRV-ID _imap.example.net, ainsi que les DNS-ID example.net et mail.example.net (là encore, on pourra ajouter un nom de domaine dans le CN, si on tient à gérer les vieux clients IMAP).
  • C'est presque pareil pour XMPP, avec en prime l'extension X.509 spécifique à ce protocole, XmppAddr (section 13.7.1.4 du RFC 6120).
  • Pour un service SIP qui gère user@voice.example.edu, comme SIP peut utiliser des URI (cf. RFC 5922), il faudra au moins un URI-ID sip:voice.example.edu et un DNS-ID voice.example.edu.

Ces spécifications de la section 4 étaient pour les autorités de certification. Et les gérants des services sécurisés, que doivent-ils mettre dans leurs demandes de certificats (CSR, Certificate Signing Requests) ? La section 5 précise qu'ils doivent demander tous les identificateurs nécessaires (ce qui ne veut pas dire que la CA leur donnera...), donc, par exemple, le SRV-ID et le DNS-ID dans le cas de IMAP. Si le certificat sera utilisé pour des services différents, il vaut mieux ne demander que le DNS-ID (les autres étant restreints, rappelez-vous la section 2.1).

Les gérants des services ont demandé les certificats (section 6), les CA ont émis des certificats (section 5), reste à les vérifier dans le logiciel client (section 6, qui concerne donc surtout les programmeurs). Le principe est le suivant :

  • L'application construit une liste des identités de référence. Typiquement, c'est ce que l'utilisateur a tapé au clavier ou bien sélectionné explicitement. S'il a configuré son compte de messagerie comme étant thierry.breton@iloveemail.example, le nom iloveemail.example sera une identité de référence (rappelez-vous que notre RFC ne se préoccupe que d'authentifier des serveurs, pas des personnes, donc le nom de l'individu n'est pas pris en compte). Si l'utilisateur a sélectionné https://www.dns-oarc.net/ sur une page Web, www.dns-oarc.net est une identité de référence.
  • Le serveur TLS envoie un certificat, qui contient des identités affichées.
  • Le client TLS compare les identités de référence aux identités affichées, râlant s'il n'y a pas correspondance.

Le reste de la section 6 formalise cette méthode. Quelques points particuliers, par exemple :

  • Le client doit faire attention à ne pas dériver des identités à partir d'autres identités, sauf si cela peut être fait de façon sûre. Ainsi, analyser un URI, pour en extraire le nom de domaine, si c'est fait proprement, est une opération sûre. Résoudre un nom en un autre (par exemple le serveur de messagerie à partir du MX du domaine) via le DNS est non sûr. Si on utilise DNSSEC, cela redevient sûr.
  • Mais, d'une manière générale, le RFC décourage la dérivation : seuls les noms entrés directement par l'utilisateur sont vraiment fiables comme identité de référence puisque, par définition, ils expriment la volonté directe de l'utilisateur (« je veux communiquer avec gmail.com »). La règle n'est toutefois pas absolue car, par exemple, l'utilisateur a pu « épingler » un autre nom précédemment (« je sais que le serveur XMPP de example.org est jabber.toto.example, authentifie ce dernier nom », cf. section 7.1).
  • La liste des identités de référence doit comprendre un DNS-ID. S'il y a eu une résolution SRV, elle devrait comprendre un SRV-ID (même raisonnement pour les URI-ID).
  • On peut y ajouter un CN-ID, pour réussir l'authentification avec les vieux certificats (le RFC note bien que, en l'état actuel des choses, cette possibilité est de facto une obligation, les certifiats avec CN-ID étant largement dominants).

Le RFC donne quelques exemples : une requête Web pour https://www.dns-oarc.net/ produira une liste d'identités de référence comportant un DNS-ID, www.dns-oarc.net et un CN-ID optionnel identique. Une tentative de connexion IMAP pour le domaine example.net, dont l'enregistrement SRV indiquera que le serveur est mail.example.net, donnera une liste comportant les SRV-ID _imap.example.net et _imaps.example.net ainsi que les DNS-ID example.net et mail.example.net (sans compter le CN-ID) optionnel. Le RFC ne rappelle apparemment pas que l'étape de résolution DNS de example.net en mail.example.net n'est pas forcément sûre... Le fait qu'ils soient sous le même domaine example.net n'est pas une protection parfaite (car on ne connait pas les frontières des zones DNS) et, de toute façon, le serveur n'est pas forcément dans le même domaine que celui qu'il sert. Et le RFC semble avoir oublié ici son conseil précédent de se méfier des noms dérivés...

Ensuite, il reste à comparer les deux listes (section 6.3). Le principe est celui de la première correspondance. Dès qu'une identité présentée correspond à une des identités de référence, on s'arrête, on a authentifié le serveur (section 6.6.1) et cette identité authentifiée est celle qui doit pêtre montrée à l'utilisateur. (Le cas où on voudrait que toutes les identités correspondent est laissé à une future norme.) Attention, le CN-ID dans les identités de référence est traité un peu à part : il ne doit pas être utilisé si le certificat inclus d'autres identités (comme un DNS-ID).

Cette correspondance nécessite quelques précisions (section 6.4). Ainsi, le RFC rappelle que les noms de domaine traditionnels doivent être comparés de manière insensible à la casse (RFC 4343), que les noms de domaine internationalisés doivent être transformés en A-labels (cf. RFC 5890) avant comparaison, que les jokers (indiqués par le signe *) nécessitent de l'attention particulière (par exemple, ils ne sont considérés comme spéciaux que s'ils apparaissent seuls, dans le composant le plus à gauche du nom). Globalement, faire correctement cette comparaison n'est pas trivial pour le programmeur.

Pour les CN, il est rappelé qu'un CN dans la liste des identités de référence n'est là que pour pouvoir authentifier avec les « vieux » certificats et ne doit pas être utilisé avec un certificat moderne, incluant des DNS-ID, SRV-ID ou URI-ID. S'il n'y a pas le choix (pas de Subject Alternative Name dans le certificat), l'application peut comparer ses identités de référence au CN, en suivant les règles de comparaison des noms de domaine.

Bon, si l'authentification du serveur a réussi, on continue et on affiche à l'utilisateur, sur un joli fond vert, l'identité authentifiée. Et si ça a raté, que doit-on faire ? La section 6.6.4 propose des stratégies de repli : si le logiciel est interactif, avec un humain pas loin, la méthode recommandée est de mettre fin à la connexion, avec un message d'erreur (conseil que je trouve déplorable : vu le nombre de certificats invalides, cela diminuerait nettement l'utilisabilité du Web et cela encouragerait les sites à ne pas proposer HTTPS). La possibilité de permettre à l'utilisateur de passer outre le problème et de contnuer (ce que font tous les navigateurs Web, autrement ils perdraient tous leurs clients) est mentionnée mais très découragée.

Si l'application n'est pas interactive, la démarche recommandée est d'afficher un message d'erreur et de s'arrêter. Une option pour ignorer le certificat est possible mais ne doit pas être activée par défaut. C'est ainsi que wget, fidèle à cette règle, a son option --no-check-certificate, alors que fetchmail, qui ne suit pas le RFC, a son --sslcertck pour activer la vérification.

D'ailleurs, une section entière, la 7, est consacrée à la discussion détaillée de certains problèmes de sécurité. Ainsi, les jokers font l'objet de la section 7.2. Ils sont déconseillés (pour les raisons expliquées en « New Tricks for Defeating SSL in Practice » et « HTTPS Can Byte Me ») mais, s'ils sont présents dans un certificat, le client devrait se préparer à les gérer, avec prudence.

Autre cas complexe, celui où un même serveur est accédé par plusieurs noms (virtual hosting) par exemple un serveur IMAP qui hébergerait plusieurs domaines de messagerie, ce qui est courant. Il existe plusieurs méthodes pour gérer ce cas, comme de mettre tous les noms possibles dans le certificat (pas pratique...), ou bien d'utiliser SNI (Server Name Indication, section 3 du RFC 6066). Si on met plusieurs noms dans le certificat, le RFC recommande que ce soit plusieurs DNS-ID (ou SRV-ID ou URI-UID) pas plusieurs CN.

Voilà, arrivé ici, le concepteur d'un protocole utilisant l'authentification avec X.509 sait normalement tout ce qu'il faut savoir. Il ne lui reste plus qu'à inclure dans sa spécification le texte exact et, pour lui faciliter la vie, l'annexe A contient un tel texte (pris dans le RFC 6120, section 13.7.1.2), qui peut être copié/collé avant d'être adapté à ce protocole particulier. De nombreux RFC avaient des règles spécifiques, avant la publication de notre RFC 6125 et la variété de ces règles était justement une motivation pour le développement du nouveau RFC. L'annexe B rappelle et cite les principaux RFC qui avaient traité le sujet comme le RFC 2818 pour HTTPS ou le RFC 2830 pour LDAP.

Ce RFC 6125 avait été chaudement discuté à l'IETF, ce qui explique qu'il ait mis si longtemps à être publié. Le lecteur courageux doit relire toutes les archives de la liste certid pour suivre toutes ces discussions (je recommande celles de septembre 2010 et décembre 2010).

Quelques petits trucs techniques pour ajouter des extensions comme subject alternative name avec les logiciels existants (merci à Dany Mello et Christian Pélissier ; on peut aussi consulter mon article « Plusieurs noms dans un certificat X.509 »). Avec OpenSSL, on peut aussi utiliser un fichier texte où on place l'extension. Pour une extension de type IP, le fichier ext.txt contient :

subjectAltName="IP:1.1.1.1"

puis on ajoute l'argument -extfile dans la ligne de commande d'openssl :

% openssl x509 -req -days 7300 -in moncsr.csr -CA ca.crt -CAkey ca.key \
    -set_serial 01 -out moncrt.crt -extfile ext.txt

Avec l'utilitaire certpatch (qui ne semble pas très documenté) disponible dans le paquetage isakmpd, c'est :

% certpatch -t fqdn -i www.example.org -k /etc/ssl/private/ca.key \
    oldcert.crt nwcert.crt

Avec l'utilitaire certutil (des outils de sécurité NSS), c'est :

% certutil -R -s "cn=dapou.exemple.fr,ou=DI,o=Exemple,...,c=FR" \
         -a -o $CADIR/$host.$domain.pem.csr -d $CADIR \
         -8 "cn=ldap1.exemple.fr" \
         -z random -f password-file

ldap1.exemple.fr sera le nom alternatif.


Téléchargez le RFC 6125


L'article seul

RFC 6122: Extensible Messaging and Presence Protocol (XMPP): Address Format

Date de publication du RFC : Mars 2011
Auteur(s) du RFC : P. Saint-Andre (Cisco)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF xmpp
Première rédaction de cet article le 31 mars 2011


Ce RFC normalisait le format des adresses du protocole de messagerie instantanée XMPP, également connu sous son ancien nom de Jabber. Il s'agissait d'un document transitoire, qui remplaçait une partie de l'ancien RFC 3920, et qui a lui même été remplacé par le RFC 7622.

Le protocole XMPP est le standard actuel de messagerie instantanée de l'IETF. Les utilisateurs sont identifiés par une adresse également connue, pour des raisons historiques, sous le nom de JID (Jabber IDentifier). Ces adresses ont une forme qui ressemble aux adresses de courrier électronique mais elles sont en fait complètement différentes. Ainsi, j'ai personnellement deux adresses XMPP, bortzmeyer@gmail.com (le service de messagerie Google Talk utilise en effet la norme XMPP), qui me sert surtout pour la distraction, et bortzmeyer@dns-oarc.net qui me sert pour le travail. Mais rien ne dit qu'un courrier envoyé à ces adresses fonctionnera : adresses XMPP et de courrier vivent dans des mondes différents.

Le format des adresses XMPP était spécifié à l'origine dans le document XEP-0029. Puis il a été normalisé dans la section 3 du RFC 3920. La norme XMPP ayant subi une refonte complète, qui a mené entre autre à un nouveau RFC, le RFC 6120, se posait la question du format d'adresses, dont l'internationalisation, compte-tenu de la nouvelle norme IDN, suscitait des débats. Ces débats n'étant pas terminés, la décision a été prise de sortir le format d'adresses du RFC principal, et d'en faire ce RFC 6122, jusqu'à ce qu'un consensus apparaisse sur le format « définitif ».

Donc, quels sont les points essentiels des adresses XMPP (section 2) ? Une adresse (ou JID) identifie une entité (un humain mais peut-être aussi un programme automatique). Elle comprend trois parties (donc une seule est obligatoire), la partie locale, le domaine et une ressource. Ainsi, dans bortzmeyer@gmail.com/Home, bortzmeyer est la partie locale, gmail.com le domaine et Home la ressource. Le @ et le / servent de séparateurs. Chacune des trois parties peut-être composée de caractères Unicode (cf. section 3), qui doivent être encodés en UTF-8. La partie locale doit être canonicalisée avec Nodeprep, le domaine avec le Nameprep du RFC 3491. Seul le domaine est obligatoire et bot.example.org est donc un JID valide.

Les adresses XMPP (ou JID) sont souvent représentées sous forme d'un IRI, selon le RFC 5122. En gros, un IRI XMPP est un JID préfixé par xmpp:. Mais ces IRI ne sont pas utilisés par le protocole XMPP. Dans les champs to et from des strophes (stanzas) XMPP, on ne trouve que des JID (sans le xmpp: devant). Les IRI ne servent que dans les liens dans les pages Web, comme xmpp:bortzmeyer@gmail.com (attention, ce lien ne marchera pas avec tous les navigateurs).

Le RFC détaille ensuite chaque partie. Le domaine, seule partie obligatoire, est dans la section 2.2. On peut le voir comme une identification du service auquel on se connecte (gmail.com = Google Talk), et la création de comptes et l'authentification se font typiquement en fonction de ce service. En théorie, une adresse IP est acceptable pour cette partie mais, en pratique, c'est toujours un FQDN. Ce nom de domaine peut être un IDN donc instantanée.nœud.example est un nom acceptable pour former un JID. Auquel cas, ce doit être un IDN légal (ce qui veut dire que toute chaîne de caractères Unicode n'est pas forcément un nom légal pour la partie domaine d'un JID). À noter que XMPP n'utilise pas l'encodage en ASCII des IDN (le Punycode).

Et la partie locale, celle avant le @ ? La section 2.3 la couvre. Elle est optionnelle et identifie en général une personne (mais peut aussi indiquer un programme ou bien un salon de conversation à plusieurs). Si elle est en Unicode, elle doit être canonicalisable avec le profil Nodeprep (Nodeprep est normalisé en annexe A de notre RFC).

Quant à la ressource, troisième partie du JID (après le /), également optionnelle, elle sert à distinguer plusieurs sessions par le même utilisateur (par exemple /Home et /Office). La section 2.4 la décrit en détail. Également en Unicode, elle est canonicalisée par le profil Resourceprep. Elle n'a pas de structure officielle. Un / dans une ressource (par exemple example.com/foo/bar) n'implique donc pas une hiérarchie. De même, si on y trouve quelque chose ressemblant à une adresse (par exemple joe@example.net/nic@host), cette ressource nic@host doit être traitée comme un identificateur opaque (et pas être analysée en « nom (at) machine »).

Quelles sont les conséquences de sécurité de ces adresses ? Il n'y en a guère mais, bon, il y a toujours des inquiets donc la section 4 examine en détail tous les risques, même très théoriques. Bien sûr, les adresses XMPP héritent des questions de sécurité de Stringprep (section 9 du RFC 3454) mais le RFC mentionne surtout les risques de triche sur les adresses. Il y en a de deux sortes, les usurpations et les imitations. Les usurpations (section 4.3.1) sont les cas où un méchant arrive à envoyer un message XMPP en trichant sur l'origine, par exemple si jean@example.net, une fois authentifié auprès de son propre serveur, arrive à transmettre un message prétendant venir de jeanne@jabber.example. Normalement, le protocole XMPP empêche cela, par l'authentification mutuelle des serveurs (sauf attaques un peu sophistiquées, par exemple sur le DNS). Cela dit, cette authentification n'empêche pas un serveur d'annoncer une autre partie locale (jeanne@example.net au lieu jean@example.net).

L'autre risque est celui d'imitation (section 4.3.2). Cette fois, il s'agit d'utiliser des JID légitimes et authentiques mais qui ressemblent à celui de la victime, par exemple fric@paypa1.com au lieu de fric@paypal.com (si vous ne voyez pas la différence, regardez mieux). Cette technique est souvent connue sous le nom de typejacking. Dans un accès de beaufitude, le RFC mentionne aussi le cas d'écritures « moins familières » que l'alphabet latin (moins familières pour qui ?) mais, comme le montre l'exemple du RFC ou bien celui cité plus haut, le problème arrive même en se limitant à ASCII. Si vous voulez un joli exemple avec Unicode (mais le résultat dépend de l'environnement avec lequel vous lisez cet article), le RFC cite ᏚᎢᎵᎬᎢᎬᏒ qui ressemble à STPETER mais est écrit en Cherokee. Comme un JID peut contenir à peu près n'importe quel caractère Unicode, il n'y a pas vraiment de prévention technique possible contre ce problème. Toutefois, contrairement à ce que prétend le RFC (qui évoque le spectre du hameçonnage), il est peu probable que cela ait des conséquences en pratique. Le RFC, qui exagère le risque, suggère que les serveurs XMPP qui servent une communauté homogène, linguistiquement parlant, peuvent réduire le jeu de caractères Unicode acceptés comme partie locale d'un JID (par exemple, à l'alphabet cyrillique pour un serveur russe). Une telle politique serait, je trouve, un gros recul dans l'internationalisation de l'Internet et, de toute façon, elle n'aiderait pas les serveurs internationaux comme jabber.org ou Google Talk. Une approche moins restrictive est aussi proposée par le RFC : le logiciel client XMPP pourrait prévenir visuellement l'utilisateur lorsqu'un JID utilise une écriture distincte de celle utilisée habituellement par l'utilisateur (et qui est déduisible de ses préférences).

Le RFC se termine par les annexes normalisant les profils Nodeprep et Resourceprep. Rappelons que Stringprep (RFC 3454) décrit un cadre général pour la canonicalisation de chaînes de caractères Unicode, afin de faciliter les comparaisons ultérieures. Stringprep laisse un grand nombre de choix ouverts et doit donc, avant utilisation, être réduit à un profil. Les profils normalisés sont enregistrés à l'IANA. Par exemple, Nodeprep précise que la normalisation Unicode utilisée doit être la NFKC et donne la liste des caractères interdits dans une partie locale (par exemple @, <, >, /, etc). Resourceprep, lui, est dans l'annexe B et n'est pas équivalent (par exemple, les caractères cités plus haut ne sont pas interdits dans la ressource d'un JID). Stringprep ayant depuis été abandonné (remplacé par le cadre du RFC 7564), une nouvelle version de XMPP est en cours de rédaction pour la partie « Unicode ».

La liste complète des changements par rapport au RFC 3920 figure en annexe C. Rappelons que le RFC 3920 s'appuyait, pour les parties en Unicode, sur des profils Stringprep (RFC 3454) comme Nameprep. Ce Nameprep, décrit dans le RFC 3491, ayant été supprimé à l'occasion de la réforme IDNA bis, la question se posait de l'avenir des profils Stringprep. Un groupe de travail IETF, PRECIS, a été monté pour discuter de l'avenir des normes utilisant Stringprep. Son travail n'étant pas terminé, et le groupe de travail sur XMPP ne souhaitant pas retarder la sortie de la nouvelle norme (RFC 6120), la question du successeur de Nameprep a été remise à plus tard et notre RFC 6122 normalise donc le format d'adresses XMPP tel qu'il était avant IDNA bis. Le RFC note que les implémenteurs sont encouragés à utiliser dès maintenant IDNA bis, même avant la sortie du RFC sur le format d'adresses (à part la question de la canonicalisation avec Nameprep, les différences entre l'IDN original et IDNA bis sont de peu d'importance pratique). Ce RFC a finalement été le RFC 7622, qui est désormais la norme des adresses XMPP.

Les autres changements sont limités : clarification sur l'utilisation d'adresses IPv6 littérales dans les JID (j'offre une bière au premier qui annonce un JID quelqun@[2001:db8::bad:dcaf:1] qui marche), correction de bogues dans la grammaire pour le cas de termes de longueur nulle, changements de terminologie (la partie locale se nommait node identifier, d'où le terme de Nodeprep, survivance de l'ancien vocabulaire), etc.


Téléchargez le RFC 6122


L'article seul

RFC 6121: Extensible Messaging and Presence Protocol (XMPP): Instant Messaging and Presence

Date de publication du RFC : Mars 2011
Auteur(s) du RFC : P. Saint-Andre (Cisco
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF xmpp
Première rédaction de cet article le 7 avril 2011


Le protocole XMPP, normalisé dans le RFC 6120, est souvent cité comme protocole de messagerie instantanée. Mais c'est en fait plus compliqué que cela : XMPP lui-même ne fournit qu'un service minimum de routage d'éléments XML, les vrais services devant être développés au dessus de XMPP. C'est ainsi que les services de messagerie instantanée et de présence sont normalisé dans ce RFC, le 6121. Il succède au premier RFC sur ces services, le RFC 3921.

Le protocole de base, décrit dans le RFC 6120, transmet des éléments XML, les strophes (stanzas, j'ai choisi cette traduction parce qu'elle maintenait la métaphore musicale), en temps réel ou presque. Sur ce protocole de base, des tas de services sont possibles. La messagerie instantanée est le plus connu. Décrite dans le RFC 2779, elle a aujourd'hui éclipsé la plupart des autres usages de XMPP.

XMPP a été développé vers 1999 sous le nom de Jabber. Le nom de XMPP lui est venu lors de son adoption par l'IETF en 2002, les premiers RFC sont sortis en 2004 et ils viennent d'être mis à jour par la sortie des RFC 6120 (le protocole de base), RFC 6121 (la messagerie instantanée, qui remplace le RFC 3921) et RFC 7622 (le format des adresses). De son histoire, qui s'est déroulée partiellement en dehors de l'IETF, XMPP a gardé plusieurs extensions qui ne sont pas spécifiées dans un RFC, mais dans des documents connus sous le nom de XEP (XMPP Extension Protocols) comme par exemple XEP-0160 pour le stockage des strophes si elles ne peuvent pas être délivrées immédiatement.

Qu'est-ce que la messagerie instantanée ? Vu de XMPP, ce sont une liste de connaissances (le carnet ou roster) et la possibilité d'envoyer entre ces connaissances des messages relativement courts, de manière quasi-instantanée. Contrairement au courrier électronique, dont la caractéristique principale est d'être asynchrone (on peut envoyer un message à quelqu'un qui est en vacances et qui le lira au retour), la messagerie instantanée (ou IM pour Instant Messaging ou chat ou clavardage si on veut parler comme l'Académie française) est synchrone : un message perd beaucoup de son intérêt s'il n'est pas lu tout de suite. Cela implique donc de gérer la présence : les correspondants ont besoin de savoir si le type en face est là ou pas. Comme cette information peut être considérée comme confidentielle, la présence n'est communiquée qu'à ceux qu'on a accepté comme correspondants (buddies, ce qu'un utilisateur de Facebook traduirait sans doute par ami).

Donc, les quatre fonctions :

  • Gérer le carnet,
  • Échanger des messages avec ses correspondants,
  • Informer de sa présence,
  • Gérer la liste des gens qu'on informe de sa présence.

résument très bien le RFC 2779, qui fut le cahier des charges de XMPP.

La section 1.4 de notre RFC détaille les dites fonctions. Le transport des données, la connexion au serveur, l'authentification, etc, sont des choses très importantes mais elles sont absentes de ce RFC, puisqu'elles sont déjà couvertes dans le RFC 6120. Pour résumer ce dernier : un client XMPP se connecte à un serveur XMPP et s'authentifie. La session XMPP ainsi ouverte (et qui dure typiquement des heures, voire des jours) permet de transmettre des strophes (l'élément de base d'une conversation XMPP), ces strophes pouvant être des messages lisibles par un humain (« Ça va ? Tu viens bouffer ? ») comme des messages de service comme ceux informant de la présence d'un correspondant. (Il y a aussi des messages entre serveurs, pour qu'un utilisateur puisse parler à un client d'un autre service. Contrairement à Facebook ou MSN, XMPP est un protocole Internet, donc ouvert) Une session typique est :

  • Récupération de son carnet, stocké sur le serveur,
  • Envoi de l'information de présence (« Je suis là »),
  • Échange de messages, mises à jour du carnet, réception des informations de présence des potes, etc, tout au long de la session.
  • Fin de la session quand on va se coucher le soir.

Notons que les utilisateurs ne sont pas forcément des humains, ils peuvent être des bots.

Terminées, les généralités, place au protocole. Ce RFC est très long (cent seize pages), mais la longueur vient surtout du nombre de types de messages possible, pas tellement de la complexité du protocole. Je ne vais pas détailler chaque fonction, seulement mettre en évidence quelques points.

La plus importante fonction est évidemment l'échange de messages, donc commençons par elle (alors que le RFC fait passer la gestion du carnet et celle de la présence d'abord). Elle figure en section 5. Le principe est que le client XMPP transmet au serveur des éléments <message>. Ceux-ci sont délivrés à un autre client connecté au même serveur, ou bien routés vers un autre serveur. XMPP fonctionne donc par push, pas par pull : l'information doit être délivrée tout de suite (la section 8.5.2.1.1 précise ce que doit faire un serveur si un serveur distant n'est pas disponible de suite).

L'usage le plus courant est sous la forme d'une session de discussion où plusieurs messages vont se suivre. Dans ces cas, l'élément <message> reçoit un attribut type dont la valeur est chat (section 5.2.2). Voici un exemple de message (vous noterez vite que tous les examples XMPP sont tirés de Roméo et Juliette ; je n'ai pas traduit le texte, que j'ai laissé dans la langue originale, celle de Shakespeare, pas celle des amants de Vérone, qui s'échangeaient plutôt des mots doux en italien).


   <message
       from='juliet@example.com/balcony'
       id='ktx72v49'
       to='romeo@example.net'
       type='chat'
       xml:lang='en'>
     <body>Art thou not Romeo, and a Montague?</body>
   </message>

Tiens, justement, question langues, XMPP permet d'avoir plusieurs versions du même message, en des langues différentes (section 5.2.3). Voici un exemple en anglais et en tchèque :

   <message
       from='juliet@example.com/balcony'
       id='z94nb37h'
       to='romeo@example.net'
       type='chat'
       xml:lang='en'>
     <body>Wherefore art thou, Romeo?</body>
     <body xml:lang='cs'>
        PročeŽ jsi ty, Romeo?
      </body>
   </message>

La section 3 explique le mécanisme de gestion de la présence. Celle-ci n'est transmise qu'aux abonnés, pas au public. Pour s'abonner, on envoie une demande (ici de Roméo vers Juliette) :


<presence id='xk3h1v69'
                 to='juliet@example.com'
                 type='subscribe'/>

Cette demande est en général présentée à l'utilisateur pour qu'il l'approuve (section 3.1.3). Le serveur peut alors répondre :


<presence from='juliet@example.com'
                 id='xk3h1v69'
                 to='romeo@example.net'
                 type='subscribed'/>

Une fois qu'on est approuvé, un peut recevoir des informations de présence (section 4). Celles-ci indiquent si l'entité (la personne ou le programme mais, en général, les programmes ne s'absentent pas) est disponible ou pas. Les clients XMPP l'affichent alors par exemple en vert si le contact est disponible et en rouge autrement, ou bien avec du texte comme online et offline. Donc, lorsque je lance mon client XMPP, ou bien lorsque je change manuellement l'état (le menu en bas de la fenêtre des contacts, avec Pidgin), le client XMPP envoie au serveur :

 

<presence/>

et celui-ci le retransmet aux abonnés (section 4.2.2). Le client peut aussi marquer explicitement qu'il ne veut pas être dérangé :

 

<presence type='unavailable'/>

information à laquelle on peut ajouter une explication :

 

<presence type='unavailable' xml:lang='fr'>
         <status>Je suis en vacances.</status>
       </presence>

La section 2 concerne la gestion du carnet (roster). Le serveur le stocke et le transmet à l'utilisateur, ce qui permet à celui-ci de disposer de son carnet depuis n'importe quelle machine (rappelons que XMPP est un protocole ouvert et que n'importe qui peut installer un serveur : celui-ci n'est donc pas forcément une grosse entreprise anonyme dans le nuage, il peut être géré par votre entreprise, votre association, par un copain ou par vous-même). Cela ne se fait évidemment qu'après authentification (la liste de mes copains ne regarde que moi...). À noter qu'un des changements depuis le RFC 3921 est que le carnet peut désormais être stocké sur un autre serveur que celui où on se connecte.

En gros, pour avoir le carnet, le client envoie la strophe :


<iq from='juliet@example.com/balcony'
          id='bv1bs71f'
          type='get'>
       <query xmlns='jabber:iq:roster'/>
</iq>

et le serveur lui transmet (ici, seulement trois correspondants, pour ne pas rendre cet article trop long) :


<iq id='bv1bs71f'
          to='juliet@example.com/balcony'
          type='result'>
        <query xmlns='jabber:iq:roster' ver='ver11'>
          <item jid='romeo@example.net'
                name='Romeo'
                subscription='both'>
            <group>Friends</group>
          </item>
          <item jid='mercutio@example.com'
                name='Mercutio'
                subscription='from'/>
          <item jid='benvolio@example.net'
                name='Benvolio'
                subscription='both'/>
        </query>
</iq>

Dans la liste d'élements <item> renvoyés, l'attribut jid contient l'adresse XMPP formelle (JID = Jabber ID, voir le RFC 7622) et name un identificateur plus convivial. L'élément <subscription> indique si le correspondant est abonné à notre présence, nous à la sienne, ou bien les deux. Le schéma XML complet figure en annexe D, en utilisant le langage XSD.

La section 2 couvre également le cas des mises à jour du carnet (le client ajoute ces mises à jour dans son <query>). Notez que XMPP peut aussi utiiser des enregistrements au format vCard (RFC 6350) pour remplir le carnet (annexe C et XEP-0054). Un serveur comme ejabberd gère cette possibilité.

La section 7 fournit un exemple plus détaillé d'une session complète, avec quatre utilisateurs. Lecture nécessaire si vous voulez comprendre tous les détails de XMPP.

Comme nous vivons dans un monde cruel (regardez ce qui est arrivé de tragique à Roméo et Juliette), XMPP a besoin d'une section sur la sécurité, la numéro 11. Elle traite des points comme l'importance de ne pas répondre aux demandes de présence si le demandeur n'est pas autorisé (soit explicitement, soit via une politique générale, par exemple l'autorisation de tous pour tous dans une même entreprise).

Qu'est-ce qui a changé depuis le RFC 3921 ? L'annexe E résume les principales différences. La plupart sont très pointues et ne se rencontrent pas tous les jours.

XMPP étant un protocole ancien et éprouvé, il est très largement déployé et on trouve de nombreuses implémentations :

  • Des serveurs comme ejabberd ou jabberd, si on veut créer son propre service,
  • Des clients comme Pidgin ou Empathy sur Unix (j'ai écrit un article spécifique pour les clients sur Android),
  • Des serveurs gratuits comme jabber.org ou comme Google Talk (oui, c'est tout simplement du XMPP et un abonné de Google Talk peut interagir avec n'importe quel autre abonné d'un autre service XMPP).

Et enfin, si vous voulez m'écrire, mes adresses XMPP sont bortzmeyer@dns-oarc.net pour le travail et bortzmeyer@gmail.com (du Google Talk) pour le reste.


Téléchargez le RFC 6121


L'article seul

RFC 6120: Extensible Messaging and Presence Protocol (XMPP): Core

Date de publication du RFC : Mars 2011
Auteur(s) du RFC : Peter Saint-Andre (Cisco)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF xmpp
Première rédaction de cet article le 13 avril 2011


Jabber est le nom original, et XMPP le nom IETF d'un protocole d'échange d'informations encodées en XML, protocole surtout connu pour son utilisation dans la messagerie instantanée. Ce RFC 6120 met à jour la définition originale de XMPP, qui était dans le RFC 3920.

La messagerie instantanée est une application très populaire surtout chez les moins de dix ans. Elle permet d'échanger des messages sans prendre le temps de réfléchir et en général sans craindre qu'ils soient archivés (contrairement au courrier électronique où il faut réfléchir car ce que l'on écrit restera). Elle sert à de nombreux usages, discussions entre geeks, systèmes de surveillance avec notification des problèmes, etc. À l'exception du vénérable protocole IRC (décrit - insuffisamment - dans le RFC 2810 et suivants), les systèmes existants de messagerie instantanée sont tous basés sur des protocoles privés et fermés comme MSN. La normalisation qui fait le succès du courrier électronique n'a pas réussi ici.

D'où le vieux projet (RFC 2779) de développer un protocole moderne et ouvert, adapté à cette application. C'est ce qu'on fait les développeurs du protocole Jabber en 1999, projet adopté ultérieurement par l'IETF, rebaptisé XMPP en 2002 et normalisé désormais dans ce RFC. Notre RFC décrit un protocole généraliste, un RFC compagnon, le RFC 6121, normalise les aspects spécifiques à la messagerie instantanée. Il est donc objectivement incorrect de dire que XMPP est un protocole de messagerie instantanée (c'est en fait un protocole d'échange de données XML en temps réel) mais je suis sûr que mes lecteurs me pardonneront mes abus de langage. Ce RFC 6120 est très long (notons pour la petite histoire que dix RFC sont quand même encore plus longs, le détenteur du record étant le RFC 5661), avec plus de deux cents pages, mais il est surtout composé de longues listes de détails, les principes sont relativement simples. En dépit de la longueur de ce RFC, il ne spécifie pas tout XMPP de nombreuses extensions existent, certaines très populaires (comme la possibilité pour un client de créer un compte sur un serveur directement via XMPP) et elles sont en général décrites, non pas dans un RFC, mais dans les XEP (XMPP Extension Protocols) de la XMPP Standards Foundation.

Quels sont les principes de XMPP (section 1.3) ? Les données sont encodées en XML (avec quelques bémols notés en section 11 comme l'interdiction des commentaires XML, ou des encodages autres qu'UTF-8), dans des strophes (stanzas) qui sont des petits paquets d'information. Citons Wikipédia : « Les stances sont, dans les sujets graves et spirituels, ce que le couplet est dans les chansons et la strophe dans les odes ». Ces strophes sont transmises sur une connexion TCP (section 3) entre client et serveur, ou bien entre serveur et serveur (la section 2.5 contient une très intéressante présentation des concepts « réseau » de XMPP, notamment pour répondre à la question philosophique « XMPP est-il pair-à-pair ? »). Les entités qui communiquent (ce ne sont pas forcément des humains, Jabber ayant été conçu pour permettre également la communication entre programmes) sont identifiées par une adresse, qui a une forme syntaxique proche de celle du courrier électronique. Par exemple, mon adresse XMPP est bortzmeyer@gmail.com.

XMPP, comme le courrier électronique, fonctionne par le connexion de serveurs, chacun chargé d'un ou plusieurs domaines. Les clients se connectent à un serveur (par exemple talk.l.google.com. pour Google Talk, par exemple) et s'y authentifient, puis ils transmettent les messages aux serveurs, qui se chargent de les acheminer au serveur suivant (section 2.1 du RFC). Les serveurs sont trouvés en utilisant les enregistrements SRV (RFC 2782) du DNS (section 3.2) par exemple, pour un client de l'OARC :

% dig SRV _xmpp-client._tcp.dns-oarc.net
...
;; ANSWER SECTION:
_xmpp-client._tcp.dns-oarc.net. 3223 IN SRV     0 0 5222 jabber.dns-oarc.net.
...

L'usage de SRV fait que le numéro de port utilisé n'est pas toujours le même mais 5222 (pour les communications de client à serveur) et 5269 (pour celles de serveur à serveur) sont les valeurs les plus courantes (section 14.7).

Les adresses (JID pour Jabber Identifier) sont décrites dans un autre document, le RFC 7622. Outre le classique nom@domaine, elles peuvent comporter une ressource, indiquée après la barre oblique (par exemple bortzmeyer@gmail.com/AFNIC).

La représentation des données en XML est décrite dans la section 4. Un flux de données, un stream, est un élément XML <stream>, qui comporte une ou plusieurs strophes, <stanza>. Il existe de nombreux types de strophes (section 8) sans compter les messages d'erreur, décrits en 4.9. Voici un exemple classique d'un échange (C étant le client et S le serveur), avec des strophes de type message :


   C:   <message from='juliet@example.com'
                 to='romeo@example.net'
                 xml:lang='en'>
   C:     <body>Art thou not Romeo, and a Montague?</body>
   C:   </message>
   S:   <message from='romeo@example.net'
                 to='juliet@example.com'
                 xml:lang='en'>
   S:     <body>Neither, fair saint, if either thee dislike.</body>
   S:   </message>

Des exemples plus détaillés figurent en section 9.

Contrairement à beaucoup d'autres protocoles de messagerie instantanée, conçus uniquement pour jouer, XMPP, étant prévu aussi pour le travail, dispose de fonctions de sécurité très riches. La section 5 précise l'utilisation de TLS et la 6 celle de SASL. La section 13 détaille en profondeur tous les problèmes de sécurité de XMPP.

La section 8 détaille les types de strophes disponibles. Trois types sont définis dans ce RFC, <message>, <presence> et <iq>. <message>, dont la sémantique est décrite en section 8.2.1, transporte un... message, tandis que <iq> (section 8.2.3) est une interrogation (Info / Query). Ces éléments XML ont un certain nombre d'attributs par exemple l'attribut to, sections 4.7.2 et 8.1.1, qui spécifie l'adresse du destinataire (romeo@example.net dans la pemière strophe de l'exemple ci-dessus). La syntaxe complète, exprimée en W3C Schema, figure dans l'annexe A.

Du fait de l'utilisation de XML, des attributs standard comme xml:lang sont possibles (section 8.1.5) et on peut ainsi marquer un message en tchèque :

   <presence from='romeo@example.net/orchard' xml:lang='en'>
     <show>dnd</show>
     <status>Wooing Juliet</status>
     <status xml:lang='cs'>Dvořím se Julii</status>
   </presence

L'annexe D résume les changements depuis le RFC 3920, qui avait été fait en 2004. Le format des adresses a été sorti pour être dans un document à part, le RFC 7622, le vieux protocole de rappel (dialback) a été retiré des RFC, TLS est devenu obligatoire (section 13.8, il reste à voir si ce sera mis en œuvre : au moment de la sortie de notre RFC, très peu de clients XMPP Android avaient TLS), et le reste est un certain nombre de clarifications et de corrections : il ne s'agit donc pas d'une nouvelle version du protocole, juste d'une évolution inspirée par l'expérience.

XMPP est aujourd'hui mis en œuvre dans de nombreux logiciels. C'est ainsi que le service de messagerie instantanée Google Talk utilise XMPP. Le client XMPP (qui est aussi un client de nombreux autres protocoles) le plus populaire sur Unix est sans doute Pidgin (ex-Gaim). Côté serveurs, le plus pittoresque (et pas le moins utilisé) est sans doute ejabberd, écrit en Erlang. Mais il y en a d'autres comme Movim.

Les développeurs liront avec intérêt le livre Programming Jabber qui explique comment utiliser Jabber/XMPP dans ses propres programmes.


Téléchargez le RFC 6120


L'article seul

RFC 6115: Recommendation for a Routing Architecture

Date de publication du RFC : Février 2011
Auteur(s) du RFC : T. Li (Cisco)
Pour information
Réalisé dans le cadre du groupe de recherche IRTF RoutingResearchGroup
Première rédaction de cet article le 22 février 2011


Le mécanisme de routage dans l'Internet est une invention géniale. Bien qu'ayant été décrié par tous les experts des télécoms, unanimes dans leur appréciation comme quoi cela ne pourrait jamais marcher, ce mécanisme a permis la croissance d'un réseau de quatre machines aux États-Unis à des débuts, vers des centaines de millions aujourd'hui, réparties partout dans le monde. Néanmoins, rien n'est éternel en technologie. Tous les systèmes sont un jour remplacés, ne serait-ce que parce que de nouveaux besoins émergent et que de nouveaux problèmes apparaissent. Le groupe RRG (Routing Research Group) de l'IRTF est donc chargé d'explorer, pour le moyen et long terme, les solutions qui pourraient remplacer le routage actuel, notamment pour améliorer son passage à l'échelle, le cas des réseaux multihomés et la possibilité de faire de l'ingénierie de trafic. Ambitieux défi puisqu'il faut, non seulement concevoir un système meilleur que le système qui a assuré un tel succès, mais aussi le déployer, dans un réseau qui se méfie des nouveautés.

On ne s'étonnera donc pas que le RRG a à moitié échoué. Aucune idée géniale, créant un consensus par sa beauté, n'a émergé. De nombreuses propositions, souvent astucieuses, ont été présentées et discutées mais aucune n'a fait l'objet d'un consensus. Les présidents du groupe ont fini par publier le RFC tel quel, avec les différentes contributions, les points sur lesquels un accord s'est fait, et leur recommandation personnelle, qui est de partir de la proposition ILNP. Celle-ci a été normalisée en novembre 2012 dans les RFC 6740 et suivants.

D'abord, un peu de contexte. Les documents sur lesquels se base le travail du RRG (Routing Research Group) n'ont pas tous été publiés en RFC encore. Parmi eux, le RFC 6227, cahier des charges du projet. Les autres sont seulement des Internet-Drafts. Le principal est l'exposé du problème, draft-narten-radir-problem-statement. Ces deux documents ont donné naissance à de nombreuses propositions. Attention en les lisant : il n'y a pas de censure à l'IRTF et toutes les propositions sont étudiées et discutées. Beaucoup provenaient d'une personne isolée et, s'il existe parfois des génies solitaires et incompris, les propositions individuelles sont plus souvent l'œuvre de gens assez déconnectés de la pratique. On trouvera donc de tout dans ce RFC, hommage à l'ouverture de l'IRTF, plus qu'à sa capacité de sélection...

Il y avait en effet pas mal de zozos au RRG, des fois même incapables de formater un message électronique correctement (erreurs dans les citations, par exemple). Plusieurs propositions n'ont ainsi pas encore (?) connu le moindre début de mise en œuvre.

À noter également que les bruyants partisans des solutions de type « table rase » comme John Day ou comme le projet Clean Slate n'ont pas participé du tout à cet effort. À leur décharge, il faut dire que la solution devait être déployable incrémentalement, ce qui contredisait leur postulat de départ, qui est d'ignorer l'existant. Mais cette non-participation reflète aussi leur difficulté à travailler sur des questions concrètes. Tant qu'on se contente d'interviews au New York Times, refaire l'Internet en partant de zéro est facile. S'il faut écrire de vraies normes, compréhensibles, et se confronter au jugement de ses pairs, il y a moins d'enthousiasme.

Je ne vais pas détailler chacune des nombreuses propositions, plutôt me servir de chacune pour exposer un défi particulier auquel est confronté l'architecte du futur réseau. Par manque de temps, j'ignorerai même complètement certaines des propositions.

Pour résumer ces documents de base, à quoi servait le groupe RRG (Routing Research Group) ? Il avait été établit pour trouver une nouvelle architecture de routage pour l'Internet, rien que ça. Il s'est réuni à chaque réunion IETF de 2007 à 2010, a beaucoup discuté via sa liste de diffusion, mais, comme indiqué, n'a pas atteint de consensus. Les présidents du groupe, Lixia Zhang et Tony Li, deux experts expérimentés et reconnus, ont donc fini par jeter l'éponge et décider de tout publier, en ajoutant leur recommandation personnelle en faveur d'ILNP. Chaque proposition d'architecture ou de protocole a bénéficié d'un résumé (en général par son auteur, et la plupart de ces résumés sont de lourdes publicités avec peu de détails pratiques), résumé qui inclus obligatoirement les avantages de la proposition, mais aussi de ses coûts (il n'y a pas de déjeûner gratuit...), d'une critique par un autre membre du groupe et, parfois, d'une réponse de l'auteur à cette critique. (En pratique, je trouve que certaines critiques pinaillent sur quelques détails de la proposition, et n'analysent pas assez ses grandes idées et principes.)

Mais tout n'a pas été un flop : s'il n'y a pas eu d'accord sur une proposition concrète, le groupe a quand même mis en évidence plusieurs points importants, qui n'étaient pas évidents au début, mais qui ont rencontré un large accord. Ces points étaient (section 1.2) parfois de simple terminologie, parfois portant sur des concepts plus profonds. Par exemple :

  • [terminologie] Un nœud est soit un routeur, soit une machine terminale (host).
  • [terminologie] Un nom est une suite de bits utilisée pour désigner quelque chose (c'est vague mais c'est bien pour indiquer que le terme « nom » est très générique, et qu'il existe des termes mieux définis). Il existe des noms à des tas d'endroits de la pile des couches. Dans cette définition, le nom n'est donc pas forcément lisible et mémorisable par un humain.
  • Une adresse est un nom qui mêle identification et indication de l'emplacement dans le réseau (évidemment pas dans l'espace physique). Les actuelles adresses IP sont dans cette catégorie.
  • Un localisateur est un nom qui ne sert pas à l'identification mais uniquement pour exprimer une position dans le réseau (sans être une route complète vers l'objet). Actuellement, il n'existe pas de vrais localisateurs dans l'architecture Internet.
  • Un identificateur est un nom qui ne contient pas d'information topologique (c'est-à-dire qu'il est complètement indépendant de la position du nœud, si on débranche une machine au Burkina Faso et qu'on la rebranche au Canada, ou si on passe de la connexion filaire avec le réseau local, à une connexion 3G, l'identificateur ne doit pas changer). Aujourd'hui, certains FQDN peuvent être considérés comme des identificateurs, selon cette définition. Même chose pour les clés SSH ou HIP.
  • L'intérêt de séparer les définitions des identificateurs et des localisateurs est qu'un des points consensuels du groupe RRG a été que la séparation de l'identificateur et du localisateur était à la fois faisable et souhaitable.
  • Un autre consensus s'est fait sur l'importance du multihoming, et qu'il soit possible à un coût raisonnable (la solution actuelle, avec adresses PI et BGP, ne passe pas tellement à l'échelle).

À propos de terminologie, je recommande au lecteur du RFC qui n'aurait pas suivi tous les travaux du RRG de bien lire la section 1.3, qui liste les sigles les plus courants. Tout le reste du RFC en fait une forte consommation et certains ne sont pas forcément familiers à l'ingénieur réseaux (comme ITR, Ingress Tunnel Router, qui désigne le point d'entrée d'un tunnel, pour les solutions à base de tunnel ou EID, Endpoint IDentifier, qui désigne l'identificateur de la machine de destination).

Maintenant, assez de préliminaires, place aux propositions concrètes. La première exposée est LISP, qui n'a rien à voir avec le langage de programmation du même nom et qui occupe la section 2. À noter que les « LISPiens » ont peu participé au RRG, ayant un groupe de travail IETF à eux et leur proposition étant de loin la plus avancée, puisque implémentée et déployée. Par contre, aucun RFC LISP n'a encore été publié.

LISP fait partie des propositions dites CES pour Core-Edge Separation, où une coupure très nette est faite entre le cœur de l'Internet (en gros, le monde de ceux qui ont aujourd'hui un routeur dans la DFZ) et les bords. Si LISP est largement déployé, seul le cœur aura encore des adresses IP globalement uniques et les bords auront des identificateurs uniques, qui ne seront pas des localisateurs. Un mécanisme d'annuaire (mapping) permettra de trouver l'adresse d'un routeur capable d'acheminer les paquets pour un identificateur donné et ce routeur sera le point d'entrée d'un système de tunnels, qui permettra de router ce paquet. Le tunnel n'est pas forcément fourni par le FAI, et on pourrait imaginer un nouveau métier dans l'Internet, celui de fournisseur de tunnels. Comme avec toutes les autres propositions de séparation identificateur-localisateur, les localisateurs, plutôt dépendants du FAI, sont fortement agrégeables, les identificateurs sont stables (on ne les change pas en changeant de FAI, ce que les LISPiens appellent PI for all). LISP ne nécessite aucune modification des machines terminales (c'est une solution purement dans les routeurs et encore, pas dans tous, uniquement les routeurs d'entrée et de sortie de tunnel). Ce type de solution est aussi appelée Map-and-Encap car on cherche d'abord une correspondance entre identificateur et localisateur (Map) puis on encapsule le paquet (Encap) pour la traversée du tunnel.

Notez que cette CES, cette séparation entre cœur et bords changerait le modèle classique de l'Internet, fondé sur le même protocole IP partout, du réseau local de M. Michu à celui du plus gros Tier-1. Cela rappelerait les réseaux des PTT où X.25 ne servait qu'à l'accès, d'autres protocoles (comme X.75) étant utilisés à l'intérieur du réseau de l'opérateur.

Et, comme toutes les solutions fondées sur la séparation entre identificateur et localisateur, LISP nécessite un système de correspondance (mapping) entre les deux, permettant de trouver, lorsqu'on cherche à joindre la machine d'identificateur X, à quel routeur Y il faut envoyer le paquet. Pour des raisons en partie idéologiques, LISP n'a pas considéré le DNS pour cette tâche et a plusieurs systèmes de correspondance possibles, le plus avancé se nommant ALT (pour ALternative Topology). La tâche serait relativement simple si le réseau ne changeait pas mais la réalité étant qu'il y a des pannes, des reconfigurations, etc, une bonne partie de la complexité de LISP et de sa fonction de correspondance va être dans la détection et le traitement des pannes (pas question d'envoyer des paquets à un ITR en panne). Ce problème, là encore, est commun à toutes les propositions de séparation de localisateur et d'identificateur.

C'est donc logiquement sur ces fonctions (correspondance entre identificateur et localisateur, et détection puis contournement de pannes) que se focalisent les critiques. Alors que LISP ne change pas énormément le modèle d'IP, le déploiement d'un tout nouveau système de correspondance, non testé, et qui doit encaisser d'énormes quantités d'information changeant souvent, est vu comme le plus gros risque de LISP. Parmi les problèmes posés : que va t-il advenir du premier paquet, celui pour lequel le routeur ne connait pas encore de localisateur ? Le temps que le système de correspondance l'obtienne (et une requête dans ALT peut avoir un long chemin à parcourir), le paquet va devoir attendre. Les gros routeurs, ne souhaitant pas gérer de longues files d'attente, abandonneront probablement immédiatement de tels paquets, comme ils le font aujourd'hui lorsqu'il n'y a pas d'entrée ARP pour le destinataire. La source finira par réemettre et, cette fois, la table aura été remplie et le second paquet sera acheminé. Certains protocoles pourraient mal supporter cette « perte du premier paquet » (qui n'est pas non plus un problème spécifique à LISP). La réponse des LISPiens est que le problème n'est pas si grave que cela, les caches des routeurs se peupleront vite de l'essentiel des correspondances, ne serait-ce que grâce aux pirates scannant le réseau. Quant à ALT, il n'est qu'une des propositions, LISP offre le choix de plusieurs systèmes de correspondance identificateur -> localisateur comme TREE. Le modèle de LISP ne repose pas sur une fonction de correspondance unique.

Quant à la complexité de détection des pannes, nécessitant des échanges spécifiques entre les ITR et les ETR (les routeurs d'entrée et de sortie des tunnels), elle est vue comme inévitable, et, comme LISP fonctionne déjà sur le terrain, l'argument massue des LISPiens est que « ça marche ».

Le second système présenté, RANGI (Routing Architecture for the Next Generation Internet, présenté par X. Xu), en section 3, est, au contraire de LISP, une solution basée sur les machines terminales et non plus sur les routeurs. Comme HIP, RANGI introduit un identificateur propre à la machine et les connexions TCP sont liées à cet identificateur et plus aux adresses IP. Mais, alors que l'identificateur de HIP est « plat », sans structure, ce qui le rend difficilement résolvable en localisateur (et difficilement filtrable par les pare-feux), celui de RANGI est hiérarchique, pour pouvoir être résolu en localisateur par les méthodes arborescentes qui ont fait leur preuve, par exemple avec le DNS (alors que HIP doit utiliser des techniques moins éprouvées comme les DHT).

Comme HIP, RANGI ne connait que la distinction entre routeurs et machines terminales et n'a pas de distinction entre le cœur du réseau et ses bords. On parle donc de solution CEE (Core-Edge Elimination). Comme toute solution « côté machines terminales », RANGI nécessitera une mise à jour de tous les systèmes d'exploitation. La question de savoir s'il vaut mieux modifier toutes les machines terminales (plus nombreuses, pas forcément gérées, mais moins sensibles et plus souvent changées pour une neuve) ou tous les routeurs (moins nombreux, gérés par des professionnels mais souvent difficiles à remplacer ou à mettre à jour) a été souvent discutée dans le RRG mais sans résultat ferme.

Comme toute solution de séparation de l'identificateur et du localisateur, RANGI nécessitera le déploiement du nouveau système de correspondance entre identificateur et localisateur. Mais, contrairement à LISP, RANGI envisage de réutiliser le DNS.

À noter que le RRG insistait sur la déployabilité incrémentale des solution, nécessaire pour éviter d'arrêter tout l'Internet pendant les années de la transition. RANGI la permet mais les premiers adoptants ne gagnent rien à le faire, ce qui conduit à s'interroger sur la possibilité d'un déploiement effectif. Après tout, HIP, solution élégante et sûre, normalisée depuis longtemps, implémentée pour Linux et FreeBSD, n'a jamais décollé, en partie à cause de ce problème de la « récompense initiale ».

Proposition suivante, en section 4, IVIP (Internet Vastly Improved Plumbing, dû à R. Whittle). Système de séparation cœur-bords, comme LISP, proche de LISP par beaucoup d'aspects, il s'en distingue notamment par le fait que les correspondances entre identificateurs et localisateurs sont poussées, plutôt que tirées, et que donc tous les routeurs d'entrée de tunnel ont un accès rapide à tout moment à une copie complète de la base. Cette mise à jour en temps réel élimine la nécessité pour les ITR (routeurs d'entrée des tunnels) de tester que l'ETR correspondant attend toujours les paquets à la sortie. En contrepartie, elle exige beaucoup de mémoire chez l'ITR, de l'ordre de dizaines de Go (cela semble énorme mais, d'ici à l'adoption massive, le moindre ordinateur de bureau aura autant de RAM que cela).

Cette base des correspondances, disponible en temps réel, malgré le taux de changement qu'imposent, par exemple, les machines et les réseaux mobiles, est évidemment la principale faiblesse d'IVIP. Certes, elle permet d'éliminer complètement plusieurs problèmes sérieux, concernant la mobilité ou la détection des pannes d'un ETR, mais est-elle réaliste ? Il n'y a aucun précédent développé et déployé avec succès... Le DNS ne fonctionne qu'en renonçant à la propagation instantanée des informations. DRTM (Distributed Real Time Mapping, le système de correspondance d'IVIP) fera-t-il mieux ? En tout cas, il est intéressant de voir ce que permet cette approche.

Autre point à noter : les solutions de séparation du cœur et des bords, comme LISP et IVIP, sont parmi les seules à ne pas avoir besoin de noms uniques et donc à pouvoir fonctionner avec les petites adresses IPv4. La plupart des autres solutions dépendent d'IPv6.

Mais IVIP et LISP peuvent fonctionner avec IPv6. Au contraire, hIPv4 est spécifique à IPv4. Il a souvent été dit que la séparation entre identificateur et localisateur était déjà réalisée dans l'Internet, via le NAT, où l'adresse privée est un identificateur et l'adresse publique est un localisateur. C'est bien sûr largement une boutade (par exemple, l'adresse privée n'est pas unique, une machine qui se déplace peut changer d'adresse privée, etc), mais cela peut inspirer des idées qui ont des points communs avec le NAT comme hIPv4 (protocole créé par Patrick Frejborg). L'idée de base est que chaque machine a un identificateur sous forme d'une adresse IPv4 et un localisateur de même syntaxe. Les deux noms seront insérés dans chaque paquet (une petite couche entre la couche 3 et la couche 4), les routeurs de bord du domaine faisant l'échange des noms, pour que les autres routeurs n'aient pas à être modifiés. Du fait que la machine terminale doive insérer ces deux noms (l'identificateur et le localisateur), son système d'exploitation doit être modifié et hIPv4 est donc une des rares solutions qui nécessitent des changements à la fois dans les machines terminales et dans certains routeurs. Autre problème, l'épuisement des adresses IPv4 fait qu'on peut se demander d'où viendront ces adresses... Ce problème, celui de la déployabilité, et la question (qu'on retrouve dans le NAT) des protocoles qui s'échangent directement des adresses IP (comme SIP) fait que hIPv4 fait partie des propositions qui sont explicitement rejetées.

Continuons, puisque l'imagination des participants au RRG est sans limites. La section 6 présente NOL (Name OverLay). Actuellement, dans l'Internet, les noms de domaine, gérés dans le DNS, sont complètement extérieurs à la machine elle-même. C'est au point qu'une machine n'a pas de moyen simple de connaître son propre nom de domaine (si elle en a un !) sans parler de l'idée de l'influencer ou de le changer. L'idée de base de NOL est d'ajouter une couche de gestion des noms de domaine à toutes les machines, et d'utiliser ces noms comme identificateurs. (Voir les Name-Based Sockets, en section 15, une idée qui présente de nombreuses similarités.) Il est difficile de la décrire en détail car, apparemment, aucune spécification écrite n'a été produite. Il n'est pas nécessaire de modifier le système d'exploitation mais il faudra modifier les bibliothèques utilisées habituellement pour la résolution de noms (sur Unix, la libc). NOL n'implique pas de modifier l'application des deux côtés (contrairement à NBS, name-based sockets, présenté plus loin) car des relais spéciaux traduisent les noms et les adresses IP (une sorte de routeur NAT étendu). NOL n'a pas bénéficié de critiques ou de jugements précis, peut-être en raison de son caractère trop exotique.

C'est seulement avec la section 12 qu'apparait ILNP (Identifier-Locator Network Protocol, fait par R. Atkinson & S. Bhatti, site officiel en http://ilnp.cs.st-andrews.ac.uk/, bons transparents d'introduction en à NANOG, RFC 6740 et suivants, l'architecture qui a finalement eu les faveurs des présidents du groupe. Il repose sur une stricte séparation de l'identificateur et du localisateur, avec le DNS pour passer de l'un à l'autre. Pour gérer les changements de connectivité, ILNP fait donc un usage intensif de DNSSEC et des mises à jour dynamiques du DNS (RFC 2136 et RFC 3007). L'auteur semble d'ailleurs prêter trop de pouvoirs à DNSSEC, par exemple en disant que les requêtes PTR peuvent également être authentifiées. C'est vrai qu'on peut signer un enregistrement PTR mais, lorsque le PTR de 2001:db8::dead:beef pointe vers www.amazon.com, il n'y a aucun moyen de s'assurer qu'il en a le « droit », DNSSEC ou pas.

ILNP atteint plusieurs des objectifs du RFC 5887 mais pas tous. Ainsi, certains serveurs (ceux du DNS, par exemple) doivent toujours être décrits par un localisateur. Dans son état actuel, ILNP impose l'usage du DNS pour tout (plus de ping 2001:db8:1:3::cafe), ce qui ne convient pas forcément à toutes les applications. Il faudra donc sans doute étendre ILNP sur ce point.

Dernière architecture de routage envisagée dans notre RFC, IRON/RANGER (section 16) où IRON signifie Internet Routing Overlay Network (auteur : F. Templin, décrit dans le RFC 6179) et s'appuie sur l'architecture RANGER (Routing and Addressing in Networks with Global Enterprise Recursion, RFC 5720). RANGER est dérivé de ISATAP (RFC 5214) et fournit un système de tunnels automatiques pour transporter des paquets identifiés par un... identificateur à travers un cœur qui n'utilise que des localisateurs. À son tour, RANGER s'appuie sur le mécanisme SEAL (Subnetwork Encapsulation and Adaptation Layer, RFC 5320, qui gère notamment les questions de MTU, toujours cruciales avec les tunnels. La critique de ce mécanisme note que beaucoup de détails manquent, notamment la fonction de recherche de la correspondance entre un identificateur et un localisateur. Elle remarque aussi que SEAL empêcherait de déployer les jumbogrammes. Dans sa réponse à la critique, l'auteur note que IRON ne repose pas sur un système de mapping classique mais sur une combinaison du protocole de routage et d'un protocole spécifique de distribution des correspondances. Personnellement, cela me semble encore très flou.

Une autre architecture est présentée en section 14, Évolution. Conçue par Lixia Zhang, une vétéran de l'IETF, auteure de plus de trente RFC, Évolution propose une approche du passage à l'échelle du système de routage qui est assez originale. L'idée de base est de faire feu de tout bois, en agrégeant les routes partout où on peut, sans attendre le « Grand Soir » d'une nouvelle architecture. Évolution critique la tendance des autres propositions du RRG à considérer qu'on ne peut rien résoudre tant qu'on n'a pas changé tout le routage. Mais, comme le peu de déploiement de IPv6 l'a montré, les solutions qui aideront tout le monde, une fois que tout le monde les aura déployé, ont le plus grand mal à s'imposer sur l'Internet. Les solutions qui gagnent sont au contraire en général celles qui procurent un bénéfice immédiat et à court terme aux décideurs.

Évolution propose donc de commencer par le routeur seul : tout routeur pourrait déjà agréger massivement les routes qu'il connait, économisant ainsi sa mémoire. Cet effet est d'autant plus marqué que le routeur a peu de liens physiques possibles. Ensuite, au sein cette fois d'un système autonome, on pourrait désigner certains routeurs comme étant les seuls à avoir une connaissance complète des liens externes, la plupart des routeurs de l'AS pouvant alors se contenter de tunnels vers ces « super-routeurs », créant une sorte de schéma Map-and-Encap local. Une fois cette « agrégation virtuelle » réalisée à l'intérieur de plusieurs AS, ceux-ci pourraient annoncer ces super-routeurs via BGP, étendant leur bénéfice aux autres AS. Enfin, une séparation plus intense entre le contrôle des routes (fait par BGP, et qui limite l'agrégation puisqu'il faut pouvoir annoncer les routes aux autres) et la transmission effective des paquets (où le routeur peut se contenter d'une FIB bien plus petite que sa RIB) complèterait le dispositif. Le point important d'Évolution est que chaque étape apporte ses bénéfices, et qu'il n'est donc pas indispensable de faire miroiter des bénéfices lointains aux décideurs pour les convaincre. Chaque étape a sa récompense propre.

Mais Évolution a ses propres problèmes. Certaines des techniques d'agrégation perturbent les systèmes existants (par exemple, l'agrégation de N préfixes en un super-préfixe, qui couvre un espace plus grand que ne le faisaient les N sous-préfixes, crée des adresses routables qui n'existaient pas avant, ce qui peut entraîner de nouvelles boucles de routage, et peut gêner les systèmes de sécurité comme RPF - RFC 3704). D'autre part, l'agrégation virtuelle allonge le chemin pris par les paquets, et peut aussi gêner RPF. À noter qu'Évolution ne fournit pas de solution pour la mobilité, concept à la mode, mais dont il n'est pas évident qu'il doive être géré par le système de routage (plutôt que, par exemple, une combinaison de DHCP et de meilleures applications).

Une autre critique faite à Évolution est plus philosophique : en fournissant des bénéfices à court terme, n'encourage-t-on pas les rustines sur un système déjà pas mal rapiécé, au risque de détourner les gens d'une transition, certes coûteuse mais nécessaire ?

On l'a vu, un problème commun à toutes les propositions de séparation du localisateur et de l'identificateur est le système de correspondance (mapping) entre les deux. Cela a mené certains à concentrer leurs efforts sur ce problème et à travailler sur des systèmes de correspondance génériques, pouvant être utilisés pour plusieurs protocoles. C'est le cas de LMS (Layered Mapping System), en section 8. Comme le ALT de LISP, il repose sur une hiérarchie des noms (système de résolution bien plus éprouvé que les systèmes plats, qu'utilisent par exemple les DHT). Mais, contrairement à ALT, la correspondance entre noms est complètement déconnectée du routage : ce ne sont pas les FAI ou les opérateurs réseau qui font la résolution de noms.

Autre système de correspondance, le 2-phased mapping de la section 9. Ce système vise à trouver l'ETR (le routeur de sortie du tunnel, celui qui est le plus « proche » du réseau visé) correspondant à un préfixe donné, le préfixe contenant l'identificateur de la machine visée. Tout serait simple si cette correspondance préfixe -> ETR était relativement statique. Mais, évidemment, ce n'est pas le cas et 2-phased mapping considère qu'un système qui stockerait toutes les relations préfixe -> ETR de la planète ne tiendrait pas longtemps. Son idée centrale est d'intercaler un numéro de système autonome (AS) entre les deux, de façon à avoir une relation préfixe -> AS -> ETR. Les systèmes autonomes connaissent en effet certainement leurs clients et donc les ETR qui les desservent. Il ne reste donc qu'à créer un système pour que les AS puisse informer le système de résolution des préfixes qu'ils servent. On peut donc envisager de d'abord résoudre le préfixe en un numéro d'AS puis d'interroger ce dernier. Ce système en deux étapes (les résultats de chacune pouvant être mis en cache) passe certainement mieux à l'échelle. À noter que les deux étapes ne sont pas forcées d'utiliser les mêmes techniques (par exemple, la première pourrait être faite avec le DNS, ou bien avec un serveur centralisé, type whois, et la seconde avec une extension à BGP). L'idée n'a toutefois pas été assez développée pour être considérée sérieusement par le RRG.

On l'a vu, toutes les propositions soumises au RRG ne concernaient pas forcément une architecture de routage nouvelle, certaines présentaient une solution auxiliaire, qui allait aider les nouvelles architectures. C'est le cas des Name-based sockets de la section 15. L'idée de base est de ne manipuler, depuis les applications, que des noms et de laisser les couches basses gérer et stocker les adresses. Dans la proposition actuelle, ces name-based sockets permettraient aux applications d'initier et de recevoir des communications uniquement avec les noms. Il ne s'agit pas seulement de cacher les adresses IP dans une bibliothèque utilisée par l'application (comme le font, par exemple, les bibliothèques curl et neon pour les programmeurs C) mais de déplacer leur gestion bien plus bas, dans la pile IP elle-même, permettant ainsi des choses comme le changement d'adresse IP en cours de communication.

En quoi est-ce que cela aiderait le routage ? Eh bien, cela réduirait la nécessité de disposer d'adresses PI et transformerait l'adresse IP est un nom largement invisible, comme l'est l'adresse MAC aujourd'hui. La souplesse que cela apporterait permettrait, par exemple, d'agréger plus radicalement les préfixes. Les NBS (name-based sockets) ont bien d'autres propriétés intéressantes comme de rendre le NAT largement inoffensif (si l'application ne voit jamais d'adresses IP, leur changement par le routeur NAT n'aura pas de conséquence).

Les NBS sont donc une solution situéee dans la machine terminale, sans changement des routeurs. Leur déploiement suppose donc leur adoption par les systèmes d'exploitaion (rappelez-vous qu'il ne s'agit pas d'une simple couche pour aider le programmeur, les NBS doivent interagir fortement avec IP et donc être dans le noyau). NBS est plus longuement documenté dans l'article de Vogt, « Simplifying Internet Applications Development With A Name-Based Sockets Interface ».

Quelles sont les limites des NBS ? D'abord, certaines applications auront toujours besoin d'adresses IP, par exemple celles nécessaires au bootstrapping comme les serveurs DNS. Ensuite, un réseau ne pourra abandonner ses adresses PI que lorsque toutes ses machines auront migré vers NBS.

Où cela nous mène t-il ? Comme indiqué au début, aucune proposition n'a recueilli le consensus du groupe. La section 17 expose donc la seule recommandation des présidents du groupe. Ceux-ci exposent d'abord le contexte, celui d'un Internet faiblement coordonné, sans point de décision central, et où les changements ne peuvent être introduits que de manière incrémentale. Tout changement étant compliqué, il faut choisir avec soin les changements qu'on propose. L'Internet a tenu, et très bien, jusqu'à présent, grâce à un grand nombre de modifications partielles, faites au fur et à mesure que les problèmes se posaient. Mais l'accumumation de ces changements a fini par mener à un réseau excessivement complexe et difficiles à maintenir. Les présidents du RRG proposent donc à la fois des changements à court terme, pour traiter les cas les plus urgents et une « bonne » solution à long terme, dont ils reconnaissent qu'elle n'existe pas encore. La recommandation est donc de travailler sur trois techniques :

  • À court terme, une agrégation plus vigoureuse des préfixes, comme proposé dans le plan Évolution (section 14 et Internet-Draft draft-zhang-evolution).
  • À long terme, une nouvelle architecture fondée sur ILNP (Identifier-Locator Network Protocol, section 12).
  • À court et moyen terme, travailler à rendre la renumérotation des réseaux plus facile, pour diminuer la pression en faveur des adresses PI. Décrit dans le RFC 5887, cette question est désormais du ressort du futur groupe de travail Renum.

Pourquoi ces choix ? L'agrégation de Évolution parce qu'on a besoin de solutions à court terme. ILNP parce que c'est une solution architecturalement propre, qui sépare nettement identificateur et localisateur, et qui ne dépend pas de tunnels. Et la rénumérotation facilitée parce que, quelle que soit la solution finale choisie, on ne pourra pas éviter des rénumérotations de temps en temps.


Téléchargez le RFC 6115


L'article seul

RFC 6108: Comcast's Web Notification System Design

Date de publication du RFC : Février 2011
Auteur(s) du RFC : C. Chung (Comcast), A. Kasyanov (Comcast), J. Livingood (tComcast), N. Mody (Comcast), B. Van Lieu
Intérêt historique uniquement
Première rédaction de cet article le 24 février 2011


Soit un FAI avec beaucoup de clients résidentiels. La plupart utilisent une machine sous Windows. Beaucoup de ces machines sont infectées par un des innombrables virus ou vers qui existent pour cette plate-forme. Devenues des zombies, ces machines participent désormais à diverses opérations illégales comme les dDoS ou l'envoi de spam. Si le FAI détecte, par le comportement de ces machines, ou par des rapports qui lui sont envoyés, qu'un de ses clients a été zombifié, comment le prévenir ? Vues les marges financières existantes dans cette industrie, pas question d'envoyer un technicien compétent chez le client pour lui expliquer. Il n'est même pas possible de l'appeler et de passer une heure à répondre à ses questions idiotes, cela mangerait tout le profit retiré de l'abonnement de ce client. Ce RFC décrit le système qu'utilisait Comcast pour prévenir ses abonnés.

Il existe bien sûr d'autres méthodes, comme de couper purement et simplement la connexion Internet dudit client. Cette méthode est régulièrement réclamée par certains éradicateurs. Outre qu'elle n'est pas dans l'intérêt financier du FAI (le client arrêterait de payer s'il était coupé), elle n'est pas envisageable dans un État de droit (en France, le Conseil Constitutionnel avait cassé une version de la loi Hadopi car elle prévoyait une coupure de l'accès Internet sans jugement). Même dans un pays de cow-boys, cette mesure est largement jugée comme trop radicale (voir la description de la section 12, plus loin). En outre, l'utilisateur risque de ne pas la comprendre, de croire à une panne et d'embêter le support utilisateur. Comcast a donc choisi une autre approche, celle de la notification à l'utilisateur, dont on espère qu'il réagira et prendra des mesures pour éliminer le malware de sa machine.

Concevoir un tel système de notification n'est pas évident. Il n'existe (heureusement) pas de moyen technique standard permettant à un tiers, le FAI, de faire soudain apparaître des messages sur l'écran de l'utilisateur (un tel mécanisme serait vite détourné par des plaisantins). Envoyer un courrier est simple et automatisable mais rien ne garantit que l'utilisateur les lit (la plupart ne le liraient pas ou bien, peut-être à raison, considéreraient-ils qu'il s'agit de hameçonnage).

L'approche de Comcast est donc de profiter du fait que la plupart des utilisateurs passent beaucoup de temps à regarder des pages Web. Il « suffit » de détourner les pages HTML, d'y insérer le message et bingo ! Le message apparaîtra à l'écran. Voici une copie d'écran de http://www.example.com/, avec l'exemple de modification que donne le RFC en section 8. Cette modification consiste simplement en l'ajout d'un peu de JavaScript: web-notification-example.png (On note que la possibilité d'accuser réception, mentionnée plus loin dans le RFC, est absente de cet exemple. Notez aussi le commentaire dans le code CSS qui insiste sur l'importance de ne pas hériter des styles qui seraient déjà présents dans la page.)

Bref, ce mécanisme est une attaque de l'homme du milieu, réalisée pour la bonne cause. Les auteurs insistent beaucoup sur le fait que leur solution repose sur des normes ouvertes et n'utilise pas de DPI mais cela me semble tout à fait secondaire. Le point important est que le FAI joue un rôle plus actif dans la chasse aux zombies et, pour cela, s'insère dans les communications de son client. Ce n'est pas forcément une mauvaise idée mais c'est une modification sérieuse du modèle traditionnel (où le client était seul maître à bord, même si, la plupart du temps, il ne se rendait pas du tout compte de la responsabilité qu'il avait.) Pour l'instant, il n'existe pas de travail organisé à l'IETF sur ce problème des machines zombies et chacun en est donc conduit à expérimenter seul (cf. section 13 du RFC).

Les détails pratiques suivent. La solution décrite très en profondeur est spécifique à DOCSIS mais pourrait être adaptée assez facilement à d'autres types d'accès. Les techniques utilisées sont le protocole ICAP (RFC 3507) et HTTP, les logiciels étant Squid et Tomcat.

Voyons d'abord le cahier des charges exact. Il figure en section 3. Je ne vais pas répéter tous ses points ici, seulement les plus importants. D'abord, les principes généraux :

  • N'est utilisé que pour les notifications de problèmes sérieux (comme le recrutement dans un botnet), pas pour des publicités.
  • Tourne sur le port 80, celui de HTTP, car à peu près tous les utilisateurs s'en servent. Ne doit pas gêner les autres protocoles qui utiliseraient ce port. D'une manière générale, ne doit pas perturber ou casser des applications.
  • N'utilise pas de ReSeTs TCP comme le faisait Comcast pour démolir les connexions BitTorrent de ses utilisateurs (sauf erreur, c'est la première fois que Comcast reconnait officiellement qu'il utilisait cette méthode (RFC 3360), après l'avoir nié pendant longtemps).
  • Permet à l'utilisateur de dire « Oui, je sais  » et de faire ainsi cesser les notifications.
  • Respecte les pages Web existantes, n'en supprime pas du contenu et n'en insère pas (à vous de voir si l'exemple Javascript montré plus haut respecte ce principe). Le RFC note justement que toute modification des pages Web existantes susciterait une levée de boucliers.

Ensuite, ceux liés au relais HTTP :

  • Logiciel libre, avec un client ICAP (Squid a été choisi, entre autres pour cette gestion d'ICAP).
  • Possibilité d'ACL car les notifications ne doivent être envoyés qu'à certains utilisateurs, et que certaines pages Web ne doivent pas être affectées du tout.

Il y a aussi quelques exigences techniques pour le serveur ICAP (un protocole, normalisé dans le RFC 3507, permettant à un serveur ou relais de demander au serveur ICAP des changements à apporter au contenu qu'ils servent) et pour l'arrière-plan du système (la partie qui va noter les comportements bizarres des machines, ainsi que les actions de réparation des utilisateurs).

Armée de ces bons principes, les sections 4, 5, 6 et 7 présentent le système effectivement déployé. Le relais Squid... relaie les requêtes HTTP et, lorsqu'il reçoit une réponse, demande au serveur ICAP si et comment la modifier. Le serveur ICAP utilise GreasySpoon. Si la notification est nécessaire, il répond avec un bout de code Javascript à insérer dans les pages. Un serveur Tomcat garde les messages à envoyer aux utilisateurs (il peut y avoir plusieurs types de messages). Un équipement de load-balancing est utilisé pour séparer le trafic HTTP du reste (même s'il tourne sur le port 80) et pour n'aiguiller vers le relais Squid que les clients listés comme suspects. Le dessin n° 1 montre tous ces composants et leur interaction. Le dessin n° 2, plus concret, illustre les connexions réseau entre ces composants. À noter qu'il ne semble pas y avoir de protection contre un malware qui supprimerait la notification (après tout, il contrôle la  machine de l'utilisateur).

Voici pour le fonctionnement technique. Maintenant, quelques considérations de sécurité, en section 10. D'abord, la rédaction du message de notification doit être très soignée, notamment pour éviter que l'utilisateur ne la considère comme du hameçonnage. Le message ne doit pas mener à une page où l'utilisateur est invité à taper son mot de passe. Il doit fournir un moyen d'obtenir plus de détails, par exemple un numéro de téléphone ou tout autre mécanisme de validation indépendante.

Un tel système de modification des pages Web vues, à des fins de notification, est-il Bon ou Méchant ? La section 11 discute cette question philosophique. Certains peuvent penser que le changement, par un intermédiaire technique, le FAI, est un franchissement de la ligne rouge. Selon ce point de vue, les intermédiaires ne devraient jamais tripoter le contenu des communications. Le RFC ne répond pas réellement à ces objections (à part en affirmant que Comcast a de « good motivations » et par l'argument traditionnel de chantage que, si on refuse ce mécanisme, on aura pire, par exemple à base de DPI) mais note que, au minimum, l'existence de ce système doit être annoncée aux clients (actuellement, la plupart des FAI gardent un silence complet, vis-à-vis de leurs propres clients, sur les éventuelles opérations de « gestion du réseau » qu'ils effectuent).

Et, compte-tenu des objections que peut soulever ce système, fallait-il publier ce RFC ? C'est un débat traditionnel à l'IETF : lorsqu'une idée ne fait pas l'objet d'un consensus, mais est largement déployée sur l'Internet, faut-il la documenter dans un RFC (évidemment sans que celui-ci ait le statut de norme, cf. RFC 1796 et RFC 2026), au risque que des gens croient que l'idée bénéficie d'un soutien de l'IETF, ou bien l'ignorer, au risque que les RFC ne reflètent plus la réalité de l'Internet ? La section 11 répond également à ce débat de fond en considérant qu'il vaut mieux publier, ne serait-ce que pour aider aux futurs débats.

Le problème de ces notifications est d'autant plus complexe que le FAI n'est pas tout seul face aux décisions à prendre : de nombreux organismes, au gouvernement ou ailleurs, font lourdement pression sur les FAI pour que ceux-ci fassent quelque chose contre les machines zombies. Est cité Howard Schmidt, conseiller d'Obama pour la cybersécurité, qui dit « As attacks on home-based and unsecured networks become as prevalent as those against large organizations, the need for ISPs to do everything they can to make security easier for their subscribers is critical for the preservation of our nation's information backbone. » Le RFC dit clairement qu'un des buts de cette technique de notification est de satisfaire de telles demandes.

Mais, pour atteindre ce but, y a-t-il d'autres méthodes ? La section 12 présente une alternative possible, le jardin fermé. Dans un tel système, les clients détectés comme zombifiés sont limités à l'accès à un petit nombre de sites Web, par exemple ceux de sites liés la sécurité, ou à la mise à jour de leur système d'exploitation. De facto, cela notifie l'utilisateur qu'il y a un problème. On peut aussi rediriger toutes les autres connexions HTTP vers un serveur présentant un message d'alerte. Mais c'est beaucoup plus violent, en coupant l'accès à des services que l'utilisateur peut considérer comme essentiels, comme une conversation téléphonique qui serait alors brutalement interrompue. La responsabilité du FAI serait alors clairement engagée. Le RFC rappelle à juste titre qu'il n'y a pas que le Web ! Et rejette donc l'idée du jardin fermé.

Ah, et mon opinion personnelle ? Je pense que cette méthode est un compromis acceptable. Sur le principe, c'est une attaque de l'intermédiaire et une violation de la neutralité du réseau mais l'ampleur du problème des machines Windows infectées, qui attaquent ensuite les autres, est tel qu'il peut être justifié de prendre des mesures un peu dures. Après, tout dépendra des détails concrets de réalisation (taux de fausses alertes, par exemple).

Un article avait été fait à l'occasion des premiers tests, « Comcast to send infected-PC alerts ».


Téléchargez le RFC 6108


L'article seul

RFC 6106: IPv6 Router Advertisement Options for DNS Configuration

Date de publication du RFC : Novembre 2010
Auteur(s) du RFC : J. Jeong (Brocade/ETRI), S. Park (Samsung), L. Belœil (France Telecom R&D), S. Madanapalli (Ordyn)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF 6man
Première rédaction de cet article le 30 novembre 2010
Dernière mise à jour le 22 décembre 2010


Il existe deux méthodes pour configurer une machine IPv6 automatiquement, DHCP (RFC 8415) et RA (Router Advertisement, RFC 4862). Pendant longtemps, l'avantage de la première était de pouvoir indiquer d'autres informations que l'adresse IP, comme par exemple les adresses des serveurs DNS. Le RFC 5006 avait apporté cette possibilité à la configuration par RA. Mais son statut n'était qu'expérimental. Désormais, voici la même option mais sous la forme d'une vraie norme. (Ce RFC a depuis été à son tour remplacé par le RFC 8106.)

Si on gère un gros réseau, avec de nombreuses machines dont certaines, portables, vont et viennent, s'assurer que toutes ces machines ont les adresses IP des serveurs de noms à utiliser n'est pas trivial (section 1 du RFC). On ne peut évidemment pas utiliser le DNS, cela serait tenter de voler en tirant sur les lacets de ses chaussures. Et configurer à la main les adresses sur chaque machine (par exemple, sur Unix, en les écrivant dans le fichier /etc/hosts) est bien trop difficile à maintenir. Se passer du DNS est hors de question. Pour les machines bi-protocoles (IPv4 et IPv6), une solution possible était d'utiliser un serveur de noms en v4. Mais pour une solution purement v6 ?

La solution la plus populaire actuellement est DHCP (RFC 8415 et RFC 3646). Son principal inconvénient est qu'elle est à état : le serveur DHCP doit se souvenir des baux qu'il a attribué. Sur un gros réseau local, le nombre de requêtes à traiter, chacune nécessitant une écriture dans une base de données, peut devenir très lourd.

Une autre solution est sans état et repose sur une nouveauté d'IPv6, les RA (Router Advertisements, cette méthode est aussi appelée ND, pour Neighbor Discovery, les RA en étant un cas particulier), décrits dans le RFC 4862. Ce sont des messages envoyés à intervalles réguliers par les routeurs et qui informent les machines non-routeuses des caractéristiques essentielles du réseau, comme le préfixe utilisé (par exemple 2001:DB8:BEEF:42::/64). Le routeur diffuse ses messages et n'a pas besoin d'écrire quoi que ce soit sur son disque, ni de faire des traitements compliqués lors d'une sollicitation, il répond toujours par le même message RA.

Ces RA peuvent diffuser diverses informations, par le biais d'un système d'options. Le principe de notre RFC est donc d'utiliser ces RA pour transporter l'information sur les serveurs de noms récursifs utilisables sur le réseau local, via des nouvelles options notamment celle nommée RDNSS (le numéro 25 lui a été affecté par l'IANA).

La section 1.1 du RFC rappelle qu'il existe plusieurs choix, notre RFC 6106 n'étant qu'une possibilité parmi d'autres. Le RFC 4339 contient une discussion plus détaillée de ce problème du choix d'une méthode de configuration des serveurs de noms (notons qu'il existe d'autres méthodes comme l'anycast avec une adresse « bien connue »). La section 1.2 décrit ce qui se passe lorsque plusieurs méthodes (par exemple DHCP et RA) sont utilisées en même temps.

La méthode RA décrite dans notre RFC repose sur deux nouvelles options, RDNSS, déjà citée, et DNSSL, qui n'existait pas dans le RFC précédent (section 4). La première permet de publier les adresses des serveurs de noms, la seconde une liste de domaine à utiliser pour compléter les noms courts (formés d'un seul composant).

La première option, RDNSS, de numéro 25, est décrite en section 5.1. Elle indique une liste d'adresse IPv6 que le client RA mettra dans sa liste locale de serveurs de noms interrogeables.

La seconde option, DNSSL, de numéro 31, est en section 5.2 (les deux options sont enregistrées dans le registre IANA, cf. section 8). Elle publie une liste de domaines, typiquement ceux qui, sur une machine Unix, se retrouveront dans l'option search de /etc/resolv.conf.

Sur Linux, le démon rdnssd permet de recevoir ces RA et de modifier la configuration DNS. Pour FreeBSD, on peut consulter une discussion sur leur liste. Les CPE de Free, les Freebox, émettent de telles options dans leurs RA (apparemment, à la date de publication de notre RFC 6106, uniquement des RDNSS). Voici ce qu'affiche Wireshark :

...
Ethernet II, Src: FreeboxS_c3:83:23 (00:07:cb:c3:83:23), 
             Dst: IPv6mcast_00:00:00:01 (33:33:00:00:00:01)
...
Internet Control Message Protocol v6
    Type: 134 (Router advertisement)
...
    ICMPv6 Option (Recursive DNS Server)
        Type: Recursive DNS Server (25)
        Length: 40
        Reserved
        Lifetime: 600
        Recursive DNS Servers: 2a01:e00::2 (2a01:e00::2)
        Recursive DNS Servers: 2a01:e00::1 (2a01:e00::1)

et les serveurs DNS annoncés répondent correctement. (Vous pouvez récupérer le paquet entier sur pcapr.net.)

Autre mises en œuvre de ces options, dans radvd, qui a déjà l'option RDNSS et bientôt (en décembre 2010) la nouvelle DNSSL (ainsi que pour les logiciels auxiliaires). Quant à Wireshark, le code a déjà été écrit mais n'est pas encore intégré.

La section 6 de notre RFC donne des conseils aux programmeurs qui voudraient mettre en œuvre ce document. Par exemple, sur un système d'exploitation où le client RA tourne dans le noyau (pour configurer les adresses IP) et où la configuration DNS est dans l'espace utilisateur, il faut prévoir un mécanisme de communication, par exemple un démon qui interroge le noyau régulièrement pour savoir s'il doit mettre à jour la configuration DNS.

RA pose divers problèmes de sécurité, tout comme DHCP, d'ailleurs. Le problème de ces techniques est qu'elles sont conçues pour faciliter la vue de l'utilisateur et de l'administrateur réseau et que « faciliter la vie » implique en général de ne pas avoir de fonctions de sécurité difficiles à configurer. La section 7 traite de ce problème, par exemple du risque de se retrouver avec l'adresse d'un serveur DNS méchant qui vous redirigerait n'importe Dieu sait où (les RA ne sont pas authentifiés). Ce risque n'a rien de spécifique aux options DNS, toute la technique RA est vulnérable (par exemple, avec un faux Neighbor Advertisement). Donc, notre RFC n'apporte pas de risque nouveau. Si on considère cette faiblesse de sécurité comme insupportable, la section 7.2 recommande d'utiliser SEND (RFC 3971).

À noter que l'annexe A résume les changements depuis le RFC 5006. Passage sur le chemin des normes, ajout de la nouvelle option DNSSL (DNS Search List) plus diverses précisions sur le protocole. Depuis, le RFC 8106 a été publié et c'est lui qui est désormais la norme pour cette option.

Merci à Alexis La Goutte pour ses informations.


Téléchargez le RFC 6106


L'article seul

RFC 6105: IPv6 Router Advertisement Guard

Date de publication du RFC : Février 2011
Auteur(s) du RFC : E. Levy-Abegnoli, G. Van de Velde, C. Popoviciu (Cisco Systems), J. Mohacsi (NIIF/Hungarnet)
Pour information
Réalisé dans le cadre du groupe de travail IETF v6ops
Première rédaction de cet article le 24 février 2011


Comme le décrit très bien le RFC 6104, la situation de la sécurité des RA (Router Advertisement, cf. RFC 4861) n'est pas satisfaisante. Les « faux RA », envoyés par un méchant ou par un maladroit, sont trop fréquents. Notre RFC 6105 propose donc une solution. Elle est bien plus légère que SEND et repose sur un filtrage au niveau deux.

Je vous renvoie à mon article sur le RFC 6104 pour davantage de détails sur le problème. Ici, je ne vais parler que de la solution. Elle fonctionne pour un réseau partagé où les participants doivent passer par un commutateur (on ne peut donc pas l'utiliser pour du WiFi ad hoc, cf. section 5) et elle nécessite que ledit commutateur mette en œuvre le système décrit dans ce RFC (cf. section 2 et sa figure 1).

Officiellement, SEND (RFC 3971), reste la solution de choix. Après l'obligatoire rappel que SEND résoudrait tous les problèmes, notre RFC rappelle qu'il n'est pas réaliste d'espérer un déploiement massif de SEND dans les années à venir. Pire, le RFC reconnait que certains équipements (on pense au célèbre grille-pain IPv6) n'auront jamais SEND. La solution proposé, RA Guard, est donc un système de filtrage des RA par le commutateur, suivant plusieurs méthodes possibles. Le commutateur sert donc de centre de contrôle, autorisant ou bloquant les RA selon plusieurs possibilités.

Quelles sont ces possibilités ? Les sections suivantes les décrivent. D'abord, le RA guard sans état (section 3). Dans ce mode, le commutateur examine les RA entrants et les bloque ou pas en ne tenant compte que du contenu du RA et de sa propre configuration. Il n'a donc pas de mémoire, pas d'état. Sur quelle base décider ? L'adresse MAC source du RA, le port sur lequel le RA a été reçu, l'adresse IP source, le ou les préfixes annoncés dans le RA… Le commutateur a pu être configuré pour autoriser ou interdire sur la base de ces informations. Une fois le RA considéré comme légitime, il est transmis sur toutes les interfaces, comme n'importe quel paquet. Le RFC présente par exemple une solution ultra-simple où l'administrateur du commutateur indique juste un port comme étant celui du routeur officiel, et les RA arrivant sur les autres ports seront donc simplement ignorés. Cette méthode a l'inconvénient de nécessiter une configuration manuelle.

Plus sophistiquée, le RA guard avec état (section 4). Le principe est d'apprendre automatiquement à quoi ressemblent les RA légitimes, avant de se mettre à bloquer les autres. Dans sa version la plus simple, le commutateur écoute pendant un moment (défini par l'administrateur), notant qui envoie les RA, puis considère que, après ce laps de temps, tout autre RA est illégitime. Cela protège donc contre les RA anormaux survenant après cette période d'apprentissage. Si un nouveau routeur légitime arrive, on recommence l'apprentissage de zéro.

La section 4.1 décrit les détails. Au début, le commutateur est dans l'état LEARNING où il écoute les RA. Fait-il suivre tous les RA pendant cette phase, ou bien les bloque-t-il tous ? C'est configurable selon le degré de paranoïa de l'administrateur. Une fois cette phase terminée, les interfaces passent dans l'état BLOCKING ou FORWARDING selon qu'elles recevaient des RA acceptables ou non. (Le RFC ne mentionne donc que la possibilité d'apprendre les interfaces où se trouve un routeur légitime, pas celles d'apprendre son adresse MAC.) La section 7 suggère fortement que l'administrateur jette un coup d'œil à la liste des interfaces à RA légitimes, pour vérifier… Par contre, elle ne rappelle pas que le mécanisme est mis en danger si un routeur illégitime est présent dès la phase d'apprentissage. Normalement, ce cas est traité par le fait que cette technique est combinée avec des filtres manuels comme ceux de la section précédente.

Encore plus ambitieux, la possibilité pour le commutateur d'être un mandataire SEND (section 4.2). L'un des problèmes de SEND est que chaque machine du réseau, grille-pain et frigidaire inclus, doit faire de la cryptographie (parfois compliquée, par exemple s'il faut récupérer des certificats intermédiaires) et être configurée avec un certificat. Avec le mandataire SEND, seul le commutateur va valider les annonces signées par SEND. Il les fera suivre ou les bloquera en fonction du résultat de la validation.

Je ne connais pas de liste d'implémentations officielles de ce service. Apparemment, certains le déploieraient déjà, si on en croit des témoignages. Fin 2011, Juniper annonçait RA Guard pour les versions 12.x, Cisco a déjà cette fonction dans des engins comme le Cisco 3750g avec « advanced enterprise featureset » (voir un bon article sur le sujet et un plus détaillé, du même auteur). Brocade n'a rien communiqué. Une technique permettant de contourner le RA guard a déjà été décrite.


Téléchargez le RFC 6105


L'article seul

RFC 6104: Rogue IPv6 Router Advertisement Problem Statement

Date de publication du RFC : Février 2011
Auteur(s) du RFC : T. Chown (University of Southampton), S. Venaas (Cisco)
Pour information
Réalisé dans le cadre du groupe de travail IETF v6ops
Première rédaction de cet article le 24 février 2011


Il y a une tension permanente en sécurité des réseaux, entre la sécurité et la facilité d'usage (quelqu'un a une meilleure traduction pour convenience ? « ergonomie » ?). Ainsi, le protocole IPv6 permet l'autoconfiguration sans état des machines, par le biais d'annonces, les RA (Router Advertisement) diffusées par les routeurs. C'est très pratique et IPv4 n'a rien de tel. Mais qui dit que la machine qui diffuse est un vrai routeur légitime ? Rien. Les « RAcailles » (mauvaise traduction de rogue RA), ces annonces envoyées à tort, sont très fréquents dans la réalité. Avant que des solutions soient proposées et discutées, ce court RFC spécifie précisément le problème.

Le mécanisme des RA (Router Advertisement) est décrit dans le RFC 4861. Le principe est que le ou les routeurs officiels du réseau local diffusent des informations telles que le préfixe à utiliser sur ce lien (ce qui permet l'autoconfiguration du RFC 4862) ou l'adresse IP du routeur à utiliser par défaut. Les « RAcailles » sont des annonces RA envoyées par un engin qui n'est pas routeur officiel. Cela peut être dû à une attaque délibérée, ou tout simplement à une erreur de configuration, par exemple une machine configurée pour monter un hotspot WiFi avec réseau ad hoc et qui diffuse donc des RA, se croyant le routeur officiel. Ce phénomène est fréquent sur les réseaux sans-fil partagés (on le voit à chaque réunion IETF, dont les participants sont pourtant censés être des experts, et il faut des annonces répétées au micro pour que les machines émettant des RAcailles se taisent ; un exemple à la réunion d'Hiroshima est décrit dans ce message). Mais on le voit aussi dans des réseaux filaires, par exemple les résidences d'étudiants.

Sur un réseau sans-fil partagé, il n'y a guère de moyen de repérer le coupable, dont on ne connait que l'adresse MAC. Encore aujourd'hui, la solution la plus courante (décrite en section 3.7) est de filtrer les RA, sur la base de l'adresse attendue (liste blanche), ou sur celle des adresses repérées comme erronées (liste noire). Mais cela diminue évidemment sérieusement l'intérêt de l'autoconfiguration (toujours cette tension entre sécurité et facilité d'usage). Sur Linux, cela serait quelque chose comme :

% ip6tables -A INPUT -m mac --mac-source 00:1b:77:bc:a4:e6 -j DROP

(Exercice pour le lecteur : cette commande bloque absolument tout le trafic en provenance de 00:1b:77:bc:a4:e6. Comment ne bloquer que les RA ? Benjamin Bachelart suggère ip6tables -A INPUT -m mac --mac-source 00:1b:77:bc:a4:e6 -p icmpv6 --icmpv6-type router-advertisement -j DROP qui semble correct mais je ne l'ai pas testé.)

Quel problème posent ces RAcailles ? La section 1 les résume : si les machines présentes les croient, et utilisent les informations qu'ils contiennent, elles peuvent se trouver partiellement ou totalement coupées du réseau. Par exemple, si elles changent l'adresse IP du routeur par défaut, pour celle indiquée dans le RAcaille, tous les paquets qui ne sont pas envoyés au réseau local sont transmis à un routeur voyou, qui peut les transmettre... ou pas.

Un point important de ce RFC est qu'il se focalise surtout sur les RAcailles accidentels, ceux provoqués par une erreur de configuration, qui sont de loin les plus fréquents aujourd'hui (les méchants sont plus habiles mais les maladroits sont beaucoup plus nombreux...). En outre, si les RAcailles sont émis par un attaquant conscient de ce qu'il fait, protéger contre eux serait très insuffisant : s'il peut émettre des faux RA, il peut aussi bien interférer avec le protocole ND.

Donc, première question (section 2), quel phénomène peut mener à l'envoi de RAcailles par une machine ? Il y en a trois :

  • La traditionnelle erreur commise par l'administrateur réseaux (qui tape les mauvaises commandes sur le routeur, ou bien sélectionne la mauvaise option dans un cliquodrome),
  • L'erreur commise par un utilisateur qui n'est pas l'administrateur réseaux (comme dans l'exemple du réseau ad hoc cité plus haut, par exemple suite à l'activation de ICS, qui transformera également la machine en un serveur DHCP IPv4, ou bien dans le cas d'un portable configuré pour un réseau isolé et connecté ensuite à un autre réseau),
  • L'attaque délibérée par le méchant, prélude à une DoS ou bien à une attaque de l'intermédiaire. Notons bien que ce genre d'attaques est rarement signalé (alors que les récits de RAcailles accidentels abondent). Le RFC relègue donc ce problème pour de futures études et se concentre sur le problème le plus fréquent.

Et quelles sont les solutions possibles ? La plupart seront détaillées dans d'autres RFC comme le RFC 6105 mais la section 3 du nôtre donne quelques pistes. La plus évidente est de laisser tomber l'autoconfiguration et de revenir aux solutions à configuration manuelle. Sûr mais pas forcément enthousiasmant pour l'administrateur du réseau. D'autant plus que cela n'éliminera pas les erreurs... Pour être cohérente, une telle solution implique, outre la configuration manuelle de l'adresse IP et du routeur, d'ignorer les éventuels RA (avec Linux, il faut mettre la variable sysctl net.ipv6.conf.all.accept_ra à 0).

Autre solution, profiter de ce que les RA soient diffusés à tous pour les observer et détecter ainsi rapidement les RAcailles. C'est ce que fait NDPMon, par exemple. Fait dans le commutateur, comme le propose le RFC 6105, cela pourrait permettre le blocage des RAcailles en temps réel. Le filtrage par les commutateurs peut aussi être configuré manuellement, par le biais d'ACL. Après tout, l'administrateur réseaux sait sur quel(s) port(s) du commutateur se trouvent les routeurs légitimes et il peut donc bloquer les RA sur les autres (quelqu'un a des exemples concrets avec des commutateurs réels ? Je n'ai jamais essayé.) Notez que cela marche seulement si toutes les communications passent par le commutateur, ce qui est typiquement le cas aujourd'hui des réseaux filaires. Avec un réseau sans-fil ad hoc, il faudra trouver autre chose.

De plus haute technologie, il y a aussi l'inévitable solution utilisant la cryptographie, SEND (RFC 3971), où les annonces des routeurs légitimes sont signées. SEND est très peu déployé en pratique, sans doute en raison de sa complexité, et du fait qu'il faille configurer chaque machine avec le certificat de la CA. Du point de vue sécurité, SEND est la solution idéale (cf. section 6), mais il est probablement peu adapté aux environnements assez ouverts, comme un campus ou bien un café avec WiFi, où chacun administre sa machine. Le principal avantage de SEND est qu'il fonctionne aussi en cas d'attaque délibérée et intelligente et il convient donc bien aux environnements qui exigent un haut niveau de sécurité.

D'autres solutions techniques ? Mais oui, l'imagination des experts étant inépuisable. Par exemple, puisque le RFC 4191 ajoute une option Préférence aux RA, pourquoi ne pas mettre cette option à la valeur maximale pour les routeurs légitimes, en espérant que les accidentels la laissent à une valeur plus faible ? Mais le RFC n'indique pas si cette option est souvent reconnue par les clients. Autre idée, se servir des protections de la couche 2 (par exemple 802.1X) pour limiter l'accès au réseau. Le problème est qu'authentification n'est pas autorisation. Une machine peut avoir légitimement un accès, sans être pour autant autorisée à envoyer des RA. Il reste le filtrage au niveau de la machine, déjà mentionné. Son principal inconvénient est qu'il faut manuellement maintenir à jour les ACL, ce qui supprime une bonne partie de l'intérêt de l'autoconfiguration.

Et la contre-attaque ? Si une machine envoie des RAcailles sans y être autorisée, on n'a pas de raison d'avoir des scrupules à la faire taire. Une autre solution aux RA non autorisés est donc de surveiller le trafic (comme avec NDPMon) et de générer des faux RA, ayant la même adresse source que les RAcailles, avec une durée de vie de zéro. Cet empoisonnement devrait donc masquer le RAcaille par le RA à durée de vie nulle (et qui ne sera donc pas utilisé par les machines). Cette technique est mise en œuvre dans la suite logicielle KAME et a déjà été déployée lors de réunions IETF. On peut télécharger le source en http://ramond.sourceforge.net. À noter qu'un tel outil pourrait aussi parfaitement être utilisé pour lancer une belle attaque par déni de service (cf. section 7).

Enfin, dernière solution proposée par notre RFC, configurer les machines pour n'utiliser que DHCPv6 et renoncer à l'autoconfiguration sans état. DHCP peut allouer les adresses. Une nouvelle option, en cours de normpalisation, lui permettra d'indiquer également le routeur à utiliser. DHCP présente de nombreux avantages pour l'administrateur réseaux, notamment d'un meilleur contrôle de la configuration des machines. Mais on n'a fait que déplacer le problème. Comme le montre l'expérience d'IPv4, les serveurs DHCP non autorisés sont un problème, autant que les RA non autorisés... Le seul avantage serait que le problème est mieux connu avec DHCP (voir aussi la section 5.2).

Les différentes solutions, avec leur domaine d'application, sont résumées dans un tableau en section 4. La section 5 discute ensuite d'autres problèmes liés à celui des RAcailles. Par exemple, un RA n'est pas forcément envoyé par diffusion, il peut être transmis directement à une machine et, dans ce cas, a des chances de ne pas être détecté par d'éventuels outils de surveillance. Les RAcailles accidentels seront sans doute en multicast mais un attaquant, lui, choisira peut-être donc l'unicast.

La section 5.2 compare les menaces de RA par rapport à celles de DHCP. De même que les RA peuvent être protégés avec SEND, DHCP peut être protégé par des options d'authentification (RFC 3315, section 21). Mais ne nous voilons pas la face : personne n'utilise ces options de sécurité (elles ont même été larguées par le RFC 8415). Elles sont bien trop contraignantes, alors qu'on choisit justement RA ou DHCP pour se simplifier la vie.

L'importance d'une surveillance du réseau, avec un logiciel comme NDPMon, est rappelée dans la section 5.4. Si cette recommandation est appliquée, l'administrateur réseaux saura au moins ce qui se passe. Actuellement, il est probable que la plupart de ces administrateurs ne savent même pas si le problème existe dans leur réseau.

Toujours dans la série « guérir si on n'a pas pu prévenir », la section 5.5 est consacrée aux conséquences. Si les RAcailles existent et que certaines machines en ont tenu compte, que faire ? Le comportement de la machine touchée est très imprévisible (plusieurs adresses, plusieurs routes par défaut, et, avec SHIM6, la machine peut même croire qu'elle est réellement connectée à plusieurs réseaux). Aujourd'hui, il n'y a pas de moyen simple, une fois les RAcailles supprimés, de ramener ces machines à la normale, on risque d'attendre jusqu'à deux heures (RFC 4862, section 5.5.3) avant que la machine n'oublie le RAcaille.

Quelques documents à lire sur ce sujet et des logiciels à essayer :


Téléchargez le RFC 6104


L'article seul

RFC 6094: Summary of Cryptographic Authentication Algorithm Implementation Requirements for Routing Protocols

Date de publication du RFC : Février 2011
Auteur(s) du RFC : M. Bhatia (Alcatel-Lucent), V. Manral (IP Infusion)
Pour information
Réalisé dans le cadre du groupe de travail IETF opsec
Première rédaction de cet article le 3 février 2011


Plusieurs protocoles de routage utilisent de la cryptographie pour l'authentification. C'est le cas par exemple d'OSPFv2 (RFC 2328), IS-IS (RFC 1195) et RIP (RFC 2453). Limitée au début à MD5, la liste des algorithmes utilisées croît petit à petit mais dans le désordre. L'idée de ce RFC est de spécifier le minimum d'algorithmes qu'un routeur sérieux doit gérer, de manière à garantir l'interopérabilité. Il faut être sûr que tous les routeurs aient au moins un algorithme en commun.

La section 1 détaille le problème. Lorsque qu'un protocole de routage (prenons comme exemple OSPFv2, RFC 2328, annexe D) permet d'authentifier ses pairs, il peut le faire par un mot de passe passé en clair, ou bien par un condensat cryptographique du mot de passe et d'autres informations. (D'autres protocoles sous-traitent l'authentification à une couche inférieure, comme OSPFv3 - RFC 5340 - qui la délègue à IPsec mais ils sont hors-sujet pour ce RFC. Depuis le RFC 6506, OSPFv3 a de toute façon une authentification à lui.) Le mot de passe en clair offre peu de sécurité puisque n'importe quel sniffer peut le capter. Ce mot de passe n'est vraiment efficace que contre les accidents, pas contre les attaques délibérées. La protection par condensat cryptographique n'a pas cet inconvénient. Elle fonctionne en résumant un message composé d'un secret partagé (le mot de passe) et d'autres informations connues des routeurs. Ainsi, le mot de passe ne circule jamais en clair.

Traditionnellement, la fonction de hachage utilisée était MD5 (RFC 1321) mais des attaques cryptographiques réussies contre MD5 mènent à son abandon progressif. L'avantage de MD5 était que tout le monde le connaissait et l'utilisait, alors que la migration vers de nouveaux algorithmes fait courir un risque de babelisation. Il faut noter que les attaques connues contre MD5 (RFC 4270) ne s'appliquent pas forcément à l'utilisation qu'en font les protocoles de routage et que la vulnérabilité de MD5 est donc encore dans le futur. Néanmoins, il est plus prudent de prévoir son remplacement dès aujourd'hui. Les remplaçants envisagés sont en général de la famille SHA. Ceux-ci seront sans doute à leur tour remplacés dans le futur, la cryptanalyse ne cessant jamais de progresser. L'ancienne normalisation, qui indiquait « en dur » la fonction de hachage dans la spécification du protocole de routage, n'est donc plus adaptée. Les sections suivantes du RFC détaillent la situation pour les principaux protocoles de routage cherchant, pour chacun d'eux, comment éliminer MD5 tout en ayant un algorithme commun.

Commençons par la section 2, consacrée à IS-IS. Si la norme ISO originelle ne permettait que le mot de passe en clair, le RFC 5304 a ajouté la possibilité de cryptographie, d'abord avec MD5 puis, dans le RFC 5310, d'autres algorithmes comme la famille SHA. L'avantage de l'authentification par mot de pass en clair est que, normalisée dès le début, elle fonctionne avec toutes les mises en œuvre de IS-IS. Sa sécurité est très mauvaise (il est trivial d'écouter le réseau pour découvrir le mot de passe). Il est donc recommandé d'utiliser les solutions cryptographiques, mais cela implique des algorithmes communs. Si un routeur ne connait que SHA-256 et l'autre que SHA-1, ils ne pourront pas s'authentifier mutuellement. Or, même si les deux routeurs mettent en œuvre le RFC 5310, cette situation est possible.

Notre RFC ne fait pas de choix mais demande que les futurs RFC sur IS-IS choisissent au moins un algorithme obligatoire, qui sera donc connu de tous les routeurs, et qui ne soit pas MD5.

L'autre grand protocole de routage interne, OSPF, fait l'objet de la section 3. Si OSPFv3 reposait entièrement sur IPsec et n'avait pas de mécanisme d'authentification propre (cela a changé avec le RFC 6506), OSPFv2 (de très loin le plus utilisé) a son mécanisme à lui. Ce dernier, dans la norme originale (RFC 2328), permettait le mot de passe en clair ou bien de la cryptographie avec MD5. Le RFC 5709 ajoutait la possibilité d'utiliser la famille SHA. Mais les seuls mécanismes d'authentification obligatoires sont ceux de l'ancien RFC (y compris le plus simple, « pas d'authentification »). Comme avec IS-IS, il est donc nécessaire qu'une nouvelle norme dise clairement quel est l'algorithme standard et sûr que doivent mettre en œuvre tous les logiciels OSPF.

Quant à OSPFv3 (section 4), du fait qu'il utilise IPsec, ses algorithmes communs sont ceux d'IPsec, ESP (RFC 4522) qui lui même utilise SHA-1 (RFC 2404). Ce dernier sera sans doute remplacé bientôt par AES (qui avait été introduit dans le RFC 3566).

Et le bon vieux RIP, dans sa version RIPv2 (section 5) ? Sa norme actuelle est le RFC 2453, qui ne prévoyait comme authentification que le mot de passe en clair. Le RFC 2082 ajoutait MD5 que le RFC 4822 a remplacé par SHA. Toutefois, comme les deux autres protocoles cités, RIP n'a pas d'algorithme unique garanti et une nouvelle norme est donc nécessaire, pour éviter que les routeurs ne se rabattent sur MD5 (ou, pire, sur le mot de passe en clair) pour pouvoir interopérer.

La version RIPng, elle (section 6), comme OSPFv3, se repose entièrement sur IPsec et donc sur les mêmes algorithmes.

La section 7 résume et rappelle les problèmes de sécurité abordés. D'abord, tous les mécanismes étudiés ici ne fournissent que l'authentification. Si on désire en plus de la confidentialité, il faut chercher ailleurs (par exemple IPsec avec ESP). D'autre part, les experts en cryptographie conseillent généralement de changer les clés régulièrement, diverses attaques cryptanalytiques prenant du temps. Il ne faut donc pas en donner à l'ennemi. Or, aucun de ces protocoles de routage ne fournit de mécanisme pour un remplacement coordonné des clés, il faut tout gérer à la main.


Téléchargez le RFC 6094


L'article seul

RFC 6092: Recommended Simple Security Capabilities in Customer Premises Equipment for Providing Residential IPv6 Internet Service

Date de publication du RFC : Janvier 2011
Auteur(s) du RFC : J. Woodyatt (Apple)
Pour information
Réalisé dans le cadre du groupe de travail IETF v6ops
Première rédaction de cet article le 25 janvier 2011


Ah, la sécurité informatique... Sujet de polémiques sans fin, à l'IETF comme ailleurs. Faut-il des pare-feux ? Faut-il protéger le PC de M. Michu par défaut ? Vaut-il mieux la liberté ou bien la sécurité (réponse en un paragraphe, de préférence) ? Il est très difficile de réunir un consensus sur ce thème et, après avoir essayé, le groupe de travail v6ops de l'IETF a décidé de produire uniquement des recommandations sur la configuration d'un pare-feu pour les CPE (les « boxes ») IPv6, sans s'engager sur la question de savoir s'il fallait un pare-feu ou pas...

Le CPE (Customer Premises Equipment) est le petit boîtier qui connecte le réseau du client résidentiel (M. Michu) au FAI. Parfois fourni par le FAI, parfois acheté en supermarché, il est typiquement laissé tel quel, sans changement de la configuration, et sa configuration par défaut a donc une grande importance. Aujourd'hui, où le principal protocole de l'Internet est IPv4, le CPE a en général une configuration par défaut qui inclut l'allocation d'adresses IP privées (RFC 1918) aux machines du réseau local, et une connexion au FAI, par laquelle arrivera une adresse IP publique. Certaines personnes croient que le fait que les machines « internes » ont une adresse IP privée leur assure une certaine sécurité. C'est largement faux mais, ce qui est sûr, c'est que le mécanisme de traduction d'adresses entre l'intérieur et l'extérieur empêche l'ouverture de connexion à la demande des machines extérieures. Si une imprimante a un serveur HTTP pour sa configuration, le monde extérieur ne peut pas s'y connecter par des moyens normaux (il existe plusieurs moyens « anormaux » comme le changement DNS, et c'est pour cela que le bénéfice en terme de sécurité est douteux). Parfois, on est content de ce barrage (qui empêche les méchants barbares de se connecter à notre innocente imprimante, qui n'est probablement pas configurée de manière très sûre, avec son mot de passe d'usine jamais changé), parfois on le regrette (quand le transfert de fichiers en pair-à-pair échoue ou bien quand un coup de téléphone SIP s'établit mais que la voix ne passe pas). Ce filtrage de fait peut en effet frapper aussi bien les applications légitimes que les autres.

Et en IPv6 ? Le NAT s'est imposé pour IPv4 car, de toute façon, vu le manque d'adresses IPv4, il n'y avait pas le choix. Mais en IPv6, on revient à l'abondance. Chaque machine du réseau local a une adresse IP unique au niveau mondial et redevient donc contactable. La sécurité largement illusoire que fournissait le NAT disparait. Que faut-il mettre à la place ? Un pare-feu ? Et, si oui, configuré comment à sa sortie d'usine ? (Rappelez-vous que M. Michu ne changera probablement jamais la configuration. La règle d'ergonomie que rappelle notre RFC est que le réglage de la sécurité dans le CPE doit être facile à faire et encore plus facile à ignorer.)

Notre RFC 6092 ne répond pas à toutes les questions sur la sécurité d'IPv6. Il vise le cas où on veut fournir une sécurité simple dans un environnement simple, celui de l'accès Internet résidentiel. Les cas plus complexes, par exemple celui d'un réseau d'une entreprise, avec des ingénieurs compétents, sont délibérement laissés de côté (section 1 et RFC 4864). Ici, ce RFC propose un compromis jugé raisonnable dans ce contexte, entre la sécurité et le respect du principe de connexion de bout en bout, qui est à la base du succès d'Internet.

Chaque virgule de ce RFC a été négociée avec acharnement. Ainsi, le statut de ce document est « pour information » mais il utilise le vocabulaire normatif du RFC 2119, tout en précisant en section 1.2 que c'est uniquement pour la précision du discours.

La section 2 du RFC décrit le modèle de réseau considéré. Le CPE est un engin simple (on ne peut donc pas lui demander des services complexes), routeur par défaut du réseau local (RFC 8504), et n'ayant typiquement qu'une seule interface avec l'extérieur, celle qui mène au FAI, plus un petit nombre d'interfaces vers l'intérieur (par exemple Ethernet et WiFi). Pour ce qui concerne la sécurité, leur vision du monde est également très simple : un univers rassurant et civilisé du côté du réseau local, un monde hostile et dangereux de l'autre côté. Le RFC 4864 résume les services de sécurité attendus : filtrer les paquets clairement anormaux (comme les paquets venant de l'extérieur mais prétendant avoir une adresse IP source interne, ou comme les paquets martiens du RFC 4949), ne pas permettre de paquets entrants sans qu'une « connexion » ait d'abord été initiée de l'interieur, permettre des exceptions manuellement configurées (sur la base des adresses IP et ports source). En IPv4, un routeur NAT fournissait plusieurs de ces services sans même y penser, comme effet de bord de la traduction d'adresses (qui, en IPv4, impose de garder un état, donc de se souvenir des connexions ouvertes). En IPv6, routage et filtrage sont nettement séparés. Le RFC 4864 proposait donc de répondre au besoin des utilisateurs (qui s'attendent au même niveau de protection en IPv4 et IPv6) en ayant par défaut un pare-feu à état, qui bloque les connexions entrantes.

Il faut noter que certaines applications voudraient bien autoriser les connexions entrantes, au moins depuis certaines adresses. Il n'existe pas actuellement de mécanisme normalisé pour qu'une application puisse dire au CPE « je veux bien recevoir des connexions sur mon port 443, s'il te plait, laisse-les passer ». Plusieurs projets ont été discutés à l'IETF mais sans résultat consensuel pour l'instant.

Autre point à garder en tête, le CPE est un routeur et doit donc se comporter comme tel (RFC 8504, sur les obligations des routeurs). Il doit également (section 2.1) bloquer certains paquets dangereux, comme les usurpateurs ou les martiens cités plus haut, ainsi que ceux ayant l'en-tête de routage 0 (RFC 5095). En revanche, le CPE ne doit pas empêcher le développement de nouveaux services et applications sur l'Internet. Il ne faut donc pas qu'il bloque aveuglément les paquets IPv6 ayant des en-têtes de sécurité ou de routage.

Au niveau 3, le CPE va devoir bloquer par défaut les tunnels, sauf ceux d'IPsec (car il serait paradoxal qu'un pare-feu, censé améliorer la sécurité, bloque par défaut un protocole qui permet de sécuriser le trafic). Pour la même raison, HIP doit être autorisé.

Et au niveau 4 (section 2.3) ? Le principe posé est celui d'une fermeture par défaut : pas de paquets TCP ou UDP entrants s'ils n'ont pas été sollicités de l'intérieur, par une application se connectant à l'extérieur. C'est cette simple règle, qui prend juste une phrase du RFC, qui a suscité le plus de tempêtes de discussions autour de ce document, puisqu'elle revient à renoncer, par écrit, au principe de la connectivité de bout en bout.

La section 3 du RFC transforme ensuite ces principes généraux en recommandations concrètes. Si on est pressé, on peut lire à la place la section 4, qui est un résumé de ces recommandations. Les recommandations sont identifiées par un numéro unique et je vais reprendre ici la syntaxe du RFC, qui les désigne par REC-N où N est le numéro. Dans ses recommandations, cette section s'appuie sur la classification des paquets et des flots (ensemble de paquets liés à la même « connexion ») :

  • Un paquet va vers l'extérieur s'il est issu d'une machine interne, à destination d'une machine externe et vers l'intérieur si c'est le contraire.
  • Pour les flots, c'est plus complexe. Si une machine interne fait une connexion TCP vers le port 80 d'une machine externe, la majorité des octets sera de l'extérieur (le serveur HTTP) vers l'intérieur alors qu'on considérerait plutôt cette connexion comme allant vers l'extérieur. La définition d'un flot allant vers l'extérieur considère donc que c'est le premier paquet qui détermine la direction du flot. Notons que c'est très simpliste et que cette définition ne couvre pas des cas comme SIP/RTP où l'appelant peut demander à recevoir des paquets sur une toute autre « connexion ».

La section 3.1 traite ensuite du cas du filtrage le plus simple, le filtrage sans état, où chaque paquet est examiné uniquement pour son contenu, indépendamment de tout contexte. Il ne s'agit donc que de filtrage de paquets, sans considérer les flots. Ce filtrage sans état devrait éliminer les usurpateurs (REC-5, REC-6, RFC 2827 et RFC 3704). De même, les adresses IPv6 appartenant à des services obsolètes (RFC 3879) ou non admises sur l'Internet public (RFC 6890) devraient être rejetées (REC-3). Les requêtes DNS de l'extérieur devraient être rejetées (REC-8).

Les sections 3.2 et 3.3 traitent ensuite du cas du filtrage avec état, où le CPE filtrant se souvient des paquets précédents et peut donc reconstituer des flots. Le cas facile (section 3.3) est celui où le protocole de couche 4 a une sémantique de connexion. Le pare-feu peut alors savoir exactement quand la connexion est ouverte et quand elle se termine (ce qui permet de libérer les ressources allouées pour le filtrage). Parmi les protocoles dans ce cas, TCP, SCTP mais aussi tous les futurs protocoles de transport à connexion. Un problème typique des pare-feux avec état est en effet qu'ils regardent l'établissement et la fermeture de la connexion et que cela implique qu'ils connaissent le protocole de transport utilisé (beaucoup de pare-feux de bas de gamme ne connaissent pas SCTP et le bloquent donc aveuglément, ce qui rend difficile le déploiement de ce « nouveau » protocole).

Commençons par TCP, le cas le plus simple (section 3.3.1). REC-31 demande que les CPE qui gèrent TCP le gèrent complètement et de manière conforme à la machine à états du RFC 793, y compris dans ses aspects moins connus comme l'ouverture simultanée (les deux pairs envoyant un SYN presque en même temps). C'est quand même un comble qu'il faille un RFC pour dire que les autres RFC doivent être respectés et cela donne une idée des problèmes auquel est confronté l'Internet aujourd'hui. Afin de maximiser les chances qu'une application nouvelle fonctionne correctement, REC-33 demande que le filtrage ait un comportement indépendant de la destination, c'est-à-dire que l'adresse de destination ne soit pas prise en compte pour mettre en correspondance un paquet avec un flot. Le comportement dépendant de l'adresse peut être adopté si on souhaite contrôler davantage. Voir le RFC 5382 pour plus de détails sur la gestion de TCP dans un CPE.

Autre demande de notre RFC qui ne correspond pas à l'état actuel de la plupart des CPE : REC-34 exige que, par défaut, les paquets TCP SYN entrants bloqués suscitent l'envoi d'un message ICMP Destination unreachable. Aujourd'hui, il est probable que la grande majorité des CPE avalent silencieusement le paquet TCP, sans prévenir l'envoyeur.

Et les délais de garde ? A priori, pour les protocoles orientés connexion comme TCP, ils ne sont pas nécessaires, puisque la fin d'une connexion sera toujours explicite, avec les paquets FIN (ou RST). Mais, en pratique, le CPE peut rater la fin d'une connexion (par exemple parce qu'un des pairs TCP a été éteint et n'a donc pas pu terminer proprement la connexion). Pour gérer ce cas, tous les équipements intermédiaires qui gèrent les états des connexions TCP ajoutent un délai de garde et, si aucun paquet n'est passé pendant ce délai, ils suppriment l'état, ce qui empêchera les paquets ultérieurs de passer. C'est souvent un problème pour les applications comme SSH, qui peuvent laisser passer des heures sans envoyer de paquets (avec OpenSSH, la directive ServerAliveInterval permet d'envoyer des paquets pour maintenir la connexion ouverte). Il existe aussi des mécanismes pour envoyer des paquets TCP sans réel contenu, uniquement chargés de maintenir une connexion ouverte (RFC 1122, qui spécifie une durée par défaut de deux heures, bien trop longue pour la plupart des CPE). REC-35 demande donc un délai de garde minimal par défaut de deux heures et quatre minutes (voir le RFC 5382 pour les raisons de ce choix), bien plus long que celui des CPE d'aujourd'hui.

Comme TCP a besoin d'ICMP (notamment pour découvrir la MTU du chemin), REC-36 rappelle que, si un équipement transmet du TCP, il doit aussi transmettre les messages ICMP essentiels, Destination unreachable et Packet too big. A contrario (REC-37), le passage d'un paquet ICMP ne doit pas entraîner le CPE à supprimer les états des connexions TCP (décider, lors de la réception d'un paquet ICMP, si on coupe la connexion TCP associée est un processus complexe, voir le RFC 5927).

TCP est très répandu et relativement bien connu. On peut espérer (même si c'est illusoire) que tous les CPE le gèrent bien. Mais qu'en est-il de SCTP, son concurrent bien moins connu (section 3.3.2) ? D'abord, il faut noter que SCTP a des particularités, notamment le fait qu'une même connexion puisse utiliser plusieurs adresses IP. Cela rend le modèle simple de notre RFC 6092 inapplicable puisqu'il faudrait que les différents routeurs qui voient passer les paquets d'une même connexion se coordonnent (ce qui ne serait pas « simple »). Toutefois, les applications SCTP qui n'exploitent pas toutes les fonctions de ce protocole peuvent quand même s'en tirer. Si tous les paquets passent au même endroit (un seul routeur) et que cet endroit suit le RFC 4960, comme indiqué par REC-38, alors tout peut bien se passer. En pratique, SCTP souffre bien plus du fait que beaucoup de CPE bloquent tous les protocoles inconnus, ce qui signifie en général tous ceux ayant été créés il y a moins de vingt ans (les boxes sont très conservatrices).

La section 3.2, elle, s'occupe du cas moins facile où, contrairement à ce qui se passe avec TCP ou SCTP, il n'y a pas de connexion explicite. Le CPE ne peut pas savoir quand une « session » se termine. La seule solution générale est d'attendre un certain temps après le dernier paquet vu. Autrement, il faut que le CPE connaisse le protocole applicatif utilisé (et sache ainsi, par exemple, qu'une « session » DNS, c'est typiquement seulement deux datagrammes UDP, un de requête et un de réponse). La section 3.2.2 avertit que cette méthode ne doit pas mener à une interdiction de fait des applications nouvelles, donc inconnues du CPE.

Pour ICMPv6, les recommandations concernant son filtrage figurent dans le RFC 4890 (pour le résumer : il ne faut surtout pas filtrer aveuglément la totalité d'ICMP). La règle ajoutée par notre RFC 6092 est de vérifier, avant de faire suivre un paquet ICMP, que les données de la couche transport qu'il contient correspondent à une session en cours (section 3.2.1).

Pour les autres protocoles, afin de maximiser les chances qu'une application nouvelle ou un protocole de couche 4 nouveau fonctionnent correctement, la section 3.2.2 recommande fortement que le filtrage ait un comportement indépendant de la destination (REC-11, endpoint independent filter), c'est-à-dire que l'adresse de destination ne soit pas prise en compte pour mettre en correspondance un paquet avec un flot. Le comportement dépendant de l'adresse peut être adopté si on souhaite une sécurité plus fasciste, peut-être via une option de configuration du pare-feu.

Le cas spécifique d'UDP (rappelons qu'il existe d'autres protocoles de transport que TCP et UDP) est traité en section 3.2.3. Le RFC 4787 donnait déjà des règles pour le comportement attendu d'un routeur NAT avec UDP. Ces règles s'appliquent toujours dans le cas de notre CPE IPv6. Par exemple, REC-14 demande un délai de garde minimum, avant de détruire l'état associé à un flot, de deux minutes (moins si les ports sont dans la zone bien connue, cf. REC-15). Beaucoup d'applications avaient en effet souffert de CPE qui détruisaient l'état trop tôt, empêchant les paquets ultérieurs de passer.

Et IPsec ? Il est en section 3.2.4. Comme son utilisation permet d'améliorer sérieusement la sécurité de l'Internet, il serait paradoxal qu'un équipement assurant des fonctions de sécurité le bloque. REC-21 et REC-22 demandent donc qu'IPsec passe par défaut. Même chose pour HIP avec REC-26. Notons que de telles recommandations laissent de côté le cas de futurs protocoles de sécurité, dont le déploiement risque d'être bloqué par un CPE qui interdit trop de choses par défaut.

Enfin, les applications de gestion font l'objet de la section 3.5. La plupart des CPE ne verront jamais leur configuration par défaut modifiée et, si c'est le cas, celui ou celle qui change la configuration ne sera en général pas un expert. Le RFC ne donne pas plus de détails, à part l'insistance sur le fait que ces fonctions de configuration ne doivent pas être accessibles depuis l'Internet, seulement depuis le réseau local.

On l'a vu, le comportement par défaut d'un CPE qui suit ce RFC est d'interdire les connexions entrantes. Or, certaines applications souhaiteraient pouvoir en recevoir (section 3.4), soit parce qu'elle jouent un rôle de serveur, soit parce que le fonctionnement du protocole sous-jacent implique que l'application se mette en écoute (c'est le cas de SIP). Il n'existe pas de mécanisme normalisé pour l'application de dire au pare-feu « laisse entrer les paquets RTP en provenance de 2001:db8:1010::47:1 », même s'il existe des solutions non-standard comme UPnP. Avec les CPE traditionnels, gérant de l'IPv4 NATé, les applications se servent typiquement de STUN pour « ouvrir (indirectement) une brèche » dans le pare-feu. Et en IPv6 ? Même s'il n'y a pas de NAT, les recommandations de notre RFC 6092 ont le même résultat d'empêcher les connexions entrantes. L'idéal serait un mécanisme standard équivalent à UPnP ou à des propositions comme l'Application Listener Discovery Protocol. Mais il n'existe pas et l'état actuel des discussions à l'IETF ne permet pas de penser qu'il apparaitra bientôt, bien que des propositions existent comme une extension des RFC 5189 ou RFC 4080.

En attendant, les recommendations pour les CPE sont d'offrir un mécanisme pour permettre aux applications de solliciter l'ouverture du pare-feu (REC-48) et de permettre, via une action de l'administrateur, de couper le pare-feu ou de changer sa politique pour laisser entrer les connexions (REC-49). Bien sûr, ce dernier mode impose que les machines sur le réseau local soient proprement sécurisées (le RFC utilise une formulation plus restrictive, en demandant que les machines aient leur propre pare-feu, alors que ce n'est qu'une solution de sécurisation parmi d'autres) mais il est nécessaire que cette option soit présente, car c'est la seule qui permet l'accès à toutes les potentialités de l'Internet. Sans elle, le CPE n'est pas un point d'accès à l'Internet mais un Minitel amélioré.

La section 7, consacrée spécifiquement à la sécurité, prend de la hauteur et rappelle quelques bons principes de sécurité. Elle note ainsi que le RFC ne prétend pas que la politique par défaut proposée (qu'on peut résumer par « zéro connexion entrante par défaut ») soit effective, simplement qu'elle assure le même niveau de sécurité ou d'insécurité que celui fourni par un routeur NAT d'aujourd'hui. Comme le rappelle le RFC 2993, cette politique peut même diminuer la sécurité (par exemple par l'« illusion du limes », ce qui fait qu'on se fie aveuglément à la protection qu'elle offre et qu'on oublie de sécuriser l'intérieur). Les bonnes pratiques de sécurité, et des protections comme celles recommandées dans le RFC 4864 sont donc toujours d'actualité. Après tout, les attaques ne viennent pas que de l'extérieur. Même quand l'attaquant humain n'a pas accès au réseau local, il peut trouver un moyen (via du malware, par exemple) de l'attaquer de l'intérieur.

Cette section sur la sécurité note que la grande majorité des ordinateurs dont le système d'exploitation gère IPv6 ont également un mécanisme de filtrage compatible IPv6. Ce n'est toutefois pas forcément le cas pour les autres machines, comme les imprimantes.

Petite exception au principe comme quoi la sécurité d'un réseau situé derrière un CPE IPv6 conforme à ce RFC est à peu près la même que celle d'un réseau NATé : IPsec n'est pas, par défaut, autorisé par le CPE typique actuel. De toute façon, le dernier paragraphe du RFC, écrit dans le pur style juridique états-unien, note bien que l'IETF n'est responsable de rien et ne garantit pas que les règles énoncées dans ce RFC améliorent la sécurité... C'est une innovation dans un RFC : verra-t-on le RFC sur TCP dire « L'IETF ne promet pas que vous échapperez à la congestion si vous suivez cet algorithme » et celui sur SMTP affirmera-t-il « Attention, utiliser le courrier vous expose au spam » ?


Téléchargez le RFC 6092


L'article seul

RFC 6091: Using OpenPGP Keys for Transport Layer Security (TLS) Authentication

Date de publication du RFC : Février 2011
Auteur(s) du RFC : N. Mavrogiannopoulos (KUL), D. Gillmor
Pour information
Première rédaction de cet article le 3 février 2011


Le protocole TLS, permettant de chiffrer et d'authentifier des communications sur Internet n'utilisait qu'un seul type de certificats, ceux à la norme X.509 (cf. RFC 5280). Désormais, on peut aussi se servir de certificats PGP. Ce RFC 6091 met à jour la première spécification de « PGP dans TLS », qui était dans le RFC 5081 et la fait passer du statut « expérimental » à « pour information ». (Depuis, le RFC 8446 a supprimé cette possibilité d'utiliser les clés PGP.)

Pour authentifier l'autre partie, lors d'une communication TLS (utilisée par exemple avec HTTP ou bien avec SMTP), on doit signer ses messages avec sa clé privée. Le correspondant doit connaitre la clé publique pour vérifier cette signature. Avec l'ancien protocole SSL et avec son successeur TLS (normalisé dans le RFC 5246), cela se faisait en présentant un certificat X.509. X.509 a plusieurs limites, notamment le fait qu'il dépende d'une autorité de certification. Tout le monde n'a pas envie de payer une telle autorité, pour un gain de sécurité contestable. Il était donc important d'avoir une alternative.

Celle-ci est déjà mise en œuvre dans GnuTLS (pour l'instant, le seul logiciel à le faire).

Techniquement, notre RFC dépend du mécanisme d'extension TLS spécifié dans le RFC 5246. Ces extensions permettent d'annoncer le type de certificat utilisé (extension cert_type, numéro 9 dans le registre des extensions), et donc de choisir X.509 ou bien PGP (PGP est normalisé dans le RFC 4880). Le RFC précise que ces extensions ne doivent pas être utilisées si on ne gère que des certificats X.509, pour interopérer plus facilement avec les vieilles implémentations. Sinon, si le client propose du PGP et que le serveur ne connait pas, ce dernier répond unsupported_certificate. Un registre des types de certificats possibles permettra d'ajouter plus tard autre chose que X.509 ou PGP. L'algorithme de chiffrement de la session, lui, est indépendant du fait qu'on utilise X.509 ou PGP.

Notre RFC utilise le terme de clé pour parler des clés PGP actuelles et de certificat lorsque les mêmes clés sont utilisées pour l'authentification (cf. section 2). La clé PGP est envoyée encodée en binaire, ou bien peut être récupérée sur le réseau, si celui qui veut s'authentifier indique uniquement l'empreinte de la clé (de la même façon qu'un certificat X.509 peut être récupéré sur le réseau, si celui qui veut s'authentifier indique l'URL de son certificat, cf. RFC 6066, section 5). Attention, contrairement à l'option équivalente pour X.509, la possibilité de récupérer le certificat sur le réseau ne permet pas d'indiquer le nom ou l'URL d'un serveur de certificats. Celui-ci doit être connu du serveur (qui vérifiera ensuite que les empreintes cryptographiques correspondent.)

Les changements par rapport au RFC 5081 sont résumés dans l'annexe A. Le principal, de loin, est un changement dans la sémantique du message indiquant le certificat (Client Certificate et Server Certificate) qui fait que les mises en œuvre de l'ancien RFC et celles de notre nouveau RFC 6091 ne peuvent pas interopérer. Comme l'ancien RFC n'avait que le statut « expérimental » et qu'il n'a jamais été largement déployé, ce n'est pas un trop gros problème en pratique.


Téléchargez le RFC 6091


L'article seul

RFC 6090: Fundamental Elliptic Curve Cryptography Algorithms

Date de publication du RFC : Février 2011
Auteur(s) du RFC : D. McGrew (Cisco Systems), K. Igoe, M. Salter (National Security Agency)
Pour information
Première rédaction de cet article le 4 février 2011


Dans l'arsenal des algorithmes de cryptographie utilisés sur l'Internet, on trouve de plus en plus d'algorithmes basées sur les courbes elliptiques (par exemple les RFC 4754, RFC 5289, RFC 5656 et RFC 5753, sans compter les normes d'autres SDO). Mais il n'existait apparemment pas de texte de synthèse sur cette famille d'algorithmes, utilisable comme référence pour des RFC. Ce manque est désormais comblé avec ce RFC 6090 qui résume ce que tout participant à l'IETF devrait connaître des courbes elliptiques et de leur utilisation en cryptographie. Ainsi, RSA et la factorisation en nombres premiers ne restera pas la seule méthode de cryptographie asymétrique sur laquelle faire reposer la sécurité des communications à travers l'Internet.

Ce RFC nécessite donc un peu plus de connaissances en mathématiques que la moyenne. Le débutant pourra commencer par l'excellent article d'Adam Langley, sur son blog Imperial Violet, « Elliptic curves and their implementation ». Il apprendra que les courbes elliptiques n'ont rien à voir avec les ellipses (en mathématiques, lorsqu'on classe des objets en deux types on appelle souvent l'un le type pair, le type impair ; lorsqu'on tombe sur trois types, on qualifie souvent les trois types de parabolique, elliptique et hyperbolique, en référence aux coniques), il verra de jolies images : elliptic-curve (toutes les images de cet article ont été volées à l'article sur Imperial Violet). Il devra aussi réviser quelques notions de maths (cf. section 2 du RFC) comme celle de groupe (section 2.2 du RFC). En effet, les points de la courbe elliptique, plus une opération d'addition sur la courbe (qu'on peut aussi représenter visuellement, voir l'image plus loin), qui a un élément neutre (un zéro), forment un groupe. elliptic-curve-addition (À noter que le RFC, lui, sans donner de nom à cette opération, la note * qui est d'habitude réservé, en informatique, à la multiplication, voir annexe E pour une discussion de ces deux notations possibles.)

Une fois qu'on a l'addition, on définit la multiplication par un nombre entier positif (qui consiste juste à répéter l'addition). Pour tout point de la courbe, on peut donc relativement facilement le multiplier par un nombre quelconque (ce nombre sera la clé privée). Mais l'inverse est extrêmement dur : étant donné un point résultat, et le point de départ, comment trouver le nombre qui a servi à la multiplication ? Dans le groupe formé par les nombres entiers et l'addition usuelle, c'est trivial (c'est une simple division euclidienne). Sur la courbe elliptique, c'est au contraire une tâche herculéenne. Et c'est là son intérêt pour la cryptographie. De méme que RSA reposait sur le fait qu'une composition des facteurs premiers est triviale mais que la décomposition est très difficile, la cryptographie par courbes elliptiques repose sur le fait que la multiplication sur la courbe est simple, la division très difficile. On a donc la base de la cryptographie asymétrique, une opération mathématique très difficile à inverser.

J'ai dit que la multiplication sur la courbe elliptique était simple mais tout est relatif. L'essentiel de l'article d'Imperial Violet est consacré à la mise en œuvre logicielle et beaucoup d'optimisations sont nécessaires, pour pouvoir multiplier un point en un temps raisonnable, sachant que le facteur de multiplication est un très grand nombre. L'article devient nettement plus chevelu ici, à réserver aux fanas de l'algorithmique.

Après ce petit détour par les maths, revenons au RFC. Il utilise le sigle ECC pour parler de l'ensemble des techniques de Elliptic Curve Cryptography. Ce sont donc des techniques de clé publique, qui peuvent servir à mettre en œuvre des techniques comme Diffie-Hellman ou ElGamal. Bien qu'assez ancienne, ECC est toujours relativement peu déployé, alors qu'elle fournit en général une meilleure sécurité et des performances plus importantes. Notre RFC note que c'est sans doute en partie par manque de documents normatifs facilement disponibles (un problème que notre RFC vise justement à traiter) mais aussi en raison de problèmes d'appropriation intellectuelle (la plupart des techniques ECC sont pourries de brevets jusqu'au trognon, cf. section 9).

Le RFC fournit d'abord un arrière-plan mathématique nécessaire, en section 2. Comme il n'est pas facile de lire des formules mathématiques dans le texte ASCII auquel sont contraints les RFC, la lecture n'en est pas évidente et je suggère de partir plutôt de l'article d'Imperial Violet.

Le RFC donne ensuite la définition d'une courbe elliptique en section 3 et introduit la notion de transformation d'un système de coordonnées dans un autre, afin de faciliter les calculs (cf. annexe F pour du pseudo-code). Surtout, la section 3.3 liste les paramètres dont dépend une courbe elliptique particulière. Des propriétés de ces paramètres dépend la sécurité de la courbe et ils ne doivent donc pas être choisis au hasard (la section 3.3.2 donne les critères qu'ils doivent satisfaire). Un exemple d'une courbe et de ses paramètres, la courbe P-256, normalisée par le NIST (dans FIPS 186-2) et utilisée dans le RFC 4753, est donné en annexe D. Une autre courbe elliptique connue est Curve25519, utilisée dans DNScurve.

Une fois ECC définie, on peut l'utiliser dans des algorithmes de crypto classique. La section 4 décrit ECDH, courbe elliptique + Diffie-Hellman, pour permettre à ces chers Alice et Bob de se mettre d'accord sur un secret (qui servira au chiffrement ultérieur) bien qu'ils communiquent via un canal non sûr. Le principe est simple mais génial. Alice et Bob partent du même point G de la courbe, Alice choisit au hasard un nombre j et met G à la puissance j (je rappelle que le RFC utilise la notation multiplicative, pas l'additive comme dans l'article sur Imperial Violet, et note donc cette opération G^j). Bob en fait autant avec son nombre k pris au hasard. Chacun envoie le résultat de son calcul à l'autre, qui doit alors calculer G^(j*k). Par exemple, Alice reçoit donc G^k et calcule donc G^k^j (qui est équivalent à G^(k*j)). Alice et Bob connaissent donc le secret, G^(j*k), alors que l'écoutant éventuel n'a pu le déterminer, car il ignore j et k.

De même, on peut faire une version « courbe elliptique » de ElGamal (section 5). Cet algorithme de chiffrement était basé sur un autre groupe mathématique, celui des entiers modulo N mais on peut se servir d'un autre groupe, comme celui fourni par une courbe elliptique. C'est ainsi qu'est créé ECDSA, version à courbe elliptique de DSA (cet algorithme est disponible pour DNSSEC, cf. RFC 6605 ; il est déjà mis en œuvre dans PowerDNS ; DNSSEC a déjà un algorithme à courbe elliptique, GOST, cf. RFC 7091).

L'IETF se préoccupant de faire des protocoles qui marchent dans le monde réel, il faut se poser la question de l'interopérabilité. La section 7 décrit donc des détails pratiques nécessaires. Toujours sur le côté concret, la section 8 est consacrée aux détails d'implémentation et aux tests validant celle-ci. Par exemple, un test courant est de vérifier qu'un sous-programme produit, pour des paramètres d'entrée donnés, le résultat attendu. Comme le mécanisme de signature de KT-I (cf. section 5.4) est non déterministe, ce genre de tests ne va pas marcher, la signature étant différente à chaque fois. Par contre, la validation de la signature est, elle, déterministe (heureusement...) et peut donc être testée. De même, ECDH peut être testé avec les résultats des RFC 4753 et RFC 5114.

Reprenons de la hauteur : si les sections précédentes passionneront les mathématiciens et les programmeurs, la section 9 est consacrée aux problèmes que posent les brevets pour le déploiement des courbes elliptiques. Si les bases des courbes elliptiques semblent libres (en théorie, on ne peut pas breveter un théorème mathématique : mais, en pratique, les organismes comme l'Office Européen des Brevets violent régulièrement leurs propres règles, et semblent agir en dehors de tout contrôle démocratique), les optimisations nécessaires sont souvent plombées par un brevet. L'implémenteur d'une courbe elliptique doit donc, après avoir pris connaissance des règles de l'IETF sur le sujet (RFC 8179), consulter la base des appropriations intellectuelles publiées.

L'unique but de la cryptographie à courbes elliptiques étant la sécurité, la section Sécurité (la 10), revient donc en détail sur les précautions à prendre pour que les courbes elliptiques remplissent leur rôle. Il existe plusieurs attaques documentées (comme celle de Pohlig-Hellman), l'algorithme de Shanks ou celui de Pollard qui sont des algorithmes génériques, marchant avec n'importe quel groupe, comme des attaques spécifiques d'une courbe elliptique particulière. Le RFC insiste notamment sur l'importance de ne prendre que des courbes dont les paramètres ont été soigneusement choisis (voir aussi le RFC 4086, et l'annexe B, puisque plusieurs opérations dépendent de nombres aléatoires).

D'autre part, la cryptographie ne fait pas de miracles : si Diffie-Hellman protège contre un attaquant passif, il ne peut rien contre un intermédiaire actif.

Merci à Michael Le Barbier Grünewald pour sa relecture mathématique.


Téléchargez le RFC 6090


L'article seul

RFC 6082: Deprecating Unicode Language Tag Characters: RFC 2482 is Historic

Date de publication du RFC : Novembre 2010
Auteur(s) du RFC : K. Whistler (Sybase), G. Adams (Skynav), M. Duerst (Aoyama Gakuin University), R. Presuhn, J. Klensin
Pour information
Première rédaction de cet article le 8 novembre 2010


Parfois, il y a des mauvaises idées. Parfois, elles sont même inscrites dans un RFC et sont alors utilisées. Lorsqu'une idée est reconnue comme mauvaise, il faut alors savoir l'abandonner. C'est ce que fait ce RFC 6082 qui abandonne officiellement l'idée du RFC 2482 qui fournissait un mécanisme d'indication de la langue utilisée, dans un texte brut en Unicode.

Le RFC 2482 réservait plusieurs caractères Unicode entre U+E0000 et U+E007F à des fins d'étiquetage, pour indiquer la langue utilisée pour écrire un texte. Par exemple, U+E0001 U+E006A U+E0061 (caractère language tag, puis caractère tag letter j puis enfin tag letter a) indiquait un texte en japonais (ja étant le japonais pour les étiquettes de langue). Il n'a pas été tellement utilisé en pratique et, aujourd'hui, a été remplacé par des mécanismes d'étiquetage globaux (comme l'en-tête Content-Language: du RFC 3282) pour le texte brut ou bien par des mécanismes plus fins pour les documents structurés (par exemple l'attribut xml:lang pour les textes en XML). Le consortium Unicode a officiellement abandonné ce mécanisme (section 16.9 de la norme Unicode 5.2) et notre RFC 6082 a été fait pour éviter que des implémenteurs tombent sur le RFC 2482 et ne le mettent en œuvre en le croyant toujours d'actualité.

Fin du parcours, donc, pour le RFC 2482, qui entre ainsi dans la catégorie « Intérêt historique uniquement » (catégorie décrite dans la section 4.2.4 du RFC 2026).


Téléchargez le RFC 6082


L'article seul

RFC 6079: HIP BONE: Host Identity Protocol (HIP) Based Overlay Networking Environment

Date de publication du RFC : Janvier 2011
Auteur(s) du RFC : G. Camarillo, P. Nikander, J. Hautakorpi, A. Keranen (Ericsson), A. Johnston (Avaya)
Expérimental
Réalisé dans le cadre du groupe de travail IETF hip
Première rédaction de cet article le 25 janvier 2011


Voici un RFC bien abstrait, qui normalise un mécanisme pour construire des réseaux virtuels (overlays) en utilisant le protocole HIP. Un de ces premiers réseaux virtuels pourrait être celui du protocole RELOAD, utilisé pour faire du SIP pair-à-pair.

Le nom de ces réseaux virtuels, HIP bone, est un jeu de mots sur l'os coxal (hip bone en anglais) et une allusion à d'autres réseaux virtuels comme le défunt 6bone. Mais le but est très différent : IPv6 ne peut pas passer sur l'infrastructure IPv4 du vieil Internet et doit donc être « tunnelé » au dessus d'IPv4, l'ensemble de ces tunnels formant le 6bone. Au contraire, HIP (RFC 7401) étant un protocole entièrement situé dans les machines terminales, il n'a pas besoin de tunnels pour marcher. On peut expérimenter avec HIP dès aujourd'hui. Alors, à quoi sert un HIP bone ? L'idée est de faciliter le développement de services pair-à-pair, d'utiliser HIP pour construire un réseau virtuel de machines HIP, les autres fonctions utiles (comme le stockage des données) étant fournies par des protocoles pair-à-pair situés au dessus (nommés peer protocol dans le RFC). Ces protocoles seront donc déchargés, grâce à HIP, de certaines des tâches de bas niveau.

HIP est un protocole de séparation du localisateur et de l'identificateur. Le routage dans le HIP bone se fait sur l'identificateur et c'est HIP qui se charge de le mettre en correspondance avec les localisateurs sous-jacents, le routage dans l'Internet se faisant sur la base de l'adresse IP (qui, en HIP, est réduite au rôle de localisateur). Si vous ne connaissez pas HIP, la section 3 du RFC sert de rappel.

Le HIP bone lui-même est introduit en section 4. Un réseau virtuel bâti au dessus d'un réseau réel comme l'Internet dépend d'un mécanisme de maintien du réseau (table de routage, tests de connectivité, pairs qui arrivent et qui repartent, etc), d'un mécanisme de stockage et de récupération de données (par exemple une DHT), et d'un mécanisme de gestion des connexions (se connecter à un pair, échanger des messages). Dans le HIP bone, HIP ne fournit que ce dernier service. L'application qui utilisera le HIP bone pourra parler directement à HIP pour certaines fonctions et au peer protocol pour les autres (cf. la figure 3 du RFC).

On l'a dit, notre RFC ne fait que spécifier un cadre assez général. Une bonne partie devra être faite dans le peer protocol et la section 5 du RFC rappelle ce qui relèvera de la responsabilité dudit protocole. Par exemple, il existe actuellement un Internet-Draft décrivant RELOAD (REsource LOcation And Disovery), draft-ietf-p2psip-base, et un autre qui décrit comment bâtir un réseau virtuel pour RELOAD au dessus de HIP, draft-ietf-hip-reload-instance.

Ainsi (section 5.1), c'est au peer protocol de gérer le délicat problème du recrutement (qui peut entrer dans le réseau virtuel). Pour aider ces protocoles situés au dessus d'un HIP bone, la section 6 liste quelques paramètres utiles qui seront mis dans les messages HIP comme le nouvel OVERLAY_ID, qui identifiera un réseau virtuel donné (car une machine HIP sera peut-être membre de plusieurs réseaux virtuels).

Voilà, une fois ce RFC 6079 lu et assimilé, il ne vous reste plus qu'à concevoir votre réseau virtuel à vous ⌣.


Téléchargez le RFC 6079


L'article seul

RFC 6077: Open Research Issues in Internet Congestion Control

Date de publication du RFC : Février 2011
Auteur(s) du RFC : Dimitri Papadimitriou (Alcatel-Lucent), Michael Welzl (University of Oslo), Michael Scharf (University of Stuttgart), Bob Briscoe (BT & UCL)
Pour information
Réalisé dans le cadre du groupe de recherche IRTF iccrg
Première rédaction de cet article le 3 février 2011


La congestion est la plaie des réseaux informatiques depuis leurs débuts. Quelle que soit la capacité de ceux-ci, les utilisations emplissent les tuyaux jusqu'à ce que ceux-ci débordent. Il y a donc depuis quarante ans, mais surtout depuis le travail de Van Jacobson en 1988 (voir son ancien mais toujours bon « Congestion Avoidance and Control », Proceeding of ACM SIGCOMM'88 Symposium, août 1988 ; attention, c'est assez matheux, réservé aux gens qui comprennent les fonctions de Liapounov), d'innombrables études et recherches sur la congestion. (Voir par exemple l'article du Wikipédia anglophone sur TCP.) Pourtant, le problème est loin d'être épuisé, comme le montre ce RFC du groupe ICCRG de l'IRTF consacré aux problèmes non résolus en matière de congestion. Couvrant tous les aspects de ce problème, il est également une passionnante lecture sur l'état actuel de l'Internet et le bouillonnement d'activité qu'il suscite toujours chez les chercheurs.

Qu'est-ce exactement que la congestion ? La section 1 la définit comme l'état d'un réseau dont les ressources sont tellement utilisées que des phénomènes visibles par les utilisateurs et objectivement mesurables (comme le retard d'acheminement des paquets, voire leur perte) apparaissent. Sur un réseau où les ressources sont partagées mais pas réservées (cas de l'Internet), la congestion se traduit par une diminution de la qualité de service. (Voir Keshav, S., « What is congestion and what is congestion control », Presentation at IRTF ICCRG Workshop, PFLDNet 2007, Los Angeles, février 2007.)

Le contrôle de congestion, lui, est l'ensemble des algorithmes qui permettent de partager les ressources en minimisant la congestion. Il existe sous deux formes, primal et dual (je n'ai pas cherché à traduire ces termes rares, apparemment issus de la recherche opérationnelle). La première fait référence à la capacité des émetteurs à adapter leur rythme d'envoi s'ils reçoivent des indications comme quoi la congestion a lieu. Sur l'Internet, c'est typiquement le rôle de TCP. La seconde forme fait référence au travail des équipements intermédiaires, les routeurs, qui détectent la congestion et réagissent, par exemple via la RED.

Aujourd'hui, des dizaines de RFC ont « congestion » dans leur titre ; le RFC 5783 fournit un survol de cette littérature et le RFC 5681 synthétise tout ce qu'il faut savoir sur la congestion dans TCP. Dans les mises en œuvre de TCP/IP aujourd'hui, d'innombrables lignes de code sont là pour réagir à la congestion. Malheureusement, un bon nombre des algorithmes et méthodes « historiques » pour gérer la congestion sur l'Internet rencontrent leurs limites avec les évolution des réseaux. Résultat, plusieurs systèmes d'exploitation sont livrés avec des algorithmes non-standard (comme, dans certains cas, Linux, avec l'algorithme Cubic ; l'algorithme en cours peut être affiché avec sysctl net/ipv4/tcp_congestion_control et les disponibles avec sysctl net/ipv4/tcp_available_congestion_control). (On peut voir aussi les projets de FreeBSD qui incluent également Cubic et d'autres.) À noter que tous les nouveaux algorithmes ne sont pas forcément un progrès. Francis Dupont fait ainsi remarquer, suite à cet article, que des algorithmes comme « TCP Vegas », excellent lors des tests, ne réussissaient pas aussi bien sur le vrai réseau.

Autre évolution, l'utilisation de solutions qui ne sont pas uniquement de bout en bout mais font participer les routeurs, comme ECN (RFC 3168).

Quels sont les défis d'aujourd'hui ? La section 2 examine les défis généraux. L'un des premiers est l'hétérogénéité de l'Internet (section 2.1). Des liens radio laissant passer quelques misérables kb/s aux fibres optiques Gb/s, l'éventail des capacités est immense. Même chose pour la latence, entre les réseaux locaux où elle est inférieure à la milli-seconde et les liaisons satellites où elle approche la seconde. Rien n'indique que de tels écarts se résorberont. On imagine le travail de TCP, qui doit fonctionner dans un environnement aussi varié. À l'époque de Van Jacobson, latence et capacité des réseaux faisait qu'une connexion TCP n'avait en transit, à un moment donné, que quelques douzaines de paquets. Aujourd'hui, cela pourrait être beaucoup plus. Il n'y a pas actuellement de consensus à l'IETF pour choisir les nouveaux algorithmes, d'autant plus que leurs interactions (entre un pair TCP qui utiliserait un ancien algorithme et un pair qui utiliserait un nouveau) sont mal connues. Si le RFC 5033 définit des critères sur le choix d'un algorithme, ceux-ci ne répondent pas à toutes les questions, comme celle de savoir si on accepte de réduire les performances des anciennes implémentations (ce que font certaines nouvelles méthodes).

Second grand problème, la stabilité (section 2.2). On souhaiterait que, à situation inchangée, les algorithmes de contrôle de la congestion convergent vers un état stable, au lieu de faire du ping-pong entre deux états (on ouvre les vannes, la congestion reprend, on diminue le débit, le trafic passe très en dessous du seuil, alors on rouvre les vannes, etc). Il existe des théories mathématiques à ce sujet pour des algorithmes en boucle fermée, comme TCP, mais qui ne servent pas dans le cas où il y a interaction entre plusieurs boucles de contrôle, ce qui est le cas de l'Internet, où le ralentissement du débit d'une connexion TCP peut pousser les autres à augmenter leur débit. On souhaite également une stabilité locale : si un système est perturbé, après la fin de la perturbation, il revient rapidement à l'équilibre.

Les modélisations issues de la théorie de l'automatique permettent d'éliminer les algorithmes les plus mauvais (s'ils ne marchent pas dans les cas simples, ce n'est pas la peine de se demander s'ils fonctionneront sur l'Internet). Mais elles sont insuffisantes pour les cas réels, l'approche la plus courante aujourd'hui est donc la simulation, ce qui ne garantit pas que ça fonctionnera en vrai. Est-ce que TCP est stable dans des conditions réelles ? Il n'y a aujourd'hui aucune certitude scientifique à ce sujet.

Ce ne sont pas les heuristiques qui manquent, lorsqu'on conçoit un nouvel algorithme de gestion de la congestion, comme par exemple le principe de la conservation des paquets (faire en sorte que l'émetteur envoie autant de paquets par seconde que le récepteur en consomme). Mais elles peuvent être trop exigeantes (c'est le cas de la conservation de paquets, dont il a été démontré qu'elle était un principe suffisant, mais pas nécessaire) ou tout simplement non démontrées.

Un exemple d'un problème réel est que TCP démarre lentement : son débit s'accroit avec le temps au fur et à mesure que l'envoyeur se rassure qu'il n'y a pas congestion. Mais beaucoup de flots de données, à commencer par les courtes connexions HTTP qui récupèrent une seule page HTML, sont de durée tellement faible que TCP n'atteint jamais son état d'équilibre et de débit maximum. Cela peut pousser certains à « améliorer » l'algorithme dans leur intérêt (c'est le cas de Google, voir leur article). Égoïsme ou bien usage normal de la liberté ? En tout cas, cela a poussé à des recherches sur un TCP résistant aux égoïstes comme dans l'article « TCP congestion control with a misbehaving receiver ».

Beaucoup plus chaude est la question de la justice, surtout dans le contexte du débat sur la neutralité de l'Internet. C'est en effet une chose d'assurer le bien de l'Internet, c'en est une autre que de vérifier que cela ne se fait pas aux dépens de certains utilisateurs, sacrifiés au bien commun. Intuitivement, la justice, dans un réseau, c'est que, en cas de sacrifices, tout le monde doit prendre sa part de manière équitable (section 2.3). On touche là clairement à des questions politiques, suscitant des articles vengeurs comme le très intéressant article de Briscoe, « Flow Rate Fairness: Dismantling a Religion » (ACM SIGCOMM Computer Communication Review, Vol.37, No.2, pp.63-74, avril 2007). Briscoe argumente essentiellement sur le fait que la justice entre les flots TCP n'a aucun intérêt, il faudrait chercher la justice entre les personnes, ou bien entre les organisations. Mais, de toute façon, la question de la justice est connue pour être impossible à définir de façon cohérente dans le parallélisme (je cite Francis Dupont) : elle est sujette à un problème de la famille du paradoxe de Condorcet sur le vote équitable, c'est-à-dire que les critères qui établissent l'équitabilité ne sont pas compatibles.

Des RFC ont également traité ce cas comme le RFC 3714. Dans l'approche traditionnelle, pour le cas ultra-simple de deux utilisateurs regardant tous les deux YouTube, la justice était considérée comme l'égalité de leurs débits. Certains idéologues du marché ont par exemple proposé de définir la justice comme « ce que les utilisateurs sont prêts à payer pour éviter la congestion ». Dans cette approche, les deux débits pourraient être très différents. Mais intégrer l'aspect financier ouvre bien d'autres boîtes remplies de questions difficiles comme le mécanisme par lequel on va comptabiliser la contribution à la congestion.

Même si on ne prend pas en compte l'argent dans l'équation, la définition de ce qui est « juste » n'est pas triviale. Pas exemple, l'égalité doit-elle être celle des bits/s ou bien celle des paquets/s ? Faut-il la mesurer sur le long terme de façon à ce qu'une application sur une machine puisse profiter à fond du réseau parce que cette machine a été raisonnable dans les heures précédentes ? Le RFC note justement que ce n'est pas forcément une question de recherche, c'est un débat, et aucun article scientifique ne va le trancher. Le RFC note également que des mécanismes trop complexes, au nom de la justice, pourraient sérieusement handicaper l'Internet (car ralentissant trop les équipements, cf. RFC 5290).

Place maintenant à l'étude détaillée des défis qui attendent l'IETF dans ce domaine. Ils font l'objet de la section 3. Le premier est celui de la répartition du travail entre le réseau (les équipements intermédiaires comme les routeurs) et machines situées aux extrémités (section 3.1). Traditionnellement, l'Internet fonctionne en limitant sérieusement les fonctions des routeurs et en concentrant le travail difficile aux extrémités, où les machines ont davantage de ressources (section 3.1.1), peuvent maintenir un état complexe, et surtout sont sous le contrôle des utilisateurs (mettre trop de fonctions dans les routeurs peut sérieusement menacer la neutralité du réseau).

En outre, si de nouveaux mécanismes de gestion de la congestion apparaissent, et qu'ils sont situés dans les couches basses (comme la couche 3), ils mettront du temps à être déployés, d'autant plus que les concepteurs de routeurs attendront sans doute que ces mécanismes soient stables avant de les câbler en dur dans leurs circuits. Mais, d'abord, que peut faire un routeur pour aider à gérer la congestion ? Il peut le faire par une meilleure gestion de ses files d'attente, ou bien il peut le faire en signalant aux extrémités les problèmes de congestion qu'il voit. La première approche est déjà utilisée mais pas de manière uniforme dans tout l'Internet. Une de ses limites est qu'on ne sait pas trop quels sont les paramètres idéaux, par exemple pour les méthodes RED ou AVQ (Adaptive Virtual Queue) et qu'on ne dispose pas de moyen de les déterminer automatiquement.

La seconde façon dont les routeurs peuvent aider, la signalisation explicite, est utilisée dans ECN (RFC 3168), Quick-Start (RFC 4782), XCP (eXplicit Control Protocol, draft-falk-xcp-spec) et dans d'autres protocoles. Contrairement à TCP, XCP sépare le contrôle de la justice (s'assurer qu'aucun flot de données ne prend toute la capacité) et le contrôle de la congestion. Mais XCP reste très expérimental et produit parfois de drôles de résultats (« An Example of Instability in XCP »). Dans tous les cas, ces mécanismes, qui donnent un plus grand rôle aux équipements intermédiaires, doivent être évalués dans le contexte du fonctionnement de bout en bout, qui est l'un des principaux piliers de l'Internet (RFC 1958), qui a assuré son succès et sa survie. La congestion est un problème intéressant précisément parce qu'elle ne peut pas se régler uniquement de bout en bout (puisque c'est un phénomène spécifique au réseau) mais il faut bien réfléchir avant de mettre dans le réseau des fonctions qui pourraient interférer avec les politiques d'utilisation des machines terminales.

Ainsi, un protocole comme XCP ne nécessite pas d'état dans le réseau (et semble donc respecter le principe de bout en bout) mais c'est uniquement à condition que les machines situées aux extrémités jouent le jeu, c'est-à-dire ne mentent pas sur les débits mesurés. Si on veut faire marcher XCP dans un environnement... non-coopératif (avec des tricheurs), les routeurs doivent alors garder trace des différents flots de données, ce qui met en péril le principe de bout en bout.

Tous ces problèmes (de comptabiliser l'usage que les différents flots de données font du réseau, et en résistant à la triche) existent depuis qu'on parle de QoS sur l'Internet, c'est-à-dire au moins depuis IntServ (RFC 2208). Le problème reste ouvert.

Une des raisons pour lesquels ils ne sont pas résolus est qu'il n'existe aucune technique (section 3.1.2) qui ne repose pas sur un état maintenu dans le routeur, par flot (donc, posant de grands problèmes de passage à l'échelle).

Autre problème pour l'usage des équipements réseaux à des fins de lutter contre la congestion, l'accès à l'information (section 3.1.3). Pour être efficace, le routeur qui veut gérer la congestion doit connaître des choses comme la capacité des liens. Attendez, me direz-vous, un routeur sait forcément que son interface ge-3/0/2 est à 1 Gb/s ! Mais c'est plus complexe que cela : par exemple en cas d'interface vers un réseau partagé (Wifi) ou en cas de tunnels (RFC 2784 ou RFC 4301 ou bien d'autres techniques). Dans ces circonstances, un routeur IP ne connaît pas forcément la capacité des liens auxquels il est connecté.

Idéalement, si le routeur connaît la capacité du lien et le débit effectif, il sait si on approche de la congestion ou pas, via une simple division. Nous avons vu que la capacité n'était pas toujours connue mais le débit ne l'est pas non plus forcément. S'il est très haché, avec de brusques pics, déterminer un débit, pour le diviser par la capacité, n'est pas trivial. Bref, le routeur manque souvent d'informations pour décider. Faut-il créer de nouveaux mécanismes pour l'informer ? Ne risquent-ils pas de tourner très vite à l'usine à gaz ? (Un routeur IP a déjà beaucoup de choses à faire.)

Deuxième défi auquel est confronté TCP/IP : différencier la perte d'un paquet due à la congestion de l'abandon de ce paquet en raison de sa corruption (section 3.2). Actuellement, un routeur abandonne un paquet lorsque la congestion empêche sa transmission sur l'interface suivante. L'émetteur va typiquement interpréter toute perte de paquets comme un signe de congestion et diminuer le débit (TCP le fait automatiquement). Mais la perte du paquet peut être due à une autre cause, par exemple une modification accidentelle d'un ou plusieurs bits, qui rendra invalide la somme de contrôle, amenant la carte réseau à ignorer le paquet anormal. De telles modifications sont rares sur un lien filaire (il faut un gros rayon cosmique) mais relativement fréquentes sur les liaisons radio. TCP diminuerait alors son débit à tort. Le problème est bien connu (voir Krishnan, Sterbenz, Eddy, Partridge & Allman, « Explicit Transport Error Notification (ETEN) for Error-Prone Wireless and Satellite Networks », Computer Networks, 2004, ou bien le RFC 6069). La solution n'est pas évidente, d'autant plus que les deux phénomènes peuvent être liés (une congestion qui se traduit par des corruptions) et qu'il n'est pas évident qu'il faille continuer à envoyer au même débit si on perd la moitié des paquets suite à la corruption (voir un exemple de discussion).

Il y a donc deux problèmes ouverts, détecter la congestion et y réagir. Pour la détection, on pourrait penser compter sur la somme de contrôle dans l'en-tête IP (à condition que la couche 2 n'ait pas déjà jeté le paquet corrompu, ce que fait Ethernet). UDP-lite (RFC 3828) et DCCP (RFC 4340) le font (sans indiquer quelle doit être la réaction à ces corruptions). Une étude a montré que cela marchait bien au-dessus de GPRS et mal au dessus du WiFi. De toute façon, toute détection de corruption dans la couche 3 poserait des problèmes de coopération entre couches, difficiles à assurer pour IP, qui est conçu pour fonctionner sur toutes les couches 2 possibles.

Quant à la réaction à la corruption, il n'existe aucun protocole standard pour cela, bien que plusieurs propositions aient été faites dans la littérature scientifique (le TCP dit « Westwood »).

Un autre « point noir » de la gestion de la congestion est la prise en compte de la taille du paquet (section 3.3). Aujourd'hui, TCP l'ignore complètement, en partie parce que les très grands paquets (> 1500 octets, la MTU d'Ethernet) sont extrêmement rares sur l'Internet. La question de savoir si TCP a tort ou raison d'ignorer ce facteur est toujours un sujet de recherche. DCCP, par contre, peut tenir compte de la taille des paquets (cf. RFC 5622). Les routeurs typiques, en cas de congestion, ne tiennent pas compte de la taille d'un paquet avant de le jeter, alors que certaines études semblent indiquer que cela pourrait être une bonne idée. Beaucoup de questions restent ouvertes sur ce sujet : le facteur limitatif sur le réseau, dans les prochaines années, sera-t-il le nombre de bits ou le nombre de paquets (sur les réseaux lents, c'est clairement le nombre de bits qui peut déclencher la congestion ; mais au fur et à mesure que les réseaux deviennent plus rapides, c'est la capacité des équipements à traiter un grand nombre de paquets qui devient problématique). En cas de congestion, faut-il diminuer le nombre de bits (en réduisant le débit d'émission, ce que fait TCP) ou le nombre de paquets (en tentant des paquets plus gros) ? Actuellement, l'émetteur ne sait pas pourquoi il y a congestion, ce qui rend difficile le changement de son comportement. Prendre en compte la distinction entre débit en bits et débit en paquets compliquerait l'Internet mais y aurait-il un bénéfice ? Si la taille maximale des paquets sur le réseau, actuellement limitée en pratique à 1500 octets dans la plupart des cas, devait augmenter, la question deviendrait brûlante. (Ce point est couvert avec plus de détails dans le RFC 7141.)

La grande majorité des études sur le comportement de protocoles comme TCP supposait un flot relativement régulier sur le long terme, permettant ainsi aux algorithmes d'atteindre leur équilibre. Mais, dans la réalité, les choses ne se passent pas comme cela : un fichier HTML typique se charge avec seulement quelques paquets, et TCP sera donc, pendant toute la durée du flot, dans l'état « démarrage ». Comment améliorer ce cas fréquent (section 3.4) ? Au départ, le protocole de transport ne connaît rien des caractéristiques de la liaison et ne peut donc pas optimiser son débit. L'algorithme standard de TCP est tout de prudence : conçu par Van Jacobson et connu sous le nom significatif de slow start, il consiste à être très modéré tant qu'on ne connaît pas les détails de la liaison (RFC 2581 et RFC 5681). Résultat, le débit moyen est souvent trop bas, le réseau restant inoccupé. Ce problème est reconnu depuis longtemps (RFC 3742) mais sa solution souffre du manque de bases théoriques à cette difficile question (le slow start a été conçu de manière empirique).

Une autre solution serait de modifier les applications pour qu'elles réutilisent les connexions TCP existantes. C'est ce que peut faire HTTP, avec les connexions persistentes (RFC 2616, section 8.1).

Les spécificités de l'Internet ajoutent un nouvel élément au tableau (section 3.5). Contrairement à quasiment tous les autres réseaux informatiques qui ont existé, l'Internet est multi-organisations (le RFC dit multi-domains, où un domain est un système autonome). Ainsi (section 3.5.1), il existe des mécanismes de signalisation de la congestion qui peuvent poser des problèmes dans un tel environnement. C'est le cas de ECN (RFC 3168) où des bits non utilisés jusqu'à présent servent à indiquer que le routeur qui les a mis commence à voir de la congestion. En environnement mono-domaine, tout va bien. Mais dans le cas où le paquet rencontre plusieurs domaines, peut-on encore faire confiance à ces bits, qui ont pu être mis ou retirés à tort, par exemple pour ralentir une victime située dans un autre domaine (sections 8 et 19 du RFC 3168) ? Pour ECN, il y a des solutions techniques possibles (comme le RFC 3540), quoique apparemment peu déployées. Mais, d'une manière générale, toutes les solutions reposant sur la confiance entre domaines sont incertaines (notre RFC cite aussi le cas de TRC, TCP rate controller, un système de surveillance que les flots TCP se comportent bien). L'échange d'informations entre domaines, qui serait certainement utile pour lutter contre la congestion, est frappé de suspicion (section 3.5.2). Mon voisin me dit-il la vérité ? Dois-je lui dire la vérité en sachant que les informations transmises peuvent, entre autres, l'aider à se faire une bonne image de mon réseau, brisant ainsi la confidentialité ? Or, tous les mécanismes de signalisation de la congestion par les équipements réseau sont affectés par ce manque de confiance.

Un problème de sécurité proche est celui des applications malhonnêtes. L'Internet résiste aujourd'hui à la congestion car chaque pair TCP respecte les règles, même quand elles vont contre son propre intérêt. Après tout, un émetteur n'a jamais intérêt à diminuer son débit, si d'autres le feront à sa place. La section 3.7 se penche sur les comportements négatifs que pourraient adopter des applications. Le problème a déjà été étudié et des solutions proposées (RFC 3540). Elles sont efficaces (peut-être trop, dit le RFC, laissant entendre qu'elles pourraient sanctionner des innocents). Mais elles sont très peu déployées. Une des raisons est peut-être que les attaques sont pour l'instant apparemment très peu nombreuses. En fait, note notre RFC, l'étude de la quantité de telles attaques est en soi un sujet de recherche. On ne sait pas vraiment dire pour l'instant s'il y a beaucoup de tricheurs (peut-être l'exemple Google cité plus haut mais il est très récent et pas assez étudié). On soupçonne évidemment que tout logiciel qui annonce qu'il va « optimiser le temps de téléchargement » risque fort d'y arriver en trichant...

TCP n'est pas le seul protocole de transport : certaines applications utilisent un protocole sans contrôle de congestion, comme UDP, et sont donc censées gérer la congestion elles-mêmes. Or, comme indiqué plus haut, ce n'est pas dans leur intérêt et on pourrait voir des abus, comme s'en inquiétait le RFC 3714. Cette question est presque un problème philosophique : une machine connectée à l'Internet est libre, elle peut notamment utiliser le protocole de transport de son choix. Envoyer des octets au maximum de ses possibilités, sans tenir compte de la congestion, n'est-ce pas abuser de cette liberté ? Comme les applications qui utilisent UDP sont souvent les plus gourmandes (vidéo en haute définition, par exemple), le RFC 8085 insistait sur la nécessité qu'elles se comportent gentiment et mettent en œuvre une forme de contrôle de congestion adaptée à leurs bsoins propres.

Les applications ont des exigences souvent très différentes vis-à-vis du réseau. Par exemple, les gros transferts de fichiers peuvent souvent s'exécuter en arrière-plan en profitant de la capacité du réseau quand il est libre, tout en réduisant sérieusement leur débit s'il ne l'est pas (section 3.6). Comment utiliser cette « élasticité » pour mieux gérer la congestion ? L'idée de marquer les paquets en fonction de ces exigences des applications n'est pas neuve (on la trouve déjà dans les bits ToS du RFC 791) mais il y a aussi des propositions plus récentes comme le RFC 3662. Mais en pratique, ces mécanismes ne sont guère utilisés. Actuellement, un groupe de travail de l'IETF, LEDBAT, travaille sur ce sujet (voir leur solution dans le RFC 6817).

Enfin, il reste les autres défis, ceux qui sont jugés relativement peu importants aujourd'hui et n'ont donc pas mérité une section dédiée. Ils sont regroupés dans la section 3.8. On y trouve, par exemple, la question de la mesure du RTT (bien des protocoles dépendent d'une bonne évaluation de ce temps). Aujourd'hui, seul l'émetteur d'un paquet a une bonne idée du RTT, en mesurant le moment où revient l'accusé de réception. Il n'existe malheureusement pas de moyen pour le receveur d'estimer le RTT, ce qui l'empêche d'ajuster son comportement. D'autre part, le RTT brut n'est pas forcément utilisable directement (par exemple parce qu'il varie brutalement dans le temps) et il est utile de se pencher sur des valeurs extrapolées, plus lisses, comme celles du RFC 2988.

Autre défi qui se posera un jour (sections 3.8.2) : le cas des logiciels bogués, qui réagissent mal lorsqu'on essaie une nouvelle technique, même si elle est parfaitement légale : beaucoup de machines sur Internet ont été programmées avec les pieds et plantent (ou même plantent leur voisin) si les données envoyées ne sont pas celles attendues (comme ce fut le cas lors de la fameuse crise de l'attribut BGP 99). Ainsi, même si on conçoit un nouvel algorithme génial de contrôle de la congestion, il sera peut-être difficile à déployer. C'est ce qui est arrivé à ECN, qui a connu bien des problèmes mais aussi au window scaling que plusieurs routeurs de bas de gamme rejettaient (c'est arrivé par exemple sur les boxes d'Alice). Y a-t-il une solution à ce problème ? Le RFC suggère une responsabilité au moins partielle de l'IETF en demandant que, à l'avenir, le comportement par défaut des équipements, face à des options ou des champs inconnus, soit mieux spécifié, pour que le vieux logiciel laisse toujours passer proprement les options récentes. Je pense personnellement que c'est une illusion : dans bien des cas, ces règles existaient et les logiciels bogués les ignorent, car leurs auteurs, dissimulés derrière leur anonymat (comment retrouver les responsables du code des AliceBox ?) ont ignoré complètement ces règles. La section 3.8.6 revient d'ailleurs sur le cas des équipements intermédiaires (middleboxes) qui sont souvent les pires (RFC 2775).

Comme déjà signalé plus haut, un défi général auquel est confronté le contrôle de congestion est celui de la sécurité (section 4). Par exemple (RFC 4948), les DoS sont possibles parce que l'Internet n'impose pas de contrôle de congestion (attention, le RFC parle de dDoS mais c'est à mon avis une erreur : si certains réseaux ont des mécanismes de contrôle de congestion obligatoires, aucun ne prévoit un mécanisme global, qui pourrait arrêter un botnet composé de milliers de zombies indépendants). De manière plus générale, aujourd'hui, le respect des règles qui empêchent l'Internet de s'écrouler sous le poids de la congestion est facultatif, laissé à la bonne volonté de chacun. Cela peut être vu comme un problème de sécurité. S'il existait des mécanismes de contrôle de la congestion qui résistent aux égoïstes prêts à tricher, ces mécanismes pourraient également être utilisés contre les DoS.

Voilà, désolé d'avoir été si long mais ce RFC est très riche et le champ des problèmes non encore résolus dans ce domaine de la congestion est immense. Étudiants futurs chercheurs, à vous de travailler à le défricher !

Merci à Pierre Beyssac pour sa relecture et ses commentaires.


Téléchargez le RFC 6077


L'article seul

RFC 6076: Basic Telephony SIP End-to-End Performance Metrics

Date de publication du RFC : Janvier 2011
Auteur(s) du RFC : D. Malas (CableLabs), A. Morton (AT&T Labs)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF pmol
Première rédaction de cet article le 20 janvier 2011


Le protocole de signalisation SIP est aujourd'hui le plus utilisé pour la voix sur IP. Il existe de nombreux fournisseurs SIP concurrents, de nombreux services SIP un peu partout. Comment les comparer ? Ce RFC se consacre à définir des métriques pour la téléphonie SIP.

Il est le premier RFC produit par le groupe de travail PMOL de l'IETF, groupe de travail qui est consacré à la définition de métriques pour les couches hautes (notamment la couche 7), le groupe IPPM se consacrant aux couches basses comme la couche 3. En suivant ses recommandations, il devrait être possible de comparer des mesures de performances SIP entre différents services. À noter qu'il existait déjà des métriques pour des systèmes de téléphonie autres, comme SS7, mais rien pour SIP.

Comme PMOL (contrairement à un autre groupe de travail sur les mesures, BMWG) établit des métriques pour le monde extérieur, le grand Internet, les résultats des mesures sont influencés par des variables extérieures à SIP, par exemple la qualité du réseau (latence et capacité libre). Les métriques définies ici n'essaient pas de séparer ces variables « réseau » des autres. On teste donc un service, pas uniquement un serveur.

D'autre part, il s'agit bien de définir des métriques (des grandeurs mesurables et définies rigoureusement) et pas des objectifs chiffrés, genre SLA. Ce RFC définit ainsi ce qu'est exactement un temps de réponse, mais pas quelle valeur de ce temps est acceptable pour l'utilisateur.

Après ces préliminaires, la section 2 définit le vocabulaire utilisé. Ainsi, End-to-end fait référence à une liaison entre les deux entités qui communiquent (deux téléphones, par exemple), même si cette communication passe, au niveau 3 par beaucoup de routeurs, et au niveau 7 par plusieurs relais SIP. Une session est la communication établie par SIP (dont le rôle principal est justement d'établir et de fermer les sessions ; le transfert de la voix encodée n'est pas directement du ressort de SIP) et elle peut donc comprendre plusieurs flots de données différents, par exemple plusieurs connexions TCP.

Enfin (non, tout le travail préparatoire n'est pas fini, on n'est pas encore arrivé aux métriques elles-mêmes), toute mesure faisant intervenir le temps, la section 3 est dédiée aux problèmes de mesure de celui-ci. C'est essentiellement une reprise du RFC 2330, section 10. Pour les besoins des mesures SIP (moins exigeantes que les mesures comme le temps d'acheminement d'un paquet IP du RFC 7679), une erreur de moins d'une milli-seconde est demandée, ainsi qu'une stabilité de un pour mille pour la fréquence de l'horloge.

La section 4 introduit enfin ces fameuses métriques. Le temps commence lorsque le premier message est envoyé par un des UA (User Agents, typiquement un téléphone, matériel ou logiciel). Même si ce premier message doit être répété, l'horloge n'est pas remise à zéro. On arrête le chrono lorsque l'opération souhaitée par l'UA est faite, même si elle a nécessité plusieurs transactions SIP (par exemple, si un appel a été redirigé). Des options comme l'authentification (qui est fréquemment utilisée dans le monde SIP car les fournisseurs de service qui procurent un accès au téléphone classique ne sont jamais gratuits) peuvent sérieusement augmenter la durée mesurée mais on n'essaie pas de les retirer du total : elles font partie du service mesuré (voir section 5.3 pour les détails). Enfin, les métriques de la section 4 ne précisent pas la taille de l'échantillon utilisé, se contentant de rappeller qu'on a en général de meilleurs résultats en augmentant la taille de l'échantillon.

Pour comprendre les métriques, il faut se rappeller que le fonctionnement typique d'un téléphone SIP est :

  • Au démarrage du téléphone, on s'enregistre auprès d'un fournisseur SIP (SSP pour SIP Service Provider) tel que OVH ou Free/Freephonie. Cela permettra, notamment, de recevoir des appels entrants même si l'appelant ne connait pas notre adresse IP actuelle.
  • Pour chaque appel téléphonique, on établit une session SIP avec le destinataire, et cette session sert à transmettre les paramètres d'envoi du flux audio (qui n'est pas envoyé dans la session SIP mais via un protocole séparé comme RTP).

Parmi les métriques définies, on trouve :

  • RRD (Registration Request Delay, section 4.1). Elle mesure le temps écoulé entre un enregistrement d'un UA auprès d'un fournisseur SIP (requête REGISTER) et la réponse réussie, typiquement 200 OK (les échecs sont comptés différemment, voir section 4.2), exprimée en milli-secondes.
  • IRA (Ineffective Registration Attempts, section 4.2) qui est le pourcentage des tentatives d'enregistrement qui échouent, soit par réponse négative, soit par expiration du délai d'attente.
  • SRD (Session Request Delay, section 4.3), qui est le délai nécessaire pour établir une nouvelle session. En termes de téléphonie classique, c'est le moment entre la composition du numéro et le décrochage du téléphone en face. En SIP, c'est le délai entre la requête INVITE et la réponse à celle-ci (la réponse pouvant être négative, par exemple un 486 - Occupé).
  • SDT (Session Duration Time, section 4.5) est la durée d'une session (d'un appel). C'est la différence entre le moment de la fin de la session (par requête explicite ou bien par expiration du délai d'attente) et la réponse réussie à un INVITE.
  • SER (Session Establishment Ratio, section 4.6) est le pourcentage de tentatives d'établissement de sessions SIP qui réussit (de même que IRA était le pourcentage de tentatives d'enregistrement auprès du SSP qui échouaient).

Le logiciel de test sipsak affiche dans certains cas des durées mais elles ne sont pas exprimées en terme des métriques de ce RFC donc il faudrait lire le source pour avoir leur sémantique exacte. Ici, l'établissement d'une session :

% sipsak -vv  -s "sip:bortzmeyer@ekiga.net"                      
...
message received:
SIP/2.0 200 OK
...
** reply received after 6.770 ms **

Et ici une session complète avec envoi d'un message :

% sipsak -vv -B "This is a test" -M -s "sip:stephane@10.10.86.76"     
...
received last message 55.642 ms after first request (test duration).

Téléchargez le RFC 6076


L'article seul

RFC 6071: IP Security (IPsec) and Internet Key Exchange (IKE) Document Roadmap

Date de publication du RFC : Février 2010
Auteur(s) du RFC : S. Frankel (NIST), S. Krishnan (Ericsson)
Pour information
Réalisé dans le cadre du groupe de travail IETF ipsecme
Première rédaction de cet article le 8 février 2011


Le protocole de sécurité IPsec a connu plusieurs versions, et de nombreuses extensions. Le programmeur qui voudrait aujourd'hui le mettre en œuvre, l'administrateur réseaux qui voudrait le déployer, doivent souvent se gratter le crâne assez longtemps, uniquement pour identifier les normes pertinentes. Pour leur faciliter la tâche, l'IETF produit un RFC spécial, la « carte routière » qui est uniquement une liste commentée des RFC qui s'appliquent à leur cas. La précédente version de la carte d'IPsec était le RFC 2411, que notre RFC 6071 remplace. Si vous voulez comprendre IPsec et IKE et que vous ne savez pas par où commencer, ce RFC 6071 pourra vous servir de guide dans la jungle des normes sur IPsec.

La section 1 commence par fournir un résumé bien utile d'IPsec et de ses protocoles auxiliaires comme IKE. IPsec vise à fournir un service de sécurité à tout service Internet, sans modifier les applications (contrairement à TLS). Si l'échange de paquets entre deux machines est protégé par IPsec, toutes leurs communications pourront être authentifiées et/ou confidentielles. On peut utiliser IPsec de bien des façons, mais les plus courantes aujourd'hui sont de créer un tunnel sécurisé entre deux sites ou bien d'établir un VPN entre un site central et des machines en promenade.

IPsec utilise la cryptographie et, pour cela, a besoin de clés. On peut les gérer de plusieurs façons (aujourd'hui, c'est souvent fait manuellement), mais la méthode standard pour la gestion dynamique des clés est IKE.

La section 2 de notre RFC classe les normes IPsec en pas moins de sept groupes : l'architecture, le protocole ESP (qui fournit authentification et confidentialité), le protocole AH (qui ne fournit que l'authentification), les algorithmes cryptographiques, les algorithmes combinés (qui indiquent comment faire fonctionner ensemble les différentes pièces), les algorithmes de préservation de l'intégrité des paquets et enfin IKE.

Du fait de la longue histoire d'IPsec, plusieurs versions de ce protocole coexistent. La version actuelle est IPsec v3 mais IPsec v2 est encore fréquemment rencontré dans la nature. La section 2.1.1 résume leurs différences. Par exemple, le protocole AH (RFC 4302), dont l'utilité est douteuse, puisque ESP fournit les mêmes services (tels que perçus par l'application), n'est plus obligatoire. AH existait en raison des restrictions à l'exportation de logiciels cryptographiques en dehors des États-Unis et de restrictions d'usage moyenâgeuses dans certains pays comme la France. Aujourd'hui que ces restrictions sont assouplies, AH ne fait que générer de la complexité supplémentaire, comme l'exposait la fameuse critique de Niels Ferguson et Bruce Schneier, « A Cryptographic Evaluation of IPsec ».

IKE a aussi plusieurs versions qui coexistent (section 2.3). La version actuelle est la v2, mais la v1 est toujours en service. La v2 se signale (section 2.3.1) entre autres par l'intégration d'EAP, l'utilisation d'ESP pour protéger IKE lui-même (avant, c'était un protocole spécifique qui s'en chargeait), par de meilleures protections contre les DoS, notamment en permettant au répondeur de ne pas allouer trop de ressources avant d'avoir authentifié l'appelant.

Outre les RFC sur IPsec et IKE, présentés plus loin, en section 3, il existe plusieurs registres IANA sur ces protocoles (section 2.4), notamment :

La section 3 décrit les documents à lire si on veut programmer IPsec. Je ne mentionne ici que ceux de l'IPsec récent (IPsec v3) mais notre RFC 6071 décrit aussi (section 3.1.1) ceux de la précédente version d'IPsec, autour du RFC 2401.

Le cœur de IPsec v3 est décrit dans trois RFC (section 3.1.2), le RFC 4301 sur l'architecture générale, le RFC 4302 sur AH et le RFC 4303 sur ESP. Autour de ce cœur, on trouve plusieurs ajouts comme la possibilité d'encapsuler IPsec dans UDP (RFC 3948) ou bien la possibilité de chiffrer sans arrangement préalable entre les parties (RFC 4322), par exemple en récupérant les clés dans le DNS (avec protection par DNSSEC bien sûr).

Sans être des ajouts à IPsec, il existe plusieurs RFC qui discutent de questions générales (section 3.3) comme la traversée des équipements NAT par IPsec (RFC 3715) ou les suggestions pour évaluer si IPsec est une solution adaptée (RFC 5406, uniquement pour le vieil IPsec v2).

IKE est traité de la même façon en section 4 : les documents de base pour la vieille - mais encore utilisée - version et pour la version actuelle, la v2 (le principal document étant le RFC 4306, suivi du document de clarification RFC 4718) puis les ajouts.

La section 5 est entièrement consacrée au délicat problème des algorithmes de cryptographie. Comme la cryptanalyse progresse sans cesse, envoyant dans les poubelles de l'histoire des algorithmes peu sûrs, et poussant à l'introduction de petits nouveaux, il est important qu'un protocole de sécurité comme IPsec puisse suivre l'état de l'art sans avoir besoin d'une révision. En nombre de RFC, c'est de loin ce secteur qui contribue le plus à la taille des normes IPsec. Pour que, dans cette variété de protocoles, deux mises en œuvre d'IPsec aient une chance de communiquer (section 5.1), il faut qu'il y ait un ensemble d'algorithmes communs. Dans IPsec, les algorithmes sont marqués comme obligatoires (toute mise en œuvre d'IPsec doit les implémenter) ou facultatifs. Le RFC 7321 définit les exigences auxquelles doivent obéir les algorithmes utilisés par IPsec, le RFC 4307, celles pour IKE.

La section 5.2 décrit ensuite les algorithmes de chiffrement eux-mêmes, par exemple l'obligatoire NULL (qui ne chiffre rien et ne protège donc rien, RFC 2410), l'obligatoire AES-CBC (RFC 3602, le facultatif Camellia (RFC 4312), etc.

Si la section 5.2 listait les algorithmes de chiffrement, la 5.3 décrit ceux utilisés pour le contrôle d'intégrité. On y trouve HMAC-SHA1 (RFC 2404), dont la mise en œuvre est obligatoire, mais aussi la famille SHA-2 (optionnelle, cf. RFC 4868), et même MD5 (RFC 2403) pas conseillé mais pas interdit non plus, les multiples vulnérabilités de MD5 n'affectant apparemment pas (pour l'instant) son usage en HMAC (RFC 4835).

Certains algorithmes peuvent fournir à la fois le chiffrement et l'intégrité, et la section 5.4 décrit ces combinaisons. Ainsi, AES en mode CCM CBC-MAC permet d'assurer les deux tâches (RFC 4309).

Pas de cryptographie sans nombres aléatoires (section 5.5), par exemple pour générer les clés de sessions de IKE. C'est donc une nouvelle série d'algorithmes qui doit être spécifiée.

Le zoo des algorithmes de cryptographie utilisés devient donc d'une taille impressionnante et on peut se demander si deux pairs IPsec trouveront une combinaison d'algorithmes qu'ils peuvent utiliser tous les deux ! La section 5.6 expose donc les suites. Une suite est un ensemble cohérent d'algorithmes qui simplifie le travail du programmeur : si on implémente toute la suite, on a un groupe d'algorithmes qui interopérera avec les autres utilisateurs de la même suite. En outre, il est plus facile de se référer à une suite qu'à une longue liste d'algorithmes. C'est ainsi que le RFC 4308 décrivait deux suites, « VPN-A », qui inclut 3DES, HMAC-SHA-1, et un mode Diffie-Hellman et « VPN-B » qui inclut AES-CBC, AES-XCBC-MAC et un mode Diffie-Hellman plus long. On peut ainsi choisir tout un ensemble d'algorithmes avec un seul bouton dans la configuration (« Use VPN-B: Yes »). Le RFC 4869 a ajouté quatre autres suites, tirées de normes « Suite B » de la NSA. Elles incluent la famille SHA-2.

Tiens, puisque j'ai parlé de Diffie-Hellman, mécanisme pour permettre à deux pairs de trouver des clés secrètes communes pour pouvoir communiquer, la section 5.7 décrit les RFC qui mentionnent cette méthode dans le contexte d'IPsec. Ainsi, le RFC 5903 est la dernière norme pour l'utilisation de courbes elliptiques dans le cadre Diffie-Hellman, et le RFC 5114 définit de nouveaux groupes pour cet algorithme.

Dans le monde réel, IPsec a connu de nombreux usages qui dépassaient parfois le strict cadre de ce qui était normalisé. La section 7 décrit certains de ces usages, qui étendent et facilitent l'utilisation d'IPsec. Ainsi, les RFC 3586 et RFC 3585 se penchent sur la question de définitions formelles des politiques de sécurité IPsec, le RFC 4807 décrit une MIB pour la gestion IPsec (il semble très peu utilisé), etc.

Une extension intéressante a été BTNS (Better-Than-Nothing Security, section 7.5) qui a introduit le concept de « la plus mauvaise sécurité est celle qu'on ne déploie pas » dans le monde IPsec. Celui-ci était réputé pour sa rigidité et son strict respect des bons principes techniques de sécurité. Ainsi, les protocoles IPsec imposaient une authentification des deux pairs, sans laquelle une attaque de l'intermédiaire était possible. Très bonne idée sauf que, en pratique, cette authentification nécessitait une lourde infrastructure d'identité (par exemple à base d'IGC) et qu'elle a, en pratique, pas mal freiné le déploiement d'IPsec. D'où cette évolution récente (2008) d'accepter un mode sans authentification, BTNS, qui permet d'établir une session IPsec avec des gens qu'on ne connait pas (pensez à un serveur Web, qui ne connait évidemment pas chacun de ses clients à l'avance). Les RFC 5386 et RFC 5387 décrivent BTNS.

Le talon d'Achille de tout protocole de cryptographie est souvent dans la gestion des clés. Où les stocker, comment garantir que la clé privée est en sécurité, que la clé publique est bien authentique ? Pour la seconde question, la garantie que la clé publique est bien la bonne, la section 7.8 rappelle le mécanisme IPSECKEY qui permet de stocker les clés publiques dans le DNS (RFC 4025). Ce mécanisme est resté largement théorique à ce jour (après tout, le DNS n'offrait typiquement que peu de garanties de sécurité) mais la signature de la racine avec DNSSEC le 15 juillet 2010 lui a redonné de l'actualité. Il est désormais possible de valider une clé trouvée dans le DNS.

Le programmeur qui implémente IPsec doit se rappeler que c'est un mécanisme général, situé en desous de la couche transport. Normalement, il est invisible aux applications. Toutefois, certains protocoles intermédiaires font un usage spécifique d'IPsec et la section 8 en donne une liste. Ainsi (section 8.2) OSPF, depuis la version 3 (RFC 4552 et RFC 5340), a remplacé son ancien mécanisme d'authentification spécifique par IPsec. OSPF fonctionnant souvent en diffusion restreinte, cela ne permet pas IKE impose l'usage de clés manuelles. En pratique, ce mécanisme de sécurisation semble très peu déployé et le passage à IPsec, trop complexe par rapport à l'ancienne méthode, a donc réduit la sécurité de OSPF (en sécurité, comme souvent dans d'autres domaines de l'ingéniérie, le mieux est l'ennemi du bien...)

Autre protocole de routage qui aurait bien besoin de davantage de sécurité, BGP. La section 8.6 décrit ce que IPsec peut lui apporter. Le RFC 5566 décrit ainsi une méthode pour protéger les session BGP. En pratique, elle semble quasi-inutilisée, les opérateurs préférant le RFC 2385 (ou peut-être demain son successeur, le RFC 5925). À noter que le plus gros problème de BGP, en pratique, n'est pas l'authentification du pair, mais la confiance qu'on accorde à ce qu'il transmet. Et, là, IPsec ne peut rien.

Autre consommateur d'IPsec, HIP (section 8.3 et RFC 7401). HIP est un protocole de séparation de l'identificateur et du localisateur. Il introduit donc des failles potentielles liées à l'indirection supplémentaire, par exemple d'un méchant essayant de rediriger un trafic important vers une victime en faisant croire que l'adresse IP de la victime est la sienne. N'ayant pas de mécanisme de sécurité propre, HIP délègue la protection de son trafic à IPsec (RFC 5202 et RFC 5206).

IPsec garantissant l'intégrité du trafic IP, il peut rentrer en conflit avec des protocoles qui modifient les paquets, pour de bonnes raisons, par exemple la compression. D'où le nombre de RFC sur l'interaction entre IPsec et ROHC (section 8.5), par exemple le RFC 5856 qui permet de comprimer les paquets dans un tunnel IPsec ou le RFC 5858 qui décrit des extensions à IPsec lui permettant de mieux s'entendre avec ROHC.

Si certains protocoles, comme dans la section précédente, utilisent IPsec, d'autres réutilisent seulement IKE pour leurs besoins propres (section 9). C'est le cas par exemple d'EAP (RFC 5106).

Voilà, ce résumé d'un long RFC (et qui se termine par une longue bibliographie) aura réussi, je l'espère, à donner une idée de la richesse et de la complexité du monde d'IPsec.

Merci à Yves Rutschle pour avoir relu et trouvé une grosse bogue.


Téléchargez le RFC 6071


L'article seul

RFC 6069: Making TCP more Robust to Long Connectivity Disruptions (TCP-LCD)

Date de publication du RFC : Décembre 2010
Auteur(s) du RFC : A. Zimmermann, A. Hannemann (RWTH Aachen University)
Expérimental
Réalisé dans le cadre du groupe de travail IETF tcpm
Première rédaction de cet article le 13 décembre 2010


Depuis très longtemps, un des problèmes du protocole de transport TCP est le fait qu'il réduise son débit en cas de pertes de paquets, pensant que cette perte provient d'une congestion. Mais si la perte de paquets était due à une coupure temporaire de la connectivité (ce qui est fréquent avec les liaisons radio), il est inutile de diminuer le débit, puisque le problème ne venait pas d'une congestion. TCP devrait au contraire continuer au même rythme, surtout une fois que la connectivité est rétablie. Une solution au problème pourrait être d'utiliser les messages ICMP pour mieux diagnostiquer la cause de la perte de paquets et c'est cette approche que ce RFC 6069 suggère d'essayer.

Rappelons que TCP fonctionne en envoyant des données dont l'autre pair doit accuser réception. S'il ne le fait pas à temps, TCP réemet les données et, s'il n'y a toujours rien, TCP en déduit que le réseau est surchargé (et jette donc des paquets) et, bon citoyen, il réagit en diminuant le rythme d'envoi (RFC 2988 et section 1 de notre RFC 6069). C'est ce comportement qui évite à l'Internet de s'écrouler sous la charge. Il n'est donc pas question que TCP soit modifié pour envoyer systématiquement au maximum de ses possibilités, « au cas où ça passe ». Mais, parfois, TCP est excessivement prudent. Si je débranche puis rebranche un câble réseau pendant le transfert d'un gros fichier, TCP va ralentir alors qu'il n'y avait aucune congestion (voir l'article de Schuetz, S., Eggert, L., Schmid, S., et M. Brunner, « Protocol enhancements for intermittently connected hosts », dans SIGCOMM Computer Communication Review vol. 35, no. 3). En pratique, le cas le plus embêtant se produit avec les réseaux sans-fil où de tels « branchements/débranchements » sont fréquents, soit en raison d'une modification soudaine du médium (une pluie intense, si on est dehors, ou bien un parasite soudain), soit en raison d'un déplacement de l'ordinateur. Peut-on détecter qu'une absence d'accusés de réception était due à une coupure temporaire du réseau ?

D'abord (section 2), il faut distinguer deux sortes de coupure du réseau. Les courtes sont celles qui durent moins longtemps que le délai de retransmission de TCP. Si les files d'attente du routeur situé avant la coupure sont suffisamment grandes, il pourra « tamponner » les paquets et il n'y aura même pas de perte, juste des variations de délai (cf. RFC 3522, RFC 4015 ou RFC 5682). Les longues coupures sont celles qui durent plus longtemps et où l'émetteur TCP doit donc commencer à renvoyer des paquets déjà transmis. Suivant le RFC 5681, TCP ne se contente pas de réémettre, il diminue son rythme de transmission. Si la connectivité revient, TCP ne va pas s'en apercevoir tout de suite et, même si les accusés de réception réapparaissent, TCP continuera à envoyer à un rythme réduit, sans bonne raison, juste parce qu'il a cru à la congestion. Idéalement, TCP devrait, au contraire, recommencer à pleine vitesse dès que la liaison est rétablie.

Comment détecter la coupure et le rétablissement ? La section 3 rappelle l'existence des paquets ICMP Destination Unreachable (RFC 792, RFC 1812 et RFC 4443). Ces paquets sont envoyés par le routeur, vers l'émetteur, si le routeur est obligé de jeter le paquet (codes 1, Host unreachable ou 0, Network unreachable). Mais attention, ils ne sont pas parfaits : ils ne sont pas envoyés en temps-réel (et donc arriveront peut-être après que TCP ait trouvé tout seul qu'il y a un problème) et ils sont en général limités en quantité.

Ces paquets ICMP contiennent les premiers octets du paquet qui a déclenché le problème et l'émetteur peut donc, en recevant le paquet ICMP, trouver la connexion TCP en cause. Le principe du nouvel algorithme expérimental TCP-LD (TCP Long Disruption) est donc d'utiliser ces messages ICMP pour différencier la congestion et la coupure. Dans le cas d'une coupure, cela vaudra la peine de réessayer de manière plus agressive.

L'algorithme est présenté en section 4. Le principe est simple : lorsque TCP a déjà dépassé son délai de garde, attendant un accusé de réception, et en cas de réception d'un message ICMP indiquant une coupure, TCP ne va pas augmenter les délais de retransmission. Au retour des accusés de réception, TCP reprendra « plein pot ». Les détails figurent par la suite. D'abord, TCP-LD ne s'applique qu'aux TCP qui suivaient l'algorithme de retransmission du RFC 2988. L'algorithme ne doit être utilisé qu'une fois la connexion complètement établie. Les seuls messages ICMP pris en compte sont ceux qui sont émis en réponse à des données TCP qui ont fait l'objet d'une retransmission. (Et autres détails, l'algorithme complet figure dans cette section 4.)

Une discussion des différents points à garder en tête figure en section 5. Elle insiste sur le fait que l'algorithme TCP-LD n'est déclenché que s'il y a réception des messages ICMP indiquant une erreur et expiration du délai de garde. Cela garantit que TCP-LD ne sera utilisé qu'en cas de longue coupure. Il y a quand même des cas qui prennent TCP-LD en défaut. C'est le cas par exemple de l'ambiguité analysée en section 5.1. Cette ambiguité vient du fait que le paquet TCP (et donc le message ICMP d'erreur qui concerne ce paquet) n'indique pas s'il s'agit d'une transmission ou d'une retransmission. Ce n'est pas un problème en pratique mais, si l'émetteur TCP qui reçoit le paquet ICMP peut être sûr qu'il y a eu retransmission, il n'est pas forcément sûr que le message d'erreur était en réponse à la retransmission. Encore plus rigolo (section 5.2), TCP-LD peut associer à tort un message ICMP à une session TCP ayant connu une retransmission, simplement parce que le numéro de séquence a dépassé sa valeur maximale et est revenu au début (sur des réseaux rapides, les 32 bits qui stockent le numéro de séquence TCP ne suffisent pas longtemps). La probabilité que cela arrive et interfère avec une coupure réelle est toutefois très faible. D'autres problèmes amusants (pour ceux qui connaissent bien TCP) forment la fin de la section 4, comme par exemple les risques liés aux paquets dupliqués. Un certain nombre des problèmes exposés pourraient être résolus avec l'option d'estampillage temporel de TCP (RFC 7323 et section 6 de notre RFC) : les estampilles pourraient lever certaines ambiguités.

TCP-LD est une technique « côté émetteur » seulement, et qui peut donc être déployée unilatéralement. Y a-t-il des risques à le faire ? La section 7 explore ces risques. Par exemple (section 7.1), si un émetteur TCP essaie de détecter une coupure définitive en se donnant une limite maximale au nombre de retransmissions, l'utilisation de TCP-LD, qui va réduire l'intervalle entre les retransmissions, pourra amener à des conclusions erronées. Il faut donc évaluer la durée maximale qu'on accepte avant de couper en temps, et pas en nombre de retransmissions.

Je l'ai dit au début, ce problème est perçu depuis très longtemps par les utilisateur de TCP. Il y a donc eu bien d'autres efforts pour le résoudre. La section 8 les résume. On y trouve par exemple des modifications des couches inférieures (RFC 3819) ou bien des modifications des routeurs IP, pour qu'ils analysent suffisamment de TCP pour pouvoir générer des messages d'information. TCP-LD, par contre, ne nécessite pas de modification des couches basses, ni des routeurs intermédiaires.

Un point important de ce schéma est que les messages ICMP ne sont sécurisés en rien et que d'autres RFC, comme le RFC 5927, demandent de s'en méfier et au minimum de ne pas agir sans les avoir sérieusement validés. Quels sont donc les risques (section 9) ? Un attaquant pourrait, soit générer des faux messages ICMP Destination Unreachable pour que TCP, croyant à une coupure et pas à une congestion, continue à inonder le réseau, soit au contraire empêcher les messages ICMP d'arriver, ramenant TCP à la situation avant TCP-LD. Dans le premier cas, les paquets ICMP nécessiteraient d'inclure une partie du paquet TCP, dont des éléments difficiles à deviner, comme le numéro de séquence et les mécanismes de validation du RFC 5927 conviendraient donc. Si elles échouent, l'attaquant qui arrive à trouver le numéro de séquence et les autres informations a de toute façon la possibilité de monter des attaques bien pires.

L'algorithme TCP-LD avait été présenté en 2009 à la réunion IETF 75 de Stockholm. Les transparents (« Make TCP more Robust to Long Connectivity Disruptions ») sont en ligne. Ils exposent l'algorithme et le résultat d'une évaluation après mise en œuvre sur Linux. Plein de jolis graphes. À propos de Linux, le travail des auteurs était disponible en http://www.umic-mesh.net/downloads/linux-tcp.html et a depuis été intégré (sous une forme modifiée) dans le noyau standard : regardez tcp_v4_err() dans net/ipv4/tcp_ipv4.c et les commentaires mentionnant draft-zimmermann-tcp-lcd (l'ancien nom de ce RFC 6069).


Téléchargez le RFC 6069


L'article seul

RFC 6068: The 'mailto' URI Scheme

Date de publication du RFC : Octobre 2010
Auteur(s) du RFC : M. Duerst (Aoyama Gakuin University), L. Masinter (Adobe), J. Zawinski (DNS lounge)
Chemin des normes
Première rédaction de cet article le 5 octobre 2010


Le plan d'URI mailto:, qui permettait d'indiquer une adresse de courrier à contacter, était normalisé dans le RFC 2368. Désormais, il est remplacé par ce RFC 6068, qui introduit notamment la possibilité d'internationalisation des adresses indiquées en paramètre de mailto:.

La plupart des plans d'URI, comme http: ou ftp: permettent de désigner une ressource accessible quelque part sur le Web. mailto: est un cas à part dans la mesure où il sert plutôt à déclencher une action, l'envoi d'un message. L'usage le plus connu du plan mailto: est dans HTML, quand on écrit quelque chose du genre :


<p>N'hésitez pas à <a href="mailto:contact@example.org">signaler</a> tout problème que vous verriez dans ces
pages. Merci d'avance.</p>

et le lecteur verra un lien sur le mot « signaler ». Sélectionnant ce lien, son navigateur lui proposera alors d'envoyer un courrier à contact@example.org (ou bien déléguera cette tâche à un MUA).

La syntaxe formelle des URI mailto: figure en section 2. Outre l'adresse de destination (comme dans l'exemple ci-dessus), la grammaire permet de spécifier des champs qui seront pré-remplis comme Subject: (la grammaire ne met pas de limite sur les noms de ces champs, donc elle peut servir pour tout nouveau champ inventé). Juste après le nom du plan, mailto et le deux-points obligatoire, figure l'adresse du destinataire. Elle est évidemment à la syntaxe normalisée dans le RFC 5322, avec quelques restrictions, notamment l'interdiction des commentaires (dans l'adresse Jean Durand <jean@durand.example>, « Jean Durand » est le commentaire). La section 6 fournit de nombreux exemples, que je reprends ici (parfois un peu adaptés). Par exemple, un URI mailto: de base peut être <mailto:chris@example.com> (en utilisant la convention de l'annexe C du RFC 3986 d'écrire l'URI entre chevrons). Un URI avec sujet peut être <mailto:infobot@example.com?subject=current-issue>.

En théorie, n'importe quel en-tête peut être ainsi spécifié et, par exemple, un logiciel qui archive une liste de diffusion sous forme de page Web (comme Mhonarc) pourrait mettre un In-Reply-To: dans les URI, pour garantir qu'une réponse ne casse pas les fils de discussion. Le RFC cite cet exemple :


<li><a href="mailto:list@example.org?In-Reply-To=%3C3469A91.D10AF4C@example.com%3E">
Foo larger than Bar?</a> 2010-10-04 08:28</li>

C'est très astucieux mais, en 2010, je ne connais aucun archiveur qui fasse cela...

Si on spécifie deux champs dans l'URI mailto:, on les sépare par le & : <mailto:joe@example.com?cc=bob@example.com&subject=hello>.

Bien des caractères qui sont légaux dans une adresse de courrier peuvent poser des problèmes dans un URI. C'est le cas par exemple de %, de /, de ?, etc. Ceux-ci doivent être encodés en « pour-cent », c'est-à-dire que, par exemple, ? devient %3F (la valeur de l'octet en hexadécimal). Ainsi, un URI avec indication du corps du message et un espace dans ce corps peut être <mailto:infobot@example.com?body=send%20current-issue>. Un URI pour écrire à gorby%kremvax@example.com devrait s'écrire <mailto:gorby%25kremvax@example.com>. (Cet exemple du RFC fait référence à une vieille blague Usenet.)

Si les caractères à encoder ne sont pas dans ASCII, c'est leur forme UTF-8 qui est encodée pour-cent, octet par octet. Ainsi, Stéphane devient St%C3%A9phane. Doit-on appliquer le même traitement aux caractères dans la partie « domaine » (à droite du @) de l'adresse, si le domaine est un IDN ? Oui, on peut, en appliquant l'encodage pour-cent à la forme UTF-8. Si l'adresse est druon@académie-française.fr, on peut l'écrire druon@acad%C3%A9mie-fran%C3%A7aise.fr dans un URI mailto: mais il faudra le transformer en Punycode (druon@xn--acadmie-franaise-npb1a.fr) au moment de la composition du message, ce qui garantira que cela fonctionne toujours, même avec des applications anciennes. Un exemple plus sophistiqué est donné en section 6.3 avec le mot japonais nattō, qui s'écrit en Unicode U+7D0D U+8C46. Pour écrire à user@"natto".example.org, on aura alors un URI <mailto:user@%E7%B4%8D%E8%B1%86.example.org?subject=Test&body=NATTO>.

Même les champs supplémentaires indiqués dans l'URI peuvent avoir besoin d'être encodés pour-cent, car leur nom peut contenir des caractères ASCII mais interdits dans un URI. C'est encore plus vrai pour les valeurs des champs, qui ont des chances de contenir des caractères non-ASCII. Ainsi, demander du café (cf. RFC 2324) par courrier se fera avec un URI <mailto:user@example.org?subject=caf%C3%A9>. body pose un cas particulier car ce n'est pas un vrai champ de l'en-tête, c'est un pseudo-champ qui identifie le corps du message. Il peut être en UTF-8 (et donc encodé pour-cent), mais on ne doit pas le stocker en Quoted-Printable ou autres encodages utilisés dans le courrier. De toute façon, ce pseudo-champ est conçu pour de courts messages, pas pour du multimédia compliqué.

Des surencodages peuvent ensuite avoir besoin de s'appliquer, selon le contexte. Ainsi, si un URI mailto: comprend un & (utilisé comme délimiteur de paramètres), il ne posera pas de problème en texte seul mais, en XML, il devra être écrit &amp; (regardez le source XML ou HTML de cet article pour des exemples...).

Après ces détails de syntaxe, le mode d'emploi des URI mailto: (section 3). Les normes sur les URI spécifient leur syntaxe mais en général ne donnent guère de détails sur leur résolution : un URI est avant tout un identificateur. Pour mailto:, l'usage typique est d'envoyer un courrier à l'adresse donnée en paramètre, en incluant les champs supplémentaires donnés dans l'URI.

L'encodage des URI, sujet compliqué, justifie une section entière, la numéro 5. Le RFC 3986 impose un surencodage de certains caractères, que l'on peut trouver dans une adresse, dans un en-tête, ou dans le corps du message. Un exemple typique est l'espace, qui doit être écrit %20. Quant aux fins de ligne, elles doivent suivre la règle de l'Internet et être composées de deux caractères, %0D%0A. Tout logiciel qui produit des URI mailto: doit donc faire attention à encoder ces caractères « spéciaux ». Par exemple, dans un formulaire HTML, il est courant de représenter l'espace par un +. Mais cela peut créer une confusion avec les vrais +, qui peuvent se retrouver dans un URI mailto:, y compris dans l'adresse comme dans l'exemple bill+ietf@example.org que cite le RFC. Bref, l'espace doit être représenté avec %20 et le + par lui-même ou par %2B.

À noter que ce RFC n'inclut pas la possibilité d'utiliser des adresses de courrier complètement internatonalisées, la spécification de celles-ci étant encore marquée « expérimental ». Elle est devenue norme complète en 2012 avec le RFC 6530.

Les changements depuis le RFC 2368 sont rassemblés en section 9 : le principal est évidemment la possibilité d'inclure de l'UTF-8, encodé en pour-cent, possibilité qui ajoute l'internationalisation aux URI mailto:. Le nouveau plan mailto: est désormais enregistré dans le registre des plans, tel que documenté en section 8.

Comme l'utilisation normale d'un URI mailto: est une action (envoyer un message), il faut soigner la sécurité, à laquelle la section 7 est consacrée. L'utilisateur n'est pas forcément conscient de ce qu'il fait (d'autant plus que le texte du lien peut être trompeur, par exemple <a href="mailto:victim@example.com">Envoyez un message à attacker@example.net</a>). Le RFC insiste donc que le logiciel ne doit pas envoyer de message en réaction à un mailto: sans l'accord explicite et informé (affichage du contenu complet, et des en-têtes) de l'utilisateur. Autrement, l'utilisateur risque, sans s'en rendre compte, d'envoyer des messages qui lui vaudront des ennuis (par exemple parce qu'ils contiennent des menaces).

D'autre part, les URI mailto:, étant structurés, se prêtent bien à l'analyse et donc à la récupération automatique. Comme cette récolte a en général pour but l'envoi de spam, il peut être préférable de ne pas utiliser d'URI mailto: (c'est le cas de ce blog pour l'adresse indiquée en bas de chaque page).

Autre problème, la section 4 met en garde contre les en-têtes « dangereux ». Une liste indicative se trouve en section 3, incluant par exemple les en-têtes de routage du courrier comme Apparently-To:. From: est aussi dangereux (car il permet de faire envoyer un message qui ment sur sa source). Le RFC cite ensuite quelques en-têtes « sûrs » : Subject:, Keywords: et le pseudo en-tête body. Si un URI mailto: contient des en-têtes dangereux, le navigateur ne doit pas envoyer le message, ou alors il doit le « censurer » en ne tenant pas compte des dits en-têtes. De toute façon, en pratique, le créateur d'un URI mailto: ne peut pas espérer que les en-têtes autres que Subject: et body soient compris par le navigateur.


Téléchargez le RFC 6068


L'article seul

RFC 6067: BCP 47 Extension U

Date de publication du RFC : Décembre 2010
Auteur(s) du RFC : M. Davis (Google), A. Phillips (Lab126), Y. Umaoka (IBM)
Pour information
Première rédaction de cet article le 8 décembre 2010


Le RFC 5646 (alias « BCP 47 » pour Best Common Practice 47), qui normalise les étiquettes de langue, prévoyait un mécanisme d'extension par le biais de sous-étiquettes d'un seul caractère. Ce RFC 6067 spécifie la première de ces extensions à rentrer en service, pour indiquer l'information de localisation du consortium Unicode.

Les étiquettes de langue sont utilisées pour marquer du contenu sur le Web mais également en plein d'autres endroits, afin d'indiquer la langue utilisée. Leur norme, le RFC 5646 décrit un mini-langage permettant d'indiquer la langue mais aussi l'écriture, le pays, voire la variante dialectale. Ainsi, ru-petr1708 désignera le russe tel qu'il était écrit dans l'ortographe de Pierre Ier, avant la réforme de 1917. Ce langage de construction des étiquettes est très riche mais ne permet de faire une étiquette qu'à partir de sous-étiquettes déjà enregistrées dans le registre des langues (ou bien à partir de sous-étiquettes purement privées). Il n'y a notamment pas de moyen pour utiliser les catalogues existants.

Or, un de ces catalogues est particulièrement utilisé, le catalogue des locales décrit dans le TR35 et géré par le consortium Unicode. C'est pour pouvoir l'utiliser que l'extension « u » est créée par notre RFC. (Le singleton « u » voulant dire Unicode.) Il permettra d'étiqueter avec davantage de précision un document. Ainsi, en-u-cu-usd désignera un texte en anglais dont, grâce à l'extension « u », on pourra savoir qu'il utilise le dollar états-unien (usd) comme unité monétaire.

Les données utilisables avec cette extension proviennent du CLDR, le grand dépôt des locales géré par le consortium Unicode et qui contient des choses aussi variées que les jours fériés par pays ou bien les différents ordres de tri utilisés.

Le RFC 5646/BCP 47 (section 3.7) impose un certain nombre de règles pour la création d'une extension, notamment l'indication précise de l'autorité en charge du catalogue accessible via l'extension, et de ses politiques. La section 2 de notre RFC 6067 satisfait à cette règle en décrivant comment est géré CLDR.

Maintenant, quelle information peut-on indiquer avec l'extension « u » ? La section 2.1 les liste en renvoyant à la section 3 du TR35. On peut indiquer des attributs, des clés et des types. Aujourd'hui, aucun attribut n'est défini. Les clés, elles, ont exactement deux caractères et sont définis par le TR35. ca désigne un calendrier, co un ordre de tri, cu la monnaie, tz le fuseau horaire, etc. Les types sont les valeurs associées aux clés. Ainsi, ca-coptic désigne le calendrier copte. Une étiquette complète comme de-DE-u-co-phonebk sera « l'allemand tel qu'écrit en Allemagne, utilisant l'ordre de tri phonebk, i.e. celui normalisé pour l'annuaire téléphonique (qui se nomme phonebook dans CLDR, qui n'a pas les mêmes contraintes de taille) ». en-u-tz-usden sera l'anglais avec le fuseau horaire Mountain Time. Et es-u-cu-mxn sera l'espagnol avec comme unité monétaire le peso mexicain. Bien sûr, dans la plupart des cas, il n'y aura pas besoin d'étiqueter les textes avec ce niveau de précision. (Merci à Doug Ewell pour la plupart des exemples.) Mais certaines utilisations pourront en avoir besoin.

CLDR distribue des fichiers contenant les informations nécessaires pour tous les types possibles en http://unicode.org/Public/cldr/. Si vous voulez l'ordre de tri allemand, il est en common/collation/de.xml.

La section 2.2 du RFC contient le formulaire d'enregistrement obligatoire (RFC 5646, section 3.7) pour une extension. « u » est donc désormais le premier élément du registre des extensions..

Attention à un petit piège : les extensions comme « u » n'ont rien à voir avec les Extended Language Subtags (alias extlangs), qui sont un mécanisme (pas le seul) pour représenter des idiomes intermédiaires entre une « vraie » langue et un dialecte.


Téléchargez le RFC 6067


L'article seul

RFC 6066: Transport Layer Security (TLS) Extensions: Extension Definitions

Date de publication du RFC : Janvier 2011
Auteur(s) du RFC : Donald Eastlake 3rd (Stellar Switches)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF tls
Première rédaction de cet article le 18 janvier 2011


Ce RFC décrit les extensions au protocole cryptographique TLS (résumées en section 1.1). Je n'en cite que certaines ici, lisez le RFC pour une liste complète. Ces extensions ne changent pas le protocole : un client ou un serveur TLS qui ne les comprend pas pourra toujours interagir avec ceux qui les comprennent. Le serveur doit en effet ignorer les informations contenues dans le Hello Client qu'il ne connait pas (section 7.4.1.2 du RFC 5246).

Le mécanisme général des extensions figure dans le RFC 5246, notamment la section 7 de ce dernier (voir la structure en 7.4.1.2). En gros, le principe est d'ajouter des données à la fin du paquet Hello, qui marque le début de la négociation TLS. Dans le langage de spécification propre à TLS, la liste des extensions possibles est un enum (indiqué en section 1.1) mais elle est désormais en ligne à l'IANA.

SNI (Server Name Indication, section 3) permet au client TLS d'indiquer au serveur le nom sous lequel il l'a trouvé. Cela autorise le serveur à présenter des certificats différents selon le nom sous lequel on y accède, fournissant ainsi une solution au problème récurrent de l'authentification avec TLS lorsqu'un serveur a plusieurs noms. À noter que SNI fonctionne avec les IDN, le RFC décrivant le mécanisme à suivre. Si le RFC 4366 permettait au client d'envoyer plusieurs noms, cette possibilité a été supprimée.

Maximum Fragment Length, section 4, permet au client d'indiquer qu'il souhaiterait des fragments de données de taille plus réduite. Cela peut être utile pour un client contraint en mémoire ou en capacité réseau, par exemple un téléphone portable. Certains de ces clients contraints apprécieront également Truncated HMAC (section 7) qui autorise à réduire la taille du MAC utilisé pour protéger l'intégrité des paquets.

Normalement, dans TLS, le certificat du client est envoyé pendant la session TLS. Mais l'extension Client Certificate URLs (section 5) permet au client d'indiquer un URL où le serveur ira chercher le certificat, allégeant ainsi le travail du client (là encore, c'est prévu pour les clients limités en puissance ou en capacité réseau). Une somme de contrôle en SHA-1 est ajoutée à la liste des URLs envoyés, pour permettre davantage de vérifications (autrement, le serveur risquerait, en cas d'empoisonnement DNS, par exemple, de récupérer un mauvais certificat). Dans le même esprit, la section 8 décrit (Certificate Status Request), une extension qui permet d'indiquer la volonté d'utiliser OSCP (RFC 6960), un protocole d'interrogation de la validité de certificats X.509 (plus léger que l'habituel téléchargement de la liste de certificats révoqués, suivi d'un traitement local).

Qui dit nouvelles extensions, dit nouvelles erreurs. La section 9 est donc consacrée aux nouveaux codes d'erreur, pour toutes les extensions décrites. La plus évidente étant unsupported_extension où le client TLS reçoit une extension qu'il n'avait pas demandé (mise dans son Hello). Certaines n'existaient pas dans le RFC 4366 comme certificate_unobtainable, utilisé si le mécanisme de Client Certificate URLs de la section 5 n'arrive pas à récupérer le certificat indiqué.

Tout le protocole TLS servant à la sécurité, il est normal de se demander si les extensions en question vont avoir un effet positif ou pas sur la sécurité. C'est ce que fait la section 11, qui examine les points forts ou faibles de la sécurité de chaque extension. SNI ne semble pas poser trop de problème, par contre Client Certificate URLs fait que le serveur TLS va jouer un rôle de client (en général, avec le protocole HTTP), ce qui soulève des questions : le client TLS ne va t-il pas utiliser cette extension pour pousser le serveur à attaquer un serveur HTTP, d'autant plus que le client TLS contrôle complètement l'URL ? Ou bien le client TLS coincé derrière un pare-feu ne va-t-il pas essayer de convaincre le serveur TLS de récupérer quelque chose de son côté du pare-feu ? Un serveur HTTP normalement non accessible depuis l'Internet pourrait ainsi être indirectement attaqué, si un serveur TLS gérant cette extension se trouve sur son réseau. Il est donc recommandé que cette extension ne soit pas activée par défaut et seul un jeu limité de plans d'URL soit accepté (ce dernier conseil me semble vain : le plan http: sera forcément sur la liste et c'est sans doute le plus intéressant pour un attaquant).

Quant à Truncated HMAC, elle peut aboutir à affaiblir la sécurité puisque le HMAC court est forcément moins fiable. Ce n'est pas forcément très grave car une attaque par force brute contre ce HMAC ne peut pas être faite hors-ligne mais doit être exécutée pendant la session TLS et qu'une seule erreur de la part de l'attaquant coupe la session.

L'annexe A résume les changements depuis la RFC 4366. Le principal est que la RFC 4366 spécifiait à la fois un mécanisme d'extension et des extensions spécifiques. Le mécanisme d'extension ayant été mis dans le RFC 5246 (section 7.4.1.2 à 7.4.1.4), notre RFC 6066 ne contient plus que les extensions.

D'autre part, l'extension SNI a été simplifié en éliminant la possibilité de noms en UTF-8. Désormais, IDN ou pas, le nom doit être représenté en ASCII. Et le condensat cryptographique sur les certificats reçus par l'extension Client Certificate URLs est désormais obligatoire.


Téléchargez le RFC 6066


L'article seul

RFC 6062: Traversal Using Relays around NAT (TURN) Extensions for TCP Allocations

Date de publication du RFC : Novembre 2010
Auteur(s) du RFC : S. Perreault (Viagenie), J. Rosenberg (jdrosen.net)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF behave
Première rédaction de cet article le 30 novembre 2010


Le protocole TURN, qui permet à deux machines coincées derrière des routeurs NAT de communiquer en utilisant un relais tiers, a été normalisé dans le RFC 5766 (remplacé depuis par le RFC 8656), dans une version minimale, uniquement pour IPv4 et seulement pour UDP, les services « incontestables », qui étaient pressés d'avoir une solution. Depuis, des extensions à TURN sont développées pour d'autres services. C'est ainsi que ce RFC 6062 permet d'utiliser TURN pour établir des liaisons avec TCP.

TURN, tel que normalisé dans le RFC 5766, pouvait déjà utiliser TCP entre le client et le relais (le serveur). Mais, en sortie du relais, vers l'autre pair, c'était forcément de l'UDP. Cela posait un problème (section 1 du RFC) lorsque l'autre pair ne pouvait pas faire d'UDP, ou bien lorsque les propriétés de TCP (notamment de fiabilité) étaient nécessaires. Supposons un logiciel d'audio-conférence : le son est typiquement transmis en UDP (car la rapidité est préférable à la fiabilité, pour ce service) mais si on veut ajouter un système permettant aux participants de se montrer des images, TCP est certainement préférable, afin de transférer le fichier représentant l'image. Avec le protocole TURN, cela se nomme une « allocation TCP » et ce sera désormais possible, aussi bien en demandant une session TCP entrant vers un pair, qu'en acceptant une session TCP sortant d'un pair.

La section 3 rappelle le fonctionnement de TURN : le client TURN ouvre une connexion avec le serveur TURN (qui servira de relais) pour le contrôle (messages TURN, pour ouvrir et fermer des connexions). De plus, pour chaque connexion avec un pair, le client TURN aura une connexion de données pour faire passer ses données (son et image, dans l'exemple précédent), avec divers protocoles (par exemple RTP). Pour chacune de ces connexions de données, il y aura également une connexion entre le relais (le serveur TURN) et le pair avec qui on communique.

Pour avoir une allocation TCP, le client TURN va envoyer, sur la connexion de contrôle, une requête Allocate avec un attribut REQUESTED-TRANSPORT indiquant TCP. Le serveur, s'il accepte la requête, écoutera alors en TCP. Chaque fois qu'il voudra envoyer des donnée à un pair, le client enverra une requête Connect au serveur TURN et celui-ci se connectera à son tour en TCP au pair. Enfin, le client devra ouvrir une nouvelle connexion TCP pour les données (voir section 4.3). Une fois cette dernière connexion établie, le relais « connectera » les deux connexions (client->relais et relais->pair) puis relaiera les données entre les deux pairs.

Dans le cas où le client accepte que ce soit le pair qui initie la session, il indique d'abord au serveur qu'il accepte les connections entrantes (requête CreatePermission), le serveur écoute en TCP et, établit la connexion avec le pair et, lorsque c'est fait, signale au client que le pair est arrivé. Le client peut alors faire une connexion TCP vers le serveur puis tout continue comme dans le cas précédent.

Les détails pratiques figurent dans la section 4 (obligations du client) et 5 (obligations du serveur). On notera que, pour relayer du TCP, la connexion entre le client et le serveur doit être en TCP (pour relayer de l'UDP, elle pouvait être en UDP ou TCP). Outre l'attribut REQUESTED-TRANSPORT déjà mentionné, qui doit avoir la valeur 6 (pour TCP), le client doit prendre soin de ne pas inclure des attributs spécifiques à UDP comme EVEN-PORT (qui force l'utilisation d'un port de numéro pair, et qui n'est utile que pour UDP, voir le RFC 5766, section 14.6). TURN utilisera un attribut CONNECTION-ID qui sera indiqué lors de l'acceptation d'une allocation TCP, et devra être donné par le client lors de sa connexion TCP ultérieure, pour permettre au relais de mettre les deux opérations en correspondance.

Le serveur, lui, doit accepter toutes les connexions TCP entrantes (section 5.3), du moment qu'une allocation a été faite (et, donc, un port réservé). Un essai avec telnet montrera donc toujours Connected to $HOSTNAME. C'est ensuite que le serveur TURN vérifie que le client avait donné la permission de se connecter. Sinon (ou si le client, bien qu'il ait donné la permission, ne se manifeste pas lorsqu'on lui signale que le pair est arrivé), la session, à peine acceptée, sera close d'autorité.

La section 6 décrit l'enregistrement à l'IANA des nouvelles méthodes (Connect, ConnectionBind et ConnectionAttempt), d'un nouvel attribut CONNECTION-ID et de nouveaux codes d'erreur 446 (déjà une connexion pour ce couple adresse/port) et 447 (échec de la connexion avec le pair) dans le registre des paramètres STUN (rappelez-vous que TURN est défini comme une extension de STUN).

Enfin, la section 7, sur la sécurité, met en garde contre un petit piège : entre l'acceptation d'une connexion et son branchement de l'autre côté, le relais risque de recevoir des données, qu'il doit tamponner (section 5.2). Le tampon risquant de devenir trop gros, la section 7 demande qu'une taille maximale lui soit fixée.

Une mise en œuvre se trouve dans le service de Viagénie mais ne semble pas activée à l'heure actuelle. Pour une implémentation libre, turnserver a cette option TCP depuis la version 0.4.

Merci à Simon Perreault pour sa relecture et ses remarques.


Téléchargez le RFC 6062


L'article seul

RFC 6059: Simple procedures for Detecting Network Attachment in IPv6

Date de publication du RFC : Novembre 2010
Auteur(s) du RFC : S. Krishnan (Ericsson), G. Daley (NetStar Networks)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dna
Première rédaction de cet article le 2 décembre 2010


Un engin mobile connecté à l'Internet change souvent de réseau. Il se déplace, s'attache à un autre réseau, perd le contact avec la borne WiFi, retrouve du 3G un peu plus loin et, chaque fois, il peut se retrouver sur un réseau différent, avec des paramètres différents mais aussi parfois sur un réseau déjà visité, auquel cas il peut peut-être réutiliser tout de suite des paramètres mémorisés. Il est donc nécessaire de pouvoir déterminer rapidement à quel réseau on est attaché, et si les paramètres précédents sont toujours valables. C'est le but de la méthode exposée dans ce RFC, équivalent IPv6 du RFC 4436.

Le but, comme exposé par la section 2.1, est donc de rendre la mobilité plus agréable, sans avoir à changer les routeurs, sans dégrader le service existant (par exemple, le temps de réponse ne doit jamais être pire qu'avec les méthodes actuelles), en acceptant des faux négatifs (un réseau déjà visité n'est pas reconnu) mais jamais les faux positifs (un réseau nouveau est pris à tort pour un réseau connu).

A-t-on besoin d'un nouveau protocole pour cela ? Après tout (section 2.2), il existe déjà la procédure standard de Neighbor Discovery du RFC 4861. Le nouveau Simple DNA ne sera pas une amélioration de ND dans tous les cas mais il aidera dans certains, notamment ceux où l'engin se déplace régulièrement parmi un ensemble de quelques réseaux. Si le réseau est complètement nouveau, Simple DNA n'apportera rien (mais n'aura pas d'inconvénients). De même, Simple DNA n'aidera pas pour le cas où le réseau est statiquement configuré, il ne marche qu'avec les adresses allouées par Router Advertisement (RFC 4862) ou DHCP (RFC 8415).

Simple DNA va fonctionner en interrogeant les routeurs connus pour voir s'ils sont toujours là. Une autre approche aurait été possible, en interrogeant les couches basses (section 2.3) pour voir si l'attachement au réseau n'avait pas changé (par exemple, même si le RFC ne le mentionne pas, en WiFi, on peut regarder le SSID et l'adresse MAC de la borne). Mais cette méthode aurait été moins générale.

Donc, comment fonctionne ce Simple DNA (section 2.4) ? Le fait d'être connecté à un réseau est signalé par les couches basses (Link Up en Ethernet ou WiFi). Reste à trouver à quel réseau on est connecté. Simple DNA utilise à la fois des paquets unicast Neighbor Solicitation (RFC 4861, section 7.2.2) et des paquets multicast Router Solicitation (RFC 4861, section 6.3.7) pour tester les routeurs dont il se souvient. Si aucun ne répond, Simple DNA passe aux procédures normales, Stateless address autoconfiguration ou bien DHCP. Le fait de se servir de Neighbor Solicitation permettra d'obtenir une réponse plus rapide (les routeurs ne répondent pas instantanément aux Router Solicitation).

Bien sûr, dans la réalité, tout ne se passe pas aussi bien. Simple DNA dépend de plusieurs choses, résumées par la section 2.5 : le fait que le couple {adresse MAC du routeur, adresse IP du routeur locale au lien} soit unique et le fait que les machines sont prévenues lorsque le lien physique devient fonctionnel (RFC 4957 et section 5.4 de notre RFC).

La section 4 note ensuite que la mise en œuvre complète de l'algorithme nécessite une nouvelle structure de données, la SDAT (Simple DNA Address Table). Elle va contenir la liste des routeurs déjà vus et est donc composée d'entrées indexées par le couple {adresse MAC du routeur, adresse IP du routeur locale au lien}. Elle contiendra les informations suivantes : l'information a-t-elle été obtenue par DHCP ou bien autoconfiguration sans état, adresse IP de la machine, durée de vie, préfixe utilisé, l'information a-t-elle été sécurisée par SEND, ainsi que des informations spécifiques à DHCP. Ainsi, si Simple DNA trouve qu'un réseau a déjà été visité, il a toutes les informations sous la main pour configurer immédiatement l'interface réseau.

La marche exacte à suivre de la part de la machine qui se trouve connectée est détaillée en section 5 (avec une représentation en pseudo-code en section 6). La section 5.5 décrit ainsi l'envoi des paquets de sondage (un Router Solicitation pour voir si un routeur répond, des Neighbor Solicitations pour tester les routeurs dont on se souvient, six au maximum à la fois, pour ne pas surcharger le réseau). C'est là qu'est précisé le fait que ces paquets de sondage devraient être envoyés en parallèle, pour diminuer le temps total de l'opération (et garantir ainsi que Simple DNA ne prendra jamais plus de temps qu'une méthode classique).

Le traitement des réponses est en section 5.7 : il est important que la machine vérifie que les adresses MAC correspondent bien à ce dont elle se souvient. Sinon, cela signifie que le réseau est en fait différent et qu'il faut abandonner Simple DNA pour revenir à la méthode habituelle. Naturellement, si on reçoit un Router Advertisement normal, il faut l'utiliser, quelles que soient les informations stockées dans la table SDAT.

Bien plus embêtant est le cas où les informations recueillies sont incohérentes (section 5.7.3). Par exemple, si le test d'un routeur avec le Neighbor Solicitation ne coïncide pas avec les Router Advertisement reçus. Dans ce cas, le RFC décide qu'il faut croire le Router Advertisement (sauf si SEND est utilisé). Si le conflit est entre des tests par Neighbor Solicitation et DHCP, il faut faire confiance à DHCP.

Autres recommandations, ne pas effectuer de tests de duplication d'adresses (RFC 4862, section 5.4) si on retourne à un réseau connu et ne pas insister éternellement si les Neighbor Solicitations ne ramènent pas de réponses du tout : ce cas veut sans doute dire simplement que le réseau ne marche pas.

Ah, et si on tient à faire de l'IPv4 ? La section 8 rappelle que IPv4 a aussi un système équivalent (RFC 4436) mais qui suit un algorithme très différent (IPv4 n'a pas de Router Advertisement, par exemple).

Enfin, comme avec toutes les techniques de configuration automatiques ou semi-automatiques, il y a un sérieux problème de sécurité (section 10). Les messages reçus peuvent être des faux. À part utiliser SEND (RFC 3971), il n'y a pas de solution miracle, et la seule recommandation de notre RFC est de veiller à ce que des informations non sécurisées par SEND ne remplacent pas des informations sécurisées. Autrement dit, si on avait visité un réseau qui avait un routeur SEND et, qu'en revenant sur un réseau qui semble le même, on reçoit des Router Advertisement non-SEND, il ne faut pas les utiliser. (J'ai d'ailleurs bien l'impression que, si on suit strictement les règles du RFC, on ne pourra jamais se connecter à un réseau qui avait SEND mais a choisi ensuite de l'abandonner, sauf à vider la SDAT à la main.)

Reléguée en annexe A, une dernière recommandation. Bien que le DNA de IPv4 puisse se combiner avec des adresses manuellement configurées, les problèmes que cela a soulevé (notamment pour les réseaux qui utilisaient à la fois des adresses manuelles et des automatiques) font que DNA IPv6 déconseille formellement son utilisation dans les cas où l'adresse a été fixée à la main par l'administrateur système.


Téléchargez le RFC 6059


L'article seul

RFC 6057: Comcast's Protocol-Agnostic Congestion Management System

Date de publication du RFC : Décembre 2010
Auteur(s) du RFC : C. Bastian (Comcast), T. Klieber (Comcast), J. Livingood (Comcast), J. Mills (Comcast), R. Woundy (Comcast)
Intérêt historique uniquement
Première rédaction de cet article le 8 décembre 2010


Pour tout FAI, la gestion de la congestion est un problème récurrent. Même avec de très gros tuyaux, les utilisateurs, avides de profiter de leur abonnement à l'Internet (et poussés par des évolutions comme le remplacement de cours sous forme texte par des conneries multimédia genre webinar), envoient de plus en plus de paquets. Beaucoup de FAI, lors de débats sur la neutralité du réseau défendent leur droit à « gérer la congestion » par tous les moyens, même les plus inavouables. C'est ainsi que l'un des plus gros FAI états-uniens, Comcast, s'est rendu célèbre en usurpant l'adresse IP de ses propres abonnés pour couper leurs sessions BitTorrent fin 2007. Ces méthodes de cow-boys ont suscité beaucoup de protestation et, dans ce RFC, Comcast annonce un changement de cap et l'adoption d'un nouveau système de gestion de la congestion, neutre (protocol agnostic car « neutre » est un gros mot pour les FAI) et fondé sur des mesures objectives (le nombre d'octets envoyés ou reçus). Ce système est mis en œuvre dans le réseau de Comcast depuis la fin de 2008.

Comcast, qui connecte des dizaines de millions de foyers états-uniens, notamment par le câble (des détails sur leur réseau figurent en section 7), s'est donc fait allumer par la FCC au sujet de ses curieuses pratiques de gestion du réseau, qui consistaient à générer, depuis un boîtier Sandvine, des faux paquets TCP de type RST (Reset) prétendant venir des pairs, de manière à couper les sessions pair-à-pair (voir le rapport très détaillé de l'EFF ou son résumé à Ars Technica). Ce mécanisme visait, de manière complètement arbitraire, un protocole réseau particulier, BitTorrent.

La section 1 du RFC resitue le problème de la congestion. TCP est un protocole gourmand : tant qu'il n'y a pas de perte (cf. RFC 7680) de paquets, il va augmenter le débit jusqu'à ce que le réseau ne puisse plus suivre et le signale en laissant tomber certains paquets (TCP réduira alors le débit). La congestion est donc un état normal du réseau (sinon, cela veut dire qu'il est sous-utilisé).

Le mécanisme déployé étant spécifique au réseau de Comcast, il est utile, pour suivre le RFC, de bien apprendre la section 3 sur la terminologie, notamment si on n'est pas habitué aux réseaux par câble TV coaxial. Ainsi, un modem câble est le CPE, l'engin placé chez le client, et un CMTS (Cable Modem Termination System, cf. section 2.6 du RFC 3083) est l'équipement situé dans les locaux du FAI où sont connectés les clients (à peu près l'équivalent d'un DSLAM pour les FAI ADSL). Le tout fonctionne grâce à la norme DOCSIS dont les documents sont disponibles en http://www.cablelabs.com/. D'autre part, la rubrique terminologique en section 3 référence également les RFC sur la qualité de service, les RFC 1633 et RFC 2475.

Le nouveau système de contrôle de la congestion a évolué, comme le résume la section 4, en partie en suivant les débats à l'IETF comme l'atelier de 2008, qui a été documenté dans le RFC 5594. La contribution de Comcast à cet atelier consistait en un document « Service Provider Perspective ». Le système décrit par Comcast à l'occasion de cet atelier (et qui avait été également présenté dans les réponses de Comcast à la FCC, qui était mécontente du système de piratage des sessions BitTorrent) a été progressivement déployé à partir de la fin de 2008.

En quoi consiste ce système de contrôle de la congestion ? La section 5 résume ses principes. Plusieurs éléments du réseau étant partagés, le but du système est de partager « équitablement » ces éléments (le terme « équitablement » est entre guillemets dans le RFC car il n'est pas évident d'en donner une définition rigoureuse). D'autre part, le système actuel est agnostique (le RFC aurait pu dire « neutre » mais la plupart des FAI ne veulent pas entendre parler du concept de neutralité), c'est-à-dire qu'il ne cible pas un protocole particulier, il tient juste compte d'un facteur objectif : le débit de la ligne de l'abonné. L'algorithme (simplifié) est donc le suivant : le logiciel surveille en permanence l'usage des ressources réseau. Si l'une de celles-ci devient congestionnée, le logiciel regarde quel client sur cette ressource consommait plus que les autres et lui affecte une priorité plus basse. Cela n'aura pas de conséquence pratique si les lignes ont de la capacité suffisante mais, si la congestion empêche de faire passer tous les paquets, ceux de ce(s) client(s) seront retardés, voire jetés (cela peut sembler violent mais c'est le mécanisme normal d'IP pour gérer la congestion ; les protocoles de transport savent réagir à ce problème, par exemple TCP réduit automatiquement son débit). Si le client diminue son usage, sa priorité redevient normale.

Ne serait-ce pas préférable, en cas de congestion, d'augmenter la capacité du réseau ? Certes, dit la section 6, mais le problème est plus compliqué que cela. D'abord, l'ajout de capacité nécessite souvent des travaux matériels, qui prennent du temps. Ensuite, quelle que soit la capacité du réseau, il y aura des pics de trafic imprévus et aucun réseau ne peut être assez dimensionné pour éviter complètement la congestion. (De même qu'aucun autoroute ne peut être assez large pour un samedi 1er août.) Pouvoir gérer la congestion est donc une nécessité.

Quelles sont les valeurs numériques exactes utilisées pour des opérations comme « abaisser la priorité » ? L'abaisser de combien ? Et que veut dire exactement « proche de la congestion » ? 90 % 95 % ? La section 7 du RFC traite de l'implémentation concrète des principes de la section 5. Elle commence par un excellent résumé de l'architecture du réseau de Comcast, où 3 200 CMTS servent environ 15 millions d'utilisateurs. Le réseau, comme illustré dans la figure 1 du RFC, est en fait mixte, les CMTS étant connectés en fibre optique, seul le dernier mile étant en câble de cuivre coaxial. La section 7.1 définit ensuite rigoureusement la métrique utilisée pour déclarer qu'un CMTS approche de la congestion. Ensuite, la valeur numérique a été déterminée par des essais en laboratoire : aujourd'hui 70 % d'utilisation en montée et 80 % en descente pendant 5 minutes de suite. La section 7.2 traite de la seconde partie de l'algorithme : définir ce que signifie, pour un utilisateur, « consommer plus que sa part ». (Les chiffres exacts dépendent de l'abonnement qu'il a souscrit : les riches ont plus que les pauvres.)

Ce RFC n'hésite pas devant les chiffres précis. Ainsi, un exemple donné est celui d'un abonné à un service à 22 Mb/s descendants. Malgré plusieurs usages simultanés (un flux vidéo HD depuis Hulu à 2,5 Mb/s, un appel Skype à 131 kb/s, et un flux musical à 128 kb/s), il reste en dessous de la limite. L'idée est donc que beaucoup d'utilisations, même multimédia, n'amèneront pas à la limite. Lors de tests avec de vrais utilisateurs, par exemple à Colorado Springs en 2008, 22 utilisateurs sur 6 016 ont été « déprioritisés ». Lors de tels tests, quel a été le ressenti des utilisateurs ? La section 7.3 note simplement que personne ne s'est plaint.

La section 9 argumente même que ce mécanisme, prévu pour gérer la minorité la plus gourmande des utilisateurs, est aussi utile en cas de congestion plus globale. Par exemple, si une brusque épidémie de grippe se développe, forçant l'arrêt des transports publics et amenant de nombreuses entreprises à fermer, le télétravail depuis la maison va brusquement augmenter. Le réseau tiendra-t-il ? En tout cas, le même mécanisme de gestion de la congestion peut être utile.

Rien n'étant parfait en ce bas monde, quelles sont les limites de ce système ? La section 10 en cite quelques unes. Entre autres, le mécanisme de Comcast ne signale pas à l'utilisateur qu'il a été déprioritisé. Cela empêche ses applications de s'adapter (par exemple en basculant vers une résolution vidéo plus faible) et l'utilisateur de changer son comportement.

D'autres mécanismes de contrôle de la congestion pourraient apparaître plus tard, par exemple issus des travaux de l'IETF, que la section 11 résume. Des groupes de travail comme Conex (signalisation explicite de la congestion), Alto (recherche du meilleur pair dans un réseau pair-à-pair) ou Ledbat (transfert de grosses quantités de données en arrière-plan, en se glissant dans les moments où le réseau est libre) produiront peut-être des solutions meilleures (voir le RFC 6817 pour Ledbat).

Enfin, la section 12, sur la sécurité, est une lecture intéressante : à chaque fois qu'on construit un tel appareillage, il faut se demander s'il ne risque pas d'être mal utilisé. Ici, la principale crainte est le risque d'injection de fausses données, pour bloquer les utilisateurs (une attaque par déni de service). Les équipements de statistiques doivent donc être protégés contre un accès non autorisé. Moins grand est le risque pour la vie privée : si le trafic par modem (donc par foyer) est stocké, cela n'inclut pas les adresses IP de destination, les ports, etc.

Arrivé au terme de ce très intéressant document, très détaillé (il faut noter qu'aucun FAI dans le monde n'a fait un tel effort de documentation, comparez par exemple avec le silence complet que maintient Free face aux accusations de shaping), quel bilan tirer ? D'abord, que les protestations des clients, de l'EFF et les menaces de la FCC ont eu un effet positif. Ensuite, je pense personnellement que le système est bon dans son principe. Face à la congestion, un problème auquel peut être confronté tout réseau, quelles que soient les dimensions de ses tuyaux, il est nécessaire de prendre des mesures. Celles-ci doivent être publiquement exposées (et, on l'a dit, Comcast est le seul à le faire) et être non-discriminatoires, fondées sur des problèmes objectifs (le débit dans les tuyaux) et pas sur les intérêts financiers du FAI (comme les opérateurs 3G qui interdisent la VoIP mais qui autorisent la vidéo ; cette dernière consomme pourtant bien plus de ressources mais, elle, elle n'empiète pas sur le business traditionnel de l'opérateur...). Donc, le principe du système de gestion de la congestion de Comcast est bon. Maitenant, tout est dans l'exécution en pratique. Le système effectivement déployé est-il celui décrit ? Les évolutions futures respecteront-elles les principes posés ? Poser la question n'est pas de la paranoïa. Comcast a déjà menti, par exemple en niant la création de faux TCP resets même si la section 8 du RFC reconnait aujourd'hui leur usage (cf. RFC 3360). Le lecteur des aventures de Thursday Next pensera certainement au tome 4, « Something rotten », où la tentaculaire société Goliath tente de faire croire qu'elle est devenue une église n'agissant plus que pour le bien commun...

Ce RFC a été reclassé « intérêt historique seulement » en août 2020, Comcast n'utilisant plus ce système.


Téléchargez le RFC 6057


L'article seul

RFC 6056: Transport Protocol Port Randomization Recommendations

Date de publication du RFC : Janvier 2011
Auteur(s) du RFC : M. Larsen (TietoEnator), F. Gont (UTN/FRH)
Réalisé dans le cadre du groupe de travail IETF tsvwg
Première rédaction de cet article le 18 janvier 2011


Lorsqu'un méchant attaquant tente de s'infiltrer dans une conversation en TCP, par exemple pour la couper ou la ralentir, il doit, soit être sur le trajet des paquets et pouvoir les regarder soit, dans le cas le plus fréquent, celui d'une attaque en aveugle, deviner un certain nombre d'informations qui « authentifient » la connexion TCP. Parmi celles-ci, le port source est trop souvent trop facile à deviner. Notre RFC expose pourquoi et surtout comment rendre ce port source plus dur à trouver.

De manière plus rigoureuse : lors d'une attaque en aveugle (où le méchant n'est pas en position de sniffer les paquets de la connexion TCP), les paquets mensongers injectés par le méchant ne seront acceptés par la machine victime que si le penta-tuple {Adresse IP source, Adresse IP destination, Protocole, Port Source, Post Destination} est correct (cf. RFC 5961 et RFC 5927). Pour la sécurité de TCP face à ces attaques en aveugle, il vaut donc mieux que ce tuple soit caché. Mais une partie est triviale à deviner (par exemple, pour une connexion BGP, le port de destination sera forcément 179 dans un sens et, dans l'autre, ce sera le port source). Il faut donc faire porter l'effort sur les autres parties, en essayant de les rendre le moins prévisibles possible. Une telle protection fonctionnera aussi bien avec les attaques par TCP lui-même que en passant par ICMP.

Bien sûr, cela ne remplace pas une bonne protection cryptographique des familles mais le moins qu'on puisse dire est qu'IPsec est laborieux à déployer et le but de notre RFC est de fournir une solution aujourd'hui. Il est à noter que les mécanismes de ce RFC peuvent être déployés unilatéralement et ne changent pas les protocole de transport (il n'est d'ailleurs pas spécifique à TCP ; ainsi, le DNS, protocole qui tourne surtout sur UDP, a dû déployer des techniques analogues, notamment en réponse à la faille Kaminsky ; voir le RFC 5452).

La section 1 du RFC résume ce problème (voir aussi les RFC 4953, RFC 5927 et RFC 5961). Dans un protocole client-serveur, le protocole est souvent déterminé par l'application (BGP ne peut tourner que sur TCP), le port de destination est souvent fixe (80 pour HTTP), les adresses IP des serveurs en général connues. L'adresse IP du client n'est pas en général secrète (pour BGP, les adresses IP de tous les participants à un point d'échange sont un secret de Polichinelle). Il ne reste donc que le port source pour empêcher l'attaquant de fabriquer des faux paquets qui seraient acceptés. Certes, stocké sur 16 bits, il ne peut stocker, dans le meilleur des cas, que 65 536 valeurs différentes mais c'est mieux que rien. L'idée n'est pas de fournir une protection absolue mais simplement de rendre la tâche plus pénible pour l'attaquant.

Et, justement, il existe des moyens de faire varier ce port source de manière à rendre difficile sa prédiction par l'attaquant. Cela ne vaut pas des techniques comme l'authentification TCP du RFC 5925 mais c'est déjà un progrès pour la sécurité. En dépit du titre du RFC, il ne s'agit pas de rendre le port source réellement mathématiquement aléatoire mais simplement plus dur à deviner.

Place maintenant à l'exposé des méthodes. Juste un peu de vocabulaire : une « instance » est une communication identifiée par un penta-tuple (c'est équivalent à une connexion pour les protocoles de transport à connexions comme TCP). L'« ID » d'une instance est simplement le penta-tuple {Adresse IP source, Adresse IP destination, Protocole, Port Source, Post Destination}.

Il y a port et port. La section 2 explique le concept de « port temporaire ». Pour chaque protocole (TCP, UDP ou autre), les 65 536 valeurs possibles pour les ports se répartissent en « ports bien connus » (jusqu'à 1023 inclus), « ports enregistrés » (jusqu'à 49151 inclus) et « ports dynamiques et/ou privés » (le reste). Normalement, une application de type client/serveur se connecte à un « port bien connu » (parfois à un « port enregistré ») et utilise comme port source un port temporaire pris parmi les ports dynamiques. Pour que l'ID d'instance soit unique (sinon, il ne jouerait pas son rôle), une mise en œuvre simple est d'avoir une variable par protocole, mettons next_ephemeral, qui indique le prochain port libre et est incrémentée à chaque connexion. L'algorithme est en fait un peu plus compliqué que cela (section 2.2) car il faut tenir compte des ports déjà en service, et de ceux que l'administrateur système a manuellement interdit (par exemple, dans le serveur DNS Unbound, la plage de ports à utiliser se configure avec outgoing-port-permit et outgoing-port-avoid, dans son concurrent BIND, avec use-v6-udp-ports et avoid-v6-udp-ports ; autre exemple, dans FreeBSD, la fonction in_pcblookup_local() vérifie les ports utilisés).

Mais le principal problème de cet algorithme simple est que le port source choisi pour la communication est facile à deviner. Si l'attaquant gère un serveur auquel le client se connecte, il lui suffit de regarder le port utilisé, d'ajouter un, et il saura le port utilisé pour la connexion suivante. Il pourra alors monter facilement les attaques décrites dans les RFC 4953 et RFC 5927.

Avant de trouver une solution à ce problème de prédictibilité, il faut se pencher sur le problème des collisions entre ID d'instances. Même si le client fait attention à utiliser un penta-tuple qui n'est pas en service de son côté, il peut parfaitement choisir un port source qui correspondra à un penta-tuple encore en activité de l'autre côté. En effet, l'autre côté doit garder la connexion (et donc le penta-tuple) en mémoire jusqu'à être sûr que plus aucun paquet IP n'est encore en route et, si le client est très actif (ouvre de nouvelles connexions souvent), le risque de tomber sur un penta-tuple encore en activité est élevé. Cela peut alors entraîner les problèmes décrits dans le RFC 1337. Choisir le prochain port de manière incrémentale, comme dans l'algorithme exposé plus haut, minimise le risque, puisqu'on ne réutilisera un port qu'après que toute la plage possible ait été épuisée.

Comment faire alors ? Faut-il choisir entre la sécurité qu'apportent une sélection non-linéaire du port source à utiliser et le sécurité par rapport aux collisions d'ID d'instances ? La section 3 expose plusieurs méthodes pour rendre le prochain port source plus difficile à prédire pour un attaquant. D'abord, qu'attend t-on d'un algorithme d'embrouillage du choix du port ? On voudrait à la fois qu'il rende la prédiction difficile pour l'attaquant, qu'il minimise le risque de collision d'ID, et qu'il ne marche pas sur les pieds des applications qui sont configurées pour un port précis (par exemple un serveur SSH qui écouterait sur le port 4222). Un algorithme qui assurerait la première fonction (rendre la prédiction difficile) pourrait, par exemple, être de tirer au hasard le prochain port utilisé. Mais les deux autres fonctions en souffriraient... N'imposons donc pas un vrai tirage aléatoire et voyons les compromis raisonnables. Le premier algorithme présenté, celui qui incrémente le numéro de port de un, a les problèmes inverses (il minimise la réutilisation mais maximise la prédictibilité).

On l'a vu, la plage des ports temporaires allait traditionnellement de 49152 à 65535. Mais elle est trop étroite pour assurer une vraie inprédictibilité du port source et la section 3.2 demande donc que, par défaut, la plage utilisée par les algorithmes de choix aille de 1024 à 65535. Comme cette plage inclus des ports réservés à l'IANA, l'algorithme de choix doit donc faire attention à ne pas sélectionner des ports qui sont utilisés sur la machine locale (ou qui pourraient l'être).

Place maintenant aux algorithmes effectifs. La section 3.3 décrit successivement les différents algorithmes possibles, avec du pseudo-code proche du C pour leur implémentation. L'algorithme 1, en section 3.3.1, est celui de simple tirage au hasard de la variable next_ephemeral à chaque utilisation. Si le port sélectionné n'est pas utilisable (par exemple parce qu'un serveur écoute déjà sur ce port), on essaie le suivant, puis le suivant etc. Attention, si on veut qu'il soit efficace, il faut que le générateur aléatoire le soit réellement (cf. RFC 4086). La traditionnelle fonction random(), dans la plupart des cas, ne l'est pas. Comme cet algorithme 1 n'a pas de mémoire, il peut sélectionner un port qui avait été utilisé récemment, augmentant ainsi les risques de collision des ID d'instances. En outre, il a une autre faiblesse : s'il existe une longue plage de ports déjà utilisés, et que le tirage au hasard fait tomber dans cette plage, le port situé immédiatement après la plage sera très souvent sélectionné, ce qui augmente la prévisibilité.

L'algorithme 2, en section 3.3.2, améliore l'algorithme 1 en tirant au hasard, non seulement le port initial, mais aussi l'incrément à utiliser si le port initial n'est pas libre. Il est donc le moins prévisible mais, en cas d'extrême malchance, il peut échouer à trouver un numéro de port, même s'il y en a un de libre.

L'algorithme 3 (section 3.3.3, inspiré du mécanisme décrit par Bellovin dans le RFC 6528) renonce à utiliser un générateur aléatoire et repose au contraire sur un condensat des paramètres de l'instance (adresses IP, etc). Prenons une fonction F qui reçoit les deux adresses IP, le numéro de port de l'autre partie et une clé secrète et les condensent en un nombre qui sera l'incrément appliqué à la variable next_ephemeral. En dépendant des paramètres de l'instance, on minimise la réutilisation des ID d'instances. On peut d'ailleurs ajouter d'autres paramètres comme, sur un système multi-utilisateurs, le nom de l'utilisateur. Cette fonction F doit évidemment être une fonction de hachage cryptographique comme MD5 (RFC 1321). Certes, MD5 a aujourd'hui des faiblesses cryptographiques connues mais il ne s'agit que de rendre le prochain port imprévisible, tâche pour laquelle il suffit. La clé secrète, elle, est ici pour empêcher un attaquant qui connaitrait la fonction de hachage utilisée de faire tourner le même algorithme et de prédire ainsi les numéros de port. Elle est typiquement choisie aléatoirement au démarrage de la machine.

L'algorithme 3 peut être perfectionné en ajoutant un second condensat, qui servira à indexer une table des variables next_ephemeral (au lieu d'avoir une variable unique). C'est l'algorithme 4, présenté en section 3.3.4.

Enfin, le dernier algorithme, le numéro 5 (section 3.3.5) choisit l'incrément de next_ephemeral au hasard mais l'applique ensuite de manière déterministe, ce qui limite les risques de collision d'ID puisque le numéro de port utilisé augmente à chaque fois (et repart une fois arrivé au bout). Notez le rôle du paramètre N (dont le RFC dit qu'il devrait être configurable) pour déterminer si on utilise de petits incréments (plus prévisibles mais diminuant les risques de collision) ou des grands (avec les avantages et les inconvénients renversés).

Certains de ces algorithmes dépendent d'une clé secrète, choisie au hasard. Comment choisir celle-ci ? La section 3.4 qu'elle doit être assez longue (128 bits sont recommandés). Elle suggère aussi de changer cette clé de temps en temps. Mais attention : juste après le changement, le risque de collision va augmenter.

On l'a vu, il existe plusieurs algorithmes acceptables pour atteindre notre objectif de sélection de numéros de port peu prévisibles. Lequel choisir ? La section 3.5 est une évaluation comparée desdits algorithmes, basée sur le très bon article de Mark Allman, « Comments On Selecting Ephemeral Ports », publié dans ACM Computer Communication Review, 39(2), 2009. Tous ces algorithmes évitent les collisions de manière satisfaisante (moins de 0,3 % des cas mais le chiffre exact dépend de beaucoup de choses, comme le rythme d'ouverture et de fermeture des nouvelles connexions). L'étude empirique d'Allman montre que les algorithmes 1 et 2, les seuls réellement aléatoires sont aussi, comme attendu, ceux qui montrent le plus de collisions d'ID d'instances. Les algorithmes 3 et surtout le 4 sont ceux qui imposent la plus grande consommation de ressources machines (calcul du condensat cryptographique et, pour le 4, consommation de mémoire pour la table). À noter enfin que, dans certains systèmes d'exploitation et certaines applications (celles qui appellent bind() sans indiquer de numéro de port), les algorithmes 3 et 4 ne sont pas utilisables car l'adresse IP et le port distant ne sont pas connus au moment où on sélectionne le port local et la fonction de hachage ne dispose donc pas d'assez d'arguments. Le système d'exploitation doit alors se rabattre sur un algorithme comme le 2 ou bien effectuer un bind() paresseux en retardant l'allocation effective du port local jusqu'au moment où la connexion est réellement faite (avec, par exemple, connect()). C'est par exemple ce que fait Linux. (Pour l'anecdote, ce point avait été ma contribution à ce RFC, en 2008, au début du processus d'écriture.)

De nos jours, un grand nombre de machines sont coincées derrière un routeur NAT ou plus exactement NAPT (Network Address and Port Translation, RFC 2663) qui utilise les numéros de ports pour démultiplexer le trafic entre les différentes machines du réseau local. Comme l'explique la section 4, les techniques d'obscurcissement du prochain numéro de port peuvent être alors prises en défaut si le routeur NAPT change ces ports par d'autres, choisis de manière trop prévisible. Le RFC impose donc que le routeur NAT, soit conserve les numéros de port (RFC 4787 et RFC 5382), soit choisisse lui-même les ports selon un mécanisme non prévisible.

Une fois les algorithmes exposés, compris et analysés, la section 5 reprend à nouveau de la hauteur pour parler d'une approche générale de la sécurité. D'abord, elle rappelle qu'un attaquant qui n'est pas aveugle, qui peut sniffer le réseau où passent les paquets, se moque des algorithmes exposés ici puisqu'il peut lire directement le numéro de port dans les paquets. Dans ce cas, il n'y a pas d'autre solution que des protections cryptographiques comme celles du RFC 4301.

Plus rigolo, certains choix pour la liste des ports exclus peuvent poser de sérieux problèmes de sécurité. Ainsi, si un système d'exploitation prend comme liste de ports à éviter la totalité de la liste IANA, il ne doit pas utiliser l'algorithme 1 car les ports qui se trouvent immédiatement après la liste réservée seront sur-représentés.

Comment est-ce mis en œuvre en pratique ? L'annexe A du RFC précise les choix effectués par les principaux systèmes d'exploitation libres (pour les autres, on ne sait pas s'ils sont sûrs puisqu'on ne peut pas examiner le source). Ainsi, Linux utilise l'algorithme 3, avec MD4 comme fonction de hachage (même si le RFC dit que c'est MD5). Sur un Linux 2.6 de septembre 2010, le code se trouve (de haut en bas, dans l'ordre des appels successifs), en indiquant fichier-source:fonction :

  • net/ipv4/inet_hastables.c:inet_hash_connect (qui utilise net/ipv4/inet_connection_sock.c:inet_get_local_port_range pour récupèrer auprès de sysctl les ports utilisables),
  • net/ipv4/inet_hastables.c:inet_sk_port_offset,
  • drivers/char/random.c:secure_ipv4_port_ephemeral qui fait le hachage des paramètres indiqués par l'algorithme 3 (adresses et ports).

FreeBSD, OpenBSD et OpenSolaris utilisent l'algorithme 1. La séquence des appels est (dans le HEAD du CVS de FreeBSD en octobre 2010) :

Merci à Benoit Boissinot pour son aide dans la navigation dans le source de FreeBSD.

Une petite anecdote historique pour terminer : la prédiction correcte des numéros de série des tanks allemands pendant la Seconde Guerre mondiale a permis aux Alliés de calculer le nombre de tanks ennemis. Comme quoi, toute information trop régulière et prévisible peut être exploitée par l'ennemi.


Téléchargez le RFC 6056


L'article seul

RFC 6055: IAB Thoughts on Encodings for Internationalized Domain Names

Date de publication du RFC : Février 2011
Auteur(s) du RFC : D. Thaler (Microsoft), J. Klensin, S. Cheshire (Apple)
Pour information
Première rédaction de cet article le 22 février 2011


Ce RFC de l'IAB fait le point sur un petit problème lié aux IDN, problème qui, semble t-il, n'avait jamais été traité en détail avant. La norme actuelle (RFC 5890 et suivants) est connue sous le nom d'IDNA pour IDN in Applications car elle ne change rien au protocole et que tout le travail doit être fait dans l'application. Toutefois, «application » est un terme un peu vague. Par exemple, un programme écrit en C doit-il convertir le U-label (forme Unicode du nom) en A-label (forme ASCII) avant l'appel à la fonction de bibliothèque getaddrinfo() ? Ou bien est-ce que getaddrinfo() doit le faire seul ? (Pour les impatients, la réponse, qui arrive au terme d'un long RFC, est que l'application ne doit pas convertir en Punycode avant d'être certaine que la résolution de noms se fera avec le DNS, dans l'espace public.)

Les deux méthodes mènent en effet à des résultats différents dès qu'un autre protocole que le DNS est utilisé pour la résolution de nom. En effet, contrairement à ce qu'on lit parfois, l'appel de getaddrinfo() n'est pas un appel au DNS mais aux mécanismes de résolution de nom locaux. Par exemple, sur un système d'exploitation qui utilise la GNU libc comme Debian, le mécanisme se nomme NSS (pour Name Service Switch) et le fichier /etc/nsswitch.conf permet de le configurer. Si ce fichier contient une ligne comme :

hosts:      files ldap dns

alors, un appel à getaddrinfo() par une application qui veut récupérer l'adresse IP correspondant à un nom de domaine ne produira pas forcément une requête DNS, le nom sera peut-être trouvé dans /etc/hosts ou dans LDAP d'abord. Dans ce cas, traduire le nom en ACE (ASCII compatible encoding, c'est-à-dire traduire palais-congrès.fr en xn--palais-congrs-7gb.fr, selon le RFC 3492) serait une erreur car LDAP, par exemple, est nativement Unicode depuis le début et n'a nul besoin de l'ACE.

La section 1 du RFC rappelle la terminologie, les textes de référence (comme le RFC 2130) et les concepts, notamment la notion d'encodage. Elle rappelle aussi que des opérations aussi simples que l'égalité sont plus complexes en Unicode qu'en ASCII. Cette même section revient sur la question des API, résumée plus haut. La lecture du RFC 3490 pourrait faire croire à l'implémenteur d'IDN que la situation est simple (figure 1 du RFC) avec l'application parlant au stub resolver DNS qui parle à l'Internet. La réalité est en fait plus riche comme le montre la figure 2, avec un niveau d'indirection supplémentaire entre le sous-programme appelé par l'application (par exemple getaddrinfo(), normalisé dans le RFC 3493) et les techniques de résolution utilisées, le DNS mais aussi LLMNR (RFC 4795), Netbios (RFC 1001), /etc/hosts (RFC 952), etc.

Tiens, justement, ces API, elles prennent des noms de domaine sous quelle forme ? UTF-8 ? Punycode ? Autre ? La section 1.1 se penche sur ce problème. La description de getaddrinfo() dit juste que le nom (le paramètre nodename) est un char *, une chaîne de caractères, sans indiquer d'encodage. Les règles des chaînes de caractères en C font que l'octet nul ne peut pas en faire partie, ce qui élimine des encodages comme UTF-16 et UTF-32. En pratique, le nom passé peut être de l'ASCII (c'est le cas s'il a été traité par Punycode), de l'ISO 8859, du ISO-2022-JP (très répandu au Japon) ou de l'UTF-8. On peut noter qu'il est possible de distinguer algorithmiquement certains de ces différentes encodages avec des règles comme « Si le nom comporte un ESC, U+001B, alors, c'est de l'ISO-2022-JP, sinon si n'importe quel octet a un bit de poids fort à un, c'est de l'UTF-8, sinon, si le nom commence par xn--, c'est du Punycode, sinon enfin c'est de l'ASCII traditionnel. » Ces règles ne sont pas parfaites (celle-ci ne tient pas compte des ISO 8859, d'autre part un nom ASCII traditionnel peut théoriquement commencer par xn-- sans être un A-label) et on peut préférer des règles plus sophistiquées comme celle exposée dans « The Properties and Promizes of UTF-8 ». Quant à ISO 8859, c'est le plus ennuyeux, car il n'y a aucun moyen fiable de reconnaître un membre du jeu ISO 8859 d'un autre. Dans un texte long, des heuristiques sont possibles mais les noms de domaines sont trop courts pour fournir assez d'information pour distinguer, par exemple, ISO 8859-1 de ISO 8859-15.

Enfin, il n'y a pas que le getaddrinfo() du RFC 3493, il y a d'autres sous-programmes comme, sur Windows, GetAddrInfoW qui accepte de l'UTF-16.

Tout cela, c'était pour expliquer que des sous-programmes de résolution de noms comme getaddrinfo() ne reçoivent pas toujours assez d'information pour savoir ce qu'ils doivent faire. L'autre moitié du problème est décrit dans la section 2 : il y a d'autres protocoles de résolution que le DNS. Par exemple, la technologie privée d'Apple, Bonjour, a des noms entièrement en UTF-8 (ce qui est conforme aux recommandations du RFC 2277). Une application qui traduirait les noms Unicode en ACE empêcherait donc Bonjour de trouver la machine portant ce nom. Même chose avec les autres protocoles comme le fichier hosts (RFC 952. Ainsi, si je mets dans mon /etc/hosts sur Unix :

64.170.98.32 café-crème

je peux l'utiliser sans problème :

% ping -c 1 café-crème 
PING café-crème (64.170.98.32) 56(84) bytes of data.
64 bytes from café-crème (64.170.98.32): icmp_req=1 ttl=70 time=155 ms

--- café-crème ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 155.568/155.568/155.568/0.000 ms

Traduire trop tôt est donc une méthode déconseillée : la traduction en ACE devrait se faire bien plus tard, lorsqu'on connait le protocole de résolution employé. Et cela ne peut pas se faire dans l'application à proprement parler, puisqu'elle ne connait jamais ce protocole.

D'ailleurs, puisque des protocoles comme LDAP utilisent Unicode de bout en bout, pourquoi le DNS n'en fait-il pas autant ? La section 3 décrit ce problème (voir aussi mon article « Pourquoi avoir développé IDNA au lieu d'utiliser directement l'Unicode dans le DNS ? »). Elle rappelle que, contrairement à ce que disent souvent les ignorants, le DNS est parfaitement capable, depuis le début, de faire passer autre chose que l'ASCII, a fortiori autre chose que le sous-ensemble LDH (Letters, Digits and Hyphen) de l'ASCII. Cette erreur est tellement répandue qu'il a fallu, en 1997, consacrer une part du RFC 2181 (section 11) à tordre le coup à cette idée. Le DNS peut donc gérer des octets où le huitième bit est à un et donc, par exemple, des noms en UTF-8 (il n'est donc pas en contradiction avec le RFC 2277 qui pose comme principe que UTF-8 est l'encodage Unicode de l'Internet). Il y a des raisons techniques pour ne pas utiliser UTF-16 ou UTF-32 (présence d'octets nuls qui pertuberaient les bibliothèques écrites en C pour lesquelles c'est une marque de fin de chaîne) mais UTF-8 ne pose pas de problème. En prime, UTF-8 est un sur-ensemble d'ASCII, toute chaîne ASCII est forcément une chaîne UTF-8, ce qui fait qu'une application peut tout traiter comme de l'UTF-8, même les noms existants.

Donc, le DNS ne pose pas de restrictions ASCII ou LDH. Par contre, les applications peuvent, elles, en imposer. Ainsi, pour le Web, l'ancienne norme des URI, le RFC 2396 (remplacé depuis par le RFC 3986), limitait (dans sa section 3.2.2) le nom de machine présent dans l'URL au jeu LDH (lettres, chiffres et tiret). C'est en raison de cette limitation (présente dans d'autres protocoles) que beaucoup de registres n'autorisent que ces noms à l'enregistrement.

Si le DNS n'est pas limité à l'ASCII, pourquoi ne pas faire des IDN uniquement en mettant carrément de l'UTF-8 dans les noms ? Certes, la représentation des chaînes de caractères dans le DNS ne permet pas d'indiquer l'encodage utilisé mais, après tout, le RFC 2277 dit clairement que, sur l'Internet, en l'absence de mention contraire, tout est en UTF-8. Cette méthode a effectivement été utilisée dans certaines zones, notamment privées (non visibles depuis l'Internet public). Elle marche : l'application passe de l'UTF-8 au résolveur qui la transmet aveuglément au DNS, qui sait répondre à ces requêtes. Le principal problème de cette méthode (et qui est à peine esquissé dans notre RFC 6055) est la canonicalisation. Le fait que les requêtes DNS soient insensibles à la casse ne marche pas pour l'Unicode, où les règles sont bien plus complexes (pensons au ß allemand dont la majuscule comprend deux lettres, SS, voir le RFC 5198 pour un point de vue plus large). C'est cette absence d'une canonicalisation satisfaisante (qui affecte également les autres protocoles comme LDAP), bien plus qu'une soi-disant incapacité du DNS à gérer l'Unicode, qui explique pourquoi l'actuelle norme IDN n'utilise pas UTF-8.

Parmi les autres surprises que nous réserve la résolution de noms, la section 3 note aussi que le nom actuellement résolu n'est pas forcément celui tapé par l'utilisateur. Il est en effet fréquent que le nom tapé soit complété par des noms de domaines locaux. Par exemple, sur Unix, le fichier /etc/resolv.conf contient souvent une directive search qui indique les noms « suffixes » à essayer (voir la section 6 du RFC 1536, le RFC 3397 et la section 4 du RFC 3646 pour d'autres exemples). Si ce fichier contient search foo.example bar.example et qu'un utilisateur tape le nom de machine toto, le résolveur essaiera successivement toto.foo.example et toto.bar.example. Si foo.example et bar.example utilisaient des règles différentes (par exemple que l'un de ces domaines autorise de l'UTF-8 brut et pas l'autre), la pauvre application qui reçoit le nom toto n'aurait pas de moyen de prévoir ce qui va se passer. (Ici, toto est en ASCII. Mais si on le remplace par café ?)

La section 3.1 donne une longue liste d'exemples détaillés des comportements actuels des applications. On y voit entre autres ce qui peut se passer lorsque l'application est « trop maligne » et tente de traduire trop tôt les noms. Par exemple, l'application reçoit le nom crème, le traduit en Punycode (xn--crme-6oa) mais resolv.conf contient un nom en UTF-8, mettons café.example et le résolveur (qui ne fait pas de conversion en Unicode) va alors chercher la chaîne incohérente xn--crme-6oa.café.example !

Après toutes ses considérations, très détaillées, est-il encore possible de donner une recommandation ? Oui, et elle tient en un paragraphe dans la section 4 : « Une application qui va appeler un sous-programme de résolution de noms ne doit pas convertir le nom en Punycode si elle n'est pas absolument certaine que la résolution se fera uniquement avec le DNS public. ». En d'autres termes, l'application plus haut qui appelerait aveuglément, par exemple, le sous-programme idna_to_ascii_8z() (qui, avec la GNU libidn, convertit du jeu de caractères local vers Punycode) avant de faire un getaddrinfo() a tort.

La section 4 de notre RFC laisse une possibilité à l'application d'essayer plusieurs méthodes, comme de tenter getaddrinfo() sur le nom brut, puis sur le nom punycodé. Mais ce n'est pas obligatoire. Même recommandation pour les traductions d'adresses IP en nom : une application « intelligente » peut se préparer à recevoir de l'UTF-8 ou du Punycode et réagir proprement dans les deux cas.

Dans tous les cas, une autre recommandation importante du RFC est que les API de résolution de noms spécifient clairement l'encodage qu'elles attendent. Sur Windows, GetAddrInfoW() spécifie bien qu'il prend de l'UTF-16 alors que la norme de getaddrinfo() (le RFC 3493) n'en parle pas, faisant que la mise en œuvre de getaddrinfo sur Windows utilise la page de code Windows alors que celle de MacOS utilise UTF-8.

On peut noter que la norme IDN a été révisée récemment mais, pour les questions discutées dans ce RFC, cela n'a pas de conséquence.

Aujourd'hui, l'erreur qui consiste à traduire en ACE sans faire attention semble assez fréquente. C'est le cas par exemple d'echoping avec sa bogue #3125516.

Merci à Pascal Courtois pour sa découverte d'une bogue gênante dans ce texte (pas dans le RFC).


Téléchargez le RFC 6055


L'article seul

RFC 6053: Implementation Report for ForCES

Date de publication du RFC : Novembre 2010
Auteur(s) du RFC : E. Haleplidis (University of Patras), K. Ogawa (NTT Corporation), W. Wang (Zhejiang Gongshang University), 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 8 novembre 2010


C'est bien joli de spécifier des protocoles réseau, encore faut-il qu'ils soient implémentés. Une des raisons pour lesquels les protocoles de la famille TCP/IP ont battu à plate couture les protocoles ISO, pourtant soutenus par divers moyens bureaucratiques, est l'accent mis sur la disponibilité de programmes mettant en œuvre les spécifications, les RFC. Ces programmes permettent de vérifier que la norme est implémentable (contrairement à beaucoup de normes qui sont restés sur le papier car irréalistes) et que les différentes implémentations interopèrent. Ce RFC 6053 est le rapport décrivant trois mises en œuvre du protocole ForCES (Forwarding and Control Element Separation, un protocole de communication à l'intérieur d'un routeur, entre ses divers éléments). Il suit donc les règles et principes du RFC sur les rapports d'implémentation, le RFC 5657.

Un petit rappel d'abord. ForCES (Forwarding and Control Element Separation), normalisé dans le RFC 5810, définit un modèle (RFC 3746) où le routeur est composé de CE (Control Element) qui pilotent des FE (Forwarding Element). Les CE parlent les protocoles de routage comme OSPF, les FE font la transmission des paquets. Entre CE et FE, les messages ForCES peuvent être transmis par plusieurs protocoles, le plus utilisé (car le seul qui soit obligatoire) étant SCTP-TML (SCTP-based Transport Mapping Layer) normalisé dans le RFC 5811 et fondé sur SCTP. (Voir la section 2 pour des rappels plus complets.)

Place aux tests, maintenant. Trois mises en œuvre indépendantes ont été testées (section 3) : celle de NTT, celle de l'université de Patras, et celle de l'université de Zhejiang Gongshang (aucune des trois n'est distribuée publiquement pour l'instant). Les tests ont été globalement couronnés de succès, la plupart des bogues ont été corrigées immédiatement, les manques ayant été identifiés et les programmeurs ayant promis qu'ils les combleraient bientôt. Le test d'interopérabilité a été fait en juillet 2009. Les chinois n'étaient pas présents physiquement sur le lieu du test, ce qui a été l'occasion de tester ForCES sur une longue distance, et à travers le NAT. Outre les trois implémentations citées, le test mettait en jeu des modifications locales de deux analyseurs réseaux répandus, Wireshark et tcpdump. (Le travail sur Wireshark a été publié dans « Method and implementation of building ForCES protocol dissector based on wireshark » par Feng Luo, Ligang Dong et Fenggen Jia, à la conférence Information Management and Engineering (ICIME), 2010. Le patch se trouve dans la bogue #3534. Quant à tcpdump, la gestion de ForCES a été intégrée à partir de la 4.1.1. Vous pouvez voir des exemples en ligne.)

Comment se fait un tel test d'interopérabilité ? La section 4 résume la méthodologie suivie. Les développeurs ont d'abord rempli un questionnaire où ils devaient indiquer quelle étaient les fonctions de ForCES que leur programme gérait. Les différents programmes ont ensuite été mis l'un en face =de l'autre dans le labo et ont échangé des messages. Le bon fonctionnemement a été vérifié à la fois par les réactions des programmes et par l'examen des sniffers. Quelques raccourcis ont été pris (section 5). Par exemple, bien qu'IPsec soit obligatoire pour SCTP-TML, il n'a pas été testé, en considérant qu'IPsec était un protocole suffisamment mûr pour qu'on puisse se dispenser de le tester.

La section 6 donne tous les détails des tests, des messages testés, et de leurs résultats. Par exemple, un des tests était d'activer le heartbeat (l'envoi de messages réguliers, permettant de vérifier que le système fonctionne toujours) sur un FE (section 6.1.2.6), puis de changer l'intervalle d'émission des battements.

On l'a dit, le test a été globalement réussi. Mais il y a eu quelques petits problèmes, listés dans la section 6.2.3. Par exemple, une ambiguité est apparue dans la section 4.2.1.2 du RFC 5811 (qui n'était pas encore publié au moment du test, et qui a finalement été publié en corrigeant l'ambiguité) quant au niveau de priorité à donner à une réponse lorsque la question n'avait pas le niveau de priorité standard. Il y avait aussi de franches bogues, comme le FE et le CE attendant tous les deux une action et se bloquant mutuellement ou bien comme un mauvais calcul du champ « longueur » des messages (qui ne doit pas inclure les bits de remplissage). Il y avait aussi des problèmes qui n'étaient de la faute, ni de la norme, ni du programme mais qui reflétaient des limites de ForCES (comme la détection trop lente, dans certains cas, des coupures de la liaison entre CE et FE : SCTP-TML n'est pas forcé de réagir en temps réel à une telle coupure).

Deux autres RFC sur la mise en œuvre de ForCES sont le RFC 6369 et le RFC 6984, ce dernier rendant compte d'un test d'interopérabilité équivalent, mais plus récent.


Téléchargez le RFC 6053


L'article seul

RFC 6052: IPv6 Addressing of IPv4/IPv6 Translators

Date de publication du RFC : Octobre 2010
Auteur(s) du RFC : C. Bao (CERNET Center/Tsinghua University), C. Huitema (Microsoft), M. Bagnulo (UC3M), M. Boucadair (France Telecom), X. Li (CERNET Center/Tsinghua University)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF behave
Première rédaction de cet article le 1 novembre 2010


Il existe plusieurs mécanismes pour assurer la co-existence entre les protocoles IPv4 et IPv6. Ce RFC ne normalise pas un nouveau mécanisme mais spécifie les formats d'adresse à utiliser pour les traducteurs IPv4<->IPv6, les logiciels qui vont convertir d'un format dans l'autre. Il est donc le socle des résultats de la nouvelle version du groupe de travail IETF Behave qui, depuis l'échec de NAT-PT, essaie de normaliser une technique de traduction d'adresses permettant d'assurer la coexistence dans certains cas.

Le RFC du groupe Behave qui décrit le cadre général de cette traduction (Framework for IPv4/IPv6 Translation) est le RFC 6144. Empruntons-lui quelques exemples. Supposons par exemple un réseau purement IPv6 (hypothèse réaliste à l'heure où il ne reste plus que quelques mois d'adresses v4) et qui veut parler aux serveurs Web existants qui n'ont que v4. Un des mécanismes possibles est la traduction d'adresses. Supposons que le site Web convoité soit en 198.51.100.129. La machine purement v6 interroge un serveur DNS 64 (protocole pas encore normalisé) qui lui répond « Va voir en 64:ff9b::c633:6481 » (c633:6481 == 198.51.100.129). Elle émet alors un paquet IPv6 vers cette adresse. Sur le trajet, un traducteur d'adresses va prendre ce paquet, le traduire en v4 algorithmiquement et, lorsque la réponse reviendra, il la traduira en v6, l'envoyant à la machine cliente. Voici un exemple où une machine purement IPv6 tente de contacter Twitter, service purement IPv4 :

% telnet twitter.com 80
Trying 64:ff9b::80f2:f0f4...
Connected to twitter.com.
Escape character is '^]'.

Bien sûr, cette présentation est très sommaire mais c'est parce que le travail de spécification n'est pas encore terminé. La première étape de cette spécification est de décider des adresses utilisées et c'est ce que fait notre RFC. (Il pourrait d'ailleurs, dans le futur, être utilisé par des techniques autre que la traduction, comme l'encapsulation, cf. section 1.1.)

Un peu de vocabulaire, d'abord (section 1.3) :

  • Un traducteur d'adresse est tout dispositif qui va tripoter des adresses, qu'il ait accès aux paquets (dans ce cas, on peut l'appeler « traducteur v4/v6 » ou « traducteur IP ») ou pas (cas d'un serveur DNS 64).
  • IPv4-embedded IPv6 address, une adresse IPv6 qui contient une adresse IPv4 (comme dans l'exemple 64:ff9b::c633:6481 plus haut).
  • IPv4-converted IPv6 address, un cas particulier des précédentes,
  • IPv4-translatable IPv6 address, un autre cas particulier des IPv4-embedded IPv6 address, où l'adresse IPv6 est globalement unique et peut donc être routée dans le grand Internet.

Les traductions peuvent être sans état (stateless) ou bien avec état (stateful). Dans le premier cas, le traducteur n'a aucune mémoire. Chaque paquet est traité isolément, comme si le traducteur venait juste de démarrer. Cela permet donc de traiter une bien plus grande quantité de paquets et assure les meilleures performances et, surtout, le passage à l'échelle. Dans le second cas, celui de la traduction avec état, la traduction dépend des paquets précédents, par exemple parce que le traducteur se souvient que les paquets venant de tel port sont destinés à telle adresse. Nécessitant une table des correspondances en mémoire, la traduction avec état passe moins à l'échelle. Mais, dans certains cas, elle est la seule réaliste, puisqu'on ne peut pas stocker toutes les informations dans une seule adresse, surtout si elle est IPv4.

Armé de ces définitions, quels sont les formats d'adresses IPv4-embedded possibles ? La section 2 les liste. D'abord, un préfixe spécial a été réservé à l'IANA (cf. section 6) pour certaines de ces adresses : 64:ff9b::/96 (section 2.1). Lorsque vous verrez passer une adresse IPv6 commençant par ce préfixe, vous pouvez être sûr de voir une adresse IPv4 embarquée.

Ensuite, toutes les adresses IPv6 IPv4-embedded, qu'elles utilisent ce préfixe ou pas, suivent le même format (section 2.2) : un préfixe (64:ff9b::/96 ou bien un préfixe tiré de l'espace d'adressage de l'opérateur), l'adresse IPv4, un suffixe (parfois nul). Pour respecter la section 2.5.1 du RFC 4291, un octet nul est parfois ajouté au milieu de l'adresse IPv4. Six longueurs de préfixe sont acceptées, 32, 40, 48, 56, 64, ou 96 (cette dernière est celle qui est typiquement utilisée avec le préfixe 64:ff9b::/96). Les sections 3.3 et 3.4 expliquent quelle longueur choisir selon les cas.

Si on utilise un préfixe de longueur 48, comme l'octet qui va des bits 64 à 71 inclus doit être nul, l'adresse IPv4 est en deux parties. On a donc d'abord le préfixe IPv6, les deux premiers octets de l'adresse IPv4, un octet nul, le reste de l'adresse IPv4 et un suffixe de cinq octets. Avec un préfixe de longueur 96, tout est plus simple, le prefixe occupe les douze premiers octets, l'adresse IPv4 prend le reste (et le suffixe est absent). Le tableau 1 dans la section 2.2 résume les autres possibilités.

Une fois ce format défini, la section 2.3 décrit le (très simple) algorithme qui permet de passer d'une adresse IPv4 à une adresse IPv6 et réciproquement.

Petite question de présentation : comment afficher les adresses IPv6 IPv4-embedded ? Bien sûr en obéissant au RFC 4291 (section 2.2) et au RFC 5952. Comme le RFC 4291 permet de représenter les quatre derniers octets (et uniquement ceux-ci) sous la forme d'une adresse IPv4, l'adresse 64:ff9b::c633:6481, citée plus haut, aurait aussi pu s'écrire 64:ff9b::198.51.100.129, ce qui est certainement plus lisible.

Ensuite, comment utiliser ces adresses sur un vrai réseau ? La section 3 couvre les questions de déploiement. D'abord, le préfixe 64:ff9b::/96 ne doit être utilisé qu'avec des adresses IPv4 globalement uniques (donc, par exemple, pas avec celles du RFC 1918). Moins évident, il ne doit pas non plus être utilisé pour construire des adresses IPv6 IPv4-translatable, celles-ci devant être globalement uniques. Si tout le monde est libre de se servir de ce préfixe 64:ff9b::/96, on ne peut pas compter qu'on recevra les paquets qui lui sont adressés depuis un point quelconque de l'Internet. Son usage normal est limité à l'intérieur d'un réseau (section 3.1), autrement, il faut se servir de préfixes spécifiques d'un opérateur.

Pendant qu'on parle de ce préfixe, il faut noter que les opérateurs qui s'en servent peuvent l'annoncer dans leurs tables de routage et qu'il apparaîtra donc sur l'Internet, par exemple si un opérateur décide de fournir un service de traduction d'adresses à un autre. Mais une telle annonce devrait normalement être contrôlée (section 3.2) et ne pas être transmise à toute la DFZ. Et, normalement, ceux qui annoncent ce préfixe en BGP doivent logiquement fournir un service de traduction ensuite (ou bien ils créent un trou noir).

Quel préfixe choisir pour ses services de traduction ? La section 3.3 donne quelques conseils. Par exemple, la « meilleure » longueur est sans doute 32, car, une fois l'adresse IPv4 ajoutée, la totalité de l'information se trouve dans les bits « de routage » (les 64 premiers). Pour le routage, c'est donc la meilleure solution mais obtenir de son RIR un /32 entier uniquement pour le service de traduction d'adresses peut être dificile. Des préfixes plus longs sont donc plus raisonnables. Le RFC suggère par exemple qu'un opérateur qui a un /32 en tout consacre un /40 au service de traduction (moins de 0,5 % de son espace d'adressage). S'il s'agit d'un simple client et pas d'un opérateur, et qu'il a un /48, un /56 conviendra pour le service de traduction. Mais la valeur exacte dépend aussi du scénario de coexistence considéré.

En cas de traduction avec état (section 3.4), les choix peuvent être différents et le préfixe 64:ff9b::/96 est souvent la solution la plus intéressante.

Un des intérêts de ce RFC est la section 4, qui explique les raisons des choix faits. Ainsi, le suffixe, pour les formats où il y en avait un, aurait pu être utilisé pour stocker de l'information sur les ports (section 4.1). Cela aurait augmenté les chances de pouvoir faire une traduction sans état. Cette option n'a pas été retenue dans l'immédiat mais pourrait être ajoutée plus tard. En attendant, le suffixe a obligatoirement tous ses bits à zéro ce qui, pour le format avec préfixe /32, mène à un identificateur d'interface (les 64 derniers bits d'une adresse IPv6) entièrement nul. C'est normalement interdit (section 2.6.1 du RFC 4291) mais notre RFC explique que c'est acceptable dans le contexte limité de la traduction d'adresse.

Le choix de la valeur 64:ff9b::/96 pour le préfixe de référence est expliqué en section 4.2. D'abord, le préfixe existant pour les adresses IPv4, ::ffff:0:0/96 (section 2.5.5.2 du RFC 4291), aurait pu être réutilisé (c'était prévu dans la section 2.1 du RFC 2765). Cela aurait simplifié l'effort de normalisation. Le problème est que, justement, ce préfixe est déjà connu. Plusieurs mises en œuvre d'IPv6 le traitent à part (par exemple, Windows génère systématiquement des paquets IPv4 lorsqu'on lui présente ces adresses IPv6).

Il fallait donc allouer un nouveau préfixe. Un /32 aurait permis d'avoir tous les bits significatifs dans les 64 premiers bits mais n'aurait pas permis d'utiliser la représentation texte avec une adresse IPv4 (qui n'est possible qu'à la fin d'une adresse v6). Finalement, un préfixe /96 a été choisi. Sa valeur 64:ff9b::/96 n'a pas été tirée au hasard : elle est neutre pour le calcul de la somme de contrôle. La somme de 64 et de ff9b est ffff, ce qui est équivalent à zéro en complément à un. (Depuis, un autre préfixe l'a rejoint, le 64:ff9b:1::/48 du RFC 8215.)

Ces systèmes de traduction d'adresse posent-ils des problèmes de sécurité ? Oui, dit la section 5 qui en expose certains. Par exemple, un paquet peut mentir sur son adresse IP source, qu'il y ait traduction ou pas. En fait, note la section 5.1, un traducteur IP est comme un routeur, il a les mêmes vulnérabilités et il peut mettre en œuvre les mêmes protections. Ainsi, lorsqu'il reçoit un paquet IPv6 incluant une adresse IPv4, il peut, avant traduction, s'assurer que la machine était autorisée à utiliser cette adresse IPv4 (si le paquet vient de l'intérieur d'un réseau, c'est relativement facile). D'autres tests sont possibles comme les vérifications du chemin de retour (cf. RFC 3704).

D'autre part, lorsqu'un pare-feu teste les adresses IPv4 (section 5.2), on pourrait imaginer un attaquant qui envoie des paquets IPv6 avec adresse v4 embarquée. Le paquet v6 ne serait pas arrêté par les filtres v4 mais, après traduction, le paquet v4 pourrait faire des dégâts. Il est donc crucial que le pare-feu vérifie les adresses v4 embarquées comme si elles étaient natives.


Téléchargez le RFC 6052


L'article seul

RFC 6049: Spatial Composition of Metrics

Date de publication du RFC : Janvier 2010
Auteur(s) du RFC : A. Morton (AT&T Labs), E. Stephan (France Telecom Division R&D
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF ippm
Première rédaction de cet article le 4 janvier 2011


Prenant la suite du RFC 5835, ce nouveau RFC du groupe de travail IPPM définit la composition spatiale des métriques, ou comment passer des mesures faites sur des parties du chemin d'un paquet à la mesure sur le chemin complet.

Déjà, le RFC 2330 spécifiait des possibilités de composition temporelle et spatiale des mesures faites sur le réseau. Le RFC 5835 définissait ensuite plus rigoureusement le cadre général des compositions de mesures. Il posait des exigences comme, par exemple, le fait qu'une fonction de composition devait spécifier si les mesures partielles étaient faites avec les mêmes paquets ou pas (cf. section 2.2). Finalement, notre RFC 6049 précise ce cadre pour les compositions dans l'espace : si un paquet se promène sur l'Internet et va de A à C en passant par B, peut-on composer deux mesures, faites de A à B et de B à C, en une mesure pour le chemin complet, de A à C ? Et, si oui, comment ?

D'abord, pourquoi cet exercice ? Juste pour le défi intellectuel ? Non, dit la section 1.1, il existe des raisons pratiques à cette composition. Les RFC qui définissent les métriques, comme le RFC 7679 sur le délai d'acheminement d'un paquet ou bien le RFC 7680 sur le taux de pertes de paquets tiennent pour acquis qu'on a un accès complet à la source et à la destination et qu'on peut donc effectuer une mesure de bout en bout. Mais, parfois, ce n'est pas possible, par exemple parce que le chemin franchit une frontière administrative, et on n'a parfois que la possibilité de mesurer des sous-chemins (comme dans l'exemple de A à C ci-dessus). La composition spatiale devient alors un moyen de calculer la mesure sur le chemin complet.

Dans le futur, on pourrait même imaginer d'autres possibilités comme, dans le cas où on n'a pas de mesure pour un des sous-chemins, de calculer la valeur à partir de la mesure du chemin complet et des mesures sur les autres sous-chemins (« soustraction » et non plus « addition »). Mais cette possibilité n'est pas encore définie par le RFC (cf. section 2.1 et 2.3, qui pose que, pour l'instant, si la mesure n'a pas été faite sur un des sous-chemins, c'est le résultat entier qui est indéfini).

Pour définir les compositions elles-mêmes, le RFC procède en deux temps. La section 3 définit les paramètres communs à toutes les métriques et les sections suivantes définissent les paramètres spécifiques aux trois métriques retenues, le délai d'acheminement, le taux de pertes et la variation du délai.

Parmi les paramètres génériques, on peut citer par exemple (section 3.1.8), les causes possibles de déviation par rapport à la vérité de base (section 3.7) du RFC 5835. Ainsi, lorsqu'on mesure sur une partie du chemin, rien ne garantit que les paquets suivront le même chemin que si on mesure sur le chemin complet, en raison, entre autres, de l'ECMP. Sans compter le fait que, si les mesures ne se font pas au même moment, le routage a pu changer entre la mesure d'un sous-chemin et celle du chemin complet.

Les trois métriques spécifiques suivent cet exposé des paramètres génériques. La première est le délai d'acheminement (RFC 7679). D'abord, avant de composer de tels délais, la section 4.1 définit la notion de Type-P-Finite-One-way-Delay-<Sample>-Stream qui est une réduction d'une série de mesures, excluant celles où le paquet n'est pas arrivé (cela permettra de calculer des choses comme la moyenne). Cette façon de simplifier le problème est analogue à celle du RFC 3393 et est également utilisée dans la Recommandation UIT Y.1540, « Internet protocol data communication service - IP packet transfer and availability performance parameters ».

Armé de cette nouvelle définition, on peut s'attaquer à celle de Type-P-Finite-One-way-Delay-Mean (section 4.2). Informellement, c'est simplement la moyenne des délais. Et, finalement, on en arrive à la fonction composée, Type-P-Finite-Composite-One-way-Delay-Mean, qui est simplement la somme des moyennes des délais, somme prise sur tous les sous-chemins. Pour prendre un exemple trivial, si un paquet met en moyenne 0,12 ms pour aller de A à B et 0,05 ms pour aller de A à C, alors la Type-P-Finite-Composite-One-way-Delay-Mean sur le chemin de A à C (s'il passe par B, bien sûr), sera de 0,17 ms. Naturellement, cela suppose que le nombre de paquets utilisé pour calculer la moyenne sur chaque sous-chemin soit suffisant pour qu'on ait une valeur représentative. Il y a aussi d'autres conditions : par exemple, si la distribution des paquets sur un sous-chemin est multi-modale, la moyenne ne voudra pas dire grand'chose.

Comme on a défini une moyenne, on peut définir un minimum (section 4.3). Type-P-Finite-Composite-One-way-Delay-Minimum est la somme des délais minimaux d'acheminement sur chaque sous-chemin. Si on a fait trois tests et que le trajet de A à B a pris 0,12, puis 0,16 puis enfin 0,1 ms, et que celui de B à C a pris 0,05 ms à chaque fois, le Type-P-Finite-Composite-One-way-Delay-Minimum vaut 0,1 + 0,05 = 0,15 ms. On voit que cela suppose que les délais des sous-chemins sont indépendants, ce qui est raisonnable.

Cela, c'était pour le délai d'acheminement, pour lequel on a défini deux fonctions de composition, pour la moyenne et pour le minimum. La section 5 passe au taux de pertes de paquet. En partant de la définition de la perte Type-P-One-way-Packet-Loss du RFC 7680, on peut définir une probabilité de pertes, Type-P-One-way-Packet-Loss-Empirical-Probability puis une composition de cette probabilité, Type-P-Composite-One-way-Packet-Loss-Empirical-Probability. La définition est un peu plus compliquée que pour les compositions précédentes mais, de manière résumée, la probabilité de survie sur le chemin complet est le produit des probabilités de survie sur chaque sous-chemin. Comme la probabilité de perte est 1 - la probabilité de survie, le calcul est facile à faire.

Toutes ces métriques (je n'ai pas détaillé la troisième, présentée en section 6) ont été enregistrées dans la MIB qui sert de registre des métriques (cf. RFC 4148).


Téléchargez le RFC 6049


L'article seul

RFC 6045: Real-time Inter-network Defense

Date de publication du RFC : Novembre 2010
Auteur(s) du RFC : Kathleen M. Moriarty (EMC)
Intérêt historique uniquement
Première rédaction de cet article le 8 novembre 2010


La sécurité, face aux innombrables attaques que connaissent les réseaux tous les jours, nécessite un échange d'information permanent. Ce RFC normalise donc un format permettant d'échanger et de traiter ce genre d'informations (depuis mis à jour dans le RFC 6545). Il sera donc peut-être un outil technique utile pour les CSIRT et les opérateurs.

La section 1 résume les problèmes de la sécurité des réseaux auxquels les opérateurs font face. Une fois l'attaque détectée, que ce soit un hameçonnage, une DoS ou une pénétration réussie dans un système connecté au réseau, il faut rédiger un rapport, transmettre à l'opérateur d'origine de l'attaque, demander à un opérateur amont de prendre des mesures pour limiter les dégâts, demander de continuer l'enquête en suivant la trace de l'attaquant, etc. Par exemple, si on veut suivre une trace de paquets dont l'adresse IP source est mensongère, et que le filtrage recommandé par le RFC 2827 n'est pas en place, il faut repérer par quel câble sont entrés ces paquets et envoyer ensuite à l'opérateur situé derrière une demande de continuation de l'enquête. Il n'y a pas de mécanisme formel pour cela. Ça se fait typiquement par téléphone ou par envoi d'un courrier en langue naturelle, ce qui augmente les coûts de traitement.

Le nouveau format, normalisé dans ce RFC 6045 (puis dans le RFC 6545, qui lui a succédé), se nomme RID pour Real-time Inter-network Defense et se base sur le format IODEF du RFC 5070, qui lui-même utilise XML. L'apport par rapport à l'IODEF de base est de cibler la circulation d'informations en « temps réel ». RID vise donc à permettre la réponse immédiate à une attaque. Par exemple, lorsqu'une dDoS est perpétrée par un botnet, il faut certes retrouver les zombies mais aussi identifier le contrôleur qui les commande. RID permet de demander un suivi de la trace des premiers, puis ensuite du second.

La section 2 traite de l'intégration aux systèmes existants. L'opérateur a typiquement un système de gestion centralisé de son réseau, un NMS. Le futur IHS (Incident Handling System) qui recevra et enverra les messages RID devra être intégré à ce NMS. La détection de l'attaque pourra se faire manuellement, ou via un IDS mais cette question est hors-sujet pour RID, qui se contente de permettre le signalement d'attaques, une fois celles-ci détectées.

Quelles sont les obstacles que rencontrent les tentatives de remonter à la source d'une attaque ? La section 3 en donne une liste, et c'est une lecture très recommandée pour comprendre la variété des problèmes auxquels fait face l'opérateur réseau lors d'une attaque. Par exemple, certaines attaques utilisent tellement peu de paquets qu'il est difficile de les répérer. D'autre part, pour prendre rapidement une « empreinte » des paquets utilisés pour l'attaque, les techniques à base d'une fonction de hachage ont souvent été utilisées (cf. « Hash-Based IP Traceback »). Or, certaines attaques ont un contenu des paquets qui varie énormément et il est difficile de trouver une « signature » qui permettrait de dire à l'opérateur précédent « Voici ce que je cherche ». Les nombreuses techniques de traceback pour IP ont été utilisées pour déterminer quelles étaient les informations importantes à inclure dans RID. Ainsi, il est essentiel d'inclure beaucoup d'informations dans le message RID car les champs significatifs et l'attaque, permettant de repérer les paquets, peuvent être n'importe lesquels. RID permet même d'envoyer la totalité du paquet, si nécessaire (section 3.2).

Une fois que le message RID est prêt, que fait-on pour la communication avec les autres opérateurs et avec les CSIRT ? Les sections 4.1 et 4.2 font remarquer que le courrier électronique n'est pas forcément adapté car il peut être trop lent. Mais, de toute façon, il faut prévoir plusieurs canaux de communication car, en cas d'attaque, certains deviendront peut-être inutilisables. Un réseau distinct de celui utilisé pour le trafic « normal » peut donc être nécessaire (voir plus loin le commentaire de la section 6). Le RFC suggère qu'on peut profiter des négociations qui précèdent un accord de peering pour mettre en place un canal de communication sécurisé.

Recommandation utile ou vœu pieux ? En tout cas, la section 4.2 rappelle également que RID ne devrait être utilisé que pour lutter contre des attaques, et pas pour perpétuer des sabotages (en dénonçant un innocent dans l'espoir qu'il se fasse filtrer) ou pour censurer.

Maintenant, place au format utilisé (section 4.3), fondé sur IODEF (RFC 5070). Il y a six messages RID possibles :

  • TraceRequest où on demande à un partenaire d'examiner son réseau pour voir d'où venait l'attaque (l'idée est que, partant de celui qui a détecté l'attaque, on envoit des Tracerequest successifs en remontant peu à peu vers la source de l'attaque).
  • Investigation où on demande une enquête mais pas un traçage de l'attaque, car le demandeur pense avoir déjà identifié la source.
  • Report où on transmet de l'information, sans demander d'action immédiate.
  • IncidentQuery où on demande des détails sur une attaque dont on a entendu parler (les deux derniers types de message sont typiquement pour la communication avec un CSIRT).
  • RequestAuthorization et Result servent à porter les résultats intermédiaires ou finaux.

La section 4.4 décrit plus en détail chacun de ces types.

La section 4.5 fournit plusieurs jolis exemples, que j'ai simplifié ici. Par exemple, une TraceRequest envoyé par un CSIRT qui a détecté une DoS et qui demande à un opérateur réseau de tracer l'attaque. Le message est composé d'un document RID puis du document IODEF qui décrit l'attaque :


<iodef-rid:RID> <!-- Le schéma est enregistré en
https://www.iana.org/assignments/xml-registry/ns.html -->
  <iodef-rid:RIDPolicy MsgType="TraceRequest" 
                       MsgDestination="RIDSystem">
    <iodef:Node>
      <iodef:Address category="ipv4-addr">192.0.2.3</iodef:Address>
    </iodef:Node>
    <iodef-rid:TrafficType type="Attack"/>
    <iodef:IncidentID name="CERT-FOR-OUR-DOMAIN">
      CERT-FOR-OUR-DOMAIN#207-1
    </iodef:IncidentID>
  </iodef-rid:RIDPolicy>
</iodef-rid:RID>
<!-- IODEF-Document accompanied by the above RID -->
<iodef:IODEF-Document>
  <iodef:Incident restriction="need-to-know" purpose="traceback">
    <iodef:DetectTime>2004-02-02T22:49:24+00:00</iodef:DetectTime>
    <iodef:StartTime>2004-02-02T22:19:24+00:00</iodef:StartTime>
    <iodef:ReportTime>2004-02-02T23:20:24+00:00</iodef:ReportTime>
    <iodef:Description>Host involved in DOS attack</iodef:Description>
    <iodef:EventData>
      <iodef:Flow>
        <iodef:System category="source">
          <iodef:Node>
            <iodef:Address category="ipv4-addr">192.0.2.35
...

Et la première réponse, qui indique que la demande de traçage a été approuvée :


<iodef-rid:RID>
  <iodef-rid:RIDPolicy MsgType="RequestAuthorization"
                       MsgDestination="RIDSystem">
    <iodef-rid:TrafficType type="Attack"/>
  </iodef-rid:RIDPolicy>
  <iodef-rid:RequestStatus AuthorizationStatus="Approved"/>
</iodef-rid:RID>

Et enfin la réponse finale :


<iodef-rid:RID>
  <iodef-rid:RIDPolicy MsgType="Result"
                       MsgDestination="RIDSystem">
    <iodef:Node>
      <iodef:Address category="ipv4-addr">192.0.2.67</iodef:Address>
    </iodef:Node>
    <iodef-rid:TrafficType type="Attack"/>
    <iodef:IncidentID name="CERT-FOR-OUR-DOMAIN">
      CERT-FOR-OUR-DOMAIN#207-1
    </iodef:IncidentID>
  </iodef-rid:RIDPolicy>
  <iodef-rid:IncidentSource>
    <iodef-rid:SourceFound>true</iodef-rid:SourceFound>
    <iodef:Node>
      <iodef:Address category="ipv4-addr">192.0.2.37</iodef:Address>
    </iodef:Node>
  </iodef-rid:IncidentSource>
</iodef-rid:RID>
<!-- IODEF-Document accompanied by the above RID -->
<iodef:IODEF-Document>
  <iodef:Incident restriction="need-to-know" purpose="traceback">
    <iodef:IncidentID name="CERT-FOR-OUR-DOMAIN">
      CERT-FOR-OUR-DOMAIN#207-1
    </iodef:IncidentID>
    <iodef:DetectTime>2004-02-02T22:49:24+00:00</iodef:DetectTime>
    <iodef:StartTime>2004-02-02T22:19:24+00:00</iodef:StartTime>
...
      <iodef:Expectation severity="high" action="rate-limit-host">
        <iodef:Description>
          Rate limit traffic close to source
        </iodef:Description>
      </iodef:Expectation>
      <iodef:Record>
        <iodef:RecordData>
          <iodef:Description>
            The IPv4 packet included was used in the described attack
          </iodef:Description>
          <iodef:RecordItem dtype="ipv4-packet">450000522ad9
          0000ff06c41fc0a801020a010102976d0050103e020810d9
          4a1350021000ad6700005468616e6b20796f7520666f7220
          6361726566756c6c792072656164696e6720746869732052
          46432e0a
          </iodef:RecordItem>
        </iodef:RecordData>
      </iodef:Record>
    </iodef:EventData>
    <iodef:History>
      <iodef:HistoryItem>
        <iodef:DateTime>2004-02-02T22:53:01+00:00</iodef:DateTime>
        <iodef:IncidentID name="CSIRT-FOR-OUR-DOMAIN">
          CSIRT-FOR-OUR-DOMAIN#207-1
        </iodef:IncidentID>
        <iodef:Description>
          Notification sent to next upstream NP closer to 192.0.2.35
        </iodef:Description>
      </iodef:HistoryItem>
      <iodef:HistoryItem action="rate-limit-host">
        <iodef:DateTime>2004-02-02T23:07:21+00:00</iodef:DateTime>
        <iodef:IncidentID name="CSIRT-FOR-NP3">
          CSIRT-FOR-NP3#3291-1
        </iodef:IncidentID>
        <iodef:Description>
          Host rate limited for 24 hours
        </iodef:Description>
      </iodef:HistoryItem>
    </iodef:History>
  </iodef:Incident>
</iodef:IODEF-Document>

L'entiéreté du schéma XML, en xsd, figure en section 5.

Comme déjà noté, l'utilisation de ces messages RID ne va pas sans risques. La section 6 les analyse. D'abord, il faut évidemment un canal sécurisé pour les transmettre. Sécurisé au sens de :

  • Confidentiel, puisque les informations RID peuvent être très sensibles,
  • Fiable (disponible), puisque l'attaque rendra peut-être inutilisable les canaux normaux,
  • Authentifié, parce que ceux à qui on demande d'agir sur la base de messages RID voudront savoir à qui ils ont affaire.

Un canal physique dédié faciliterait l'obtention de ces propriétés mais n'est pas forcément réaliste. Le RFC recommande donc plutôt un tunnel chiffré. En combinant TLS sur le tunnel et les signatures XML du RFC 3275 sur le message, on atteint la sécurité désirée. Le protocole exact utilisé est normalisé dans un autre document, le RFC 6046. Bien qu'il utilise le chiffrement, RID ne repose pas uniquement sur la sécurité du canal et permet de chiffrer aussi le message par le chiffrement XML.

RID soulève aussi des questions liées à la protection de la vie privée et la section 6.6 les étudie. RID fournit le moyen de spécifier des détails comme l'extension du « domaine de confiance » à qui on peut envoyer les informations (élément PolicyRegion, section 4.3.3.3).


Téléchargez le RFC 6045


L'article seul

RFC 6041: ForCES Applicability Statement

Date de publication du RFC : Octobre 2010
Auteur(s) du RFC : A. Crouch, H. Khosravi (Intel), A. Doria (LTU), X. Wang (Huawei), K. Ogawa (NTT Corporation)
Pour information
Réalisé dans le cadre du groupe de travail IETF forces
Première rédaction de cet article le 30 octobre 2010


Le protocole ForCES (Forwarding and Control Element Separation), décrit dans le RFC 5810, normalise la communication entre les différents éléments d'un routeur, de façon à permettre la création d'un routeur par l'assemblage de composants venus de constructeurs différents. Ce RFC 6041 se focalise sur l'applicabilité de ForCES, à savoir dans quels cas ce protocole est applicable et ce qu'on peut exactement lui demander. Ce RFC peut donc servir d'introduction de haut niveau à ForCES.

ForCES considère un routeur comme composé d'un élément de contrôle, qui parle les protocoles de routage comme OSPF, c'est le CE (Control Engine), et d'un ou plusieurs éléments qui transmettent effectivement les paquets, les FE (Forwarding Engine). ForCES est le mécanisme par lequel le CE communique avec ses FE. Outre le protocole lui-même, dans le RFC 5810, ForCES a aussi un modèle de données (RFC 5812) et un protocole de transport (RFC 5811). Dans quels cas peut-on les employer et, inversement, quand sont-ils inapplicables ? La section 4 forme le cœur du RFC et c'est surtout elle qui est résumée ici.

D'abord, ForCES est prévu pour des routeurs assez gros pour que les fonctions de contrôle et de transmission soient séparées. Sur un engin bas de gamme, où tout tient dans le même circuit, ForCES n'est sans doute pas utile. Par contre, les routeurs du milieu et du haut de gamme ont déjà une séparation physique entre le mécanisme de contrôle et les mécanismes de traitement des interfaces réseaux. Comme ce CE et ces FE doivent communiquer (par exemple, si le CE apprend par OSPF qu'une route pour 192.0.2.192/26 passe par l'interface ge-0-1, il doit communiquer cette information au FE qui gère cette interface, mais aussi à tous les autres pour qu'ils lui transmettent ce trafic). Les routeurs ont donc tous un protocole de communication entre CE et FE mais il est toujours privé (un des rares qui soit documenté est le Netlink de Linux, dans le RFC 3549). Avec ForCES, se profile la possibilité d'un protocole standard pour les remplacer.

Quels services, dans cette communication entre FE et CE, peuvent être assurés par ForCES ? Notons bien (section 4.1) que ForCES ne traite pas de la découverte par le CE de ses FE, découverte qui doit être assurée autrement. En revanche, une fois celle-ci effectuée, ForCES pilote l'association entre CE et FE, et la transmission des informations comme, par exemple, le nombre de ports réseaux que gère le FE. Le CE peut ensuite configurer le FE (par exemple en lui indiquant les adresses IP locales, qui doivent être transmises au CE), comme indiqué en section 4.1.3.

Mais le principal service assuré par ForCES est évidemment l'envoi d'informations de routage (section 4.1.4). Un CE transmet à ses FE les adresses IP à router, de façon à ce que les paquets soient transmis à la bonne interface réseau.

La section 4.1 note de nombreux autres services. Citons-en juste un : l'envoi par le CE de règles de filtrage (quels paquets abandonner, et sur quels critères), en section 4.1.7.

De quoi a besoin ForCES pour rendre ces services, et qui n'est pas forcément présent sur tous les routeurs ? De capacité réseau (section 4.2). Entre le CE et le FE, la capacité n'est pas infinie et des opérations comme l'envoi d'une table de routage complète peuvent être non-triviales sur un réseau d'interconnexion lent, d'autant plus que ForCES se veut utilisable pour des futures tables de routage, plus grandes que celle d'aujourd'hui (fin octobre 2010, il y a 340 000 entrées dans la table de routage BGP globale).

Cette question de la capacité en amène une autre, celle de la localité. ForCES sépare logiquement le CE et le FE. Peuvent-ils aussi être séparés physiquement, et mis dans des boîtes différentes ? La section 4.3 examine la question. Le principe est que la disponibilité du routeur ne devrait pas être affectée par la séparation du contrôle et de la transmission. La connexion entre le FE et le CE est doit donc être un bus très fiable, ou en tout cas aussi fiable que le CE, de façon à partager son sort. En pratique, cela veut dire que ForCES est utilisable sans problème pour les NE (Network Element, typiquement un routeur) où tout tient dans une seule boîte, avec des lames différentes pour le CE et les FE, mais un seul châssis et une interconnexion en Ethernet, PCI, etc (le cas de la majorité des routeurs actuels). Une telle configuration simplifiera notamment les problèmes de sécurité (cf. section 5). Mais ForCES peut aussi marcher dans des cas où CE et FE sont situés dans des boîtiers séparés.

Pas de protocole réaliste sans possibilité de gestion. La section 6 détaille le comportement de ForCES face aux exigences de la gestion du réseau. Le point important est que, quel que soit le degré de séparation entre CE et FE, ForCES permet de voir le routeur comme un élément unique. Cela se réalise en faisant passer l'essentiel des fonctions de gestion à travers le CE. Notre RFC recommande ainsi que tous les messages SNMP soient transmis au CE (par exemple en utilisant les mécanismes du RFC 2741). Ceux qui vont quand même directement traités par les FE doivent, ou bien être en lecture seule, ou bien permettre une notification du CE, afin que celui-ci reste seul maître. ForCES dispose d'une MIB, décrite dans le RFC 5813, qui permet d'accéder à des informations comme les associations entre le CE et les FE.


Téléchargez le RFC 6041


L'article seul

RFC 6039: Issues with existing Cryptographic Protection Methods for Routing Protocols

Date de publication du RFC : Octobre 2010
Auteur(s) du RFC : Vishwas Manral (IP Infusion), Manav Bhatia (Alcatel-Lucent), Joel Jaeggli (Checkpoint Software), Russ White (Cisco Systems)
Pour information
Réalisé dans le cadre du groupe de travail IETF opsec
Première rédaction de cet article le 24 octobre 2010


Le groupe de travail IETF opsec travaille à améliorer la sécurité des protocole de routage. Ce RFC du groupe (l'un des premiers, après les très intéressants RFC 4778 et RFC 5635) fait le point sur l'utilisation actuelle de la cryptographie dans ces protocoles et ses limites, les problèmes qu'elle soulève, notamment de gestion des clés.

Plusieurs protocoles de routage ont des mécanismes standards pour protéger par la cryptographie les informations transmises. OSPF v2 (RFC 2328), OSPF v3 (RFC 5340), IS-IS (RFC 1195), BGP (RFC 4271), ou des protocoles qui, sans être à proprement parler « de routage », en sont néanmoins proches comme BFD (RFC 5880), sont tous capables de prendre un condensat cryptographique de l'information transmise, en utilisant une fonction de hachage comme MD5 (RFC 1321) et une clé secrète. Le routeur récepteur, s'il a la même clé secrète, peut refaire le calcul du condensat et, s'il trouve la même valeur, être rassuré que le message vient bien d'un routeur autorisé, et qu'il n'a pas été modifié en route. (On notera que l'utilisation de protocoles à clés publiques est infiniment plus rare, au point d'être à peine mentionné dans le RFC.)

Notons que ces protocoles n'assurent pas de service de confidentialité : un méchant qui espionne la communication entre deux routeurs peut toujours apprendre les routes échangées.

Comme le note la section 1 du RFC, qui étudie les problèmes génériques, communs à tous les protocoles de routage, cette approche a des limites : l'utilisation de clés secrètes partagées entraine une gestion manuelle des clés, plutôt pénible. Remplacer une clé compromise est ainsi une opération longue et risquée (il est facile d'oublier un routeur, ce qui cassera les communication entre les routeurs ayant la nouvelle clé et les autres). D'autre part, plusieurs cas existent où les attaques par rejeu sont possibles.

Comme le note la section 1.1, la fonction de hachage la plus couramment utilisée est MD5. Celle-ci n'est pas sans reproche, cryptographiquement parlant. Des attaques par collision (trouver deux messages qui ont le même condensat cryptographique) ont déjà été publiées par exemple par Xiaoyun Wang, Xuejia Lai, Dengguo Feng & Hongbo Yu, dans « Collisions for hash functions MD4, MD5, HAVAL-128, and RIPEMD », Crypto 2004 Rump Session. En revanche, des attaques dites « pré-image » (où on produit un message qui a le même condensat qu'un message donné, ce qui est beaucoup plus difficile qu'une attaque par collision) ne semblent pas avoir été publiées. Pour le cas particulier des protocoles de routage, les collisions ne sont pas trop à craindre car beaucoup de champs dans un message ne peuvent pas prendre des valeurs arbitraires (par exemple, dans OSPF le champ « Link State Advertisement function code - section A.4.2.1 du RFC 5340 - peut valoir seulement de 1 à 14). Pour les attaques pré-image, elle seraient sans doute plus graves, mais la taille relativement limitée des messages de routage limite sans doute les risques d'exploitation effective.

SHA-1 a aussi ses faiblesses (section 1.2) mais il faut bien voir qu'elles ne sont pas réellement utilisables pour une attaque, dans les conditions spécifiques des protocoles de routage (cf. RFC 4270 pour un bon arrière-plan sur la question.)

Les sections suivantes détaillent ensuite les problèmes pour le cas spécifique de chaque protocole. À chaque fois, sont indiqués les problèmes d'ordre pratique (gestion des clés) et ceux d'ordre technique (faiblesses dans le protocole). OSPF v2 fait l'objet de la section 2. Les routeurs OSPF d'un même réseau peuvent s'authentifier en condensant les paquets et une clé secrète avec MD5 (RFC 2328, annexe D.3). Cette clé se configure avec :

interface eth0
  ip ospf authentication message-digest
  ip ospf message-digest-key 1 md5 MACLESECRETE

sur Quagga et avec :

authentication-type md5;
	interface fe-0/0/1.0 {
	     authentication {
	         md5 1 key "$9$dEbgoZUjqP5GUApO1hcgoaJHq"; MACLESECRETE 
	     }
	}

sur JunOS. Il existe aussi un mécanisme expérimental de signature des messages par des clés asymétriques (RFC 2154) mais qui n'a apparemment jamais été déployé.

Le condensat cryptographique s'applique aux messages échangés entre routeurs, pas à l'information de routage elle-même. Autrement dit, MD5 dans OSPF sécurise le canal mais pas le message (le LSA). OSPF ne fournit aucun mécanisme de négociation de paramètres comme l'algorithme de hachage utilisé. Si on veut utiliser SHA (RFC 5709), tous les routeurs d'un même lien doivent être manuellement configurés de manière identique. D'une manière générale, tout changement dans les clés doit faire l'objet d'une prudente intervention planifiée et manuellement exécutée.

L'authentification cryptographique dans OSPF a aussi des problèmes techniques (section 2.2) comme le fait que la même clé soit utilisé pour tous les routeurs d'un même réseau Ethernet, obligeant à largement partager le secret.

Pour OSPF v3 (RFC 5340 et section 3), encore peu déployé, la situation est toute différente. Il n'a pas de mécanisme d'authentification intrinsèque et ses utilisateurs sont censés s'appuyer sur IPsec (par exemple RFC 4303, sans chiffrement, comme spécifié dans le RFC 2410, pour avoir juste la signature). La norme de sécurité d'OSPF v3 (RFC 4552) précise que les clés IPsec doivent être gérées manuellement, pas avec un protocole comme IKE parce que le modèle de fonctionnement d'OSPF (un-vers-plusieurs) est très particulier.

Même si le RFC n'en dit pas un mot, le principal problème d'OSPF v3, aussi bien technique que pratique, est qu'IPsec est très peu déployé et que peu d'administrateurs réseaux ont envie de s'y mettre pour assurer une fonction qui, en OSPF v2, ne prenait que deux lignes de configuration.

Et le concurrent d'OSPF, IS-IS (RFC 1195 et section 4 de notre RFC) ? Lui aussi peut utiliser MD5 pour l'authentification (voir RFC 5304). Mais, contrairement à OSPF, la signature porte sur l'annonce d'état d'un lien, pas sur un message échangé entre deux routeurs. Cela veut dire qu'on peut authentifier un routeur distant, mais cela oblige (section 4.1) tous les routeurs à avoir la même clé... Comme OSPF, pas moyen de négocier la clé, ou l'algorithme de condensation. Si on veut remplacer MD5 par SHA-256, un gros travail de gestion est à prévoir.

Faut-il également parler de l'antédiluvien RIP ? La section 6 lui consacre quelques paragraphes. La version historique, dans le RFC 1058, avait zéro service de sécurité. La version 2, actuellement normalisée dans le RFC 2453, et dispose désormais d'un mécanisme d'authentification analogue à ceux des autres protocoles (cf. RFC 4822).

Bien que n'étant pas un protocole de routage, BFD (RFC 5880) est tellement souvent utilisé dans les routeurs qu'il mérite sa section de ce RFC, la 7. BFD sert à détecter la panne d'une liaison. Il dispose d'un mécanisme d'authentification optionnel (sections 4.2 et 6.7 du RFC 5880), à clés partagées. Il hérite donc des problèmes de gestion de clés de ce système.

Et BGP, vedette des protocoles utilisés sur l'Internet, puisque c'est lui qui assure le routage entre opérateurs ? La section 5 détaille ce protocole. BGP est forcément transporté sur TCP. Il peut donc utiliser les options d'authentification de TCP comme celle du RFC 2385 (très répandue en pratique dans le monde BGP) ou bien celle du RFC 5925, plus récente, bien meilleure et plus rare en pratique. Pour cette raison, notre RFC 6039 ne couvre que l'authentification MD5 du RFC 2385. Parmi les problèmes de gestion, il y a le fait que BGP est typiquement utilisé de part et d'autre d'une frontière administrative. Cela complique sérieusement les opérations de gestion de clés. Par exemple, quand avez-vous pour la dernière fois changé un mot de passe MD5 sur une session BGP avec un pair ? (Réponse : vous ne l'avez probablement jamais fait.) Sur un gros point d'échange, un routeur BGP peut se connecter à des dizaines, voire des centaines de pairs, et la gestion des « mots de passe MD5 » pour tous ces pairs est un défi. En général, on ne complique pas ce défi en essayant de suivre des bonnes pratiques, comme le changement des mots de passe...

Et les problèmes techniques de BGP ? Comme il utilise TCP, il profite de ses mécanismes de sécurité (comme les numéros de séquence qui protègent des rejeux) et il hérite de ses faiblesses (voir l'excellent exposé de Convery & Franz à Black Hat, « BGP Vulnerability Testing: Separating Fact from FUD », un modèle pour toute analyse de la sécurité). À plusieurs reprises, les fabricants de routeurs BGP ont dû mettre à jour leur logiciel pour traiter ces vulnérabilités.

À noter que le RFC ne mentionne pas du tout ce qui est probablement la plus grosse faiblesse de sécurité de BGP : le fait qu'on puisse authentifier le voisin, mais pas l'information qu'il envoie (ou relaie). Savoir que c'est bien mon pair 2001:db8:face:b00c::1 avec qui je parle, c'est très bien mais, lorsqu'il annonce une route vers 2001:db8:137::/48, comment savoir s'il a le droit de le faire ou bien si Pakistan Telecom a fait mumuse ? Il n'existe pour l'instant aucun protocole standard pour cela.


Téléchargez le RFC 6039


L'article seul

RFC 6038: TWAMP Reflect Octets and Symmetrical Size Features

Date de publication du RFC : Octobre 2010
Auteur(s) du RFC : A. Morton, L. Ciavattone (AT&T Labs)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF ippm
Première rédaction de cet article le 11 octobre 2010


Voici deux petites extensions au protocole de mesure active TWAMP. L'une permet de demander le renvoi d'octets choisis par le client. L'autre permet de garantir l'usage de paquets de même taille dans les deux directions.

L'IETF a deux protocoles de mesure active, OWAMP (One-way Active Measurement Protocol, RFC 4656, unidirectionnel, et TWAMP (Two-Way Active Measurement Protocol, RFC 5357), bidirectionnel. Avec TWAMP, un client peut demander une réponse à des paquets de tests qu'il envoie et en déduire des informations sur le réseau (comme le RTT). Mais le RFC original ne garantit pas grand'chose sur ces paquets de retour (section 4.2.1 du RFC 5357), ce qui peut être gênant dans certains cas. Désormais, le client peut décider d'une partie du contenu des paquets de test, ainsi que de leur taille (sections 1 et 2 du RFC).

La possibilité de réflexion d'octets, choisis par le client, ouvre de nombreuses possibilités à ce dernier comme d'étiqueter les paquets de la manière de son choix, en pouvant relire l'« étiquette » au retour.

La section 4.2.1 du RFC 5357 recommande que le serveur TWAMP choisisse des paquets de réponse qui soient de taille proche de celui des paquets reçus. Mais ce n'était pas une obligation. La nouvelle option indique que le client veut l'égalité des tailles de paquets.

Ces deux options sont signalées par des bits du champ Mode (section 3.1 du RFC 4656) autrefois inutilisés. Un serveur TWAMP correct doit ignorer ces bits s'il ne les connait pas, assurant ainsi la compatibilité des nouveaux clients avec les anciens serveurs.

Les détails pratiques figurent en sections 3 (pour la session de contrôle du test) et 4 (pour celle de test à proprement parler). Les deux nouveaux bits ont été enregistrés dans le registre IANA (voir aussi la section 6). La section 3.2 décrit le format des paquets de l'option « Reflect Octets » qui permet d'indiquer deux octets à réfléchir lors de l'acceptation de la session (ce qui permet de vérifier que le serveur gère bien cette extension). On indique aussi le nombre d'octets (au maximum 65536) à réfléchir lors du test. L'autre option, « Symmetrical Size » n'a pas nécessité de changer le format.

Enfin, la section 4.2 normalise le comportement du réflecteur en présence de ces nouvelles options. Les deux extensions en question sont optionnelles et ne seront pas forcément mises en œuvre par tous les serveurs TWAMP. Il n'existe de toute façon pas encore de mise en œuvre de TWAMP en logiciel libre.


Téléchargez le RFC 6038


L'article seul

RFC 6036: Emerging Service Provider Scenarios for IPv6 Deployment

Date de publication du RFC : Octobre 2010
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 23 octobre 2010


Maintenant que de nombreux FAI, dans le monde, ont déployé IPv6 et l'offrent comme service à leurs clients, il est temps de regarder ce qu'ils ont fait et de le documenter. Les auteurs de ce RFC ont donc commis un questionnaire début 2010 sur le thème « comment avez-vous déployé IPv6 », et l'ont envoyé à un certain nombres de FAI. Notre RFC 6036 résume les réponses.

Pendant longtemps, la décision de passer à IPv6 ou pas semblait ouverte. On déployait IPv6 quand, comme Nerim, on avait une clientèle techniquement exigeante, et on ne le déployait pas lorsqu'il n'y avait pas de demande des clients (le cas le plus fréquent). Mais, aujourd'hui, le business ne peut plus continuer comme avant, les adresses IPv4 étant presque épuisées. Cela laisse trois choix aux FAI (section 1 du RFC) :

  • Essayer d'économiser à l'extrême les adresses IPv4, en en allouant de moins en moins aux clients (ce qui est difficile pour l'accès individuel, où il n'y a déjà qu'une seule adresse par foyer) et en essayant d'acheter des adresses IPv4 sur les marchés gris ou noirs.
  • Installer de plus en plus de traduction d'adresse en étages successifs et laisser les clients déboguer les problèmes qui en résulteront.
  • Déployer IPv6.

Que font aujourd'hui les FAI ? L'enquête va essayer de répondre à cette question, en se focalisant sur ce qui est de la responsabilité directe des FAI, l'adressage, le routage, la gestion, le DNS, et en excluant les applications (qui sont souvent un des freins à la migration vers IPv6).

Plusieurs RFC couvrent ce champ. Par exemple, le RFC 4029 parle du déploiement chez un FAI, et prévoit la « double pile » (v4 et v6) sur tous les équipements. Compte-tenu du retard pris et de l'épuisement des adresses v4, cela ne sera sans doute pas possible et il faut aujourd'hui envisager la cohabitation et la communication entre des machines purement v4 et d'autres purement v6. Le RFC 5211 est une vision plus générale du déploiement d'IPv6, les FAI étant juste un cas particulier. Le RFC 4779 documente le déploiement de IPv6 dans des réseaux d'accès courants comme le câble TV ou l'ADSL. Les RFC 5181 et RFC 5121 traitent, eux, des accès 802.16. Les questions de sécurité sont abordées dans le RFC 4942 ainsi que dans le RFC 4864, ce dernier se focalisant sur la protection du réseau local du client.

Les normes IPv6 de base sont assez stables (la plupart des RFC récents n'ont touché qu'aux détails) mais le travail continue activement à l'IETF, par exemple dans des domaines comme la traduction d'adresses.

Place maintenant à l'étude elle-même (section 2). Le questionnaire figure dans l'annexe B. Il a été expédié à des listes d'opérateurs comme NANOG. 31 réponses ont été reçues. Seuls les volontaires répondaient, ce qui biaise évidemment les résultats (une liste - incomplète car certains ont demandé l'anonymat - des répondants figure en section 7). Les auteurs du RFC notent que les FAI qui ont déployé IPv6 étaient probablement plus prompts à répondre. Les réponses étaient confidentielles. Les réponses agrégées figurent dans l'annexe A.

Que trouve t-on dans ces réponses ? Les répondants fournissent de l'accès à l'Internet par un grand nombre de moyens (section 2.2), xDSL, DOCSIS, Ethernet, WiMAX et bien d'autres. Sur les adresses IP utilisées, plusieurs répondants poussent le négationnismes jusqu'à dire qu'ils n'auront jamais d'épuisement des adresses IPv4, les autres répondants citant, pour leur propre pénurie, des dates entre 2010 et 2015. En 2010, plusieurs FAI en Asie - 19 % des répondants - n'ont déjà plus une seule adresse IP publique et allouent du RFC 1918 à leurs clients ; ceux-ci n'ont donc pas un vrai accès Internet. 39 % des répondants utilisent des adresses privées en interne.

42 % des répondants ont déjà une offre IPv6 (section 2.4), mais moins d'1 % de clients l'utilise. 48 % des répondants ont une telle offre en travaux, avec l'idée d'ouvrir entre 2010 et 2013 (rappelez-vous que les réponses n'ont pas été vérifiées...) Donc, 10 % des répondants, en 2010, moins d'un an avant l'épuisement de la réserve IANA, ne font rien... Le pronostic sur le dépassement d'IPv4 par IPv6 en terme de trafic varie évidemment mais tourne autour de 2015.

Quelle technique de déploiement ? 94 % des répondants ont une épine dorsale en double-pile (section 2.5). 39 % ont ou bien vont avoir un relais 6to4 (je n'ai pas vérifié si cela incluait les relais 6rd comme ceux de Free) et 16 % du Teredo. Une des questions portait sur « les systèmes qui ne gèrent pas IPv6 ». Si les gros routeurs de l'épine dorsale sont évidemment tous prêts pour IPv6 depuis très longtemps, le maillon faible concerne plutôt des systèmes plus discrets : les CPE sont le plus souvent cités mais aussi les DSLAM, les répartiteurs de charge ou des logiciels comme celui de gestion des adresses IP des clients ou bien le système de facturation. À la question de savoir si des engins comme les CPE pourraient être mis à jour, beaucoup de réponses étaient « nous l'espérons »...

Parmi ceux qui allouent des adresses IPv6, les préfixes existants vont d'un /19 à un /48 (!) et celui alloué au client va de /48 à /64 en passant par plusieurs /56 (le RFC 6177 donne des recommandations à ce sujet). Pour déléguer le préfixe du client à la CPE, les méthodes vont de la configuration manuelle à DHCPv6 et SLAAC (StateLess Address AutoConfiguration). Certains utilisent Radius ou PPPoE bien qu'ils n'aient pas de moyen standard de déléguer un préfixe.

La moitié des répondants gèrent déjà des serveurs double-pile (SMTP, HTTP, IMAP). Des systèmes internes comme la surveillance du réseau semblent également v6isés à 50 % alors que les systèmes de facturation et de compatibilité, dejà cités, ne le sont qu'à 23 %.

Comment gérer la coexistence d'IPv4 et IPv6 ? 58 % des FAI ne croient pas aux clients « fixes » purement v6. Interrogés sur la date où la dernière application purement v4 disparaitra, les réponses sont souvent du type « au moins dix ans ». Il faudra donc gérer la coexistence. Sur ce point, la section 2.5 ne montre aucun consensus sur les solutions : un traducteur du genre NAT, par exemple, ou bien d'autres mécanismes pas forcément précisés.

Certains FAI ont IPv6 en production depuis des années. Quelles expériences peuvent-ils en tirer ? La section 3 fait le point. Ceux qui ont fait le choix de la double pile native (c'est le cas de Nerim en France) en sont contents. Mais ceux ceux qui utilisent 6to4 ou 6rd aussi. La plupart des répondants estiment a posteriori que le passage à IPv6 était plutôt facile, une opération qu'ils classent dans la catégorie « comment arriver à manger un éléphant ? » (la réponse est « une bouchée à la fois »). Les difficultés rencontrées portaient sur la difficulté à convaincre certains (il existe encore des négationnistes qui, cherchant à justifier leur inaction, prétendent que l'épuisement des adresses IPv4 est un faux problème) et, naturellement, sur le fait que, comme tous les changements d'infrastructure qui n'apportent pas un bénéfice immédiat et visible, le passage à IPv6 est difficile à justifier auprès de la direction, qui ne voit que l'intérêt financier immédiat. Des problèmes moins connus sont aussi soulevés, comme l'importance d'impliquer les gens qui font le support utilisateur, puisque certaines applications mal écrites ne se rabattront pas sur IPv4 si une connexion IPv6 échoue, ce qui peut entraîner des protestations des clients.

Puisqu'on parle des problèmes, quels sont les principaux manques à l'heure actuelle, pour le FAI qui veut passer à IPv6 ? La section 4 liste les réponses faites à ce sujet :

  • Les produits « bas de gamme » qui ne gèrent pas IPv6 (CPE, appliances SIP, IDS, ...). Sans compter ceux chez qui IPv6 est bogué, ou incomplet (un répondant cite le cas d'un CPE théoriquement IPv6 mais dont les fonctions de shaping ne marchaient qu'en IPv4) ou bien plus lent qu'IPv4. Dans le domaine du logiciel, si le logiciel libre n'est pas trop mal placé, beaucoup de logiciels commerciaux ne gèrent toujours pas IPv6.
  • L'offre de protocoles n'est pas encore complète (et, contrairement au point précédent, celui-ci est sous la responsabilité directe de l'IETF). La section 4.2 note que les répondants estiment qu'il n'existe pas de protocoles satisfaisants pour la délégation d'un préfixe v6 à la CPE, pour les mécanismes de contrôle des pare-feux comme UPnP, pour l'allocation d'adresses IP avec PPPoE ou Radius. (À noter que les réponses sont parfois mal informées ; ainsi, la demande d'un VRRP v6 a été satisfaite dans le RFC 5798 et celle d'une indication des serveurs DNS dans les Router Advertisement dans le RFC 6106. Le problème est donc en réalité désormais un problème de mise en œuvre et de déploiement, plus de protocole. Le cas inverse arrive aussi, où le FAI qui envisage de déployer v6 n'est pas conscient des limites de certains protocoles, voir la section 4.3.)
  • Enfin, des gros problèmes qui ne peuvent pas être résolus par les programmeurs ou par l'IETF demeurent : difficulté à trouver un vendeur de transit IPv6 en Amérique du Nord ou en Asie, problèmes de PMTU persistants, ...

Téléchargez le RFC 6036


L'article seul

RFC 6029: A Survey on Research on the Application-Layer Traffic Optimization (ALTO) Problem

Date de publication du RFC : Octobre 2010
Auteur(s) du RFC : I. Rimac, V. Hilt, M. Tomsu, V. Gurbani (Bell Labs, Alcatel-Lucent), E. Marocco (Telecom Italia)
Pour information
Première rédaction de cet article le 23 octobre 2010


Dans le cadre des travaux menés à l'IETF (groupe de travail ALTO, RFC 5594, etc) et à l'IRTF sur le problème de l'optimisation du transfert de fichiers en pair-à-pair, ce RFC sert de bibliographie : il rassemble des pointeurs, classés et organisés, sur la littérature existante en matière d'optimisation, de recherche du « meilleur pair ».

Le pair-à-pair est un concept difficile à définir et encore plus à mesurer. D'autant plus, même si le RFC ne mentionne pas ce problème, que la répression dont il fait l'objet à l'instigation des ultras de l'appropriation intellectuelle oblige ses utilisateurs à diverses astuces pour dissimuler son utilisation, rendant ainsi les statistiques difficiles. Par exemple, les estimations de la part de trafic qui revient au pair-à-pair varient de 40 à 85 %... Une chose est sûre, cela représente un trafic important, et qu'il est donc logique de chercher à optimiser. Lorsqu'on utilise le pair-à-pair pour des transferts de fichier (avec des systèmes comme BitTorrent), le contenu convoité est répliqué sur de nombreux pairs à travers le monde (section 1 du RFC). Le problème est « Quel pair utiliser ? » Isolé, le pair qui veut récupérer un fichier ne peut utiliser que le hasard, ou bien des mesures qu'il fait lui-même et qui sont souvent imparfaites (par exemple, la mesure de la latence avec un ping ne donne qu'une vague idée du débit qu'on obtiendra). La DHT typique ne donne que des optimisations locales, qui ne sont pas forcément bonnes globalement. C'est le problème central de l'optimisation, décrit dans le RFC 5693.

Il y a plusieurs solutions à ce problème, comme des réseaux de machines faisant des mesures applicatives et donnant accès au résultat de ces mesures (Azureus le fait), ou bien comme des fournitures d'information aux pairs par le FAI, pour que les destinataires puissent prendre des décisions informées. Ce RFC résume la littérature existante sur ces solutions, en s'appuyant sur le RFC 4981.

La section 2 du RFC examine les résultats de recherche publiés sur ce thème, comme « The impact of DHT routing geometry on resilience and proximity » de Gummadi, K., Gummadi, R., Gribble, S., Ratnasamy, S., Shenker, S., et I. Stoica, qui étudie la relation entre le réseau overlay de plusieurs algorithmes de DHT et le réseau physique sous-jacent. Leur conclusion est notamment que les géométries les plus simples (comme l'anneau) sont les meilleures.

Pour les autres résultats de recherche, la section 2 les classe en deux groupes : les méthodes fondées sur des mesures faites uniquement par l'application (comme Meridian) et celles fondées sur une coopération entre les couches (comme P4P).

Les premières sont traitées plus en détail dans la section 2.1. L'idée de base est que les machines mesurent un coût (typiquement, la latence) par rapport à un certain nombre d'amers et qu'on peut ensuite calculer le coût de la communication entre deux machines, par le biais d'un système de coordonnées Internet. C'est ainsi que fonctionnent IDmaps ou GNP. Tous les deux dépendent d'un réseau d'amers stables. Au contraire, Vivaldi est entièrement distribué et c'est le système utilisé dans le client BitTorrent Azureus.

Les algorithmes cités dans le paragraphe précédent forment une sous-catégorie du groupe « Mesures faites par l'application ». Cette sous-catégorie est celle des systèmes de coordonnées explicites, qui essaient, à coup de mesures, de déterminer la topologie sous-jacente. Dans un réseau aussi complexe que l'Internet, où des inégalités aussi simples que l'inégalité triangulaire (qui dit que le coût pour aller de A à C est inférieur ou égal au coût de A à B plus celui de B à C) ne sont pas forcément vraies, il n'est pas évident qu'une telle approche soit efficace. D'où la seconde sous-catégorie, basée sur une mesure des distances. Moins générales, ces méthodes (dont la plus connue est Meridian) sont peut-être plus réalistes.

Dans tous les cas, toutes les mesures faites par les applications doivent se poser la problème de ce qu'on mesure. Le plus simple est de mesurer la latence (ce que fait, par exemple, la commande ping). Or, des métriques comme la capacité (RFC 5136) ou comme le taux de pertes de paquets (RFC 7680) seraient sans doute plus utiles. Plus difficiles à estimer par des mesures actives, elles conviennent par contre bien aux mesures passives (voir « Internet tomography » de Coates, M., Hero, A., Nowak, R., and B. Yu et ou iPlane).

Toutes les techniques de la section 2.1, où l'application cherche à se faire une idée de la topologie du réseau souffrent des mêmes problèmes : l'Internet est compliqué (section 3). Par exemple, le chemin le plus court n'est pas forcément le meilleur. Et la topologie ne renseigne pas sur les coûts financiers des liens, par exemple sur le fait que le transit est plus cher que le peering. Enfin, comme toutes les mesures actives, elles ajoutent à la charge du réseau.

Deuxième groupe, dans la section 2.2, les méthodes fondées sur une coopération entre les couches. Ce sont celles où l'application, au lieu de devoir faire les mesures elle-même, peut interroger un service qui a été configuré (typiquement par le FAI) avec des informations sur le réseau, sa capacité, son coût, etc. La plus connue est P4P (section 2.2.1) où des serveurs, les iTrackers, sont interrogés par les applications qui récupèrent ainsi des informations utiles. Des expériences, par exemple celle décrite dans le RFC 5632 indiquent que les gains de temps pour un téléchargement peuvent dépasser un facteur 2. Si le RFC ne parle pas des problèmes politiques, on note que ce mécanisme nécessite que le FAI soit prêt à révéler une partie de la structure de son réseau.

Une autre solution, décrite dans la section 2.2.2, est celle des « oracles » où l'application, au lieu d'avoir accès à des informations sur le réseau, fournit une liste de pairs potentiels et l'oracle lui indique les plus favorables. Là encore, le RFC ne rentre pas dans les questions politiques mais on voit que l'oracle acquière beaucoup d'informations sensibles, notamment sur les pairs avec qui on communique.

Une variante (section 2.2.3) du cas de l'oracle est celui où les deux machines qui veulent communiquer se connaissent déjà mais hésitent sur les adresses IP à utiliser, puisque ce choix influencera le chemin pris (cela ne concerne évidemment que les machines ayant plusieurs adresses). Cette approche, utilisée dans le système IDIPS (voir Saucez, D., Donnet, B., and O. Bonaventure, « Implementation and Preliminary Evaluation of an ISP-Driven Informed Path Selection », CoNEXT 2007) pourrait être utilisé pour le pair-à-pair en considérant l'ensemble des pairs possibles comme étant une immense machine virtuelle qu'on cherche à atteindre, un genre d'anycast.

Bien des questions restent ouvertes à l'heure actuelle (section 4). Ainsi, le problème des machines malveillantes qui vont essayer, dans le cas où le système de mesure est distribué, de perturber les mesures ou d'injecter de faux résultats (section 4.2). Dans un réseau de la taille de l'Internet, et compte-tenu du fait que certains ont un intérêt financier à limiter le partage de fichiers, il ne fait guère de doute qu'il y aura de telles machines pirates. Il n'existe pas actuellement de solutions miracles contre elles. Des tests de vraisemblance ont été proposés, pour vérifier si les mesures d'une machine ne s'écartent pas trop de celles des autres. Mais ces tests sont souvent fondés sur des suppositions qui ne sont pas forcément vraies sur l'Internet (comme l'inégalité triangulaire citée plus haut). Dans les cas où les pairs interrogent un oracle, la question de l'authentification de l'oracle est également cruciale. Mais les réseaux pair-à-pair se prêtent mal aux lourdes solutions d'identité comme les PKI.

Une variante de ce dernier problème se pose d'ailleurs au sujet de l'intégrité des données transmises (section 4.3). Ce n'est pas tout d'authentifier le pair ou l'oracle, encore faut-il être sûr que les informations reçues n'ont pas été modifiées en cours de route. Une telle modification permettrait, par exemple, d'affecter un coût très faible à une cible et de faire réaliser ainsi une dDoS contre elle (RFC 4732).

Enfin, parmi les différents problèmes encore largement ouverts, on peut citer les cas où l'optimisation marche trop bien (section 4.6). Poussée à l'extrême, en effet, l'optimisation ferait que les pairs ne s'adressent qu'à des pairs très proches, chez le même FAI et dans la même région. Les grands essaims pair-à-pair se fragmenteraient alors en essaims locaux, n'ayant pas de communication entre eux, ce qui réduirait la redondance qui fait la solidité du pair-à-pair (voir « Pushing BitTorrent Locality to the Limit » de Stevens Le Blond, Arnaud Legout et Walid Dabbous).


Téléchargez le RFC 6029


L'article seul

RFC 6020: YANG - A data modeling language for the Network Configuration Protocol

Date de publication du RFC : Octobre 2010
Auteur(s) du RFC : M. Bjorklund (Tail-f Systems)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF netmod
Première rédaction de cet article le 6 octobre 2010


Le protocole standard Netconf (normalisé dans le RFC 6241) permet de configurer un équipement réseau (par exemple un commutateur) à distance. Netconf fonctionne par des RPC dont les paramètres sont des actions à faire effectuer par l'équipement configuré, ou bien les nouvelles valeurs que peut prendre telle ou telle des variables de configuration de cet équipement. Mais comment savoir quelles actions sont possibles, quelles variables existent, et quelles valeurs elles peuvent prendre ? Jusqu'à présent, cela pouvait se spécifier uniquement dans une documentation en langue naturelle fournie avec l'équipement. Désormais, il est possible de spécifier ces informations dans un langage formel, Yang, que décrit notre RFC.

Ce RFC 6020 est très détaillé, près de deux cents pages. Et je n'ai pas personnellement d'expérience pratique avec Yang. Donc, je ne donne ici qu'un très bref résumé. Un tel survol se trouve également dans la section 4 du RFC : Yang modélise les données qui seront utilisées par Netconf. Ces données sont représentées sous forme arborescente. Yang est modulaire (section 5 du RFC), un module Yang pouvant se référer à d'autres modules. Yang définit un ensemble de types pour décrire les données (section 9 et RFC 6991). Il permet également d'indiquer les contraintes que doivent respecter les données. Yang, langage de haut niveau, ne décrit pas l'encodage utilisé sur le câble.

Yang a donc bien des points communs avec le SMI des RFC 2578 et RFC 2579. Avant Netconf, beaucoup de gens pensaient que toute la gestion des équipements réseau se ferait en SNMP, en s'appuyant sur ce modèle SMI. Si, pour la lecture des variables, SNMP s'est largement imposé, force est de constater que, pour l'écriture de variables et pour les actions, SNMP reste très peu utilisé, au profit de toute une galaxie de mécanismes privés (Web, REST, SSH + CLI, etc), galaxie que Netconf vise à remplacer. Une MIB du SMI peut donc être traduite en Yang, l'inverse n'étant pas vrai (Yang étant plus riche).

La syntaxe de Yang utilise des groupes emboîtés, délimités par des accolades. Mais une syntaxe équivalente, en XML, existe, sous le nom de Yin. Tout module Yang peut être traduit en Yin sans perte et réciproquement (voir la section 11 pour plus de détails sur Yin).

Donc, un engin donné, routeur ou autre équipement qu'on veut gérer, est décrit par des modules Yang. Lorsqu'un serveur Netconf à bord dudit engin met en œuvre un module Yang, cela veut dire qu'il permet de modifier, via Netconf, les variables décrites dans le module (le serveur typique met en œuvre plusieurs modules). Voici le début d'un module possible :

     // Only an example, not a real module. 
     module acme-system {
         namespace "http://acme.example.com/system";
         prefix "acme";

         organization "ACME Inc.";
         contact "joe@acme.example";
         description
             "The module for entities implementing the ACME system.";

         revision 2010-08-05 {
             description "Initial revision.";
         }
...

On l'a dit, Yang est arborescent. Les feuilles de l'arbre (section 4.2.2.1 du RFC) contiennent une valeur particulière, par exemple, ici, le nom de l'engin géré :

       leaf host-name {
           type string;
           description "Hostname for this system";
       }

Ici, leaf est un mot-clé de Yang qui indique une feuille de l'arbre (plus de nœuds en dessous), host-name est le nom que l'auteur du module a donné à une variable, de type « chaîne de caractères ». Lorsqu'un serveur Netconf enverra cette information à un client (ou réciproquement), elle sera encodée en XML ainsi (Netconf utilise XML pour l'encodage des messages) :


       <host-name>my-router.example.com</host-name>

Donc, pour résumer, Yang modélise ce qu'on peut lire ou modifier, Netconf permet de le lire ou de le modifier effectivement.

Par contre, si un nœud de l'arbre Yang n'est pas une feuille, il est désigné par le mot-clé container. Par exemple, il y a ici deux containers emboîtés et une feuille :

     container system {
         container login {
             leaf message {
                 type string;
                 description
                     "Message given at start of login session";
             }
         }
     }

Lorsque Netconf utilise cette donnée, cela ressemblera, sur le câble, à ceci :


     <system>
       <login>
         <message>Good morning</message>
       </login>
     </system>

Yang dispose d'un certain nombre de types pour représenter les données (section 4.2.4 et RFC 6991), mais on peut aussi créer ses types (sections 4.2.5 et 7.3) par exemple ainsi :

     typedef percent {
         type uint8 {
             range "0 .. 100";
         }
         description "Percentage";
     }

     leaf completed {
         type percent;
     }

On a ajouté un intervalle de validité au type prédéfini uint8. Autre exemple, en indiquant une valeur par défaut, et en dérivant d'un type défini dans le module inet :

     typedef listen-ipv4-address {
         type inet:ipv4-address;
         default "0.0.0.0";
     }

Yang a bien d'autres possibilités, décrites en détail dans les sections suivantes. Par exemple, dans un monde idéal, tous les engins mettant en œuvre un module Yang donné géreraient la totalité des variables du module. Mais, comme ce n'est pas forcément le cas, Yang permet des déviations (sections 5.6.3 et 7.18.3). Prenons l'exemple du RFC, un routeur BGP qui suit un module Yang BGP. Le module ne donne pas de limite au nombre de pairs BGP mais un routeur bas de gamme pourrait avoir une limite, disons à 16 pairs. Un client Netconf qui tenterait de configurer un dix-septième pair recevrait donc une erreur. Le mot-clé Yang deviation permettrait audit client de savoir à l'avance en quoi ce routeur particulier dévie du modèle BGP général. Le client Netconf n'aurait donc pas à essayer pour voir, il pourrait savoir à l'avance que l'opération de configuration du dix-septième pair ne marchera pas.

La syntaxe formelle de Yang est décrite en section 6. Elle ressemble à celle de langages de programmation comme C ou à celle de SMIng du RFC 3780 (RFC qui n'a pas eu de succès). Cette syntaxe favorise la lisibilité par des humains, le cahier des charges étant de privilégier les lecteurs, pas les auteurs de modules, ni les programmeurs d'outils Yang. À noter que, comme dans toutes les normes modernes, Yang n'est pas limité à l'ASCII et peut utiliser tout Unicode.

Bien que Yang n'utilise pas XML, il réutilise un langage de ce monde, XPath (sections 6.4 et 7.5.3). XPath sert à indiquer les dépendances entre nœuds de l'arbre.

Yang permet en effet de définir des contraintes (section 8) que doivent respecter les variables, avec la directive must. Par exemple :

         must "ifType != 'ethernet' or " +
              "(ifType = 'ethernet' and ifMTU = 1500)" {
             error-message "An ethernet MTU must be 1500";
         }

Voici un exemple de requête Netconf complète, correspondant à une variable Yang. Soit un équipement muni d'un serveur SSH et d'un serveur Netconf pour sa configuration. Disons que le serveur Netconf met en œuvre la variable Yang port, définie ainsi :

     leaf port {
         type inet:port-number;
         default 22;
         description "The port which the SSH server listens to"
     }

La requête Netconf <edit-config> (RFC 6241, section 7.2) qui configure le serveur SSH pour écouter sur le port 2022 serait :


     <rpc message-id="101"
          xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"
          xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
       <edit-config>
         <target>
           <running/>
         </target>
         <config>
           <system xmlns="http://example.com/schema/config">
             <services>
               <ssh>
                 <port>2022</port>
               </ssh>
             </services>
           </system>
         </config>
       </edit-config>
     </rpc>

Le choix de Yang comme langage standard pour la description des capacités d'un serveur Netconf ne s'était pas fait sans mal. Plusieurs concurrents avaient été envisagés notamment Relax NG, un choix logique puisque Netconf utilise XML. Un langage de description de schémas comme Relax NG semblait donc un choix raisonnable. Parmi les discussions à ce sujet, citons par exemple le débat qui avait eu lieu sur la liste du secteur Applications de l'IETF. Les raisons du choix de Yang, telles que vues par les concepteurs de Yang, sont décrites sur le site officiel du projet mais je trouve cette comparaison très unilatérale.

Un bon tutoriel Netconf, couvrant également Yang, est disponible en http://www.aims-conference.org/issnsm-2008/06-netconf-yang.pdf.

Quelles sont les mises en œuvre de Yang ? Il en existe une liste sur le site officiel. Voyons par exemple l'outil pyang, qui sert à valider des schémas Yang et à les convertir dans d'autres formats. Il ne semble plus maintenu depuis longtemps mais, bon, il marche. Il peut produire du XSD et du RelaxNG - enfin du DSDL mais c'est presque pareil. Voici un exemple de test d'un schéma invalide (leaf a été tapé laf) :


% pyang test.yang
test.yang:11: error: unexpected keyword "laf"

Et, si on corrige :

% pyang test.yang
% 

Maintenant, convertissons en Yin :


% cat test.yang
 module acme-foo {
         namespace "http://acme.example.com/foo";
         prefix "acfoo";

         list interface {
             key "name";
             leaf name {
                 type string;
             }

             leaf mtu {
                 type uint32;
                 description "The MTU of the interface.";
             }
         }
     }

% pyang -fyin test.yang
<?xml version="1.0" encoding="UTF-8"?>
<module name="acme-foo"
        xmlns="urn:ietf:params:xml:ns:yang:yin:1"
        xmlns:acfoo="http://acme.example.com/foo">
  <namespace uri="http://acme.example.com/foo"/>
  <prefix value="acfoo"/>
  <list name="interface">
    <key value="name"/>
    <leaf name="name">
      <type name="string"/>
    </leaf>
    <leaf name="mtu">
      <type name="uint32"/>
      <description>
        <text>The MTU of the interface.</text>
      </description>
    </leaf>
  </list>
</module>

Et voici une conversion du même code en DSL :


% pyang -fdsdl test.yang
<?xml version='1.0' encoding='UTF-8'?>
<grammar datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"
	 ns="http://acme.example.com/foo"
	 xmlns="http://relaxng.org/ns/structure/1.0"
	 xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0"
	 xmlns:acfoo="http://acme.example.com/foo"
	 xmlns:dc="http://purl.org/dc/terms"
	 xmlns:dsrl="http://purl.oclc.org/dsdl/dsrl"
	 xmlns:nm="urn:ietf:params:xml:ns:netmod:dsdl-attrib:1"
	 xmlns:sch="http://purl.oclc.org/dsdl/schematron">
  <dc:source>YANG module 'acme-foo' (automatic translation)</dc:source>
<start>
   <zeroOrMore>
      <element name="interface" nm:key="name">
	  <element name="name">
	     <data type="string"/>
	  </element>
	  <optional>
	     <element name="mtu"><a:documentation>The MTU of the interface.</a:documentation>
		<data type="unsignedInt"/>
	     </element>
	  </optional>
       </element>
   </zeroOrMore>
</start>
</grammar>

Outre pyang, il y a bien entendu même un mode Emacs, yang-mode.

Le site officiel du projet, http://www.yang-central.org/, contient beaucoup d'autre information sur Yang. Une version de plus récente de Yang existe aussi, la 1.1, normalisée dans le RFC 7950.


Téléchargez le RFC 6020


L'article seul

RFC 6018: IPv4 and IPv6 Greynets

Date de publication du RFC : Septembre 2010
Auteur(s) du RFC : F. Baker (Cisco), W. Harrop, G. Armitage (CAIA, Swinburne University of Technology)
Pour information
Première rédaction de cet article le 30 septembre 2010


Il y a longtemps que les chercheurs en sécurité des réseaux utilisent des darknets, des réseaux dont les adresses IP ne sont normalement pas attribuées, pour analyser les attaques. Si on annonce une route vers un tel réseau, le trafic qu'on capte est essentiellement composé d'attaques ou de reconnaissances préalables à une attaque puisque rien de légitime ne peut utiliser ces réseaux. L'inconvénient des darknets est qu'ils sont trop gros et trop visibles : les attaquants apprennent vite leur existence et les mettent alors sur leur liste « pas touche » et les attaques cessent. Ce RFC décrit une alternative, le greynet, dont le préfixe IP est alloué et routé mais au sein duquel certaines adresses ne correspondent pas à une machine en activité.

Normalement, un routeur IP doit jeter les datagrammes destinés à une adresse qui ne répond pas aux requêtes ARP (RFC 826) ou ND (RFC 4861). On pourrait envisager de configurer des règles spéciales par adresse IP, pour copier les datagrammes destinés à ces machines vers la sonde d'observation. Mais, pour construire facilement le greynet, le RFC suggère une autre méthode : configurer le routeur pour que, au lieu de jeter les paquets qui ne peuvent pas être délivrés, il les copie vers la machine de surveillance. Toute adresse IP non affectée devient alors membre du greynet.

On peut ainsi détecter les attaques (ou les reconnaissances) vers ces adresses, mais aussi les cas d'usurpation de ces adresses par un tiers. Ces usurpations vont en effet produire du backscatter, de l'émission par les cibles en réponse aux reconnaissances, et une partie au moins de ce backscatter atteindra le greynet.

La section 2 sert ensuite de manuel pour l'administrateur réseaux qui voudrait déployer un tel système. Il doit évidemment d'abord mettre en place la machine de collecte, qui va recevoir les paquets, les enregistrer et plus tard les analyser. Ensuite, il peut utiliser le routage IP normal et choisir un préfixe non utilisé pour le router vers cette machine, créant ainsi un darknet (section 2.1). Sur Linux, par exemple, cela se ferait avec route add -net 192.0.2.128/25 gw 198.51.100.1192.0.2.128/25 est le préfixe du darknet et 198.51.100.1 l'adresse de la machine de collecte.

Mais s'il veut faire un greynet, il lui faut un routeur un peu spécial (section 2.2) qui va devoir, lorsqu'il reçoit un paquet pour lequel il n'a pas eu de réponse aux requêtes ARP et ND, le faire suivre à la machine de collecte. C'est à la fois plus simple qu'un darknet (pas de configuration explicite, à part l'adresse de la machine de collecte, cf. section 3) et plus compliqué (aucun routeur IP normal ne sait faire cela : en cas de non-réponse à ARP et ND, le paquet est abandonné).

La première documentation des greynets était dans « Greynets: a definition and evaluation of sparsely populated darknets », dans la 30th Conference on Local Computer Networks de l'IEEE en 2005. Elle a été suivie de plusieurs expériences, résumées dans la section 1.1 du RFC. L'utilisation du routeur pour identifier les adresses du greynet (ce sont celles qui ne répondent pas en ARP ou en ND) est venue après. La première mise en œuvre était sur un routeur Linux. Le fichier à récupérer est http://www.owenstephens.co.uk/files/neigh_fwd.c, et il se place dans le répertoire net/core des sources du noyau. Il faut ensuite appeler les fonctions nécessaires depuis neighbour.c, le moyen le plus simple étant sans doute de patcher ce dernier avec http://www.owenstephens.co.uk/files/neighbour.c.diff. (Merci à Owen Stephens pour avoir mis les sources en ligne.)

L'ajout d'IPv6 est venue encore ultérieurement. Bien qu'on entende souvent dire qu'un balayage complet d'un réseau IPv6 est impossible, vu le nombre d'adresses possibles, le RFC 7707 a montré que c'était faux. En pratique, les attaques IPv6 n'ont jamais été observées dans la nature mais il ne fait guère de doute que cela se produira un jour.

Un dernier avertissement pour ceux qui veulent tenter l'aventure : lisez bien la section 6 sur la sécurité. Tout dispositif de collecte peut faire l'objet d'abus, par exemple par un méchant qui, sachant qu'une collecte est en cours, va tenter de la saturer en envoyant plein de paquets.


Téléchargez le RFC 6018


L'article seul

RFC 6014: Cryptographic Algorithm Identifier Allocation for DNSSEC

Date de publication du RFC : Novembre 2010
Auteur(s) du RFC : P. Hoffman (VPN Consortium)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dnsext
Première rédaction de cet article le 22 novembre 2010


L'allocation d'un nouveau numéro pour un algorithme cryptographique dans DNSSEC exigeait auparavant un RFC sur le chemin des normes. Désormais, n'importe quel RFC conviendra, ce qui est une libéralisation bienvenue.

Ces numéros sont attribués par l'IANA, stockés dans un registre public et permettent, lorsqu'on récupère un enregistrement DNSSEC, de savoir comment l'interpréter. Ainsi, le TLD .pm est signé avec l'algorithme de numéro 8, soit RSA/SHA-256 :

% dig +dnssec ANY pm.
...
pm.  172800 IN RRSIG SOA 8 1 172800 20100818151448 20100719141448 14659 pm. oepDlhY...

L'espace de nommage de ces codes ne fait qu'un seul octet, soit 256 possibilités seulement. Ce point a fait l'objet d'inquiétudes au moment de la libéralisation de l'allocation.

La norme DNSSEC, le RFC 4034 (section 7), reprenant des normes antérieures, impose un « IETF standards action » pour enregistrer un nouveau code, sauf pour 253 et 254, qui sont utilisables pour de expérimentations sans formalité. Une « IETF standards action », comme nous l'apprend le RFC 5226, est la publication d'un RFC situé sur le chemin des normes. C'est donc une opération plutôt lourde (mais possible : GOST a eu le numéro 12 ainsi, grâce au RFC 5933).

La section 2 du RFC explique le pourquoi de la libéralisation :

  • Certains algorithmes méritants peuvent avoir du mal à passer sur le chemin des normes, par exemple par suite de craintes sur les brevets qui les plombent, ou simplement parce qu'il n'ont pas encore été scrutés avec suffisamment d'attention. (Voir aussi la section 5 pour une discussion sur la sécurité des algorithmes et leur normalisation.)
  • Les demandes sont peu fréquentes (on n'invente pas un nouvel algorithme de cryptographie tous les jours !) et il y a donc peu de chances de voir les huits bits de l'espace occupés immédiatement.

Pour être complètement en sécurité, notre RFC demande à l'IETF de réévaluer les critères d'allocation lorsque 120 entrées du registre auront été allouées (en juillet 2010, on en a 11...). C'est pour cela que la plage 123-251 du registre est marquée comme réservée. Et les codes 253 et 254 restent disponibles pour les expérimentations.

Quelles sont les conséquences pour les mises en œuvre de DNSSEC (section 3) ? D'abord, il faut bien voir qu'un programme qui fait du DNSSEC n'a jamais été obligé d'implémenter tous les algorithmes du registre. Ceci ne change pas. Il y aura donc toujours des algorithmes qui ne seront pas universellement mis en œuvre. Les seuls algorithmes qui sont garantis sont ceux indiqués comme obligatoires dans le RFC 4034 (annexe A.1) ou son successeur. Actuellement, il n'y a que RSA/SHA-1.

Enfin, notons que le RFC précise que l'ordre des algorithmes dans le registre n'implique rien sur leur force cryptographique respective, ou leur sécurité...

Comme notre RFC ne fait que changer une règle d'allocation dans un registre IANA, toute sa partie normative se concentre dans la section 4, « IANA considerations ». En un mot, un RFC de n'importe quel statut suffit désormais pour demander un code dans le registre. Certains cas dans DNSSEC n'étaient pas couverts par cette libéralisation, mais c'est désormais le cas depuis le RFC 9157.


Téléchargez le RFC 6014


L'article seul

RFC des différentes séries : 0  1000  2000  3000  4000  5000  6000  7000  8000  9000