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 5992: Internationalized Domain Names Registration and Administration Guideline for European languages using Cyrillic

Date de publication du RFC : Octobre 2010
Auteur(s) du RFC : S. Sharikov (Regtime Ltd), D. Miloshevic (Afilias), J. Klensin
Pour information
Première rédaction de cet article le 5 octobre 2010


Les noms de domaines internationalisés connaissent en ce moment un intérêt particulier, notamment en raison de leur déploiement (très tardif) dans la racine (ainsi, .рф a été ajouté le 12 mai 2010). Plusieurs RFC ont été publiés pour adapter la norme IDN (Internationalized Domain Names) à différentes écritures et/ou langues et notre tout neuf RFC 5992 s'ajoute à la liste, pour le cas de l'alphabet cyrillique.

Contrairement au RFC 5564 qui n'envisageait que le cas d'une seule langue, ce RFC 5992 veut couvrir la plupart des langues qui utilisent aujourd'hui une écriture, la cyrillique. Il s'applique donc au russe mais aussi au bulgare, à l'ukrainien, au serbe, etc.

Parmi toutes les écritures existantes, beaucoup ne servent que pour une seul langue. Ce n'est pas le cas de l'alphabet cyrillique, qui sert pour plusieurs langues slaves mais aussi pour des langues parlées dans l'ancien empire des tsars tel que le same de Kildin ou (bien que cela ne soit plus guère le cas depuis la chute de l'URSS) les langues « asiatiques » comme l'azéri ou le kirghiz. Ce RFC se focalise sur les langues utilisées en Europe, ce qui inclus les langues slaves et le cas particulier du same de Kildin.

À noter que le cyrillique, dérivé de l'alphabet grec, partage avec ce dernier et avec son cousin l'alphabet latin, plusieurs caractères, ce qui peut mener dans certains cas à des confusions. Les problèmes que pourraient poser celles-ci ne sont pas détaillés dans le RFC, qui fait sans doute allusion au FUD comme quoi IDN augmenterait les risques de hameçonnage.

D'autre part, même dans les pays où l'écriture officielle est uniquement en cyrillique, et où son usage domine, on constate également une certaine présence de l'alphabet latin (par exemple pour les sigles techniques, regardez un article d'informatique écrit en russe, pour un exemple voir l'article du Wikipédia russophone sur le Web et ses mentions de HTML). Les utilisateurs souhaiteraient donc parfois pouvoir enregistrer des noms de domaine mêlant les deux alphabets, ce que le RFC déconseille fortement, sans expliquer pourquoi (section 1).

La section 1.1 expose la question des caractères « similaires » (terme impossible à définir rigoureusement, entre autres parce que cela dépend de la police d'affichage). Sans expliquer vraiment le problème, le RFC propose d'utiliser des mécanismes de « variantes » tels que présentés dans les RFC 3743 et RFC 4290.

Place maintenant aux langues et à leurs caractères. La section 2 décrit précisement les caractères nécessaires pour chaque langue. Vingt-trois « caractères de base » sont introduits, car ils sont communs à toutes les langues. Ils vont de U+0430 (а) à U+0448 (le cha, ш), mais avec quelques trous. Ils incluent en outre les chiffres et le tiret. Il suffit donc ensuite de définir pour chaque langue les quelques caractères supplémentaires nécessaires. (On peut noter que la liste utilisée par le registre du .eu a 32 caractères.)

Ainsi, le « serbo-bosnien » utilise les vingt-trois caractères de base plus sept autres, comme le U+045F (« dzhe », џ). Le bulgare n'a pas ce caractère mais se sert entre autres du U+044F (ya, я). Le russe a besoin de trente-trois caractères en tout. Le RFC donne la liste complète pour chaque langue slave. Celles qui ne s'écrivent pas en cyrillique (ou qui ne s'écrivent plus dans cet alphabet, comme le moldave) ont été omises. À noter que, pour certaines langues, il existait déjà une liste officielle des caractères nécessaires. C'est le cas du monténégrin pour lequel la norme gouvernementale est http://www.gov.me/files/1248442673.pdf. En revanche, pour d'autres langues, il semble que l'orthographe ne soit pas complètement stabilisée. C'est le cas de l'ukrainien où les chiffres vont de trente-et-un à trente-quatre caractères (la dernière valeur étant recommandée par le RFC, pour être sûr de tout couvrir). Par exemple, certains affirment que le U+044A (ъ) est nécessaire, d'autres disent qu'il vaut mieux utiliser le U+044C (ь) à la place. (À noter que les linguistes considèrent souvent que certaines langues n'en sont pas réellement, elles ont juste un nom différent pour des raisons politiques. Le monténégrin n'existe ainsi que depuis l'indépendance du Monténégro, tout le monde l'appelait serbe avant...)

Seule langue non-slave du groupe, le same de Kildin fait l'objet de la section 2.4. Son orthographe n'est pas normalisée et son système de sons est complexe, et difficile à rendre en cyrillique. Il faut donc rajouter trente-trois caractères au jeu de base comme par exemple le U+04CE (ӎ). La section 2.4 contient des références vers des sources plus précises sur cette langue et son orthographe, si vous voulez approfondir la question.

Une fois ces listes établies, on peut compiler des tables qui indiquent les caractères autorisés (sections 3 et 4). La section 5 donne le format de la table qui figure dans l'annexe A du RFC : elle comprend au moins ligne de quatre colonnes par caractère. La première colonne indique le point de code Unicode du caractère cyrillique, la seconde son nom, la troisième et la quatrième les points de code et noms d'un caractère latin ou grec qu'on peut confondre avec le caractère cyrillique. Ainsi, U+0430 (le а cyrillique) est indiqué comme confondable avec le petit a latin, U+0061, mais aussi avec l'alpha grec, si on met les deux lettres en majuscules (le +++ dans la première colonne indique que la confusion n'existe qu'en cas de changement de casse). De même, le U+0433 (г, le ge) est indiqué comme proche du petit r, U+0072. Notez qu'il s'agit bien d'une confusion visuelle et pas sémantique. Le U+0440 (р) peut être confondu avec le p latin mais il représente un son complètement différent (proche du r).

Bien, armé de ces observations et de cette table, que peut faire un registre de noms de domaines qui accepte les caractères cyrilliques ? Prenons l'exemple classique du sigle russe de l'ancienne URSS, СССР. Ce sigle en cyrillique { U+0421 U+0421 U+0421 U+0420 } et le texte latin { U+0043 U+0043 U+0043 U+0050 } sont très proches. Alors, que doit faire un registre qui accepte les caractères cyrilliques et les latins (ce qui est le cas de .eu) ? Il peut allouer СССР et CCCP (le premier est en cyrillique, le second en latin) au même titulaire. Il peut n'autoriser qu'un des deux noms et bloquer l'autre. Ici, il n'y a que deux variantes. Mais, dans certains cas, il peut y en avoir plus (surtout en ajoutant l'alphabet grec ce qui, là encore, est le cas du .eu). Le registre peut alors choisir une solution intermédiaire en enregistrant certaines variantes et en bloquant d'autres. Ces possibilités, et leurs conséquences, sont discutées dans la section 6.


Téléchargez le RFC 5992


L'article seul

RFC 5988: Web Linking

Date de publication du RFC : Octobre 2010
Auteur(s) du RFC : M. Nottingham
Chemin des normes
Première rédaction de cet article le 29 octobre 2010


Le lien est à la base du Web. Mais, malgré plusieurs tentatives, deux choses manquaient aux liens Web que ce RFC est venu combler :

  • Un registre des types de lien,
  • Un mécanisme standard pour indiquer un lien dans une réponse HTTP.

Il a depuis été remplacé par le RFC 8288.

Bien sûr, des formats normalisés qui permettent des liens, il y en a plusieurs, et avant tout HTML, avec le fameux élément <A> (pour anchor). Il y a aussi le plus récent Atom (RFC 4287, notamment la section 4.2.7). Comme HTML, Atom avait l'idée de registre des types de liens, mais ces types étaient spécifiques à Atom. L'une des idées phares de ce RFC 5988 est de généraliser le concept de type de lien et de le rendre accessible à tous les formats et protocoles qui en ont besoin. Ce RFC décrit un cadre général pour les types de liens, en partant de celui d'Atom.

Second apport de cette nouvelle norme, une (re-)définition de l'en-tête HTTP Link:, utilisant évidemment le nouveau cadre général. Cet en-tête permettant d'indiquer un lien dans la réponse HTTP, indépendamment du document servi avait été normalisé dans le RFC 2068, section 19.6.2.4, puis, peu utilisé, avait été supprimé par le RFC 2616, avant de faire se réapparition ici, sous une forme quasi-identique à l'original. On peut voir cet en-tête comme une représentation concrète du cadre de notre RFC. D'autres apparaîtront sans doute.

Pour un exemple réel, regardez les en-têtes Link: de mon blog, il y en a un de type licence, suivant le RFC 4946. Avec Apache, cela se configure simplement avec le module headers et la directive Header set Link "<http://www.gnu.org/copyleft/fdl.html>; rel=\"license\"; title=\"GFDL\"".

Donc, qu'est-ce qu'un lien ? La section 3, la principale du RFC, le définit comme une connexion typée entre deux ressources (une ressource étant typiquement une page Web). Les ressources sont représentées par leur IRI (cf. RFC 3987, en notant que, dans la plupart des cas, les IRI des liens seront des URI). Le lien comprend :

  • Un IRI qui indique le contexte, c'est-à-dire le la ressource de départ,
  • Le type de la connexion (détaillé en section 4),
  • L'IRI cible,
  • D'éventuels attributs de la cible (comme par exemple le hreflang de HTML). Ce sont des couples clé/valeur.

Par exemple, dans le flux de syndication Atom de mon blog, on trouvera un lien <atom:link rel="alternate" href="http://www.bortzmeyer.org/expose-go.html"/> qui se décompose en un contexte (l'entrée Atom dont l'IRI est tag:bortzmeyer.org,2006-02:Blog/expose-go), un type (alternate, qui indique une version alternative de la ressource, ici une page HTML au lieu d'une entrée Atom), et une cible (ici http://www.bortzmeyer.org/expose-go.html). Il n'y a pas dans cet exemple d'attributs de la cible mais Atom en permet (par exemple hfrelang pour indiquer la langue de la cible ou bien length pour indiquer sa longueur - afin de prévenir d'un long téléchargement, par exemple).

Cette définition du lien ne place aucune limite sur la cardinalité. Il peut y avoir zéro, un ou plusieurs liens partant d'une ressource et c'est la même chose pour les lients entrants.

La section 3 s'arrête là. Puisque ce RFC propose un cadre générale, il ne formalise pas une syntaxe unique pour représenter les liens. Chaque format, chaque protocole, aura la sienne.

Un des points les plus importants de cette définition des liens, et qui est souvent ignorée des gens qui écrivent des pages Web, est la notion de type d'un lien (section 4). Par exemple, on pourrait imaginer un type copyright qui associerait, via un lien, un document à l'auteur de celui-ci. Point à retenir : ce type du lien ne doit pas être confondu avec le type de médium du RFC 6838 comme text/html ou audio/ogg.

Il y a deux sortes de type de lien : enregistrés ou bien extensions. Les premiers font l'objet de la section 4.1. Ils ont fait l'objet d'un processus formel d'enregistrement (qui a été discuté jusqu'au dernier moment) et leur liste est publiée sous forme d'un registre IANA. On y trouve par exemple via (RFC 4287) ou hub (http://pubsubhubbub.googlecode.com).

Les extensions sont spécifiées dans la section 4.2. L'idée est que, si on n'a pas envie de se fatiguer à enregistrer un type de lien, et qu'on veut quand même créer un type unique, n'ayant pas de risque de collision avec le travail des autres, on peut simplement se servir d'un URI (forcément unique) pour indiquer le type. Cette URI peut (mais ce n'est pas obligé) mener à une page Web qui décrira le type en question. Ainsi, on pourrait imaginer de réécrire le lien plus haut en <atom:link rel="http://www.bortzmeyer.org/reg/my-link-type" href="http://www.bortzmeyer.org/expose-go.html"/> (en pratique, le format Atom ne permet pas actuellement de telles valeurs pour l'attribut rel.)

Après le cadre général de description des liens, notre RFC introduit une syntaxe concrète pour le cas de l'en-tête Link: des requêtes HTTP. Les autres formats et protocoles devront s'ajuster à ce cadre chacun de son côté. Pour HTTP, la section 5 décrit l'en-tête Link:. La cible doit être un URI (et un éventuel IRI doit donc être transformé en URI), le contexte (l'origine) est la ressource qui avait été demandée en HTTP et le type est indiqué dans le paramètre rel. (Le paramètre rev qui avait été utilisé dans des vieilles versions est officiellement abandonné.) Plusieurs attributs sont possibles comme hreflang, type (qui est le type MIME, pas le type du lien) ou title (qui peut être noté title* s'il utilise les en-têtes étendus du RFC 5987). Pour la plupart de ces attributs, leur valeur est juste une indication, la vraie valeur sera obtenue en accédant à la ressource cible. Ainsi, hreflang dans le lien ne remplace pas Content-Language: dans la réponse et type ne gagnera pas si un Content-Type: différent est indiqué dans la réponse.

Voici des exemples d'en-têtes, tirés de la section 5.5 du RFC :

Link: <http://www.example.com/MyBook/chapter2> rel="previous";
    title="Previous chapter"

Ici, cet en-tête, dans une réponse HTTP, indique que http://www.example.com/MyBook/chapter2 est une ressource liée à la ressource qu'on vient de récupérer et que ce lien est de type previous, donc précède la ressource actuelle dans l'ordre de lecture. L'attribut title indique un titre relatif, alors que la vraie ressource http://www.example.com/MyBook/chapter2 aura probablement un titre du genre « Chapitre 2 ». En application des règles de la section 5.4, c'est ce dernier titre qui gagnera au final.

Un seul en-tête Link: peut indiquer plusieurs liens, comme dans l'exemple suivant :


   Link: </TheBook/chapter2>;
         rel="previous"; title*=UTF-8'de'letztes%20Kapitel,
         </TheBook/chapter4>;
         rel="next"; title*=UTF-8'de'n%c3%a4chstes%20Kapitel

Ce dernier montre également les en-têtes complètement internationalisés du RFC 5987, ici en allemand (étiquette de langue de).

Cet en-tête a été enregistré à l'IANA, en application du RFC 3864 dans le registre des en-têtes (section 6.1).

D'autre part, le registre des types de liens est désormais officiellement créé, remplaçant des registres qui étaient spécifiques à un format ou protocole (comme celui d'Atom, qui avait été créé par le RFC 4287). La section 6.2 décrit en détail ce nouveau registre. Voici, à titre d'exemple, quelques-uns des valeurs qu'on peut y trouver :

  • copyright qui indique le copyright du document (issu de la norme HTML),
  • edit qui indique l'URI à utiliser pour une modification de ce document, comme le permet le protocole APP (RFC 5023),
  • first, qui pointe vers le premier document de la série (défini par ce RFC 5988, même s'il était déjà enregistré),
  • hub qui indique l'endroit où s'abonner pour des notifications ultérieures, suivant le protocole PubSubHubbub),
  • latest-version qui indique où trouver la dernière version d'un document versionné (RFC 5829),
  • licence, qui associe un document à sa licence d'utilisation (RFC 4946),
  • next-archive, qui indique le document archivé suivant (RFC 5005),
  • related, qui indique un document qui a un rapport avec celui-ci (créé pour Atom, dans le RFC 4287),
  • replies, qui indique les réponses faites à ce document (pour mettre en œuvre le threading, RFC 4685),
  • Et bien d'autres encore...

Ce registre est peuplé par le mécanisme dit Designated Expert (cf. RFC 5226), avec exigence d'une norme écrite (l'actuel expert est Mark Nottingham, auteur de plusieurs RFC, dont celui-ci). Pour chaque type, il faudra indiquer le type (aussi nommé relation, comme par exemple previous plus haut), une description et une référence à la norme qui le formalise. Les demandes d'enregistrement sont reçues par link-relations@ietf.org. Par exemple, en novembre 2010, des relations comme search ou help (lien vers une aide en ligne) ont été ajoutées.

Attention, ce n'est pas parce qu'il y a un lien qu'il faut le suivre automatiquement. La section 7, sur la sécurité, met en garde contre la confiance accordée à un lien.

L'annexe A contient une discussion de l'utilisation des liens avec HTML 4, d'où le cadre actuel de définition des liens est issu. Le type y est indiqué par l'attribut rel. Un exemple indiquant la licence en XHTML est donc :


<link rel="license" type="text/html" title="GFDL in HTML format"
      href="http://www.gnu.org/copyleft/fdl.html"/>

L'annexe B discute, elle, de l'utilisation du cadre de définition des liens en Atom, qui utilise l'élément <atom:link> avec les attributs href pour indiquer la cible et rel pour le type. Par exemple, <atom:link rel="license" type="text/html" title="GFDL in HTML format" href="http://www.gnu.org/copyleft/fdl.html"/> indiquera la licence du flux Atom qui contient cet élément (et, oui, Atom et XHTML ont quasiment la même syntaxe).


Téléchargez le RFC 5988


L'article seul

RFC 5987: Character Set and Language Encoding for Hypertext Transfer Protocol (HTTP) Header Field Parameters

Date de publication du RFC : Août 2010
Auteur(s) du RFC : J. Reschke (greenbytes)
Chemin des normes
Première rédaction de cet article le 23 août 2010


Les requêtes et réponses du protocole HTTP incluent des en-têtes (comme User-Agent: ou Content-Disposition:) avec des valeurs, qui ne pouvaient se représenter directement qu'avec les caractères du jeu ISO 8859-1. Comme MIME, dans le RFC 2231, prévoyait un mécanisme très riche pour encoder les en-têtes du courrier électronique, ce RFC 5987 réutilise ce mécanisme pour HTTP (plusieurs en-têtes l'utilisaient déjà, de manière pas vraiment officielle). Pour le corps du message (voir par exemple le RFC 7578), rien ne change. Ce RFC a depuis été remplacé par le RFC 8187.

Cette restriction à Latin-1 vient de la norme HTTP, le RFC 2616, dans sa section 2.2, qui imposait l'usage du RFC 2047 pour les caractères en dehors de ISO 8859-1. (Le RFC 7230 a changé cette règle depuis.)

Notre RFC peut être résumé en disant qu'il spécifie un profil du RFC 2231. Ce profil est décrit en section 3, qui liste les points précisés par rapport au RFC 2231. Tout ce RFC n'est pas utilisé, ainsi le mécanisme en section 3 du RFC 2231, qui permettait des en-têtes de plus grande taille, n'est pas importé (section 3.1 de notre RFC).

En revanche, la section 4 du RFC 2231, qui spécifiait comment indiquer la langue dans laquelle était écrite la valeur d'un en-tête est repris pour les paramètres dans les en-têtes. Ainsi, (section 3.2.2), voici un en-tête, avec un paramètre title traditionnel en pur ASCII :

X-information: news; title=Economy

et en voici un avec les possibilités de notre RFC pour permettre les caractères £ et € (ce dernier n'existant pas dans Latin-1) :

X-information: news; title*=UTF-8''%c2%a3%20and%20%e2%82%ac%20rates

Par rapport au RFC 2231, deux jeux de caractères sont décrétés obligatoires (ISO 8859-1 et UTF-8) et la mention du jeu utilisée est également désormais obligatoire (section 3.2 de notre RFC). La langue elle-même est indiquée par une étiquette, selon la syntaxe du RFC 5646. Du fait de ces possibilités plus riches que celles prévues autrefois pour HTTP, les paramètres qui s'en servent doivent se distinguer, ce qui est fait avec un astérisque avant le signe égal (voir l'exemple ci-dessus). La valeur du paramètre inclus donc le jeu de caractères et l'encodage (obligatoire), la langue (facultative, elle n'est pas indiquée dans l'exemple ci-dessus) et la valeur proprement dite.

Voici un exemple incluant la langue, ici l'allemand (code de) :

X-quote: theater; 
    sentence*=UTF-8'de'Mit%20der%20Dummheit%20k%C3%A4mpfen%20G%C3%B6tter%20selbst%20vergebens.

La section 4 couvre ensuite les détails pratiques pour les normes qui décrivent un en-tête qui veut utiliser cette possibilité. Par exemple, la section 4.3 traite des erreurs qu'on peut rencontrer en décodant et suggère que, si deux paramètres identiques sont présents, celui dans le nouveau format prenne le dessus. Par exemple, si on a :

X-information: something; title="EURO exchange rates";
               title*=utf-8''%e2%82%ac%20exchange%20rates

le titre est à la fois en ASCII pur et en UTF-8, et c'est cette dernière version qu'il faut utiliser, même si normalement il n'y a qu'un seul paramètre title.

Ceux qui s'intéressent à l'histoire du développement de cette nouvelle norme pourront regarder les minutes de la réunion IETF 72. Ces paramètres étendus sont déjà mis en œuvre dans Konqueror (à partir de la 4.4.1), Firefox et Opera. Des tests plus détaillés sont présentés en http://greenbytes.de/tech/tc2231.


Téléchargez le RFC 5987


L'article seul

RFC 5983: Mailing Lists and Internationalized Email Addresses

Date de publication du RFC : Octobre 2010
Auteur(s) du RFC : R. Gellens (Qualcomm)
Expérimental
Réalisé dans le cadre du groupe de travail IETF eai
Première rédaction de cet article le 5 octobre 2010


L'arrivée des normes sur le courrier électronique entièrement internationalisé a suscité beaucoup d'intérêt et d'expériences. Un des points qui avait été laissé dans l'ombre au début est le cas de listes de diffusion. Ce RFC comblait le manque, explique le problème et donnait des recommandations. Il a depuis été remplacé par le RFC 6783.

Une liste de diffusion est un mécanisme par lequel un message, bien qu'envoyé à une seule adresse, est distribué à plusieurs destinataires. L'agent logiciel qui reçoit le message et le redistribue modifie l'adresse de retour indiquée dans l'enveloppe, de façon à ce que ce soit lui, et non pas l'expéditeur originel, qui reçoive les éventuels avis de non-remise. Dans le cas d'une « vraie » liste de diffusion (par exemple, pas un simple alias Postfix), le message ainsi modifié est réinjecté par une soumission normale.

Le message subit d'autres changements, comme par exempe l'ajout d'en-têtes spécialisés dans la gestion de listes (RFC 2369 et RFC 2919) comme List-Id:, qui contient une adresse, celle de la liste, ou List-Unsubscribe:, qui contient un URI, typiquement de plan mailto:.

Idéalement, cela s'arrêterait là. Mais certains MLM (Mailing List Manager, logiciels de gestion de listes) vont plus loin et modifient le message, par exemple pour ajouter un en-tête Reply-To:, ou pour ajouter le nom de la liste dans le sujet, ou bien pour ajouter du texte à la fin du message. Pire, certains modifient des en-têtes comme From:.

Il y a trois endroits où l'arrivée des adresses de courrier en Unicode a un impact sur les listes de diffusion :

  • Le transport des messages,
  • Les en-têtes mis dans les messages,
  • Les politiques de gestion de la liste.

Les questions soulevées par ces nouvelles adresses peuvent être purement techniques (un MLM pourrait par exemple refuser les adresses non-ASCII) ou plus sémantiques, liées aux utilisateurs (si la liste elle-même a une adresse ASCII, et qu'un de ses membres a une adresse Unicode, l'expéditeur pourrait être surpris si cette adresse Unicode venait à sa connaissance, même si toute la partie technique a bien fonctionné).

Certains de ces problèmes peuvent aussi arriver en communication directe, sans l'intermédiaire de la liste de diffusion. Mais ils se règlent plus difficilement dans le cas d'une liste car l'expéditeur d'un message, par exemple, ne peut évidemment pas s'adapter à chaque membre de la liste.

Bref, après les trois endroits mentionnés plus haut, il faut se poser les trois questions concrètes suivantes :

  • La liste peut-elle avoir elle-même une adresse en Unicode ? Par exemple évolution-langue@académie-française.fr ?
  • La liste accepte t-elle des abonnés « Unicode » comme étienne@massé.fr ?
  • La liste accepte t-elle les messages délivrés entièrement en Unicode (RFC 5336) ?

Avant d'étudier ces trois questions plus en détail, la section 3 rappelle un scénario particulièrement délicat : si le message originel nécessite UTF8SMTP, par exemple parce que l'adresse de son expéditeur comprend de l'Unicode, et que certains des destinataires de la liste ont des serveurs SMTP sans cette option, le message devra se rabattre sur de l'ASCII seul, suivant le RFC 5504, sans que le serveur SMTP de l'expéditeur original n'ait pu se rendre compte de quelque chose. Ce problème devrait disparaitre avec le temps, le repli sur l'ASCII seul étant largement considéré aujourd'hui comme une mauvaise idée, qui a été exclue de la normalisation définitive du courrier électronique avec adresses Unicode.

Après ce petit détour, revenons aux trois questions. En théorie, le système de gestion de la liste peut répondre OUI à n'importe laquelle des questions indépendamment des autres. En pratique, toutefois, on ne voit pas bien l'intérêt d'avoir une adresse en Unicode si le serveur SMTP frontal ne gère pas UTFSMTP (et réciproquement, d'ailleurs). La section 4 discute ces trois services séparement mais, logiquement, les MLM les fourniront tous ou aucun.

Donc, premier service, que la liste ait une adresse de soumission en Unicode, comme pause-café@bavardage.fr. Le RFC recommande que la liste ait aussi une adresse alternative en ASCII (alt-address du RFC 5336, section 3.4), mettons pause-cafe@bavardage.fr. À noter que la liste a aussi une autre adresse, utilisée comme expéditeur dans l'enveloppe des messages sortants, et qui reçoit donc les messages d'erreur. Pour ce cas, la liste peut très bien se contenter d'une adresse en ASCII seul et, si cette adresse est en Unicode, le RFC impose (c'est la seule obligation nouvelle de ce RFC) qu'il y aie une alt-address en ASCII, pour garantir la bonne réception des messages d'erreur.

Et pour les adresses des abonnés ? Il n'y a pas de recommandation stricte, juste le rappel qu'une liste peut, si elle le souhaite, imposer que les abonnés fournissent une adresse alternative en ASCII.

Enfin, pour UTF8SMTP, le gestionnaire de la liste doit s'assurer que tous les serveurs sur le chemin gèrent bien cette option.

Le courrier entièrement internationalisé pose un autre problème, c'est celui des en-têtes List*: tels que normalisés par les RFC 2369 et RFC 2919. Pour reprendre l'exemple de pause-café@bavardage.fr, à quoi doivent ressembler, par exemple, ces en-têtes :


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

Pour les deux derniers en-têtes, qui contiennent des URI, tout dépend du plan (ici, mailto: et http:). Même si ce dernier autorise les IRI (ce qui n'est pas le cas de mailto: aujourd'hui), le RFC demande que ce soit leur forme encodée en URI qui soit utilisée. (Notons que les IRI sont actuellement en cours de réforme à l'IETF, et qu'un des points en discussion est l'encodage du nom de domaine dans l'IRI, problème qui ne se pose pas dans cet exemple.) On aura donc, par exemple :


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>

Ces en-têtes List*: étant essentiels pour le bon fonctionnement des listes, le RFC insiste sur le fait qu'avoir également une alternative en ASCII pur est très souhaitable. Les deux adresses (Unicode et ASCII) sont indiquées dans deux URI différents, séparés par des virgules (RFC 2369, section 2).

L'en-tête List-Id (qui identifie une liste de manière unique), lui, ne prend pas un URI comme valeur et cette discussion ne s'applique pas à lui. En revanche, il est très souvent utilisé dans des systèmes de traitement automatique du courrier reçu comme les filtres Sieve. Ces filtres ne réagissent pas forcément correctement à de l'Unicode (par exemple, ils peuvent échouer à comparer la forme UTF-8 et une forme encodée différemment). Le RFC ne fournit toutefois pas de solution à ce problème.

Je ne connais pas encore de 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 au stade de la réflexion sur ce point. Le RFC 6783, version actuelle, traite le problème très différemment, notamment en raison de la suppression du repli automatique (d'un message internationalisé vers un message ASCII).


Téléchargez le RFC 5983


L'article seul

RFC 5969: IPv6 Rapid Deployment on IPv4 Infrastructures (6rd)

Date de publication du RFC : Août 2010
Auteur(s) du RFC : M. Townsley (Cisco), O. Troan (Cisco)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF softwire
Première rédaction de cet article le 23 août 2010
Dernière mise à jour le 3 septembre 2010


La délicate question de la période de transition entre IPv4 et IPv6 n'a jamais été négligée à l'IETF. Bien au contraire, plusieurs mécanismes ont été normalisés pour assurer le passage d'un protocole à l'autre. Le mécanisme « 6rd », initialement décrit dans le RFC 5569, est un de ces mécanismes. 6rd modifie le 6to4 du RFC 3056 pour garantir un chemin de retour symétrique aux paquets IP (section 1 du RFC). 6rd permet à un FAI de vendre un service IPv6 alors que son réseau interne est essentiellement IPv4. Il est surtout connu pour être la technologie déployée par Free à partir de décembre 2007. Ce RFC 5969 prend la spécification originale de 6rd, dans le RFC 5569, l'étend pour des cas comme celui où les adresses sont distribuées par DHCP et le fait passer sur le chemin des normes IETF (le RFC 5569 avait uniquement le statut « pour information »).

S'il existe plusieurs mécanismes de coexistence d'IPv4 et d'IPv6, c'est parce que les besoins sont différents. Certains FAI ont un réseau interne entièrement IPv6 depuis de nombreuses années comme Nerim. D'autres n'ont pas encore commencé le déploiement. Parfois, le FAI est en avance sur ses clients, parfois c'est le contraire comme c'était le cas pour Free où de nombreux utilisateurs réclamaient IPv6 depuis longtemps. Il existe donc une variété de techniques de coexistence v4/v6. 6rd se positionne pour le cas où le FAI :

  • n'a toujours pas migré la totalité de son réseau interne en IPv6,
  • a une connectivité IPv6 externe, et des adresses IPv6 allouées par un RIR,
  • a certains clients qui réclament une connectivité IPv6,
  • et, de préférence, contrôle le routeur situé chez les clients (cas des « boxes », nommées CE pour « Customer Edge » dans le RFC).

À l'origine, le protocole « idéal » semblait être 6to4 du RFC 3056. Simple, déjà mis en œuvre, y compris en logiciel libre et sans état (chaque paquet est traité indépendamment) donc passe bien à l'échelle. Mais il a des limites, notamment le fait le retour du paquet n'est pas garanti : la machine avec laquelle on communique va chercher son propre relais 6to4 et ne va pas forcément en trouver un. 6rd est une modification de 6to4 pour utiliser comme préfixe, non plus le préfixe 6to4 commun à tous de 2002::/16 mais un préfixe par FAI. Ainsi, le FAI doit désormais lui-même installer des relais, il ne peut plus se reposer sur les relais existants mais, en contre partie, il contrôle complètement le routage, y compris sur le chemin du retour et se retrouve ainsi dans un cas plus classique où ses routeurs servent ses clients (alors que, avec 6to4, tout le monde sert tout le monde, ce qui est très bien lorsque cela marche).

La section 4 décrit la fabrication du préfixe 6rd pour les adresses IP. Ce préfixe combine un préfixe IPv6 choisi par le FAI et tout ou partie de l'adresse IPv4 du CE. Notons que, 6rd étant un bricolage purement local au FAI, la norme n'impose pas, par exemple, le nombre de bits IPv4 conservé (ce point était déjà dans le RFC 5569, voir aussi les sections 7 et 11). Il faut juste garder 64 bits pour le réseau local, pour permettre l'autoconfiguration sans état. On peut garder moins de 32 bits de l'adresse IPv4 car certains octets sont souvent fixés sur le réseau du FAI. Par exemple, un FAI qui consacre le préfixe 2001:DB8::/32 à ses clients 6rd, pour un CE d'adresse 192.0.2.137, et dont tous les CE sont sous 192.0.0.0/8, peut garder les trois quarts de l'adresse IPv4. Le FAI aura alors un préfixe 6rd de 32 + 24 = 56 bits (ce qui laissera 72 bits pour le réseau local, permettant 256 réseaux de longueur /64), le 2001:db8:0002:8900::/56.

Chez Free (qui a un /26), en septembre 2010, les adresses IP de mon réseau sont 2a01:e35:8bd9:8bb0::/64. À partir du 29ème bit commence l'adresse IPv4. Dans mon cas, l'adresse IPv6 s'écrit en binaire 10101000000001000011100011010110001011110110011000101110110000 ou, si on retire les 28 premiers bits, 10110001011110110011000101110110000 qui donne en décimal 88.189.152.187 qui est bien mon adresse v4. Un client Free pourrait donc recevoir en théorie un /60. (Merci à Yvon @ Okazoo pour ses calculs et explications.)

Les acteurs du protocole sont :

  • Les machines sur le réseau local du client, elles parlent IPv6 nativement sur ce réseau local (si elles utilisent l'auto-configuration sans état, la Freebox leur a envoyé le préfixe par RA),
  • Les CPE (CE dans le RFC, pour « Customer Edge », comme la Freebox chez Free), qui doivent parler 6rd pour traduire dans les deux sens,
  • Les relais 6rd, en bordure du réseau du FAI (BR dans le RFC pour « Border Relays »). Chez Free, ce sont des PC Unix (qui devraient être remplacés par des Cisco fin 2010). À noter que 6rd est sans état et que chaque paquet IP peut donc être traité indépendamment des autres. Les BR peuvent donc être joints, par exemple, par l'anycast.

On peut se poser la question de savoir s'il s'agit vraiment d'IPv6 « natif ». Sans doute pas (le paquet circule dans le réseau de Free encapsulé IPv4, ce qui réduit la MTU à 1480 octets).

Pour faciliter le débogage, la section 5 du RFC recommande que CE et BR répondent à l'adresse anycast subnet router du RFC 4291 (section 2.6.1).

La section 7 couvre les mécanismes par lesquels le CE peut être configuré pour faire du 6rd proprement. Ils sont multiples mais on notera en section 7.1.1 l'arrivée d'un nouveau : une option DHCP (numéro 212) pour configurer tous les paramètres 6rd du CE (préfixe IPv6, adresse(s) des BR, nombre de bits de l'adresse v4 à conserver, etc).

La question de la longueur idéale du masque v4 est couverte en section 11. Il s'agit de voir combien de bits de l'adresse v4 doivent être gardés dans le préfixe v6. Si on utilise les 32 bits, et qu'on veut allouer un /56 à chaque client, il faut un /24 pour les servir tous. Ce n'est pas si effrayant que cela, même si tous les AS actuellement actifs le faisaient, cela ne consommerait qu'un /9. Et si ces AS n'allouaient au client qu'un /60, la consommation totale ne serait qu'un /13. À noter que Free n'allloue aujourd'hui qu'un /64 à ses clients, ce qui ne leur permet pas d'avoir plusieurs réseaux chez eux (sauf à renoncer à l'autoconfiguration sans état) et annule donc une partie de l'intérêt de IPv6.

Mais la solution la plus courante sera sans doute de ne pas utiliser les 32 bits de l'adresse IPv4 mais seulement une partie. Par exemple, si tous les CE sont dans le même /12 IPv4, 20 bits suffisent pour les distinguer et on peut alors allouer un /56 à chaque client en ne consommant en tout qu'un /36.

6to4 soulève traditionnellement des gros problèmes de sécurité, documentés dans le RFC 3964. 6rd en supprime certains, si l'implémentation suit les recommandations de la section 12, et effectue les vérifications demandées, mais l'usurpation d'adresse IP demeure relativement facile.

Quelles sont les principales nouveautés de ce RFC 5969 par rapport au RFC 5569 original ? Thibault Muchery les résume en disant que ce nouveau RFC est plus général : la solution mise en œuvre pour Free prenait avantage de certaines particularités de Free (addresses IP fixes, maitrise des logiciels de la CE - la Freebox - et des BR). La solution nouvelle reprend tout à fait le même principe, en généralisant, en standardisant (nouvelle option DHCP, etc.), en présentant plus la solution comme inscrite dans une lignée d'autres solutions, en ajoutant des contrôles plus fins pour la sécurité mais au fond c'est exactement la même solution généralisée.

Et Rémi Desprès, concepteur de la solution originale, note que l'apport majeur du RFC 5969 est la spécification d'une option DHCP pour transmettre aux CPEs (ou "CEs") les paramètres 6rd de leur domaine. (Free n'en avait pas besoin, mais c'est indispensable si les CPE sont acquis indépendamment du FAI.) Il ajoute qu'il y a par contre une régression, mais limitée, dans la section 8. La nouvelle norme envisage une l'utilisation de NUD (Neighbor Unreachability Detection) sur le lien virtuel que constitue un domaine 6rd (tout en le décrivant comme sous-optimal), une complexité à son avis superflue. Le RFC 5969, et propose une technique différente pour tester l'accessibilité des BR, à son avis superflue également. La philosophie KISS du RFC 5569 en est à son avis amoindrie, mais avoir un RFC spécifiant l'option DHCP est plus important que ces points mineurs.

On imagine que la suite des opérations sera une implémentation par Cisco, étant donnée que le RFC est rédigé par des gens travaillant pour Cisco.


Téléchargez le RFC 5969


L'article seul

RFC 5966: DNS Transport over TCP - Implementation Requirements

Date de publication du RFC : Août 2010
Auteur(s) du RFC : R. Bellis (Nominet)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dnsext
Première rédaction de cet article le 24 août 2010


La vague mention des virtual circuits (connexions TCP) dans la section 4.2 du RFC 1035 a suscité d'innombrables polémiques, que ce RFC 5966 a tranché. En deux mots, un serveur DNS doit-il fournir son service avec les protocoles de transport TCP et UDP ou bien peut-il se contenter d'UDP ? La réponse était clairement « TCP et UDP » et le remplaçant de ce document, le RFC 7766, a été depuis encore plus net.

La discussion était d'autant plus vive que certains registres procèdent à des tests techniques obligatoires avant l'enregistrement d'un nom de domaine et que ces tests peuvent inclure la disponibilité du service sur TCP. Par exemple, l'outil Zonecheck dispose d'un tel test (qui se configure avec <check name="tcp" severity="f ou bien w" category="connectivity:l4"/>) et l'AFNIC impose le succès de ce test pour un enregistrement dans .fr (contrairement à ce qu'on lit parfois, il est faux de dire « Zonecheck impose TCP », Zonecheck est configurable et c'est l'AFNIC qui choisit d'activer ce test, et décide de son caractère bloquant ou non). On a vu ainsi des discussions sur ces tests, même si les opposants ont rarement fait l'effort de prendre le clavier pour écrire une argumentation raisonnée (on les comprend quand on voit que toutes les discussions publiques sur le sujet indiquent un consensus des experts sur l'importance du service TCP, voir par exemple http://www.circleid.com/posts/afnic_dns_server_redelegation/).

Mais c'est aussi que l'approche « légaliste » de la discussion est vouée à tourner en rond. Le texte du RFC 1035 (ou celui de la section 6.1.3.2 du RFC 1123) est vague, et peut s'interpréter de différentes manières. Il faut donc revenir aux bases du DNS, pour décider si TCP est important ou pas, et pas essayer vainement de trouver un texte sacré qui trancherait la question de manière claire.

Revenons donc à ces bases (section 1 du RFC). Le DNS peut s'utiliser sur UDP et TCP. Par exemple, l'outil dig, par défaut, utilise UDP, mais l'option +tcp (ou +vc pour virtual circuit) lui fait utiliser TCP. TCP est obligatoire pour les transferts de zone (cf. RFC 5936) mais, contrairement à une légende répandue, n'est pas réservé à ces transferts et peut être utilisé pour des requêtes ordinaires. Il est notamment obligatoire si la réponse arrive tronquée (bit TC mis à un) car elle ne tenait pas dans le paquet UDP (dont la taille était autrefois limitée à 512 octets). Depuis la création du DNS, la taille des réponses a beaucoup augmenté (IDN et IPv6 mais surtout DNSSEC y ont largement contribué) et, malgré la suppression de la limite de 512 (cf. RFC 6891), TCP est donc encore plus nécessaire que dans le passé.

Arrivé là, il faut faire une distinction importante entre ce que peut le logiciel et ce qu'a activé l'administrateur système. Ainsi, le logiciel djbdns permet parfaitement TCP mais il n'est pas activé par défaut. De même, BIND ou NSD ont TCP par défaut mais un pare-feu situé devant le serveur de noms peut bloquer les accès TCP. Notre RFC 5966 sépare donc protocole et mise en œuvre et ne traite que le cas du logiciel : il précise que tout logiciel DNS doit avoir la possibilité de faire du TCP mais il ne tranche pas (délibérement) la question de savoir si TCP doit être disponible sur un serveur de noms en activité. Il note simplement que l'absence de TCP peut planter le processus de résolution de noms.

La section 3 du RFC discute ensuite les différentes questions liées à ce choix. Le principal problème est celui de la taille des réponses. Autrefois limitée à 512 octets, elle peut prendre des valeurs plus grandes (jusqu'à 65536 octets) avec EDNS0. Mais la MTU de 1500 octets est hélas une limite pratique fréquente (cf. RFC 5625, du même auteur), en raison de pare-feux mal configurés. Cela peut poser des problèmes, par exemple lors du déploiement de DNSSEC. Un simple NXDOMAIN depuis .org dépasse les 512 octets :

 

% dig +dnssec SOA certainlydoesnotexist.org

; <<>> DiG 9.6-ESV-R1 <<>> +dnssec SOA certainlydoesnotexist.org
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 64046
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 0, AUTHORITY: 8, ADDITIONAL: 1

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

;; AUTHORITY SECTION:
org.			0	IN	SOA	a0.org.afilias-nst.info. noc.afilias-nst.info. 2009281221 1800 900 604800 86400
org.			0	IN	RRSIG	SOA 7 1 900 20100907065203 20100824055203 52197 org. m3DPnEo+Ibd8W0d/cVW7sMZb8UooI6F6mOn/mQSeLiTnLRUvPaMFsd3m j12W4YgVGMyf1s/YLIItoBy7fhKDdJ2zi2r8PfuBrT9Hr+dut+IHRGDR r+6ALaqBISWeyptCe6TygeudG/1sQkQZlCvaBGKUFpsHEi831FwtMZjc hmI=
h9p7u7tr2u91d0v0ljs9l1gidnp90u3h.org. 86400 IN NSEC3 1 1 1 D399EAAB H9RSFB7FPF2L8HG35CMPC765TDK23RP6 NS SOA RRSIG DNSKEY NSEC3PARAM
h9p7u7tr2u91d0v0ljs9l1gidnp90u3h.org. 86400 IN RRSIG NSEC3 7 2 86400 20100907065203 20100824055203 52197 org. WNHP4aq9hxWHjgZ10HKlqiU6bx2PVQyCgeGJQqykAay4qTcQvD77QMRm c9efWt3M4BO7rr7bt/uY+TqsriJvB1uhvqg93Ti0fPH1SX86hhG8B09U czngma0DZ1UtaCgwpjVQJbAVYRknyfyi6NM7hWwbxUtD44EVWE14qEbb 93A=
b42oorh0vfd9ble13e1him76im76qsl6.org. 86400 IN NSEC3 1 1 1 D399EAAB B49TR2SSRPRC2FF6FIVQ25UFDMRL7Q63 NS DS RRSIG
b42oorh0vfd9ble13e1him76im76qsl6.org. 86400 IN RRSIG NSEC3 7 2 86400 20100906200816 20100823190816 52197 org. I5l7iR/5TngAspzO36TkNYGGugE2whPsUvQP/nPoNMBCC58/4TtNQysF Pdfswz5lPm14Ei8UrCSXjG17Db7yVFk4MD/oidsfweEJ2hwJqcoPAXqY bcqliZxUq/9dLW7zkH4tKwCDXfYHQKFgW7MhKr/i5JUJRkZgR0Q/7mmu PF4=
vae6tvink0oqnd756037uoir56fokhtd.org. 86400 IN NSEC3 1 1 1 D399EAAB VB1V404HEINQ7A8TQTJ9OASALN2IS19G A RRSIG
vae6tvink0oqnd756037uoir56fokhtd.org. 86400 IN RRSIG NSEC3 7 2 86400 20100907011155 20100824001155 52197 org. lHZ3Zi7vMKEcPif/SE9w31xobVq7VXcifR3EE+G1c3lxm3bKdMI9tY3x 6hOkHbUnbgY8XNvEmaobjmPYd4UdYLQa8eonTuRaupI90AZt9Fi83k6u ruCRHP0ChO9VUD+Yc68mM7spD+7nTIfRu/FkNKEuNvqSHipgR5blBfNg KZw=

;; Query time: 43 msec
;; SERVER: ::1#53(::1)
;; WHEN: Tue Aug 24 08:54:12 2010
;; MSG SIZE  rcvd: 1019

Dans tous ces cas, TCP est la seule solution fiable. À l'ère de YouTube et de ses giga-octets de vidéo, il serait curieux d'en rester au DNS de 1990 et de ses limites archaïques à 512 octets. Un serveur de noms doit donc pouvoir utiliser TCP.

Mais, lorsque le serveur de noms a le choix, quel protocole de transport doit-il utiliser ? C'est l'objet de la section 4. Elle modifie légèrement le RFC 1123 dont la section 6.1.3.2 imposait à un résolveur de tenter UDP d'abord (et de passer en TCP si la réponse arrive tronquée). Désormais, le résolveur a le droit de poser sa question en TCP d'abord, s'il a de bonnes raisons de penser (par exemple parce qu'il a déjà parlé à ce serveur) que la réponse arrivera tronquée.

Les sections 5 et 6 sont consacrées à des problèmes pratiques avec la mise en œuvre de TCP. Par exemple, comme le DNS sur TCP peut faire passer plusieurs requêtes dans une connexion TCP, notre RFC précise que les réponses ont parfaitement le droit d'arriver dans un ordre différent de celui des questions.

Restent les questions de sécurité et autres craintes qui sont mentionnées par certains objecteurs (on peut citer http://cr.yp.to/djbdns/tcp.html#why comme très bel exemple de catalogue d'erreurs et d'énormités). En effet, programmer TCP dans le serveur de noms n'est pas très difficile. Ma propre implémentation, dans Grong, fut triviale, car le langage Go, avec son parallélisme natif facilite beaucoup les choses. Mais, même en C, si le serveur utilise plusieurs sockets, par exemple pour gérer IPv4 et IPv6, ajouter TCP en prime ne changera pas beaucoup la boucle principale autour de select(). L'obligation de gérer TCP ne gênera donc qu'une petite minorité de programmeurs, ceux qui essayaient de faire un serveur DNS basé sur le traitement séquentiel des paquets.

En revanche, l'obligation de gérer TCP est parfois critiquée pour des raisons de sécurité. La section 7 discute ce problème des DoS : TCP nécessite un état sur le serveur et consomme donc des ressources. En théorie, cela rendrait les serveurs DNS plus sensibles aux DoS. Toutefois, presque tous les serveurs de noms de la racine ont TCP depuis longtemps, ainsi que la grande majorité des serveurs des grands TLD et on ne voit pas d'attaques pour autant. (Le RFC se limite au cas du DNS mais on peut aussi, en sortant du petit monde DNS, noter que l'écrasante majorité des serveurs Internet utilise exclusivement TCP... En outre, UDP a ses propres problèmes de sécurité, notamment la facilité à tricher sur l'adresse IP source, facilité qui est à la base de l'attaque Kaminsky.) Le RFC recommande toutefois la lecture de bons textes comme « CPNI technical note 3/2009  \ Security assessment of the Transmission Control Protocol (TCP)  ».

Et la charge du serveur ? Le RFC n'en parle pas mais il y avait eu des inquiétudes à ce sujet, basées sur le fait que les études montrent une augmentation relative très importante du trafic TCP lorsqu'on active DNSSEC. Ce trafic peut-il épuiser le serveur. Notons que, si un passage de 0,2 requête/s à 50 peut sembler énorme, cela reste ridicule en valeur absolue, à l'heure où le plus petit serveur HTTP en gère bien davantage.

Par contre, une autre objection contre TCP n'est pas citée, ses possibles problèmes avec l'anycast. Désolé, mais je manque de temps pour la commenter ici.

Ah, me demanderez-vous, mon opinion personnelle ? Je trouve qu'aujourd'hui, TCP est à la fois indispensable pour ne pas limiter à des valeurs ridiculement basses la taille des réponses, et facile à déployer, comme le montre l'expérience de tous les gros TLD. EDNS0 permettrait de résoudre une bonne partie des problèmes de taille (et je veux donc bien entendre les objecteurs qui diraient « le test technique devrait exiger TCP ou EDNS0 ») mais je note que les serveurs qui n'ont pas TCP n'ont pratiquement jamais EDNS0 non plus... Il n'y a donc guère de raisons valables, en 2010, d'avoir des serveurs de noms inaccessibles en TCP. (En 2016, notre RFC a été remplacé par le RFC 7766, qui augmente encore le rôle de TCP.)


Téléchargez le RFC 5966


L'article seul

RFC 5965: An Extensible Format for Email Feedback Reports

Date de publication du RFC : Août 2010
Auteur(s) du RFC : Y. Shafranovich (ShafTek Enterprises), J. Levine (Taughannock Networks), 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 31 août 2010
Dernière mise à jour le 1 septembre 2010


Les opérateurs de réseaux et de serveurs, aujourd'hui, passent beaucoup de temps à s'envoyer des rapports indiquant qu'un message reçu est en fait abusif, spam ou hameçonnage. Ces rapports sont désormais bien trop nombreux pour être traités manuellement et il est donc nécessaire de définir un format standard pour les représenter, de façon à permettre un minimum de traitement automatique sur ces rapports. C'est ce que fait notre RFC, le premier du groupe de travail MARF. Ce format s'appuie évidemment sur MIME.

Avant l'adoption du format MARF (qui précède sa normalisation formelle dans ce RFC), plusieurs opérateurs avaient défini des formats privés (section 1). Cela rendait évidemment difficile l'analyse des rapports envoyés, il fallait écrire du code pour chaque opérateur. Désormais, il existe donc un format standard, basé sur le type MIME multipart/report normalisé dans le RFC 6522. Ce format utilise le sous-type (« type du rapport ») feedback-report.

Ce n'est pas la première tentative de normalisation dans ce domaine, les précédentes n'ont pas été des succès.

Ce RFC ne fait que normaliser un format, il ne spécifie pas à qui les rapports doivent être envoyés, comment les authentifier, ou ce qu'il faut en faire, il se focalise sur l'aspect technique. Le cahier des charges figure en section 1.2 :

  • Le format devait être lisible à la fois par un humain et par un programme,
  • Le message signalé devait être inclus dans le rapport,
  • Le format devait permettre l'ajout de métadonnées,
  • Le format devait être extensible.

Ces objectifs ont-il été atteints ? Voyons la définition du nouveau format (une certaine familiarité avec le RFC 5598 est utile).

La section 2 du RFC décrit le format MARF. Un message MARF est donc un message MIME multipart/report, tel que défini dans le RFC 3462. Le type du rapport est feedback-report (donc le message contiendra un en-tête du genre Content-Type: multipart/report; report-type=feedback-report; ...). Chaque rapport ne concerne qu'un seul message, il n'y a pas de mécanisme pour l'agrégation de messages. Il comprend trois parties MIME obligatoires :

  • La première est une description en langue naturelle du rapport,
  • La seconde est un ensemble de métadonnées structurées, de type MIME message/feedback-report,
  • La troisième est le message original, de type message/rfc822 en général (rappelez-vous que MIME est récursif et qu'il est donc parfaitement possible d'avoir un message MIME dans un autre message MIME).

Le sujet du rapport doit être le champ Subject: du message original, éventuellement avec un préfixe comme FW: (pour forwarded), ce qui me semble déroutant car, en examinant sa boîte aux lettres manuellement, on ne distingue pas facilement les spams des rapports sur les spams.

Focalisons-nous un instant sur la seconde partie, les métadonnées. Le format de ce nouveau type MIME message/feedback-report est décrit dans la section 3. Cette partie est composée de plusieurs champs, suivant la syntaxe des en-têtes du courrier (attention, seule leur syntaxe est identique, un champ de même nom qu'un champ du RFC 5322 n'a pas forcément la même sémantique). Comme pour tout le contenu du rapport, le destinataire ne doit pas forcément leur faire une confiance aveugle. Ils représentent des assertions du créateur du rapport et ne sont pas forcément vérifiables.

La liste des champs n'est pas fixée définitivement, de nouveaux champs pourront être enregistrés dans le futur. Aujourd'hui, la liste des champs obligatoires comprend (section 3.1) :

  • Feedback-Type:, défini dans la section 3.5,
  • User-Agent:, indiquant le logiciel qui a produit le rapport,
  • Version:, aujourd'hui toujours 1.

Il y a aussi des champs facultatifs, parmi lesquels (sections 3.2 et 3.3) :

  • Arrival-Date: indiquant l'heure de réception,
  • Authentication-Results: qui indique les résultats des procédures d'authentification, tels que formalisés par le RFC 7001,
  • Incidents:, un nombre indiquant le nombre de fois que ce message a été reçu,
  • Reported-Domain:, qui indique le nom du coupable présumé (par exemple parce que le message vient de lui),
  • Reported-URI:, qui indique un URI pertinent pour le rapport, par exemple l'URL d'un site Web de hameçonnage pour lequel un spam faisait de la publicité,
  • Source-IP:, indiquant l'adresse IP source au moment où le message est entré dans le domaine qui génère le rapport,
  • Et bien d'autres (la liste complète et à jour figure dans le registre). Notez que certains champs facultatifs peuvent apparaitre plusieurs fois (comme Reported-URI:) et d'autres une et une seule fois (comme Arrival-Date:).

Un exemple d'une telle partie :


Feedback-Type: abuse
User-Agent: SomeGenerator/1.0
Version: 1
Arrival-Date: Thu, 8 Mar 2005 14:00:00 EDT
Source-IP: 192.0.2.1
Authentication-Results: mail.example.net;
               spf=fail smtp.mail=somespammer@example.com
Reported-Domain: example.com
Reported-Uri: http://example.com/earn_money_fast.html

La grammaire complète figure en section 3.5.

On le sait, le courrier électronique est une jungle où tout est possible. Les rapports peuvent être mensongers ou, tout simplement, incorrects techniquement. Que faire dans ce cas ? La section 4 est claire : de tels messages devraient être ignorés ou rejetés. Le principe de robustesse (« Acceptez n'importe quoi et essayez de le décoder ») ne s'applique pas aux questions de sécurité.

Je l'ai dit plus haut, une des exigences du cahier des charges était l'extensibilité. La section 6 expose les moyens déployés par MARF pour atteindre ce but. Notamment, deux registres IANA sont créés, pour pouvoir ajouter des nouvelles données : le registre des types de retours (feedback types) et celui des champs dans les métadonnées. Les types et les champs inconnus doivent donc être ignorés par les programmes, afin de pouvoir ajouter des nouveaux sans casse.

Les registres en question sont décrits de manière plus formelle dans la section 7. Celle-ci décrit l'enregistrement du nouveau type MIME message/feedback-report, le nouveau registre des métadonnées (dans lequel on peut enregistrer par la procédure « spécification obligatoire » du RFC 5226) et le nouveau registre des types de retour (même procédure pour l'enregistrement). Aujourd'hui, ce registre contient des types comme abuse (courrier non sollicité), fraud (courrier de tentative d'escroquerie), virus (courrier contenant un virus), etc.

Comme tout ce RFC porte sur un problème de sécurité, il est normal que la section dédiée à ce sujet, la 8, se demande si le nouveau format est lui-même sûr. Elle met notamment en garde contre les interprétations abusives (section 8.2) : cette norme décrit juste un format, elle ne garantit pas que les rapports, même syntaxiquement corrects, soient authentiques. Le mécanisme par lequel on décide de faire confiance (ou pas) à un rapport n'est pas spécifié par ce RFC. Il est donc déconseillé de déclencher automatiquement des actions (comme l'inscription sur une liste noire) sur la seule base d'un rapport, sans précautions supplémentaires.

Par exemple, le RFC recommande que les rapports soient un minimum authentifiés, par le biais de techniques comme SPF, DKIM ou S/MIME (ce dernier est conseillé mais, curieusement, PGP n'est pas cité).

Autre problème de sécurité lié à ces rapports, le risque d'attenter à la vie privée. La section 8.5 rappelle que la règle devrait être d'envoyer des rapports complets mais, si la protection de la vie privée le nécessite, qu'on peut supprimer certaines parties du rapport pour ne pas révéler d'informations privées. (Même si on devine que cette idée de vie privée défrise considérablement les auteurs du RFC.)

Peut-on générer automatiquement des rapports MARF (section 8.6), par exemple parce qu'un pot de miel a reçu un spam ? Le RFC met en garde : un attaquant qui sait qu'un tel générateur existe pourrait l'utiliser pour faire fabriquer des rapports contre ses ennemis, en envoyant de faux spams.

Encore un piège amusant : les rapports seront souvent générés pour des messages qui contiennent du logiciel malveillant. Ledit logiciel va se trouver dans la partie du rapport qui reprend le message original. Les processeurs de messages MARF doivent donc faire attention à ne pas, par exemple, exécuter accidentellement le méchant logiciel (section 8.7) !

Un exemple plus complet est cité dans l'annexe B2 du RFC (le message original a le sujet Earn money et prétend venir de somespammer@example.net) :


From: <abusedesk@example.com>
Date: Thu, 8 Mar 2005 17:40:36 EDT
Subject: FW: Earn money
To: <abuse@example.net>
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://www.mipassoc.org/arf/.

--part1_13d.2e68ed54_boundary
Content-Type: message/feedback-report

Feedback-Type: abuse
User-Agent: SomeGenerator/1.0
Version: 1
Original-Mail-From: <somespammer@example.net>
Original-Rcpt-To: <user@example.com>
Arrival-Date: Thu, 8 Mar 2005 14:00:00 EDT
Reporting-MTA: dns; mail.example.com
Source-IP: 192.0.2.1
Authentication-Results: mail.example.com;
            spf=fail smtp.mail=somespammer@example.com
Reported-Domain: example.net
Reported-Uri: http://example.net/earn_money.html
Reported-Uri: mailto:user@example.com
Removal-Recipient: user@example.com

--part1_13d.2e68ed54_boundary
Content-Type: message/rfc822
Content-Disposition: inline

From: <somespammer@example.net>
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
To: <Undisclosed Recipients>
Subject: Earn money
MIME-Version: 1.0
Content-type: text/plain
Message-ID: 8787KJKJ3K4J3K4J3K4J3.mail@example.net
Date: Thu, 02 Sep 2004 12:31:03 -0500

Spam Spam Spam
Spam Spam Spam
Spam Spam Spam
Spam Spam Spam
--part1_13d.2e68ed54_boundary--

Qui utilise ou utilisera ce format ? Je n'ai pas trouvé sur le site officiel de liste des implémentations (pour générer et analyser du MARF). Il faut se contenter des liens en http://wordtothewise.com/resources/arfdeveloper.html. Voir par exemple :

Mais, apparemment, plusieurs opérateurs utilisent déjà ce format. Idéalement, on devrait pouvoir l'utiliser pour soumettre des rapports à abuse@opérateur.net et à des organismes comme Signal-Spam (ce dernier semble tout à fait mort). Mais cela ne semble pas possible actuellement. En tout cas, au bureau, seule une minorité des rapports de spam que je reçois sont pour l'instant à ce format (je ne peux pas les reproduire ici, pour des raisons de protection des données personnelles ; dans beaucoup de cas, le rapport est erroné et je ne veux pas que des innocents se trouvent mentionnés). Un autre document, plus récent, le RFC 6650, décrit en détail dans quels cas utiliser ARF et comment.


Téléchargez le RFC 5965


L'article seul

RFC 5963: IPv6 Deployment in Internet Exchange Points (IXPs)

Date de publication du RFC : Août 2010
Auteur(s) du RFC : R. Gagliano (Cisco)
Pour information
Réalisé dans le cadre du groupe de travail IETF v6ops
Première rédaction de cet article le 31 août 2010


Le fonctionnement de l'Internet aujourd'hui repose largement sur des points d'échange où les différents opérateurs se connectent pour échanger du trafic IP. Le point d'échange typique fournit un réseau Ethernet où chacun connecte son routeur, et alloue des adresses IP pour configurer ces dits routeurs, qui vont ensuite établir des liens BGP entre eux. La principale conclusion de ce nouveau RFC est que la très grande majorité des points d'échange fournissant un service de couche 2, le fait d'utiliser IPv6 au lieu d'IPv4 ne change pas grand'chose à la gestion du point d'échange.

La section 1 résume l'état actuel du monde des points d'échange. Presque toujours, le service rendu est une connexion de niveau 2, quasiment uniquement en Ethernet. Le principal service de niveau 3 rendu par les gérants du point d'échange est l'attribution d'adresses IP aux routeurs des opérateurs. Curieusement, ce service n'est pas mentionné dès la section 1, qui cite à la place des fonctions moins vitales comme le serveur de routes ou bien les statistiques (globales ou bien par protocole).

La section 2 du RFC passe ensuite aux questions liées à l'interface entre la couche de liaison et la couche réseau. IPv6 sur Ethernet doit se faire selon le RFC 2464. Le commutateur Ethernet lui-même, travaillant en couche 2, n'a rien de spécial à faire. On peut se poser la question de séparer les trafics v4 et v6. Cela peut se mettre en œuvre avec deux ports physiques sur le commutateur ou bien avec deux VLAN séparés. Mais cette séparation n'est pas indispensable. (Le faire avec des ports séparés consomme des ressources matérielles sur le routeur et le faire avec des VLAN impose aux routeurs de gérer 802.1Q.) Elle complique la configuration mais peut simplifier certaines fonctions comme les statistiques.

La section 3, plutôt descriptive que normative, décrit le mécanisme d'adressage à un point d'échange. Chaque RIR a sa politique pour l'allocation d'adresses IPv6 aux points d'échange. Ce sont typiquement des préfixes de longueur /48 qui sont alloués. Ces adresses ont besoin d'être résolvables en nom par le DNS et de pouvoir être trouvées dans la base des RIR via whois. Donc, un point d'échange n'utilise pas les ULA du RFC 4193. (Voyez par exemple les adresses IP allouées sur FranceIX.)

Par raport à un réseau local IPv6 typique, il faut aussi noter que l'autoconfiguration des adresses pa l'envoi de RA (Router Advertisement) n'est typiquement pas utilisée. La configuration des routeurs est faite manuellement puisque, de toute façon, la configuration de BGP dépend de l'adresse. Puisqu'on n'utilise pas l'autoconfiguration, que mettre dans les 64 bits les plus à droite ? En IPv4, les routeurs à un point d'échange sont en général numérotés séquentiellement mais l'espace d'adressage bien plus grand d'IPv6 permet des plans d'adressage plus informatifs. Il existe plusieurs mécanismes acceptables :

  • Encoder le numéro d'AS en décimal dans les 64 bits. Ainsi, si le point d'échange utilise le préfixe 2001:db8:f00f::/64 et qu'un opérateur connecté a le numéro d'AS 64496, son adresse IP sera 2001:db8:f00f::6:4496:1 (le 1 tout à fait à droite vient de la réservation des 16 derniers bits pour mettre plusieurs routeurs par opérateur connecté, si nécessaire).
  • Certains préfèrent l'hexadécimal, moins lisible mais plus compact, donc ici 2001:db8:f00f::fbf0:1.
  • Une autre méthode est de dériver l'adresse IPv6 de la v4. donc un routeur qui aurait 192.0.2.123 en v4 recevra 2001:db8:f00f::123 en v6 (ce n'est qu'un exemple, le RFC en cite un autre, qui permet des points d'échange de plus de 256 routeurs, contrairement à mon choix de ne garder que le dernier octet).
  • etc (d'autres méthodes sont possibles).

Ces adresses IP du point d'échange doivent-elles être routées globalement ? Le débat a toujours fait rage pour IPv4 et n'est pas différent ici. Les adresses routées globalement facilitent la configuration et le débogage mais peuvent rendre le point d'échange plus vulnérable à certaines attaques. Si on ne route pas globalement ces adresses, les participants au point d'échange peuvent toujours le faire eux-même dans leur réseau, en prenant soin d'utiliser des méthodes comme la communauté no-export de BGP, pour éviter que les annonces des routes vers le point d'échange ne se propagent trop loin. Enfin, le point d'échange a aussi des services publics (pages Web, serveur DNS, serveurs NTP, etc) et ceux-ci doivent évidemment être installés sur des adresses routables, que ce soit dans le même préfixe que celles des routeurs des participants ou bien dans un préfixe différent.

Une des particularités d'un point d'échange est que les routeurs qui y sont présents appartiennent à des organisations différentes, souvent concurrentes. Le réseau Ethernet partagé n'est donc pas forcément peuplé que par des gentils paquets, on y trouve un peu de tout, des annonces OSPF aux serveurs DHCP illicites... La section 4 mentionne ce problème et ses conséquences pour la sécurité et note que le gérant du point d'échange peut, par exemple, limiter l'utilisation de la diffusion (qui sont transmis à tous) aux paquets de découverte des voisins (RFC 4861. En tout cas, bloquer les paquets Router Advertisement (qui ne devraient jamais apparaître sur le réseau du point d'échange) est conseillé.

Tiens, puisqu'on a parlé du DNS, la section 5 lui est consacrée. Elle recommande que les adresses IP du point d'échange aient un enregistrement « inverse » (enregistrement PTR) dans le DNS, pour faire de plus jolis traceroute et, de manière générale, pour faciliter le débogage.

Un autre service très populaire sur les points d'échange est le serveur de routes, discuté en section 6. Il sert parfois à échanger réellement des routes entre pairs, et parfois simplement de looking glass. Voir par exemple le looking glass du DE-CIX. Notre RFC recommande qu'il soit accessible en IPv6 mais surtout qu'il gère les extensions à BGP des RFC 2545 et RFC 4760, qui permettent de gérer plusieurs familles d'adresses IP, donc de gérer des routes IPv6. Une autre recommandation est que les routes IPv6 soient échangées sur des sessions IPv6 (ce qui n'est pas obligatoire avec BGP), pour améliorer la cohérence de l'information de routage (si un pair BGP reçoit des informations sur IPv6, il peut être sûr que le pair qui lui annonce des routes IPv6 est lui-même effectivement joignable par ce protocole).

Enfin, la section 7 traite les cas « divers ». Par exemple, un des points peu spectaculaire, mais souvent critique, d'une transition vers IPv6 est l'adaptation des systèmes d'avitaillement (la base de données qui stocke les adresses des participants au point d'échange...) : ces systèmes doivent eux aussi être migrés de manière à pouvoir gérer des adresses IPv6.

La section 8 couvre le cas des politiques d'accès au point d'échange. Les règles d'utilisation doivent bien préciser si le contrat concerne seulement IPv4, seulement IPv6 ou bien les deux. Je me souviens, il y a quelques années (les choses ont peut-être changé depuis) que le contrat avec le Sfinx ne couvrait qu'IPv4 (alors que l'organisme qui gère le Sfinx se vantait de son rôle pionnier en IPv6) et qu'il fallait une paperasserie longue et compliquée pour pouvoir faire de l'IPv6. Notez que notre RFC ne formule pas de recommandation précise sur la politique idéale. Pour moi, le contrat devrait couvrir IP, quelle que soit sa version, car il n'existe aucune justification opérationnelle pour traiter IPv6 comme un « plus », imposant un contrat nouveau.

Pour un bon survol des points d'échange IPv6, voir https://prefix.pch.net/applications/ixpdir/summary/ipv6/.


Téléchargez le RFC 5963


L'article seul

RFC 5961: Improving TCP's Robustness to Blind In-Window Attacks

Date de publication du RFC : Août 2010
Auteur(s) du RFC : A. Ramaiah (Cisco Systems), R. Stewart (Huawei), M. Dalal (Cisco Systems)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF tcpm
Première rédaction de cet article le 27 août 2010
Dernière mise à jour le 10 août 2016


Le protocole TCP, à la base de la grande majorité des transferts de données sur l'Internet, souffre depuis longtemps de plusieurs vulnérabilités. L'une d'elles est sa susceptibilité à des attaques par injection de faux paquets, qui ne proviennent pas d'une des deux extrémités de la connexion TCP. Un sous-ensemble de ces attaques, les attaques en aveugle, concerne les cas où l'attaquant n'est même pas sur le chemin entre les deux extrémités (on dit qu'il est off-path) et doit deviner les numéros de séquence TCP pour que ses faux paquets soient acceptés. Ce nouveau RFC expose le problème et des moyens d'en limiter les effets. (Il a été depuis partiellement mis à jour par le RFC 9293.)

Le problème des attaques en aveugle était traditionnellement considéré comme de peu d'importance. En effet, pour que le paquet injecté soit accepté comme légitime, il devait reproduire adresses IP source et destination, ports source et destination et un numéro de séquence situé dans la fenêtre. (Le concept de numéro de séquence TCP est décrit dans le RFC 793, section 3.3. Chaque octet transmis a un numéro de séquence et, à un moment donné, seule une plage de numéros, la fenêtre, est acceptable, car envoyée mais non encore reçue et validée.) À partir du moment où le numéro de séquence initial est choisi de manière non prédictible (ce qui n'a pas toujours été le cas, cf. RFC 6528, mais est désormais fait dans toutes les mises en œuvre de TCP), un attaquant aveugle, qui ne peut pas sniffer le réseau, n'a guère de chance de deviner juste et donc de fabriquer un faux qui soit accepté. (Voir le RFC 4953 pour les détails sur les attaques contre TCP.)

Mais les choses changent. En raison de l'augmentation de capacité des réseaux, les fenêtres TCP voient leur taille accrue, améliorant les chances de l'attaquant. Et certaines sessions TCP sont très longues (par exemple avec BGP ou avec H.323), avec des adresses IP et des ports prévisibles. En profitant de ces faiblesses, un attaquant peut alors voir ses faux paquets acceptés, et effectuer ainsi des DoS (si le faux paquet est un RST, qui coupe la connexion) ou modifiant les données (si le faux paquet contient des données).

La section 1 du RFC résume ce problème, aggravé par des implémentations comme celles de BGP qui utilisent souvent des ports prévisibles des deux côtés (même du côté client, où ce n'est pas obligatoire). La section 1.2 décrit en détail comment conduire une telle attaque, en prenant l'exemple d'une attaque RST, visant à couper des connexions TCP. La principale difficulté pour l'attaquant est que le numéro de séquence du paquet portant le bit RST doit se situer dans la fenêtre de réception actuelle (mais, bien sûr, l'attaquant a le droit d'injecter plusieurs paquets, pour essayer plusieurs fenêtres potentielles). Les chances du succès du méchant dépendent donc de la taille de la fenêtre. Elle est en général assez facile à déterminer (et cela donne une bonne idée du nombre d'essais qu'il faudra faire). Une fois qu'il a une idée du numéro de séquence utilisé, l'attaquant peut alors commencer à envoyer des paquets RST, incrémentant le numéro de séquence par la taille de la fenêtre, à chaque nouvel essai. Au bout d'un moment, il a de fortes chances de tomber juste. Les calculs complets se trouvent dans l'article de Watson, « Slipping in the Window: TCP Reset attacks, Presentation at 2004 CanSecWest » et la question est également traitée dans le RFC 4953. La section 1.3 de notre RFC contient également ces calculs de probabilité de réussite.

Le fait que l'attaquant puisse , selon les règles du RFC 793, utiliser n'importe quel numéro de séquence situé dans la fenêtre de réception lui facilite la tâche (en moyenne, seulement 2^31/$WindowSize essais). Changer TCP pour n'accepter les RST que si le numéro de séquence est exactement celui attendu protégerait sérieusement, obligeant l'attaquant à bien plus d'essais (2^31 en moyenne). Sans ce changement, avec une fenêtre typique de 32 768 octets, 65 536 paquets suffisent pour une attaque réussie, en moyenne. Et les tailles des fenêtres tendent à augmenter, en raison de l'augmentation de capacité des réseaux, ce qui rend l'attaque de plus en plus facile.

Voici d'ailleurs un exemple d'attaque menée avec un programme en Python utilisant l'excellente bibliothèque Scapy, qui permet de fabriquer facilement des paquets IP de son goût. Ici, je triche un peu en me connectant sur la machine visée, pour relever numéro de port et numéro de séquence. Dans une attaque réelle, le méchant devrait faire une boucle qui essaie toutes les valeurs possibles. Je ne l'ai pas fait ici car je ne veux pas faciliter la tâche des script kiddies et, de toute façon, Scapy est bien trop lent pour cela (n'oubliez pas que le numéro de séquence se modifie sans cesse donc un attquant lent a peu de chances). Mon but est de montrer cette attaque en pratique, pas de fournir un outil de coupure des sessions TCP. Voici donc le programme :

#!/usr/bin/env python

# Good readings:
# http://www.packetstan.com/2010/06/scapy-code-for-bad-ack-reset.html
# http://www.sans.org/reading_room/whitepapers/testing/taste-scapy_33249

from scapy import *
# Recent Scapys:
#from scapy.all import * 
import random
import sys

if len(sys.argv) != 6:
    sys.stderr.write("Usage: %s src-ip src-port dst-ip dst-port seq-number\n" % sys.argv[0])
    sys.exit(1)
ip_src = sys.argv[1]
ip_dst = sys.argv[3]
port_src = int(sys.argv[2])
port_dst = int(sys.argv[4])
seq_n = int(sys.argv[5])

ip=IP(src=ip_src, dst=ip_dst)
reset=TCP(flags="R", sport=port_src, dport=port_dst, seq=seq_n)
send(ip/reset, verbose=1) 

Ce code génère un paquet TCP portant l'option 'R' (Reset). Ici, la victime va être un PC sous Ubuntu, avec le noyau Linux 2.6.31. 192.168.2.25 se connecte en SSH (port 22) vers 192.168.2.7. Un tcpdump sur 192.168.2.25 nous montre le port source (42696) et le numéro de séquence (1307609026, n'oubliez pas l'option -S pour avoir le numéro de séquence brut et pas un numéro renormalisé) :

22:27:28.264874 IP 192.168.2.7.22 > 192.168.2.25.42696: \
         Flags [P.], seq 1307608946:1307609026, ack 3382006564, win
	 4197, \
         options [nop,nop,TS val 169 ecr 68744645], length 80

Je lance le programme d'attaque, sur une machine tierce :

% sudo python reset-one-tcp.py 192.168.2.7 22 192.168.2.25  42696 1307609100
.
Sent 1 packets.

tcpdump montre le faux paquet arrivant :

22:28:51.519376 IP 192.168.2.7.22 > 192.168.2.25.42696: Flags [R], seq 1307609100, win 8192, length 0

et la session SSH est coupée :

Read from remote host 192.168.2.7: Connection reset by peer
Connection to 192.168.2.7 closed.

Notez que je n'ai pas utilisé le numéro de séquence exact, j'ai ajouté 84, pour illustrer le fait qu'il suffit de taper dans la fenêtre, pas forcément pile au bon endroit. Si on veut maintenant adapter ce programme pour une vraie attaque en aveugle, on ne connait pas en général le port source, ni le numéro de séquence (les deux derniers paramètres de la commande reset-one-tcp.py) et il faut donc ajouter deux boucles et envoyer beaucoup de paquets.

Il existe bien sûr d'autres protections (que l'obligation d'avoir le numéro de séquence) exact contre cette attaque, variables en coût et en complexité. IPsec, l'authentification TCP-AO du RFC 5925, etc. Des ports source choisis de manière réellement aléatoire aident aussi.

Les sections suivantes décrivent en détail les différentes possibilités d'une attaque en aveugle, ainsi que les méthodes à utiliser pour les rendre moins efficaces. Ainsi, la section 3 décrit les attaques utilisant le bit RST (ReSeT) du paquet TCP. Le RFC 793 (section 3.4) précise que la connexion doit être coupée lorsqu'un paquet portant ce bit est reçu (si le numéro de séquence est bien dans la fenêtre). Une mise en œuvre correcte de TCP est donc vulnérable à des paquets envoyés en aveugle, si l'attaquant peut trouver un bon numéro de séquence. Comment limiter les risques de ce déni de service ? La section 3.2 de notre RFC décrit le mécanisme suggéré, remplaçant l'algorithme du RFC 793 : ne couper la connexion que si le paquet entrant a pile le bon numéro de séquence. Si le numéro n'est pas celui attendu, mais figure néanmoins dans la fenêtre, envoyer un accusé de réception. Puisque l'attaquant aveugle ne pourra pas le recevoir, il ne pourra pas confirmer le reset (contrairement au pair légitime, qui recevra l'accusé de réception et, ayant coupé la connexion de son côté, renverra un RST qui sera, lui, accepté, puisque son numéro de séquence correspondra audit accusé). Un tel algorithme complique donc nettement les choses pour l'attaquant. Son principal inconvénient est qu'un RST légitime, mais qui n'a pas pile le bon numéro de séquence (par exemple parce que le paquet précédent a été perdu) ne coupera pas la session TCP légitime, il faudra attendre la confirmation.

Voici une illustration de ce principe en prenant cette fois comme victime un système NetBSD (noyau 5.0.1). On garde le même programme, 192.168.2.25 se connecte toujours à 192.168.2.7 mais, cette fois, on va diriger les paquets Reset vers 192.168.2.7. Relevons, avec tcpdump, port (55854) et numéro de séquence (1901397904) :

22:35:12.306829 IP 192.168.2.25.55854 > 192.168.2.7.22: P 1901397856:1901397904(48) \
     ack 3669275671 win 347 <nop,nop,timestamp 68860664 86>

Et attaquons en tapant un peu au-dessus du bon numéro de séquence :

% sudo python reset-one-tcp.py 192.168.2.25 55854  192.168.2.7 22 1901397909
.
Sent 1 packets.

Le résultat est :

22:36:41.508530 IP 192.168.2.25.55854 > 192.168.2.7.22: \
         R 1901397909:1901397909(0) win 8192
22:36:41.508559 IP 192.168.2.7.22 > 192.168.2.25.55854: \
         . ack 1901397904 win 4197 <nop,nop,timestamp 368 68860664>

On voit le paquet d'attaque et le ACK de confirmation, disant « Ah, tu m'a envoyé un RST pour l'octet 1901397909 mais j'attendais le 1901397904 ». Le vrai pair ne va évidemment pas confirmer le ReSeT et l'attaque échoue. (Si on envoie pile le bon numéro de séquence, l'attaque réussit quand même. Mais elle est bien plus dure pour l'attaquant, qui ne peut pas profiter de la taille de la fenêtre.)

Et si l'attaquant met le bit SYN (SYNchronize) à un ? La section 4 rappelle qu'une fois la connexion TCP établie, un paquet portant ce bit, toujours si le numéro de séquence figure dans la fenêtre, va couper la connexion. La section 4.2 demande donc que, pour tout paquet SYN reçu après l'établissement initial de la connexion, quel que soit son numéro de séquence, on envoie un accusé de réception. L'attaquant aveugle ne le verra pas et ne pourra pas confirmer. Le pair légitime qui avait envoyé un SYN (ce qui ne devrait pas arriver en temps normal et signifie probablement que le pair avait perdu tout souvenir de la connexion, par exemple suite à un redémarrage) enverra alors un RST puisque, pour lui, la session n'est pas ouverte.

Les deux attaques précédentes (RST et SYN) étaient des dénis de service. Mais on peut imaginer une attaque bien pire où le méchant réussit à injecter de fausses données dans une connexion TCP. Elle fait l'objet de la section 5. Si le méchant peut trouver un numéro de séquence dans la fenêtre, ses paquets de données seront acceptés et pourront être présentés à l'application qui utilise TCP (le succès effectif de l'attaque dépend d'un certain nombre de points, et peut dépendre de la mise en œuvre de TCP utilisée).

Pour contrer cette attaque, la section 5.2 demande de durcir les conditions d'acceptation des paquets de données. Davantage de paquets légitimes seront donc rejetés, afin de pouvoir compliquer la vie de l'attaquant.

À noter (section 6) que les recommandations des trois précédentes sections ne sont pas formulées avec la même force. Utilisant le vocabulaire du RFC 2119, les deux premières sont des fortes recommandations (SHOULD) et la troisième seulement une suggestion (MAY). En effet, une injection de données par un attaquant est bien plus difficile (car les vraies données finiront par arriver, avec un numéro de séquence légèrement différent, ce qui peut mener TCP à refuser soit les fausses, soit les vraies) et ne justifie donc pas d'imposer des contre-mesures qui peuvent mener au rejet de paquets légitimes.

Dernier conseil, celui de la section 7, la nécessité de limiter la quantité d'accusés de réception (ACK) émis. Avec les contre-mesures des sections 3 à 5, le nombre de paquets ACK va augmenter. La section 7 suggère donc de les limiter, par exemple à dix ACK de confirmation pour toute période de cinq secondes (et que ces chiffres soient réglables par l'administrateur système, variable sysctl net.ipv4.tcp_challenge_ack_limit sur Linux).

On notera que le RFC ne précise pas que le compteur du limiteur doit être par connexion (comme dans le RFC 6528). Résultat, au moins chez Linux, c'est un compteur global, ce qui peut servir à communiquer des informations cruciales pour aider l'attaquant (vulnérabilité CVE-2016-5696, décrite dans l'article « Off-Path TCP Exploits: Global Rate Limit Considered Dangerous »). Deux leçons à en tirer : la sécurité, c'est difficile (corriger une bogue peut en ajouter d'autres) et la limitation de trafic, parce qu'elle change le trafic (évidemment), peut avoir des conséquences imprévues. Un nouvel Internet-Draft a été proposé, discutant de ce problème et des solutions.

En attendant, un truc possible pour limiter les dégâts de cette faille sur Linux serait de faire :

echo $RANDOM > /proc/sys/net/ipv4/tcp_challenge_ack_limit

mais de le faire souvent : l'attaque peut prendre bien moins d'une minute. (Je n'ai pas testé ce truc, dû à x0rz.) Une solution analogue (avoir une limite variant de manière aléatoire) est dans un patch du noyau Linux.

Les recommandations de notre RFC 5961 modifient légèrement le protocole TCP. Cela nécessite donc une section 8, décrivant les problèmes de compatibilité qui peuvent se poser entre deux mises en œuvre de TCP, l'une conforme à notre nouveau RFC 5961, l'autre plus ancienne. Normalement, les modifications du protocole sont 100 % compatibles avec le TCP existant. La section 8 décrit toutefois un cas limite où la coupure d'une connexion nécessitera un aller-retour supplémentaire.

D'autre part, le succès complet des contre-mesures décrites dans ce RFC impose qu'elles soient déployées des deux côtés. Une mise en œuvre moderne de TCP parlant à un vieux pair ne fournirait pas une protection complète.

Dernier problème avec les nouveaux algorithmes : le cas des middleboxes, ces équipements qui se mettent sur le trajet de deux machines IP qui communiquent et qui brisent souvent la transparence du réseau (par exemple les pare-feux). La section 9 examine les problèmes qu'elles peuvent poser. Par exemple, certains équipements ré-envoient le RST pour le compte du vrai pair TCP (section 9.1) et, s'ils ne mettent pas en œuvre les recommandations de ce RFC, peuvent ne pas traiter correctement le ACK de demande de confirmation. Ce genre de problèmes survient souvent lorsqu'une middlebox est « ni chair, ni poisson », ni un pur routeur transparent aux paquets de la couche 4 (TCP), ni un vrai pair TCP. Autre exemple cité (section 9.3), un équipement intermédiaire qui, en voyant passer le RST, supprimerait toute l'information associée à cette connexion TCP. Le ACK de demande de confirmation pourrait alors être jeté, et ne recevrait donc pas de réponse, laissant ainsi une connexion TCP ouverte.

Enfin, la traditionnelle section « Security Considerations » (section 10) synthétise l'ensemble des questions liées à ces contre-mesures. Elle rappelle notamment que le problème traité par ce RFC ne concerne que les attaques en aveugle, typiquement lorsque l'attaquant n'est pas sur le chemin des paquets. S'il l'est, par exemple si l'un des deux pairs TCP est sur un réseau Wi-Fi public, les contre-mesures des sections 3 à 5 ne s'appliquent pas, car elles peuvent facilement être contournées par un attaquant en mesure de regarder les paquets, et de voir quel est le numéro de séquence à utiliser. Ce fut le cas par exemple dans les attaques menées par Comcast contre ses propres clients ou bien dans celles perpétrées par la dictature chinoise.

Même dans le cas d'une attaque en aveugle, les contre-mesures de notre RFC n'empêchent pas l'attaque, elles la rendent simplement beaucoup plus difficile. Un attaquant chanceux peut donc encore réussir, même contre des implémentations de TCP parfaitement à jour. La section 10 rappelle (vœu pieux) que la seule vraie protection serait de généraliser IPsec (par exemple avec l'ESP du RFC 4303).

D'autre part, ce RFC 5961 ne traite que les attaques faites uniquement avec TCP mais ICMP fournit aux attaquants aveugles d'autres possibilités (traitées dans le RFC 5927). Une mise en œuvre sérieuse de TCP doit donc traiter également ces attaques ICMP.

Aucun médicament n'est sans effet secondaire et c'est également le cas ici. Les contre-mesures de notre RFC peuvent créer des possibilités d'attaque par réflexion, si l'attaquant déguise son adresse IP : des paquets comme l'ACK de demande de confirmation seront alors envoyés à un innocent. Le RFC estime ce problème peu grave car il n'y a pas amplification : l'attaquant pourrait donc aussi bien viser directement la victime.


Téléchargez le RFC 5961


L'article seul

RFC 5952: A Recommendation for IPv6 Address Text Representation

Date de publication du RFC : Août 2010
Auteur(s) du RFC : S. Kawamura (NEC BIGLOBE), M. Kawashima (NEC AccessTechnica)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF 6man
Première rédaction de cet article le 23 août 2010


Comme pour IPv4, mais de manière bien plus commune, les adresses IPv6 ont plusieurs représentations possibles. Ainsi (section 1 du RFC), l'adresse 2001:db8:0:0:1:0:0:1 peut aussi s'écrire 2001:0db8:0:0:1:0:0:1, 2001:db8::1:0:0:1, 2001:db8::0:1:0:0:1, 2001:0db8::1:0:0:1, 2001:db8:0:0:1::1, 2001:db8:0000:0:1::1 ou 2001:DB8:0:0:1::1. Cette variété peut dans certains cas être cause de confusion, notre RFC propose donc une forme recommandée (ici, 2001:db8::1:0:0:1).

La syntaxe des adresses IPv6 est fixée le RFC 4291, section 2.2. Cette syntaxe est très souple, et venait sans format recommandé, « canonique ». La section 2 liste les points où le RFC 4291 laissait le choix :

  • Possibilité d'indiquer (ou pas) les zéros initiaux dans chaque champ. 2001:db8:0:0:1:0:0:1 et 2001:0db8:0:0:1:0:0:1 sont ainsi équivalentes (deuxième champ).
  • Possibilité de compression des champs nuls consécutifs en les remplaçant par ::. 2001:db8:0:0:0:0:0:1 et 2001:db8::1 sont ainsi la même adresse. Si le :: peut apparaitre à deux endroits, le RFC 4291 impose, pour éviter toute ambiguité, de ne le mettre qu'une fois mais sans préciser où. Ainsi, 2001:db8::aaaa:0:0:1 et 2001:db8:0:0:aaaa::1 sont la même adresse.
  • Pour les chiffres hexadécimaux qui sont des lettres de A à F, on peut utiliser n'importe quelle casse.

Est-ce que cela pose vraiment des problèmes ? Parfois, dit notre RFC, dont la section 3 liste les problèmes possibles (sans les hiérarchiser, ce que je regrette car certains cas semblent quand même assez rares en pratique). Premier problème, la recherche d'une adresse dans un fichier texte ou bien avec un tableur. Si on utilise aveuglément grep sur ses fichiers, on risque de ne pas trouver l'adresse IP (avec grep, il faudrait utiliser une expression rationnelle mais les tableurs, par exemple, n'en disposent pas forcément et leurs utilisateurs peuvent ne pas y penser). Notez qu'avec un SGBD qui dispose d'un type « adresse IP » comme PostgreSQL, ce problème n'existe pas, le SGBD ne traite pas l'adresse comme du texte :

essais=> CREATE TABLE Machines (name TEXT, address INET);
CREATE TABLE
essais=> INSERT INTO Machines VALUES ('gandalf', '2001:db8::cafe:0:1');
INSERT 0 1
essais=> INSERT INTO Machines VALUES ('saroumane', '2001:db8::bad:0:1');
INSERT 0 1
essais=> SELECT * FROM Machines WHERE address = '2001:DB8:0:0:0:CAFE:0:1';
  name   |      address       
---------+--------------------
 gandalf | 2001:db8::cafe:0:1
(1 row)

On voit que, malgré une représentation toute différente de l'adresse, la machine gandalf a bien été trouvée. Si tout le monde utilisait des logiciels de gestion d'adresses IP bâtis sur ce principe, il n'y aurait pas de problème. Mais, comme le note le RFC, les méthodes « du pauvre » à base de grep ou d'Excel sont courantes. (Voir aussi les sections 3.1.3 et 3.1.4, moins convaincantes à mon avis.)

Des problèmes analogues surviennent lorsqu'on veut écrire un programme capable d'analyser des adresses IPv6 sous toutes leurs formes légales (section 3.2.1, avec laquelle je ne suis guère d'accord : il existe des bibliothèques toutes faites pour cela, dans tous les langages, comme inet_pton() pour C, et celui qui réinvente la roue en écrivant un analyseur tout neuf en PHP ou Visual Basic mérite les ennuis qu'il aura).

Le RFC cite d'autres problèmes possibles, comme le fait qu'un module de journalisation qui afficherait les adresses IP sous leur forme longue (comme 2001:0db8:0:0:1:0:0:1) produirait des historiques peu lisibles, ou comme le fait qu'un mécanisme d'audit (par exemple avec un outil comme diff) ou de gestion de versions qui analyserait des changements dans la configuration d'un routeur pourrait croire à tort qu'il y a un changement lorsqu'une adresse IPv6 passe d'une forme à une autre (section 3.2.3). Bien d'autres points analogues sont pointés du doigt par le RFC.

Enfin, le jeu de caractères étendu de l'hexadécimal entraine un risque de confusion entre D et 0, de même qu'entre B et 8 (section 3.4.3).

Quelle solution propose donc notre RFC ? La section 4 est la partie normative du document : elle définit une forme canonique qui devrait être suivie systématiquement lorsqu'une adresse IPv6 est affichée. Rien de nouveau dans cette forme, qui est déjà celle choisie par la plupart des logiciels, à part sa désignation comme forme canonique officielle. Attention, cette obligation ne porte que sur la sortie d'adresses IPv6, en entrée, un logiciel conforme à la norme IPv6 doit toujours accepter les différentes syntaxes.

Une conséquence de cette existence d'une forme canonique est que le logiciel n'affichera donc pas toujours ce qu'on lui a indiqué. Pour reprendre l'exemple PostgreSQL :

essais=> INSERT INTO Machines VALUES ('galadriel', 
                    '2001:0DB8:0:DBA8:0:0:0:1');
INSERT 0 1
essais=> SELECT * FROM Machines WHERE name = 'galadriel';
   name    |      address       
-----------+--------------------
 galadriel | 2001:db8:0:dba8::1

L'adresse sera affichée sous une forme différente de celle sous laquelle elle a été entrée. La section 3.3.1 du RFC expliquait pourtant que c'était une mauvaise idée que d'afficher sous une forme différente, petite contradiction de ce RFC.

Donc, concrètement, comment doit être affichée une adresse ?

  • Les zéros initiaux dans un champ doivent être supprimés (section 4.1). 2001:0db8::0001 doit être écrit 2001:db8::1.
  • L'indication d'une suite de champs nuls, :: doit être utilisée au maximum, doit s'appliquer à la suite la plus longue (s'il y en a plusieurs) et, en cas d'égalité, à la première (section 4.2). Ainsi, 2001:db8:0:0:0:0:0:1 doit s'écrire 2001:db8::1, 2001:db8:0:42:0:0:0:1 doit être mis sous la forme 2001:db8:0:42::1 et 2001:db8:0:0:137:0:0:1 doit être affiché 2001:db8::137:0:0:1.
  • Les chiffres hexadécimaux doivent être en minuscule (section 4.3), donc 2001:DB8::BAD:DCAF doit être 2001:db8::bad:dcaf.

Le RFC prévoit aussi le cas des adresses spéciales comme les adresses IPv4 représentées en IPv6 (section 5).

Si l'adresse IP indiquée comprend également un port, il y avait traditionnellement plusieurs formes. La section 6 rend obligatoire la syntaxe avec crochets [2001:db8::deb:1]:80, issue du RFC 3986 (section 3.2.2) et qui n'était obligatoire que pour les URL.

L'annexe A donne des conseils pour les programmeurs, qui vont devoir écrire des programmes affichant des formes correctes. Ainsi, sur FreeBSD 7.0, l'utilisation de getnameinfo() avec l'option NI_NUMERICHOST produit déjà le résultat correct, sauf pour les adresses dites spéciales.

De même, PostgreSQL produit déjà des adresses au bon format. Et avec inet_pton() ? Le programme canonicalize-v6.c montre que son comportement est bien celui du RFC :

% ./canonicalize-v6 toto 2001:db8:Bad:0:0::0:1 127.0.0.1 35:0FF::1 2001:0:0:1:b:0:0:A 2001:db8:0:0:1:0:0:0
toto -> Illegal input IPv6 address
2001:db8:Bad:0:0::0:1 -> 2001:db8:bad::1
127.0.0.1 -> Illegal input IPv6 address
35:0FF::1 -> 35:ff::1
2001:0:0:1:b:0:0:A -> 2001::1:b:0:0:a
2001:db8:0:0:1:0:0:0 -> 2001:db8:0:0:1::

Voir aussi le RFC 4038 pour des détails sur les questions IPv6 pour les applications.


Téléchargez le RFC 5952


L'article seul

RFC 5943: A Dedicated Routing Policy Specification Language Interface Identifier for Operational Testing

Date de publication du RFC : Août 2010
Auteur(s) du RFC : B. Haberman (JHU APL)
Chemin des normes
Première rédaction de cet article le 23 août 2010
Dernière mise à jour le 21 février 2011


Lorsqu'un nouveau réseau est connecté à l'Internet, il est parfois injoignable de certaines parties de l'Internet, par exemple parce que ses adresses IP sont illégalement utilisées par d'autres ou bien parce qu'il est filtré en raison d'une histoire antérieure. Les bonnes pratiques opérationnelles demandent donc la configuration d'un serveur ICMP qui répondre à des tests, par exemple depuis ping. Traditionnellement, l'existence de ce serveur était annoncé via les commentaires stockés dans la base d'un RIR (comme le commentaire remarks: pingable 2a01:190:1764:150::30 du réseau 2a01:190::/32). Ces commentaires n'étant pas analysables automatiquement par un programme, il était donc souhaitable de créer un nouvel attribut RPSL pour cela, pingable:.

Prenons l'exemple de l'allocation d'un nouveau préfixe à un RIR par exemple, l'allocation de 175/8 : le nouveau préfixe est souvent inaccessible depuis plusieurs parties de l'Internet, par exemple en raison de filtres anti-bogon. Il faut donc une étape de « débogonisation » où le préfixe sera annoncé par le RIR, des serveurs ICMP echo seront installés et testés. Lorsque les filtres anti-bogon auront été mis à jour, le test pourra cesser.

Notre RFC 5943 permet d'automatiser ce genre de tests en ayant un nouvel attribut dans la description en RPSL (RFC 4012) de la route vers le préfixe en question. Sa description complète figure dans la section 2 du RFC, avec cet exemple :

route6: 2001:DB8::/32
origin: AS64500
pingable: 2001:DB8::DEAD:BEEF
ping-hdl: OPS4-RIPE

(ping-hdl est le handle du contact technique de ce serveur de test).

Cet attribut a été mis en œuvre dans la base du RIPE en février 2011. Voyez par exemple l'objet route pour le préfixe 84.205.81.0/24. :

% whois -h whois.ripe.net 84.205.81.0/24
...
route:          84.205.81.0/24
descr:          RIPE-NCC-RIS BGP Anchor Prefix @ rrc01 - LINX
origin:         AS12654
pingable:       84.205.81.1
ping-hdl:       RISM-RIPE
...

Les processus qui testent les adresses pingable doivent prendre garde à ne pas surcharger le réseau en se limitant à un nombre raisonnable d'essais (section 3 du RFC). Naturellement, rien ne garantit que tous le feront et celui qui installe le serveur de test doit aussi déployer ses propres protections (section 4 du RFC).

L'adoption de ce nouvel attribut n'est pas allée de soi et on peut trouver un exemple des discussions qui l'ont accompagné dans les minutes de la réunion RIPE-60 (cherchez « E. A Dedicated RPSL Interface Identifier for Operational Testing »).


Téléchargez le RFC 5943


L'article seul

RFC 5936: DNS Zone Transfer Protocol (AXFR)

Date de publication du RFC : Juin 2010
Auteur(s) du RFC : Edward Lewis (NeuStar), A. Hoenes (TR-Sys)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dnsext
Première rédaction de cet article le 28 juin 2010


Parmi les protocoles qui forment le socle de l'Internet, une des particularités du DNS est la grande distance entre la norme officielle, vieille désormais de treize ans et jamais révisée intégralement, et la réalité. Celle-ci a nécessité a plusieurs reprises la publication de normes de clarification, détaillant ce que le RFC 1034 avait laissé dans l'ombre. Notre RFC 5936 continue cette tradition pour le cas des transferts de zone où un serveur de noms réclame à un serveur faisant autorité une copie complète de la zone (c'est-à-dire des données DNS). Le principal point vague était le cas où un serveur faisait également autorité pour des zones parentes ou filles de la zone transférée : devait-il tenir compte de ce qu'il avait appris à cette occasion pour « corriger » la zone transférée ? La réponse est clairement désormais non : le serveur doit transférer ce qu'on lui a donné comme contenu de la zone, pas ce qu'il a pu apprendre par ailleurs.

Un peu d'histoire d'abord : le transfert de zones (souvent désigné par le mnémonique AXFR) était officiellement normalisé dans des parties du RFC 1034 et RFC 1035 (section 4.3.5 du premier, sections 2.2, 3.2.3 et 4.2 du second). Diverses améliorations avaient été créés comme le transfert incrémental (IXFR) du RFC 1995 ou comme la notification immédiate du RFC 1996. Le protocole avait également été corrigé par la section 5.5 du RFC 2181. Bien des points étant flous dans les RFC originels, les programmeurs ont dû petit à petit concevoir une version non-officielle, mais plus précise, du protocole, et c'est elle que notre RFC décrit.

Quel est le problème qu'essaie de résoudre le transfert de zones ? Pour des raisons de fiabilité, toute zone doit être servie par au moins deux serveurs faisant autorité (et bien plus en pratique). Évidemment, il faut que ces serveurs disposent des mêmes informations, soient synchronisés. Il existe plusieurs méthodes pour cela. Parmi les TLD, par exemple, certains utilisent rsync, certains utilisent les mécanismes de réplication de la base de données sous-jacente (comme Slony pour PostgreSQL). Mais AXFR (et IXFR) sont les seuls mécanismes DNS du lot. Aussi, bien que cela ne soit pas, en toute rigueur, obligatoire, tous les logiciels serveurs de noms mettent en œuvre cette technique (section 1.2 du RFC).

Focalisons nous sur AXFR car IXFR et NOTIFY ne sont pas traités par ce nouveau RFC. La section 2 de notre RFC 5936 reprend donc le travail et décrit intégralement le protocole. Un client DNS envoie une requête AXFR en mettant le QTYPE (Query TYPE) à la valeur 252 (section 2.1) et en dirigeant la requête vers un serveur faisant autorité (jamais vers un résolveur). Avec dig, cela se fait ainsi (ici pour la zone .uk) :


% dig @ns1.nic.uk AXFR uk.

Le client doit en outre s'assurer de la valeur de certains champs (section 2.1.1). Il peut aussi ajouter une section additionnelle à la question (section 2.1.5) spécifiant l'utilisation d'EDNS (RFC 2671) et/ou d'une technique d'authentification comme TSIG (RFC 8945).

La section 2.2 décrit la réponse à cette requête. C'est une série de messages DNS (lorsqu'il est transporté sur TCP, chaque message DNS est composé d'une longueur, puis de données). Chaque message peut comporter plusieurs enregistrements. Le premier message doit commencer avec l'enregistrement SOA de la zone transférée et le dernier message se terminer avec le même SOA. À part cette règle, l'ordre des enregistrements ou des messages n'a pas de signification (ce n'est donc pas forcément l'ordre du fichier de zone). Voici une partie de la réponse à la requête faite plus haut. Elle ne comporte qu'un seul message, incluant les 195 enregistrements de cette petite zone. La réponse commence bien par le SOA de la zone transférée :


uk.			172800	IN	SOA	ns1.nic.uk. hostmaster.nic.uk. 1277504551 7200 900 2419200 172800
uk.			3600	IN	RRSIG	NSEC3PARAM 8 1 3600 20100709182231 20100625172231 44346 uk. dM777Q8sZ9sNshexmw08/cfUIAqzxjMj/MvARyuPxxNW52pfXprZ7AvM 0B27rVpIi6qEsBlypNwzZMOm56bzmDQVGBXnC77eUh9kXGEaI6tLuTta rfFWakGdcS8kn/lUOtIOhbfy6xuQRsD6+Y/iV/HEcwmpShVcea/PnSx8 eQQ=
...
_nicname._tcp.uk.	172800	IN	SRV	0 0 43 whois.nic.uk.
ac.uk.			172800	IN	NS	ns.uu.net.
...
british-library.uk.	172800	IN	NS	dns1.bl.uk.
british-library.uk.	172800	IN	NS	dns2.bl.uk.
co.uk.			172800	IN	NS	ns1.nic.uk.
...
u1fmklfv3rdcnamdc64sekgcdp05bbiu.uk. 172800 IN NSEC3 1 1 0 - 2D51R16SS5MQU6PCG2Q0L05JA7E20FC7 NS SOA RRSIG DNSKEY NSEC3PARAM
uk.			172800	IN	SOA	ns1.nic.uk. hostmaster.nic.uk. 1277504551 7200 900 2419200 172800
;; Query time: 430 msec
;; SERVER: 2a01:40:1001:35::2#53(2a01:40:1001:35::2)
;; WHEN: Sat Jun 26 18:33:50 2010
;; XFR size: 195 records (messages 1, bytes 6125)

La réponse se termine bien par le SOA de la zone transférée. Bien que dig ne l'affiche pas lors d'un transfert de zones, certaines options doivent être mises dans l'en-tête, par exemple AA pour Authoritative Answer (section 2.2.1).

Dans l'exemple ci-dessus, la section additionnelle était vide. Mais, si on authentifie le transfert avec TSIG (RFC 8945), ce n'est plus le cas. La signature de la zone transférée apparait alors dans cette section (section 2.2.5 ; mais dig l'affiche à la fin des réponses, ce qui est trompeur. Si on veut voir ce qui passe sur le réseau, il vaut mieux utiliser Wireshark.)

Cela, c'était le protocole. Maintenant, les questions les plus sérieuses posées par le transfert de zones portaient plutôt sur le contenu de ce qui est transféré (section 3). Le principe de base posé par notre nouveau RFC est que le serveur doit transférer fidèlement ce que lui-même a reçu (via un fichier de zone - la méthode traditionnelle - ou via un SGBD). Notez que cette règle semble un enfonçage de porte ouverte mais qu'elle ne l'est pas : par exemple, si la zone est très dynamique, fabriquée à la demande, alors un transfert de zones est tout simplement impossible (section 3.1). Pour prendre un exemple pour rire, c'est le cas de rp.secret-wg.org.

Mais le principal cas où l'application de la règle est délicate est celui cité dans la section 3.2 : que faire si le serveur qui fait autorité pour foo.example fait également autorité pour bar.foo.example et qu'on lui demande de transférer foo.example ? Normalement, les enregistrements NS des deux zones doivent être identiques. Mais, dans le monde réel, ce n'est pas toujours le cas. Si foo.example contient :

bar.foo.example.   IN   NS   ns1.example.net.
                   IN   NS   ns2.example.net.

(enregistrements qui ne font pas autorité mais sont nécessaire spour trouver les serveurs de la zone fille) et que bar.foo.example contient :

bar.foo.example.   IN   NS   ns1.example.net.
                   IN   NS   ns3.example.net.

(qui, cette fois, font autorité) quel jeu d'enregistrements doit renvoyer le serveur lorsqu'on lui demande foo.example ? Ce n'est pas dit clairement dans les RFC 1034 (sa section 4.2.1 est ambigue) et RFC 1035 et les serveurs de noms ont souvent eu des comportements différents sur ce point. Or, celui-ci est crucial, par exemple pour des zones signées avec DNSSEC (par exemple, les enregistrements NSEC et NSEC3 ne seront pas les mêmes, puisque le nom suivant, dans chacune des deux zones, sera différent). Notre nouveau RFC tranche : on envoie ce que contenait la zone transférée, pas ce qu'on a pu apprendre parce qu'on sert d'autres zones. Dit autrement, AXFR doit être exactement équivalent à un rsync du fichier de zone.

Pourquoi l'ambiguité a t-elle été tranchée dans ce sens ? Il y a plusieurs raisons parmi lesquelles :

  • Certains serveurs de foo.example peuvent faire autorité également pour bar.foo.example et d'autres pas. Si le serveur transférait les données « corrigées », les différents serveurs de foo.example enverraient donc des contenus différents lors d'un transfert.
  • Le débogage (ici, la détection de l'incohérence entre foo.example et bar.foo.example) serait bien plus difficile si on ne pouvait pas accéder aux données brutes stockées sur le serveur.

Même règle (transférer la zone qu'on a reçu, ne pas tenter de la « corriger » avec ce qu'on a appris dans d'autres zones) s'applique aussi à la colle, ces enregistrements d'adresses IP qui, sans faire autorité, doivent parfois être stockés dans la zone parente, pour permettre de trouver un serveur de noms qui figure dans une zone fille (section 3.3).

Il reste deux problèmes liés au contenu de la zone : la compression de données (RFC 1035, section 4.1.4) lors d'un transfert ne peut pas être la même que pour une réponse typique (section 3.4) car elle doit tenir compte de la casse (le transfert doit désormais transmettre les noms en respectant leur casse, ce qui n'est pas le cas lors d'une requête DNS classique). Et enfin, il y a le problème des noms masqués. Si un serveur permet la mise à jour dynamique (RFC 2136), une nouvelle délégation (la création dynamique d'enregistrements NS) peut masquer des anciens noms (section 3.5). Ainsi, si la zone contenait www.toto.foo.example, la création d'enregistrements NS pour toto.foo.example masque complètement www.toto.foo.example. Dans ce cas, le RFC est clair : le transfert de la zone doit inclure les noms masqués.

Une fois réglé le protocole et le contenu, reste la question du transport. La section 4 traite son cas : le transfert de zones a toujours nécessité l'utilisation de TCP (la section 4.2 explique pourquoi cela restera le cas). Mais le reste n'est pas clair : par exemple, peut-on réutiliser la connexion TCP pour un deuxième transfert de zones ? Les serveurs de noms esclaves font genéralement une requête SOA avant de demander le transfert de zones, l'examen du numéro de série que contient le SOA leur permet de savoir si un transfert est nécessaire. Cette requête SOA peut-elle passer sur la même connexion TCP que le transfert, si celui-ci a lieu ? Il est difficile de « faire parler » les vieux RFC sur ce point. Le fait qu'ils n'exigent pas que le serveur copie la question ou bien le Query ID dans la réponse semble indiquer que l'idée était en effet qu'une connexion TCP ne serve qu'au transfert de zone, et à un seul. Toutefois, notre RFC 5936 choisit de trancher en autorisant explicitement l'utilisation d'une connexion TCP pour plusieurs requêtes (pas forcément toutes AXFR). C'est même l'option recommandée, pour économiser des ressources sur le serveur.

Lorsque les RFC originels sur le DNS avaient été écrits, on prêtait moins d'attention à la sécurité qu'aujourd'hui. Ces RFC ne mentionnaient donc pas la possibilité de restreindre, voire d'interdire le transfert de zones. Comme l'explique la section 5, cette possibilité est au contraire considérée comme vitale aujourd'hui. (Voir mon article « Récupérer une zone DNS ».) Le RFC demande que l'autorisation de transfert puisse se faire par adresses IP, et par des techniques de signature comme TSIG. La politique par défaut devrait être « pas de transfert ».

Voici un exemple avec le serveur nsd (version 3) qui, comme recommandé par le RFC, ne permet pas de transfert par défaut :

zone:
        name: "bortzmeyer.fr"
        zonefile: "primary/bortzmeyer.fr"
        provide-xfr: 192.134.7.248  NOKEY

Ici, la machine 192.134.7.248 (et elle seule) est autorisée à transférer la zone (directive provide-xfr). Une tentative depuis une autre adresse donnera, par exemple sur le serveur :

Jun 28 20:23:58 aetius nsd[25004]: axfr for zone bortzmeyer.fr. \
       from client 2a01:e35:8bd9:8bb0:38cf:6d60:b99:4d94 refused, no acl matches

Avec BIND, on s'y prend en général en définissant des ACL, ici une ACL nommée my-nets :

acl my-nets {
                203.0.113.128/26; 
                127.0.0.0/8;
                2001:db8:3003::/48;
};

puis en les utilisant dans les paramètres de la zone :

zone "bortzmeyer.fr" {
    allow-transfer {
                my-nets;
        };
    ...
};

et une tentative par une autre machine sera rejetée, le serveur notant :

Jun 28 20:27:41 lilith named[20452]: \
       client 2a01:e35:8bd9:8bb0:38cf:6d60:b99:4d94#51619: \
       zone transfer 'bortzmeyer.fr/AXFR/IN' denied

Et l'intégrité des données transférées ? La section 6 se penche sur la question et spécifie qu'un transfert doit être complet, et avec succès, pour que la zone ainsi transférée soit utilisée (en d'autres termes, le transfert doit être atomique).

On l'a vu, l'ancienne norme était loin d'être claire sur tous les points. La nouvelle est, on l'espère, plus précise. Mais alors, n'y a t-il pas des risques de mauvaise entente entre anciens serveurs et nouveaux clients (ou le contraire) ? La section 7 du RFC est consacrée à ce problème de compatibilité. Elle commence par noter qu'il est difficile de donner des garanties, puisque la sous-spécification du transfert de zones fait que les anciens logiciels présentent une grande variété de comportements. Souvent, cet ancien comportement n'est pas facilement détectable automatiquement, donc la règle est qu'un nouveau logiciel qui souhaite interagir avec les anciens doit le faire via une option de configuration. Limitons nous au point de vue du serveur (section 7.1). Il ne peut pas savoir si le client accepte plusieurs enregistrements par message et l'interaction avec des clients qui n'y arrivent pas nécessite donc une option spécifique (mais qui ne doit pas être activée par défaut). (Pour le point de vue du client, voir la section 7.2.)


Téléchargez le RFC 5936


L'article seul

RFC 5933: Use of GOST signature algorithms in DNSKEY and RRSIG Resource Records for DNSSEC

Date de publication du RFC : Juillet 2010
Auteur(s) du RFC : V.Dolmatov (Cryptocom)
Intérêt historique uniquement
Première rédaction de cet article le 10 juillet 2010
Dernière mise à jour le 30 août 2019


L'algorithme de signature russe GOST R 34.10-2001 ayant été spécifié en anglais dans le RFC 5832, plus rien ne s'opposait à son utilisation dans DNSSEC. Ce RFC marque donc l'arrivée d'un nouvel algorithme dans les enregistrements DNSSEC, algorithme portant le numéro 12. (Depuis, le GOST R 34.10-2012 a été publié, puis normalisé pour DNSSEC dans le RFC 9558.)

La liste originelle des algorithmes DNSSEC figurait dans le RFC 4034, annexe A.1. La liste actuelle est un registre à l'IANA, https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xml#dns-sec-alg-numbers-1. Elle comprend désormais GOST. Notez que GOST désigne en fait une organisation de normalisation, le terme correcte serait plutôt « GOST R 34.10-2001 » pour l'algorithme de signature et « GOST R 34.11-94 » pour celui de condensation, décrit dans le RFC 5831 (voir la section 1 de notre RFC 5933).

La section 2 décrit le format des enregistrements DNSKEY avec GOST, dans lequel on publie les clés GOST R 34.10-2001. Le champ Algorithme vaut 12, le format de la clé sur le réseau suit le RFC 4491. GOST est un algorithme à courbes elliptiques, courbes décrites par Q = (x,y). Les 32 premiers octets de la clé sont x et les 32 suivants y (en petit-boutien, attention, contrairement à la majorité des protocoles Internet). Les autres paramètres de la clé figurent dans le RFC 4357.

Les bibliothèques cryptographiques existantes sont parfois capables de lire des clés GOST (section 2.1). Pour OpenSSL, il existe une distribution de GOST (par la même entreprise où travaille l'auteur des RFC GOST).

La section 2.2 donne un exemple de clé GOST publiée dans le DNS mais autant utiliser ici un exemple réel (ce domaine a des clés GOST et aussi des clés RSA de type 5) :


% dig +multi DNSKEY caint.su

; <<>> DiG 9.9.2 <<>> +multi DNSKEY caint.su
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 61873
;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;caint.su.              IN DNSKEY

;; ANSWER SECTION:
caint.su.               3600 IN DNSKEY 256 3 12 (
                                HQUwRfZDsGuso1XEVztO9nIt7S6MrC/XNYQ9Agup8oW0
                                FCfy0T52buB3czWe9YHa0kLgrcFP1pHpu19jdmO70A==
                                ) ; ZSK; alg = ECCGOST; key id = 35724
caint.su.               3600 IN DNSKEY 257 3 5 (
                                AwEAAdfmAyxcSu09Ik449sIGygbD78jxCKaBek3fhC1a
                                hO7363pdMGlXf8ZEzv7Kl+9yOokmMoTI0peVUqF57it3
                                hmqcIJQ+OsrKdsF1XBwa8VULaLh+TNb67dkdbj6iZ6Gd
                                WxkD6i2vbjvmVHtoQyKswgeR7lUn42XMRYRbYiIrI5r8
                                zT/xllwtCCxaC68V6azpk//7GrYpnwS9NGzr2cBignwj
                                Jj6VeAGfrBe5AM0XNplaFLf7NNU34qqGBKpYbogdAYzM
                                Il02dhPvruzDcadbm2a53OI2/fqchjOgZ8wSTfekuJQb
                                ReYWsNUasgqxjydMU5vweSiogGqkrUEzqn5PD/0=
                                ) ; KSK; alg = RSASHA1; key id = 697
caint.su.               3600 IN DNSKEY 257 3 12 (
                                qMxkfdx4fNxdLDU3z5KGAxrEiL1fm+dxw03js+ACY996
                                wc1wYiVbmqA1QVUmLg5bO3/IawdItM3jQcigFEi/3A==
                                ) ; KSK; alg = ECCGOST; key id = 33831
caint.su.               3600 IN DNSKEY 256 3 5 (
                                AwEAAawWrWjeYqJ+07pakuybnkLQz3xbe1rnG2g7ihfO
                                NpSLNYrNOyhcCTRbt3cgJLWR29Qh6uko9Zcd9uylHlY1
                                ru1HpBQxpzKffwUUki2e7SiTiGrj/DvJz9UH52VZyxi5
                                qf9neYBz0sxvlrLWC5JMqqGIBRUMx/clPjab72BV7exR
                                ) ; ZSK; alg = RSASHA1; key id = 15876

;; Query time: 326 msec
;; SERVER: 192.168.2.254#53(192.168.2.254)
;; WHEN: Tue Oct 23 15:59:57 2012
;; MSG SIZE  rcvd: 621


La section 3 décrit le format des enregistrements RRSIG, les signatures. On suit les RFC 4490 et RFC 4357. Voici un exemple actuellement présent dans le DNS (notez qu'il y a double signature, avec RSA et GOST, la clé GOST étant la 35724) :


dig +dnssec MX caint.su

; <<>> DiG 9.9.2 <<>> +dnssec MX caint.su
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 61031
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 4, ADDITIONAL: 10

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;caint.su.                      IN      MX

;; ANSWER SECTION:
caint.su.               3600    IN      MX      10 mail.caint.su.
caint.su.               3600    IN      RRSIG   MX 5 2 3600 20121027063752 20120927063752 15876 caint.su. E5d1eZxLgYxNg1YiNXEyQ5UGJFOyd09bmpo9AtwnpJn0ezSX0wsAnvd1 ExBWf9ue0TnPSknZxofevtOHD3cBw09Lq/ZathhEOvNhHaK4kbMEXWm7 KzwLeNDDhqNbhAbY0duDLEPCA69ege00dJFjBMtqV17TTJ13BxrFXNzs Hmk=
caint.su.               3600    IN      RRSIG   MX 12 2 3600 20121027063752 20120927063752 35724 caint.su. 52NgPC9ZmFwIgL8CsK0C+wwoM+brh4uTfw70yRDJTjbkUVivkdCakDIS YVxPLWaQO6mDMzNwC53QYqwUyEYlEQ==

...

Attention, une particularité de GOST fait que deux signatures des mêmes données peuvent donner des résultats différents, car un élément aléatoire est présent dans la signature.

La section 4 décrit le format des enregistrements DS pour GOST. La clé publique de la zone fille est condensée par GOST R 34.11_94, algorithme de numéro 3. Voici un exemple dans la nature :

% dig DS caint.su
...
caint.su.               345330  IN      DS      33831 12 3 267B93EB54BF7707BF5500900722F3B0FBFCA04FF4F1BF22735F9ABB 607832E2

Notez que ce domaine a d'autres clés et aussi la même clé condensée par les algorithmes de la famille SHA, soit six DS en tout. Ou un autre exemple dans .fr ?

absolight.fr.		172724 IN DS 12545 8 3 (
				DDA74E5E94CEA6057072B073F60A5DD37D16DC8E896A
				EC57B055888DB84B4210 )

Les sections 5 et 6 couvrent des questions pratiques liées au développement et au déploiement de systèmes GOST, par exemple un rappel sur la taille de la clé (512 bits) et sur celle du condensat cryptographique (256 bits).

GOST peut se valider avec Unbound (au moins depuis la version 1.4.4, voir l'option de compilation --enable-gost) et avec BIND (depuis la version 9.8, si elle est compilée avec un OpenSSL qui a GOST). nsd a GOST depuis la version 3.2.11, pubiée en juillet 2012. Pour les programmeurs Java, DNSjava a GOST depuis la version 2.1.7. Pour le statut (recommandé ou non) de l'algorithme GOST pour DNSSEC, voir le RFC 8624. On peut trouver des conseils pratiques pour l'utilisation de GOST en anglais à http://www.cryptocom.ru/dns/dnssec-cryptocom-en.html.


Téléchargez le RFC 5933


L'article seul

RFC 5927: ICMP attacks against TCP

Date de publication du RFC : Juillet 2010
Auteur(s) du RFC : F. Gont (UTN/FRH)
Pour information
Réalisé dans le cadre du groupe de travail IETF tcpm
Première rédaction de cet article le 7 juillet 2010


Vous voulez tout savoir sur les attaques qu'on peut perpétrer avec le protocole ICMP contre le protocole de couche 4 TCP ? Ce RFC est pour vous. Il documente les différents mécanismes par lesquels une session TCP, même protégée, peut être attaquée via le protocole de signalisation. Il ne fournit pas de solutions absolues mais documente quelques modifications dans les mises en œuvre de TCP qui peuvent réduire la gravité du problème.

D'où vient le problème ? ICMP (RFC 792) est le protocole de signalisation d'IP et permet d'informer les machines qu'un paquet n'a pas pu être transmis ou bien que le trafic est trop intense. Mais ICMP n'a aucun mécanisme de validation (sauf si on encapsule tout dans IPsec) et il est trivial pour un méchant de fabriquer un faux paquet ICMP et de l'envoyer aux machines qu'il veut attaquer. Le méchant n'a même pas besoin d'espionner le réseau visé (alors que la fabrication d'un faux paquet TCP impose de connaitre un numéro de séquence valide, ce qui est très difficile si on en peut pas lire les paquets échangés), ces attaques sont donc faisables sans qu'on soit sur le chemin attaqué (off-path). Le problème est connu depuis longtemps mais ne semble pas avoir jamais été documenté dans un RFC, avec les contre-mesures possibles (section 1 du RFC). Certaines recommandations apparaissent toutefois dans des documents comme le RFC 4907.

Notre RFC 5927 fait ce travail de documentation et suggère des solutions pour limiter les dégâts, sans modifier le protocole TCP lui-même (bien que, parfois, ces solutions sont aux limites de ce que permet le RFC 793), ce qui est conforme aux règles prudentes du groupe de travail IETF tcpm, qui s'interdit de changer le protocole.

La section 2 de notre RFC rappelle ICMP pour les lecteurs débutants. ICMP sert à signaler les problèmes rencontrés par un paquet lors de sa traversée du réseau (cf. RFC 816). Le message ICMP est typiquement émis par un routeur présent sur le trajet et son adresse IP source n'est donc pas forcément celle de la machine avec laquelle on voulait communiquer. Rien ne garantit que le message ICMP arrive bien : comme tout paquet IP, il peut être filtré, victime de la congestion ou, ce qui est fréquent de nos jours, jamais émis en raison du rate limiting, fréquemment configuré sur les routeurs IP, pour éviter qu'ils ne soient DoSés par l'émission de paquets ICMP. TCP ne peut donc pas compter uniquement sur ICMP pour signaler les problèmes, il doit aussi se débrouiller seul, ICMP accélerant simplement la détection des ennuis. ICMP pour IPv4 est normalisé dans le RFC 792. Il fournit plusieurs types de messages d'erreur que le RFC 1122 a ultérieurement classé en erreurs dures et erreurs douces. Plusieurs protocoles ont été développés en utilisant ICMP dont le plus connu est la découverte de la MTU, dans le RFC 1191. ICMP pour IPv6 est dans le RFC 4443 et, si les codes sont légèrement différents de ceux de IPv4, les principes sont les mêmes. Enfin, il existe des extensions à ICMP comme les messages structurés du RFC 4884.

Le RFC 4301 comprend une annexe D qui étudie en détail ICMP, dans le contexte de la sécurité (voir aussi la section 2.3 de notre RFC). Car, officiellement, les anciens RFC comme le RFC 1122 (dans sa section 4.2.3.9) imposaient aux machines connectés à l'Internet de réagir à certains messages ICMP, sans tenir compte du fait que ces messages ne sont pas authentifiés et sans parler de validation, même sommaire. On peut dire que TCP faisait autrefois une confiance aveugle à ICMP (section 2.2).

Cette confiance n'était pas vraiment justifiée. Comme le rappelle la même section, un attaquant peut facilement fabriquer un paquet ICMP vraisemblable, il suffit de connaître les adresses IP source et destination, ainsi que les ports source et destination. Comme expliqué dans des documents comme le RFC 4953, trouver ces quatre chiffres est parfois assez facile. Par exemple, dans le cas d'une connexion BGP sur un point d'échange, les adresses IP des deux pairs sont en général publiques, l'un des ports est le port bien connu de BGP, 179 et l'autre ne peut prendre que 65536 valeurs possibles (moins que cela, en pratique). Un attaquant, même non situé sur le réseau visé, peut donc créer un paquet ICMP qui a de bonnes chances d'être accepté (le plus simple étant de générer les 65536 paquets possibles...)

Bref, il ne faut pas faire confiance à ICMP, comme documenté dans le RFC 4907. Mais l'équilibre est difficile à trouver : si on ignore tous les paquets ICMP, on ne sera averti que très tard des problèmes sur le réseau, lorsque les délais de garde expireront. Si on les accepte tous, on s'expose à de sérieuses DoS. L'idéal est donc que la politique d'acceptation soit réglable.

Le RFC décrit les attaques ICMP possibles après l'analyse des solutions. Mais il me semble plus logique de faire l'inverse et de continuer avec les sections 5, 6 et 7. La section 5 décrit l'attaque de réinitialisation de la connexion en aveugle (blind connection-reset attack). Elle consiste à envoyer un paquet ICMP de type « erreur dure » par exemple type 3 (Destination Unreachable) avec les codes 2 à 4 (protocol unreachable, port unreachable et fragmentation needed and DF bit set). Selon le RFC 1122, TCP devrait alors couper la connexion (notez que les sections 3.2.2.1 et 4.2.3.9 du RFC 1122 se contredisent...) On a donc avec cette attaque un bon moyen de faire un déni de service sans même avoir besoin d'être situé sur le chemin des paquets (d'où le terme d'attaque en aveugle). Pire, certaines mises en œuvre de TCP/IP coupent non seulement la connexion TCP en cause mais aussi toutes celles avec la même machine. D'autre part, il faut bien se rappeler que l'attaque, étant en ICMP, ne dépend pas de la capacité de l'attaquant à fabriquer des paquets TCP et qu'elle marche donc même si la connexion TCP est protégée par des techniques comme le TCP-AO du RFC 5925.

Alors, quelles sont les solutions contre l'attaque de réinitialisation de la connexion ? La section 5.2 les décrit : compte-tenu du fait qu'un code protocol unreachable et même, dans une large mesure port unreachable n'a de sens qu'au début d'une connexion, la recommandation est d'ignorer ces paquets ICMP une fois la connexion établie. Par un raisonnement similaire, les codes fragmentation needed and DF bit set peuvent être ignorés ou plus exactement considérés comme des erreurs douces. Donc, pour résumer, sauf pour les connexions en cours d'établissement, traiter les erreurs dures comme des erreurs douces supprime l'attaque par réinitialisation. Cela a certes des inconvénients (les vrais problèmes seront détectés moins rapidement) mais rien n'est parfait dans le monde cruel de la sécurité. La robustesse de TCP étant la principale motivation pour son utilisation, le compromis semble raisonnable. À noter qu'il est mis en œuvre dans FreeBSD, NetBSD et Linux depuis de nombreuses années. Notre RFC ne fait que le documenter.

Autre attaque possible en ICMP, moins radicale, la réduction de débit en aveugle (blind throughput reduction, section 6. Elle consiste pour l'attaquant à envoyer des paquets ICMP de type 4 (répression de l'envoi, source quench). TCP devait réagir en ralentissant le débit, voire en reprenant comme si la connexion était neuve, avec une fenêtre d'envoi de petite taille. Là encore, l'attaque est connue depuis longtemps et, comme toutes les études ont montré que la répression de l'envoi était une mauvaise technique de contrôle de la congestion (cf. RFC 1812), les implémentations de TCP ignorent depuis longtemps ces paquets ICMP, préférant les mécanismes purement TCP (RFC 5681, RFC 3168), même si c'était formellement une violation de la norme (depuis la sortie du RFC 6633, la norme a rejoint la pratique). Dans le noyau Linux (net/ipv4/tcp_ipv4.c) :

	case ICMP_SOURCE_QUENCH:
		/* Just silently ignore these. */
		goto out;

Autre moyen de diminuer les performances, l'attaque contre la découverte de MTU en aveugle (blind performance-degrading attack, section 7). Si l'une des deux machines connectées en TCP met en œuvre l'algorithme PMTUD du RFC 1981 pour découvrir la MTU du chemin, des faux paquets ICMP peuvent la tromper et lui faire adopter une MTU sous-optimale. Si l'attaquant envoie des paquets ICMP de code 3 et de type 4 (fragmentation needed and DF bit set), indiquant une MTU de petite taille, la machine naïve va réduire la taille des paquets qu'elle envoie, s'empêchant ainsi de tirer profit à fond du réseau (les paquets plus petits sont moins efficaces car la part relative des en-têtes augmente et le « coût » par octet augmente puisque le coût de traitement dépend davantage du nombre de paquets que du nombre d'octets).

Si la machine utilise l'algorithme PMTUD, elle ne peut pas ignorer ces paquets ICMP. Que peut-elle alors faire ? Une solution évidente est d'abandonner PMTUD au profit du RFC 4821. Une autre solution moins radicale, mise en œuvre dans NetBSD, est d'ignorer ces paquets ICMP uniquement si la connexion progresse (si les octets envoyés font l'objet d'accusés de réception) et d'en tenir compte si les octets ne passent plus (ce qui peut indiquer effectivement un endroit où la MTU a baissé). Cette contre-mesure est décrite en grand détail dans la section 7.3.

Bon, tout cela n'est pas satisfaisant. Existe t-il une solution à ce problème de la vulnérabilité d'ICMP ? La section 3 expose d'abord les contraintes auxsquelles doit obéir une solution. Comme le paquet ICMP d'erreur ne contient qu'une partie du paquet original (en IPv4, l'en-tête IP, plus 8 octets), le processus qui va prendre la décision d'accepter ou de refuser le paquet ICMP n'a qu'une information limitée. Le RFC 1122 a autorisé les routeurs à envoyer davantage que ces malheureux huit octets mais ce n'est pas forcément ce qu'ils font. Le RFC 1812 est même plus gourmand en suggérant , pour les routeurs, d'utiliser un paquet de taille totale 576 octets. Pour les machines non-routeuses, il n'y a pas de telle recommandation. (IPv6 offre plus de place dans un paquet sans fragmentation et donc offre davantage d'information.) Avec les huit octets, on a tout juste les deux numéros de port (source et destination) et le numéro de séquence.

Ainsi, même si TCP signait ses segments avec le RFC 2385, l'information contenue dans les paquets ICMP d'erreur ne permettrait pas de valider cette signature. IPsec permettrait d'authenfifier les paquets ICMP envoyés par la machine avec laquelle on correspond mais pas forcément ceux des routeurs intermédiaires. Aujourd'hui, vu l'état du déploiement d'IPsec, cette perspective est tout à fait utopique.

La section 4 fournit des idées générales sur les contre-mesures à adopter pour résister à ces attaques. Par exemple, un test évident mais qui n'avait pas été prévu à l'origine, est de vérifier, en utilisant le numéro de séquence TCP contenu dans le message ICMP suspect, s'il correspond à des données actuellement en transit (envoyées mais qui n'ont pas fait l'objet d'un accusé de réception). Un tel test rend très difficile la tâche de l'assaillant, qui doit désormais trouver un numéro de séquence valide. Là encore, tous les Unix libres font ce test depuis longtemps. Avec Linux, les tests de validité qui échouent sont enregistrés et affichables avec netstat :

% netstat -s
...
TcpExt:
...
    13 ICMP packets dropped because they were out-of-window

Si vous voyez cet compteur s'incrémenter, cela indique que quelqu'un tente sa chance... Évidemment, si l'attaquant peut espionner le réseau (s'il est on-path), trouver un tel numéro de séquence est trivial. D'autre part, les connexions TCP à haut débit, utilisant de grandes fenêtres (RFC 7323) restent vulnérables car un plus grand pourcentage de l'espace des numéros de séquence est valide, à un moment donné. Enfin, ce test a à la fois des faux positifs (paquets ICMP légitimes mais arrivant en retard, une fois les données réceptionnées) et des faux négatifs (assaillant chanceux). Ai-je déjà dit qu'il n'existe jamais de solution de sécurité parfaite ?

Autre mesure, l'aléatoirisation du port source (section 4.2). L'attaquant devant deviner le port source, si celui-ci est prévisible (machine allouant les ports sources séquentiellement...), on lui facilite la tâche.

Dernière contre-mesure générique, commune à toutes les attaques ICMP : les pare-feux pourraient regarder dans les paquets ICMP l'adresse source du paquet TCP qui a déclenché l'erreur et jeter le paquet ICMP si cette adresse source ne correspond pas à une machine du réseau interne (section 4.3). En effet, si un méchant situé sur le réseau 192.0.2.128/25 veut attaquer la machine 203.0.113.2, il va émettre un faux paquet ICMP qui porte soi-disant sur un message envoyé par 203.0.113.2. Le pare-feu du réseau utilisé par le méchant peut donc voir que ce message est illégitime, puisque 203.0.113.2 n'est pas sur son site. Idem si un attaquant externe tente de perturber des connexions TCP entre machines internes. L'article de l'auteur du RFC, « Filtering of ICMP error messages » donne d'autres exemples. Le pare-feu d'OpenBSD met en œuvre cette technique.

Ah, et si vous voulez tester ces attaques vous-même, le code est disponible sur le site Web de l'auteur. Si vous voulez uniquement approfondir votre compréhension de la sécurité de TCP, une lecture recommandée est « CPNI technical note 3/2009 - Security assessment of the Transmission Control Protocol (TCP) ». Il existe d'autres attaques contre TCP et d'autres RFC pour les traiter, voir mon article « La sécurité de TCP : plein de nouveaux RFC depuis trois ans ».

Parmi les nombreux articles qui avaient été publiés à l'époque de la découverte de cette vulnérabilité, je recommande celui fait à l'occasion du Hackaton OpenBSD, qui explique notamment les manœuvres de Cisco pour tenter de breveter les techniques de protection.


Téléchargez le RFC 5927


L'article seul

RFC 5925: The TCP Authentication Option

Date de publication du RFC : Juin 2010
Auteur(s) du RFC : J. Touch (USC/ISI), A. Mankin (Johns Hopkins University), R. Bonica (Juniper)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF tcpm
Première rédaction de cet article le 22 juin 2010


Un des problèmes traditionnels de sécurité de l'Internet est la difficulté à s'assurer que le correspondant est bien celui qu'il prétend être. Même une authentification au niveau de l'application ne suffit pas car rien ne garantit qu'un attaquant ne va pas se glisser dans la communication après l'authentification. En effet, rien ne lie la connexion TCP sous-jacente (couche 4) à la communication authentifiée en couche 7. Ce risque de détournement d'une connexion authentifiée est particulièrement important pour les longues sessions comme celles entre deux routeurs BGP ou LDP. Deux méthodes ont été normalisées pour cela, IPsec (RFC 4301) et TLS (RFC 5246). La première, complexe à déployer entre organisations, n'a pas été un grand succès et la seconde nécessite une adaptation des protocoles applicatifs. Que reste t-il comme solution ?

Il y en a bien d'autres, bien sûr, comme SSH, mais plusieurs protocoles, à commencer par BGP, n'avaient pas envie de s'adapter et cherchaient à sous-traiter le problème de l'authentification et de l'intégrité de la connexion à des couches inférieures, IP ou TCP. La complexité d'IPsec en ayant fait reculer beaucoup, la solution de loin la plus fréquente dans le monde des opérateurs BGP (cf. RFC 4953) était la signature TCP du RFC 2385. Elle fonctionne en calculant un condensat cryptographique du paquet TCP et d'un secret partagé entre les deux machines (MD5 password dans le vocabulaire BGP). Grâce à l'inclusion de ce secret, un tiers, même s'il a accès au réseau sous-jacent, ne peut pas injecter de paquets TCP prétendant venir du pair.

Cette technique fonctionne mais a de nombreuses limites, comme le fait d'être lié à une fonction de hachage particulière, MD5, que des années de cryptanalyse ont laissé en piteux état. Notre RFC 5925 la remplace donc par une meilleure solution, l'option TCP d'authentification.

Cette option offre en outre une meilleure protection contre le rejeu, et d'une manière générale une meilleure spécification. La section 1 du RFC rappelle le long historique de cette option. La section 3 résume les raisons de son introduction : la principale est le perfectionnement régulier des attaques contre MD5, alors que le RFC 2385 ne permet pas d'utiliser d'autres algorithmes. En prime, il ne permet pas de changer les clés facilement (aucune fonction de gestion de clés, même très sommaire).

La section 3 présente aussi les principes du nouvel algorithme : fonctionnement identique à celui de son prédécesseur (calcul d'un condensat cryptographique sur le paquet, avec concaténation d'un secret), pas de solution complète de gestion de clés (l'espace pour les options dans l'en-tête TCP est bien trop faible pour cela), mais il fonctionne avec plusieurs algorithmes. D'une manière générale, il suit les recommandations du cahier des charges (jamais publié en RFC) draft-bellovin-tcpsec (voir aussi la section 12 pour un bilan détaillé de cette nouvelle option par rapport à son cahier des charges).

Quelles sont les applications possibles de cette option d'authentification (section 3.1) ? Essentiellement les sessions TCP de longue durée comme avec BGP (où les sessions de plusieurs semaines ne sont pas rares). Si tous les exemples actuels d'usage concernent des protocoles de routage, l'option ne leur est pas spécifique (même si le RFC ne le cite pas, on peut penser aussi aux longs flux de certaines applications de communication audio ou vidéo, dont la session de contrôle peut utiliser TCP). Comme IPsec est la solution officielle de l'IETF à tous les problèmes de sécurité, la même section rappelle que cette option ne remplace pas IPsec, même si personne n'en tiendra compte. La section 3.1 note aussi que l'option d'authentification TCP de notre RFC ne protège que la session, pas les données qui y transitent, qui ont pu être relayées par plusieurs acteurs (dans le cas de BGP, par plusieurs routeurs). TCP-AO (TCP Authentication Option) ne remplace donc pas les différents projets de BGP « sécurisé ». Bref, TCP-AO enrichit la palette des outils de sécurisation des protocoles mais ne prétend absolument pas être la solution à tous les problèmes.

La section 3.2 fournit un résumé de la nouvelle option TCP-AO. Elle utilise le mécanisme d'options décrit dans la section 3.1 du RFC 793, avec un nouveau numéro, 29, réservé à l'IANA (cf. section 14 du RFC), différent du numéro 19 du RFC 2385.

Contrairement à IPsec, TCP-AO n'a pas de Security Index (un identificateur unique pour une association de sécurité) explicite mais utilise pour cela le 4-tuple {adresse IP source, port source, adresse IP de destination, port destination}. Il ne permet pas le chiffrement et donc n'assure pas la confidentialité des données, seulement leur authentification et leur intégrité. De plus, il est spécifique à TCP et ne protège donc pas les paquets ICMP (cf. section 9.8).

La section 4 spécifie rigoureusement la nouvelle option numérotée 29. Son format figure en section 4.2 (l'ancien est rappelé en 4.1). La principale nouveauté est le champ KeyID, un octet qui indique la structure de données qui a été utilisée pour générer les clés de session. Cette structure, le MKT (Master Key Tuple) est décrite en détail en section 5.1. Il est important de noter que l'algorithme de hachage choisi n'apparait pas dans l'option TCP-AO (contrairement à des protocoles comme, par exemple, DNSSEC) mais qu'on l'obtient indirectement.

Et la gestion des clés ? Comment se fait-elle avec TCP-AO ? La section 5 explique les deux jeux de clés de TCP-AO : les clés maîtresses (MKT, pour Master Key Tuple) et les clés de session (traffic keys). Les MKT contiennent les paramètres de cryptographie, et elles servent à fabriquer des clés de session. Le MAC dans les paquets TCP est calculé à partir des clés de session.

Les MKT sont présentées en détail en section 5.1. Une MKT comprend :

  • L'identificateur du MKT. C'est une paire, l'identificateur d'émission, qui se retrouvera dans le champ KeyID du paquet émis, et l'identificateur de réception, qui sert pour le paquet reçu.
  • Un identifiant de connexion TCP, {adresse IP source, port source, adresse IP de destination, port destination}. Certains des éléments de ce tuple peuvent être spécifiées par un intervalle (par exemple, « ports de 8080 à 8099 ») ou même par un joker (*).
  • La clé elle-même.
  • L'algorithme de hachage utilisé (voir section 7.1), par exemple SHA-1.
  • Le choix de traitement des autres options TCP (les met-on dans le MAC ou pas ?).

Le MKT doit rester stable pendant toute une connexion TCP.

À partir du MKT va être calculée la clé de session (section 5.2), en incluant des paramètres supplémentaires comme l'ISN (Initial Sequence Number, voir la section 3.3 du RFC 793), en utilisant une fonction cryptographique nommé KDF (Key Derivation Function).

L'un des plus nets avantages de TCP-AO sur l'ancienne méthode du RFC 2385 est la possibilité de changer d'algorithme de hachage. La section 7 décrit les mécanismes généraux, les algorithmes actuellement utilisables étant dans un autre document, le RFC 5926 (en effet, comme l'ont montré les attaques contre MD5 et SHA-1, les algorithmes de cryptographie doivent être changés plus souvent que les protocoles, ce qui justifie un document séparé, qui rendra plus simple ce changement). Un autre registre IANA existe, pour ces algorithmes. La section 7.1 rappelle le fonctionnement d'un MAC : en échange d'une suite de bits et d'une clé, la fonction de hachage produit un résumé. Si la fonction de hachage est cryptographiquement bien choisi, on ne peut pas (autrement que par force brute) fabriquer une suite de bits qui donne le même résumé. L'ajout de la clé sert à assurer en outre que la suite de bits vient bien de l'émetteur attendu, seul, avec le récepteur, à connaître la clé.

La même section décrit précisement les parties du paquet qui doivent être utilisées comme point d'entrée pour la fonction de calcul du MAC. On y trouve le « pseudo-en-tête » IP comme dans la section 3.1 du RFC 793 mais aussi l'en-tête TCP (avec ou sans les options, comme indiqué dans la MKT) et les données.

Suivant le même modèle, la section 7.2 décrit le fonctionnement de la KDF, qui permet de calculer la clé de session à partir de la MKT. Un des paramètres d'entrée est l'état de la connexion TCP (incluant par exemple les numéros de séquence TCP initiaux), faisant ainsi des clés de session uniques par connexion TCP.

Rappelons que TCP-AO ne fournit pas une solution complète de gestion de clés. Il ne permet pas d'en changer de manière synchronisée en cours de session (contrairement à TLS), il ne permet pas de les négocier au début de la session... Tout doit se faire out-of-band. La section 7.3, consacrée aux clés, recommande juste de suivre les bonnes pratiques habituelles, comme déjà recommandé par le RFC 3562. Les utilisateurs doivent donc veiller par eux-mêmes à ce que les clés aient une longueur suffisante, doivent éviter de partager les MKT entre connexions indépendantes (par exemple avec des pairs BGP différents), etc.

TCP-AO fournit toutefois quelques mécanismes pour jouer avec les clés, comme l'indication de l'identificateur de la MKT, qui permet de coordonner le passage d'une MKT à une autre (section 8.1). Le choix des MKT et l'attribution des identificateurs se fait en dehors du protocole mais le démarrage de l'utilisation effective peut être synchronisé par le champ KeyID de TCP-AO.

D'autres mécanismes de sécurité sont décrits en section 8, comme les solutions anti-rejeu de la section 8.2. Comme les numéros de séquence TCP ne sont stockés que sur 32 bits, et qu'ils peuvent donc légitimement être réutilisés pendant une connexion TCP de longue durée, TCP-AO ajoute une extension à ces numéros, la SNE (Sequence Number Extension) qui, combinée avec le numéro de séquence, donne effectivement un numéro unique à chaque octet transmis. (Ou quasi-unique puisqu'il ne sera réutilisé qu'au bout de 100 exa-octets transmis. Et rappelez-vous que la MAC inclus les données donc une collision accidentelle ne se produira que si le numéro de séquence et les données sont identiques. En pratique, on peut dormir tranquille.)

La meilleure cryptographie du monde ne sert que s'il y a une liaison solide avec le canal qu'elle protège. La section 9 discute donc des interactions entre TCP et son option d'authentification TCP-AO. D'abord, l'interface de programmation (section 9.1). Aux commandes classiques de TCP (OPEN, SEND, etc, ou, pour utiliser les termes de l'API socket, connect(), write(), etc) viennent s'ajouter des commandes pour configurer les MKT, et pour choisir la MKT active. J'avoue ne pas savoir quelle forme elles prendront exactement sur Unix.

Ensuite, TCP lui-même doit être modifié pour, si une MKT est active, signer les données et inclure cette signature dans le champ Options du segment. Il faut aussi évidemment la vérifier à la réception (sections 9.4 et 9.5). Cet ajout dans un champ Options dont la taille est très limitée (40 octets en tout) ne va pas sans mal. La section 9.6 discute de la taille de l'en-tête et explique que, si on utilise TCP-AO, on ne peut pas espérer utiliser en même temps toutes les autres options TCP normalisées.

Aucune solution de sécurité n'est parfaite et toutes apportent leurs propres problèmes. La réduction de la place libre pour les options est un bon exemple. Un autre est le cas d'une machine qui redémarre alors qu'une connexion TCP était ouverte. Sans TCP-AO, elle enverra des paquets RST (ReSeT) lors de la réception des paquets TCP de son pair, puisque ces paquets ne correspondront à aucune connexion connue, le souvenir s'étant perdu lors du redémarrage. Cela permettra d'informer rapidement le pair que la connexion TCP doit être considérée comme terminée. Avec TCP-AO, ce n'est plus possible : la machine ayant tout oublié, y compris les clés de session, elle ne peut plus construire des segments TCP authentifiés. Ses RST seront donc ignorés par le pair, qui devra donc attendre l'expiration d'un délai de garde pour comprendre que la connexion TCP est finie (section 9.7 du RFC). C'est dommage mais c'est fait exprès : empêcher les RST « pirates » était après tout une des principales motivations pour l'authentification TCP. Notre RFC recommande donc d'utiliser les keepalives du RFC 1122 ou bien ceux fournis par les applications utilisés (keepalives BGP du RFC 4271 ou bien les options ClientAlive* ou ServerAlive* de OpenSSH). Ces solutions ne sont pas parfaites (pour BGP, il est recommandé d'ajouter le démarrage en douceur du RFC 4724.) Une autre option est d'enregistrer les clés de session sur disque.

Comme vu plus haut, TCP-AO ne protège que TCP, pas les éventuels paquets ICMP qui se glisseraient dans la communication. La recommandation de notre RFC (section 9.8) est donc d'accepter avec prudence et conservatisme les paquets ICMP. Par exemple, les paquets ICMP ayant le type 3 (Destination unreachable et les codes 2 à 4 (protocol unreachable, port unreachable, ...) devraient être ignorés, car ils peuvent casser une connexion TCP-AO, sans avoir eux-même besoin de s'authentifier. La même section demande que ce comportement soit configurable. Cette recommandation est analogue à celle qui s'applique à IPsec (section 6.1.1 du RFC 4301).

Normalement, la spécification du protocole devrait s'arrêter là. Mais, dans le monde réel, il faut aussi tenir compte des engins intermédiaires (middleboxes, RFC 3234) qui examinent les paquets et se permettent de les rejeter ou de les modifier s'ils ne correspondent pas à leurs préjugés. La section 11 couvre les interactions avec ces engins (certains routeurs, les pare-feux, etc). Si la middlebox ne modifie pas les adresses IP, TCP-AO devrait passer sans problème. Si elle change certaines options TCP, il faut configurer TCP-AO pour ignorer les options dans le calcul de la MAC, ce qui affaiblit la sécurité (puisqu'un attaquant pourrait en faire autant, par exemple en supprimant le window scaling ce qui empêcherait le fonctionnement normal de TCP).

Mais si la middlebox change les adresses IP, ce qui est le cas des routeurs NAT (section 11.2), TCP-AO ne peut plus fonctionner du tout. Les seules solutions sont d'encapsuler le flux TCP ou de compter sur l'extension NAT du RFC 6978.

Et les implémentations ? À l'heure actuelle, rien dans Linux (il y a un projet), FreeBSD ou NetBSD. Et je ne connaissais pas non plus de mise en œuvre pour les routeurs Cisco ou Juniper, sans doute en partie en raison des innombrables brevets qui infestent le secteur informatique. Fin 2011, lorsque la question avait été étudiée à l'IETF pour un autre protocole, la conclusion avait été qu'AO restait toujours uniquement sur le papier, hélas. Depuis, il semble (2017) que Juniper ait une mise en œuvre d'AO. Vous trouverez davantage d'informations concrètes sur ce dépôt GitHub.


Téléchargez le RFC 5925


L'article seul

RFC 5910: Domain Name System (DNS) Security Extensions Mapping for the Extensible Provisioning Protocol (EPP)

Date de publication du RFC : Mai 2010
Auteur(s) du RFC : J. Gould (Verisign), S. Hollenbeck (Verisign)
Chemin des normes
Première rédaction de cet article le 12 mai 2010


Le protocole EPP d'avitaillement d'un registre (par exemple un registre de noms de domaine), normalisé dans le RFC 5730, manipule des objets qui sont des instances d'une classe (nommée mapping). Par exemple, il existe une classe (un mapping) pour les noms de domaine, décrite dans le RFC 5731. Notre RFC 5910 décrit, lui, une extension EPP à ce mapping permettant de spécifier les données nécessaires à DNSSEC, notamment la clé publique d'une zone signée. Il remplace le RFC 4310 et les changements sont assez sérieux.

DNSSEC, normalisé dans le RFC 4033, utilise la même délégation que le DNS. La zone parente d'une zone signée délègue en indiquant la clé publique de sa zone fille. Plus exactement, la zone parente publie un condensat cryptographique de la clé publique de la zone fille, l'enregistrement DS (pour Delegation Signer), normalisé dans la section 5 du RFC 4034 (voir aussi le rappel en section 3.1 de notre RFC 5910).

Lorsqu'un bureau d'enregistrement crée un nom de domaine signé, ou bien informe le registre qu'un domaine est désormais signé, comment indique t-il ce DS ? Il y a plusieurs façons, et notre RFC propose d'utiliser EPP.

L'extension nécessaire est résumée en section 3. Elle fonctionne en ajoutant des éléments à la classe Domaine du RFC 5731. La clé peut être transmise directement, ou bien on peut envoyer le condensat cryptographique de la clé (le RFC 6781 explique pourquoi le condensat, le futur DS, devrait être obligatoire alors que la clé serait facultative, mais notre RFC ne le suis pas complètement, contrairement à son prédécesseur). Les deux méthodes, selon qu'on transmet le condensat ou la clé, sont détaillées dans la section 4. Voici un exemple d'une clé transmise sous forme d'un condensat :


   <secDNS:dsData>
     <secDNS:keyTag>12345</secDNS:keyTag>
     <secDNS:alg>3</secDNS:alg>
     <secDNS:digestType>1</secDNS:digestType>
     <secDNS:digest>49FD46E6C4B45C55D4AC</secDNS:digest>
   </secDNS:dsData>

Le RFC prévoit également que le registre de la zone parente peut également récupérer la clé dans le DNS (enregistrement DNSKEY) pour tester si le condensat reçu est correct (et il est donc recommandé que ladite DNSKEY soit publiée avant de prévenir le parent par EPP). La clé transmise au registre doit être une clé de confiance, c'est-à-dire avoir le bit SEP à 1 (cf. RFC 3757). En terminologie moderne, cette clé doit être une KSK (Key Signing Key).

Les commandes EPP pour gérer cette information font l'objet de la section 5. Ainsi, les réponses à <info> doivent désormais contenir un élément <secDNS:infData>, qui contient lui-même des éléments comme <secDNS:dsData> qui a son tour contient les champs qu'on trouve dans un enregistrement DS comme <secDNS:keyTag> (un pseudo-identificateur de la clé), <secDNS:alg> (l'algorithme utilisé), etc. L'espace de noms urn:ietf:params:xml:ns:secDNS-1.1 (ici avec le préfixe secDNS) est enregistré dans le registre IANA (voir section 8). (Le nom utilisé dans le RFC 4310 était secDNS-1.0.) Voici un exemple de réponse à <info> sur le domaine example.com :


<resData>
...
<domain:name>example.com</domain:name>
...
<extension>
  <secDNS:infData
   xmlns:secDNS="urn:ietf:params:xml:ns:secDNS-1.1">
    <secDNS:dsData>
      <secDNS:keyTag>12345</secDNS:keyTag>
      <secDNS:alg>3</secDNS:alg>
      <secDNS:digestType>1</secDNS:digestType>
      <secDNS:digest>49FD46E6C4B45C55D4AC</secDNS:digest>
    </secDNS:dsData>
  </secDNS:infData>
</extension>

Le condensat est de type SHA1 (<digestType>1</digestType>), la clé elle-même étant DSA/SHA1 (<alg>3</alg>).

L'extension DNSSEC permet évidemment de créer un domaine signé, avec <create> (section 3.2.1) :


<domain:create>
  <domain:name>example.com</domain:name>
  ...
  <extension>
  <secDNS:create xmlns:secDNS="urn:ietf:params:xml:ns:secDNS-1.1">
  <secDNS:dsData>
    <secDNS:keyTag>12345</secDNS:keyTag>
    <secDNS:alg>3</secDNS:alg>
    <secDNS:digestType>1</secDNS:digestType>
    <secDNS:digest>49FD46E6C4B45C55D4AC</secDNS:digest>
    <!-- <secDNS:keyData>, la clé elle-même, est *facultatif* -->
  </secDNS:dsData>
</secDNS:create>
 ...

Une fois le domaine ainsi créé, le registre publiera typiquement un enregistrement DS comme :

example.com.  IN DS 12345 3 1 49FD46E6C4B45C55D4AC

Bien sûr, on peut aussi ajouter DNSSEC à un domaine existant, ou bien changer une clé existante. Cela se fait avec <update> :


    <domain:update>
        <domain:name>example.com</domain:name>
    ...
    <extension>
      <secDNS:update
       xmlns:secDNS="urn:ietf:params:xml:ns:secDNS-1.1">
        <secDNS:add>
          <secDNS:dsData>
            <secDNS:keyTag>12346</secDNS:keyTag>
            <secDNS:alg>3</secDNS:alg>
            <secDNS:digestType>1</secDNS:digestType>
            <secDNS:digest>38EC35D5B3A34B44C39B</secDNS:digest>
            <!-- <secDNS:keyData>, la clé elle-même, est *facultatif* -->
          </secDNS:dsData>
        </secDNS:add>
      </secDNS:update>
     ...

Et, en utilisant <secDNS:rem> au lieu de <secDNS:add>, on peut retirer une délégation sécurisée (« dé-signer » le domaine).

Comme la grande majorité des extensions et mappings d'EPP, celle-ci est spécifiée en utilisant la syntaxe formelle des W3C schemas, ici en section 4.

Le premier RFC sur cette extension EPP était le RFC 4310. Les sections 2 et 4 sont entièrement nouvelles. La première décrit les mécanismes de migration pour ceux qui avaient déjà déployé le précedent RFC. La section 4 décrit la nouvelle interface pour les clés. Le nouveau RFC était nécessaire en raison d'une bogue dans le précédent : lors de la suppression d'une délégation signée, le RFC 4310 disait (dans sa section 3.2.5) que la délégation pouvait être indiquée par le key tag (section 5.1.1 du RFC 4034) or celui-ci, un simple condensat cryptographique de la clé, n'est pas forcément unique, vue sa faible taille. La section 5.2.5 contient le nouveau texte. Parmi les autres changements, l'introduction du concept de data interface (section 4), qui unifie la façon de passer les clés (ou leurs condensats) du client EPP au serveur. Il y a enfin quelques changements moins cruciaux, décrits dans l'annexe A.

À noter que la mise en œuvre EPP du registre brésilien inclus désormais notre RFC 5910 : http://registro.br/epp/download-EN.html.


Téléchargez le RFC 5910


L'article seul

RFC 5905: Network Time Protocol Version 4 Protocol And Algorithms Specification

Date de publication du RFC : Juin 2010
Auteur(s) du RFC : J. Burbank, W. Kasch (JHU/APL), J. Martin (ISC), D. Mills (U. Delaware)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF ntp
Première rédaction de cet article le 22 juin 2010


Dans tout système technique complexe, comme l'Internet, on a besoin d'horloges correctes. À tout moment, on lit l'heure et on en tient compte. Par exemple, l'ingénieur système qui lit les journaux d'un serveur a besoin d'être sûr de l'heure qu'ils indiquent. De même, le chercheur qui mesure le temps de propogation d'un paquet IP entre deux machines en soustrayant le temps de départ de celui d'arrivée (cf. RFC 7679) doit être sûr des horloges des deux machines, sinon la mesure sera fausse. Pour synchroniser des horloges, on pourrait munir chaque ordinateur connecté à Internet d'un récepteur GPS ou équivalent (le système Galileo, absent du RFC 1305 fait son entrée dans notre RFC 5905). Mais de tels récepteurs sont relativement chers (surtout pour les engins les moins puissants comme les PC bas de gamme ou les téléphones portables) et ne marchent pas dans toutes les circonstances (le GPS ne fonctionne bien qu'en plein air). Le mécanisme privilégié sur l'Internet est donc que seules certaines machines sont connectées à une horloge physique correcte et que les autres d'ajustent sur celles-ci, par le biais du protocole NTP, objet de ce RFC.

A priori, synchroniser une machine C sur une autre, nommée S, est simple : C demande l'heure à S et S lui donne. C'est ainsi que fonctionnait le protocole Time du RFC 868. Mais ce mécanisme a un gros défaut : il ne tient pas compte du temps de propagation dans le réseau. Lorsque C reçoit la réponse, elle n'est déjà plus correcte... La résolution d'horloge qu'on peut obtenir est donc limitée par ce temps de propagation. En outre, les algorithmes tels que celui du RFC 868 ne permettent pas de tirer profit de multiples serveurs de temps puisqu'ils ne fournissent aucun moyen de décider quel est le « meilleur » serveur.

Pour expliquer la synchronisation d'horloge, tout un vocabulaire spécifique est nécessaire. Il n'y a pas de glossaire dans le RFC mais des mots comme delay et offset sont définis en section 4 : pour résumer, une horloge peut avoir un écart (offset) avec le « vrai » temps, UTC (ou bien avec une autre horloge, si on s'intéresse juste au fait qu'elles soient synchronisées, ce qui n'est pas le cas de NTP). Si cet écart est inférieur à une certaine valeur, on dit que l'horloge est correcte (accurate). Et l'horloge peut avoir un décalage (skew), elle peut avancer plus ou moins vite qu'une autre (ce qui entrainera l'apparition ou l'aggravation d'un écart). Pire, la dérive peut être variable, auquel cas on mesure la dérivée seconde du décalage sous le nom de dérive (drift, mais NTP ignore ce facteur). Enfin, l'horloge a une certaine résolution (precision), la plus petite unité de temps qu'elle peut mesurer. Des problèmes de mesure de temps analogues sont présents dans bien d'autres RFC notamment le RFC 2330 mais aussi les RFC 4656 ou RFC 5481. Pour obtenir le temps d'un autre serveur, alors que le délai de propagation est non-nul, NTP utilise des estampilles temporelles, des valeurs de la mesure de l'horloge, mises dans le paquet. Après plusieurs paquets échangés, chaque serveur NTP connait le délai de propagation avec un autre serveur (ainsi que, au bout d'un temps un peu plus long, la gigue, la variation de ce délai, suite aux hoquets du réseau) et peut donc déduire ce délai des temps mesurés par son pair. Sur une machine Unix, voyons ce que cela donne avec la commande ntpq -c peers :

% ntpq -c peers                                   
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
+relay1.nic.fr   192.134.4.11     3 u  998 1024  377    0.297   -1.554   0.163
 gw.prod-ext.pri .INIT.          16 u    - 1024    0    0.000    0.000   0.000
+obelix.gegeweb. 145.238.203.10   3 u  695 1024  377    5.226    0.586   1.768
-ntp.univ-poitie 224.22.30.230    3 u  498 1024  377    6.885   -4.565   0.267
*ns1.azuria.net  193.67.79.202    2 u   56 1024  377    2.739   -1.411   0.305
-rps.samk.be     193.190.198.10   3 u  984 1024  377    5.293    5.930   0.317

Lorsque plusieurs serveurs NTP sont accessibles, NTP sélectionne le meilleur (en tenant compte de divers paramètres comme justement la gigue). Il n'y a pas de vote entre serveurs, NTP est une dictature où le meilleur serveur a toujours raison. NTP a également un mécanisme anti-byzantin (sections 5 et 11.2.1), qui permet d'écarter les serveurs clairement en tort (les falsetickers) et de ne retenir que ceux dont les données sont correctes (les truechimers).

La première version de NTP était dans le RFC 958. La version 2 était décrite dans le RFC 1119 et la version 3 dans le RFC 1305. Les différences (aucune n'est essentielle) entre les deux versions sont décrites dans la section 1. La version 4 a surtout introduit :

  • une modification de l'en-tête pour faciliter son utilisation avec IPv6,
  • de meilleurs algorithmes de correction (avec de meilleurs types de données), permettant à NTP d'atteindre une résolution de quelques dizaines de microsecondes, sur un réseau local,
  • un mécanisme de découverte des serveurs NTP du réseau,
  • un mécanisme d'extension,
  • un nouveau mécanisme d'authentification, autokey, normalisé dans le RFC 5906,
  • un nouveau format pour les paquets de réponse en cas d'erreur, le kiss-o'-death (section 7.4),
  • et quelques corrections de bogues.

Ces changements n'affectent pas l'interopérabilité et un client NTP v3 peut parler à un serveur v4 et réciproquement.

NTP n'était pas le premier protocole de synchronisation d'horloge, loin de là. Il a été précédé par daytime (RFC 867) ou time (RFC 868), ainsi que par des options d'ICMP comme celle du RFC 781. Il y a également eu des mises en œuvre non normalisées comme le démon timed sur Berkeley Unix. NTP a aussi été inspiré par le protocole DTS, partie du système DCE mais, contrairement à DTS, il n'impose pas que toutes les machines participantes dépendent du même administrateur. Enfin, il y a eu d'innombrables projets de recherche sur des thèmes bien plus ambitieux comme la détermination de la justesse ou de la fausseté d'une horloge, problèmes que NTP n'essaie pas de traiter.

Le problème de la synchronisation d'horloges est très complexe et plein de détails difficiles. Le RFC 5905 est donc un des plus gros RFC qui soit (plus de cent pages et, pourtant, les annexes passionnantes que comportait le RFC 1305 ont presque toutes été retirées). En outre, l'abondance des formules mathématiques, rares dans les RFC mais nécessaires ici à cause des calculs d'erreur, fait que notre RFC n'est pas très lisible en texte brut. Le lecteur a sans doute intérêt à lire plutôt l'article de David Mills (l'auteur du RFC), Network Time Protocol Version 4 Reference and Implementation Guide ou son livre, Computer Network Time Synchronization (la seconde édition est prévue pour septembre 2010). Autrement, la page Web dudit auteur, propose plein d'informations sur NTP. À noter que le prédécesseur de notre RFC, le RFC 1305 contenait davantage d'informations de nature historique et reste donc une lecture intéressante. Enfin, une lecture classique mais toujours recommandée est la note Hewlett-Packard « The Science of Timekeeping ».

Quel est le modèle de NTP ? Ce protocole considère que certaines machines ont l'information correcte (par exemple parce qu'elles l'ont obtenu d'une horloge sûre) et que le seul problème est de transmettre cette information aux autres machines. NTP ne s'essaie pas à déterminer si les serveurs ont raison ou tort, il leur fait confiance, il n'existe pas de système de vote, NTP n'est pas une démocratie. Certaines machines ont raison et les autres s'alignent.

Communiquant avec un serveur, un client NTP détermine l'écart (clock offset) avec ce serveur, le RTT (roundtrip delay) et la dispersion, qui est l'écart maximal avec l'autre horloge.

Pour cette communication, il existe plusieurs mécanismes (section 2), le plus courant étant un mécanisme client/serveur où le client NTP demande au serveur le temps. Celui-ci répond et l'information contenue dans le paquet permettra au client de déterminer les valeurs ci-dessus, notamment l'écart. En fait, NTP est plus compliqué que cela car il existe plusieurs niveaux de serveurs et chaque client utilise plusieurs serveurs, pour se prémunir contre une panne. La proximité d'un serveur avec une « vraie » horloge est mesurée par un nombre, la strate (section 3), qui vaut 1 lorsque le serveur est directement connecté à l'horloge et N+1 lorsque le serveur est coordonné avec un serveur de strate N.

Le serveur calcule ensuite (par une variante de l'algorithme de Bellman-Ford), le chemin le plus court (en utilisant comme métrique le nombre d'étapes et la strate), et c'est par celui-ci que sera transmise la valeur correcte de l'horloge (je le répète, NTP ne fait pas de pondération entre les serveurs possibles).

Les sections 6 et 7 décrivent le format des paquets. La plus importante information transportée par NTP est évidemment le temps. NTP utilise trois formats pour le temps (cf. figure 3), le plus courant étant un doublet de 64 bits. La première partie du doublet est un nombre sur 32 bits qui indique le nombre entier de secondes depuis le 1er janvier 1900. La seconde est la partie fractionnaire de cette même valeur. Cela assure donc une précision d'environ 200 picosecondes. Comme tout le fonctionnement de NTP dépend de la précision de ces estampilles temporelles, le RFC recommande que leur écriture dans les paquets soit, autant que possible, fait dans les couches les plus basses, par exemple juste au-dessus du pilote de la carte réseau.

32 bits n'est pas énorme et la valeur maximale sera atteinte en 2036. Les programmes devront donc s'adapter et faire preuve d'intelligence en considérant qu'un nombre de secondes très faible signifie « un peu après 2036 » et pas « un peu après 1900 ». (Ou alors, il faudra passer au nouveau format sur 128 bits, apparu avec NTP v4, où on a 584 milliards d'années de marge.) Plus drôle, comme la valeur zéro est spéciale (elle signifie que le temps n'est pas connu), pendant 200 picosecondes, au moment de la transition, NTP ne marchera plus.

Pour son bon fonctionnement, NTP dépend de certaines variables, décrites en section 7.3. Il y a par exemple l'adresse IP du pair mais aussi :

  • leap indicator qui indique si une seconde intercalaire est imminente,
  • la strate (1 si le serveur a une horloge, de 2 à 255 autrement),
  • la précision de son horloge,
  • un identifiant sur quatre octets, typiquement une chaîne de caractères pour un serveur de strate un, par exemple GPS pour le GPS, ATOM pour une horloge atomique ou LORC pour le bon vieux LORAN,
  • temps d'aller-retour lors de la communication avec le pair,
  • etc.

L'identifiant du type d'horloge est indiqué dans la sortie de ntpq -c peers si le pair est de strate 1, ou bien par la commande ntptrace sous le nom de refid. Par exemple, ici, clock.xmission.com est synchronisé au GPS :

% ntptrace 
localhost: stratum 3, offset 0.000175, synch distance 0.072555
tock.slicehost.net: stratum 2, offset 0.000658, synch distance 0.057252
clock.xmission.com: stratum 1, offset 0.000010, synch distance 0.000274, refid 'GPS'

NTP peut fonctionner selon plusieurs modes, en pair-à-pair (« symmetric »), en client ou en serveur mais aussi en mode diffusion (un serveur qui envoie ses données que quelqu'un écoute ou pas). Ainsi, avec le programme ntpd (voir http://support.ntp.org/) d'Unix, si on configure dans /etc/ntp.conf :

broadcast 224.0.0.1

(où l'adresse est celle de diffusion) ntpd va diffuser ses informations à tout le réseau local. Si on met :

broadcastclient

il écoutera passivement les annonces des serveurs qui diffusent. Si enfin, on écrit :

server ntp1.example.net
server ntp2.example.net

il cherchera activement à se connecter aux serveurs ntp1.example.net et ntp2.example.net pour obtenir d'eux des informations sur l'heure qu'il est. Les deux serveurs établiront alors une association entre eux.

NTP peut se défendre contre un pair qui enverrait des informations aberrantes mais il ne contient pas de système de vote qui pourrait protéger contre des pairs malveillants. Même avec un tel système, si tous les pairs participaient d'un commun accord à l'attaque, NTP serait alors trompé. Il faut donc s'assurer que les pairs sont bien ceux qu'on croit. Il existe un mécanisme d'authentification fondée sur une MAC, mais NTPv4 permet aussi l'ajout de mécanismes supplémentaires comme celui du RFC 5906. En pratique, cette sécurité est peu pratiquée ; bien que fausser l'horloge d'une machine puisse avoir de sérieuses conséquences pour la sécurité (journaux avec une heure fausse, par exemple), les attaques sur NTP semblent rares. La principale protection reste le filtrage au niveau du pare-feu.

La section 10 décrit les algorithmes de correction qui permettent de réparer dans une certaine mesure les erreurs des horloges, ou bien celles introduites par la propagation dans le réseau. NTP peut aussi bien filtrer les mesures d'une horloge donnée (en ne gardant que les meilleures) que garder les bonnes horloges parmi l'ensemble des pairs accessibles. C'est une des parties les plus mathématiques du RFC.

Les paquets NTP sont transportés sur UDP, port 123. Chaque message indique la version de NTP, le mode de l'émetteur (par exemple client, serveur ou autre), les différentes estampilles temporelles (heure de réception du paquet précédent Receive Timestamp, heure d'émission de celui-ci Transmit Timestamp, etc), précision de l'horloge locale, etc. Les estampilles temporelles sont indiquées dans le format à 64 bits décrit plus haut. Du fait que chaque paquet contienne toutes les estampilles nécessaires, les paquets sont auto-suffisants. Il n'est pas nécessaire qu'ils arrivent dans l'ordre, ni qu'ils soient tous délivrés (d'où le choix d'UDP comme protocole de transport).

Pour observer NTP en action, on peut utiliser tcpdump :

# tcpdump -vvv udp and port 123
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes
17:11:46.950459 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto UDP (17), length 76) munzer.bortzmeyer.org.ntp > tock.slicehost.net.ntp: [udp sum ok] NTPv4, length 48
        Client, Leap indicator:  (0), Stratum 3, poll 10s, precision -20
        Root Delay: 0.037567, Root dispersion: 0.082321, Reference-ID: tock.slicehost.net
          Reference Timestamp:  3448017458.952901899 (2009/04/06 16:37:38)
          Originator Timestamp: 3448018483.951783001 (2009/04/06 16:54:43)
          Receive Timestamp:    3448018483.951863646 (2009/04/06 16:54:43)
          Transmit Timestamp:   3448019506.950407564 (2009/04/06 17:11:46)
            Originator - Receive Timestamp:  +0.000080633
            Originator - Transmit Timestamp: +1022.998624563
17:11:46.950946 IP (tos 0x10, ttl 63, id 0, offset 0, flags [DF], proto UDP (17), length 76) tock.slicehost.net.ntp > munzer.bortzmeyer.org.ntp: [udp sum ok] NTPv4, length 48
        Server, Leap indicator:  (0), Stratum 2, poll 10s, precision -20
        Root Delay: 0.036941, Root dispersion: 0.012893, Reference-ID: clock.xmission.com
          Reference Timestamp:  3448019415.234667003 (2009/04/06 17:10:15)
          Originator Timestamp: 3448019506.950407564 (2009/04/06 17:11:46)
          Receive Timestamp:    3448019506.951188027 (2009/04/06 17:11:46)
          Transmit Timestamp:   3448019506.951214015 (2009/04/06 17:11:46)
            Originator - Receive Timestamp:  +0.000780425
            Originator - Transmit Timestamp: +0.000806425

On voit ici que munzer.bortzmeyer.org, machine chez Slicehost a contacté le serveur de temps, tock.slicehost.net (le second serveur NTP de cet hébergeur se nomme tick.slicehost.net) en indiquant que le paquet était émis (Transmit Timestamp à 3448019506.950407564 (soit le six avril 2009 vers 17:11:46). tock.slicehost.net répond, renvoie cette estampille dans le champ Originator Timestamp, indique qu'il l'a reçue à 3448019506.951188027, soit 780 microsecondes plus tard et qu'il a répondu à 3448019506.951214015, 26 microsecondes après la réception. munzer.bortzmeyer.org, en regardant à quelle heure il a reçu le paquet, peut en déduire le délai d'acheminement et le décalage des deux horloges. Si le serveur venait de démarrer, toutes les estampilles sont à zéro, sauf celle de transmission :

22:39:26.203121 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto UDP (17), length 76) munzer.bortzmeyer.org.ntp > tick.slicehost.net.ntp: [udp sum ok] NTPv4, length 48
        Client, Leap indicator: clock unsynchronized (192), Stratum 0, poll 6s, precision -20
        Root Delay: 0.000000, Root dispersion: 0.000000, Reference-ID: (unspec)
          Reference Timestamp:  0.000000000
          Originator Timestamp: 0.000000000
          Receive Timestamp:    0.000000000
          Transmit Timestamp:   3448384766.203066617 (2009/04/10 22:39:26)
            Originator - Receive Timestamp:  0.000000000
            Originator - Transmit Timestamp: 3448384766.203066617 (2009/04/10 22:39:26)

L'annexe A plaira aux programmeurs car elle est la seule partie qui contient du code source, en C, mettant en œuvre certains des algorithmes décrits dans le RFC.

La mise en œuvre la plus courante de NTP, sur Unix, est celle du serveur ntpd, en http://www.ntp.org/, qui ne semble pas encore avoir été mise à jour pour notre RFC 5905. Il se configure dans le fichier /etc/ntp.conf et la documentation complète figure en ligne sur http://doc.ntp.org/. La commande ntpdate permet une mise à jour sommaire, sans faire tourner de serveur :

# ntpdate pool.ntp.org
 23 Feb 01:34:10 ntpdate[3335]: step time server 192.83.249.31 offset 2.155783 sec 

Mais pour une meilleure précision, il faut un serveur tournant en permanence (autrement, il existe une version simplifiée de NTP, SNTP, décrite originellement dans le RFC 4330 et désormais dans la section 14 de notre RFC, ce protocole simplifié se distingue également par le fait que le client n'a pas besoin de gérer plusieurs serveurs). Voici par exemple une station de travail ordinaire, synchronisée au serveur NTP de son réseau, ntp.example.org :

server ntp.example.org
server 127.127.1.0
fudge 127.127.1.0 stratum 13

Les deux dernières lignes sont là pour dire à ntpd que l'horloge locale est raisonnablement stable et qu'on peut la considérer comme de strate 13. Comme on ne veut pas forcément que tout l'Internet aille ensuite noyer cette machine sous le trafic NTP et, pire, changer son horloge, on restreint souvent les possibilités de NTP à certaines actions. Par exemple :

# Exchange time with everybody, but don't allow configuration.
restrict default kod notrap nomodify nopeer noquery
# Local users may interrogate the ntp server more closely.
restrict 127.0.0.1 nomodify

Une fois cette machine synchronisée, les commandes ntpq et ntptrace permettront de regarder l'état de NTP :

% ntptrace 
localhost: stratum 3, offset 0.000116, synch distance 0.015000
fuzzer.example.org: stratum 2, offset 0.000149, synch distance 0.009868
192.0.2.77: timed out, nothing received
***Request timed out

Ici, le serveur de strate 1, 192.0.2.77 n'accepte pas des interrogation directes de la part des stations, il ne répond donc pas à ntptrace. On peut avoir plus de détails sur les pairs avec ntpq, par exemple :

ntpq> peers
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
*fuzzer.ex       192.0.2.176      2 u   50   64  377    0.304    0.107   0.064
 LOCAL(0)        .LOCL.          13 l    1   64  377    0.000    0.000   0.001

ntpq> clocklist
assID=0 status=0000 clk_okay, last_clk_okay,
device="Undisciplined local clock", timecode=, poll=33834, noreply=0,
badformat=0, baddata=0, fudgetime1=0.000, stratum=13, refid=76.79.67.76,
flags=0

qui permet de voir le délai de la communication avec le serveur de strate 2 (ce délai est logiquement de zéro avec l'horloge locale, de strate 13). On peut aussi voir qu'il y a eu association :

ntpq> associations

ind assID status  conf reach auth condition  last_event cnt
===========================================================
  1 16199  9614   yes   yes  none  sys.peer   reachable  1
  2 16200  9014   yes   yes  none    reject   reachable  1

ntpq> pstatus 16199
assID=16199 status=9614 reach, conf, sel_sys.peer, 1 event, event_reach,
srcadr=fuzzer.example.org, srcport=123, dstadr=192.0.2.1, dstport=123,
leap=00, stratum=2, precision=-20, rootdelay=1.999,
rootdispersion=7.858, refid=192.0.2.176, reach=377, unreach=0,
hmode=3, pmode=4, hpoll=6, ppoll=6, flash=00 ok, keyid=0, ttl=0,
offset=0.116, delay=0.305, dispersion=3.077, jitter=0.015,
reftime=cd848978.4d74dea3  Mon, Apr  6 2009 16:00:24.302,
org=cd848a03.2ce4faea  Mon, Apr  6 2009 16:02:43.175,
rec=cd848a03.2ce6b9ee  Mon, Apr  6 2009 16:02:43.175,
xmt=cd848a03.2cd129e9  Mon, Apr  6 2009 16:02:43.175,
filtdelay=     0.31    0.32    0.32    0.32    0.32    0.31    0.37    0.34,
filtoffset=    0.13    0.13    0.13    0.13    0.13    0.12    0.15    0.12,
filtdisp=      0.00    0.99    1.94    2.93    3.90    4.88    5.85    6.80

Ici, il n'y avait qu'une seule vraie association, de numéro 16199, avec le serveur NTP de strate 2.

Et sur un routeur Cisco ? Configurer NTP en client est simplement :

Router#config terminal
Enter configuration commands, one per line.  End with CNTL/Z.
Router(config)#ntp server 129.237.32.2
Router(config)#^Z

Le configurer en serveur pour d'autres machines, ici en strate 10 par défaut :

Router#config terminal
Enter configuration commands, one per line.  End with CNTL/Z.
Router(config)#ntp master 10
Router(config)#^Z

On peut alors vérifier l'état de NTP :

Router#show ntp status
Clock is synchronized, stratum 3, reference is 128.249.2.2
nominal freq is 250.0000 Hz, actual freq is 249.9961 Hz, precision is 2**16
reference time is BF454660.7CCA9683 (22:37:36.487 EDT Sat Sep 8 2001)
clock offset is 4.3323 msec, root delay is 136.28 msec
root dispersion is 37.69 msec, peer dispersion is 1.14 msec

Router#show ntp associations
 
      address         ref clock     st  when  poll reach  delay  offset    disp
  *~128.249.2.2      192.5.41.40     2    4    64   377    76.9    5.49     0.4
  -~130.218.100.5    198.72.72.10    3   33   128   377     7.1   13.13     0.6
  +~129.237.32.2     192.43.244.18   2   16    64   377    44.8    3.05     0.9
  +~128.118.25.3     128.118.25.12   2   48    64   377    39.7    5.50     1.4
 * master (synced), # master (unsynced), + selected, - candidate, ~ configured

Tout le monde n'a pas forcément un serveur NTP chez lui, ni un fournisseur qui lui en procure un de qualité. Il est donc pratique de faire appel à des serveurs publics. Pour cela, le projet pool.ntp.org enregistre dans le DNS l'adresse IP des volontaires qui participent au service ntp.pool.org (il ne semble pas que ces serveurs soient déjà passés en NTP v4). Il suffit au client de mettre dans sa configuration :

server pool.ntp.org
server pool.ntp.org
server pool.ntp.org
server pool.ntp.org

pour se synchroniser à quatre serveurs, pris au hasard parmi les volontaires. Notez bien que le fait de répéter la même ligne quatre fois n'est pas une erreur. Chacune de ces lignes va déclencher une requête DNS qui donnera à chaque fois une liste d'adresses IP dans un ordre différent :

% dig +short A  pool.ntp.org   
91.208.102.2
195.83.66.158
81.19.16.225
87.98.147.31
88.191.77.246

% dig +short A  pool.ntp.org
88.191.77.246
91.208.102.2
195.83.66.158
81.19.16.225
87.98.147.31

% dig +short A  pool.ntp.org
87.98.147.31
88.191.77.246
91.208.102.2
195.83.66.158
81.19.16.225

Pour être sûr d'avoir des adresses différentes, il suffit de préfixer les noms par un chiffre :

server 1.pool.ntp.org
server 2.pool.ntp.org
server 3.pool.ntp.org
server 4.pool.ntp.org

Vu avec ntpq, on pourra avoir, par exemple :

% ntpq 
ntpq> peers
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
 ks34176.kimsufi 193.52.184.106   2 u  25d 1024    0    1.116   -4.039   0.000
*ns1.azuria.net  193.67.79.202    2 u  116  256  377    1.412   -1.931   0.647
+mail1.vetienne. 129.240.64.3     3 u  208  256  377    1.657  -18.063   3.348
+ntp1.adviseo.ne 209.81.9.7       2 u  114  256  377    1.001   -3.440   1.622
ntpq> 

où des machines d'hébergeurs très différents sont utilisées, NTP choisissant le meilleur (atteignable, proche, faible gigue, etc). Bien sûr, pool.ntp.org n'offre aucune sécurité, puisque rien ne dit qu'un méchant ne s'est pas glissé dans le lot dans le but de perturber vos horloges. Mais c'est un service gratuit, fourni par la communauté et globalement de très bonne qualité. À noter que ceux qui réalisent un système d'exploitation peuvent demander un sous-domaine, pour y mettre par défaut leur machine. C'est ce que fait, par exemple, Debian et une machine Debian sera configurée par défaut avec quelque chose du genre :

server 0.debian.pool.ntp.org
server 1.debian.pool.ntp.org
server 2.debian.pool.ntp.org
server 3.debian.pool.ntp.org

NTP a nécessité la création de trois registres à l'IANA (section 16) dont :

Sinon, une bonne lecture sur NTP et ses algorithmes est le « How Does NTP Work? », de Kevin Sookocheff.


Téléchargez le RFC 5905


L'article seul

RFC 5902: IAB thoughts on IPv6 Network Address Translation

Date de publication du RFC : Juillet 2010
Auteur(s) du RFC : D. Taler (Microsoft), L. Zhang (UCLA), G. Lebovitz (Juniper)
Pour information
Première rédaction de cet article le 17 juillet 2010


Les mécanismes de traduction d'adresse (NAT) ont toujours suscité des polémiques, en raison de leur remise en cause des principes d'architecture de l'Internet. Avec IPv4, ces mécanismes sont nécessaires en raison de la pénurie d'adresses qui fait que, par exemple, un particulier n'a aucune chance d'obtenir plus qu'une adresse IPv4, même s'il a chez lui plusieurs équipements IP. Mais en IPv6 ? La pénurie disparait. Est-ce que le NAT doit donc disparaitre avec elle ? Dans ce RFC, l'IAB étudie la question et donne une réponse, certes hostile au NAT, mais très étayée et pointant du doigt quelques problèmes qui peuvent pousser certains à déployer du NAT IPv6 malgré tout.

La question initiale est pratique (section 1 du RFC) : l'IETF doit-elle normaliser des mécanismes de NAT pour IPv6 ? Elle ne l'avait pas fait pour IPv4, considérant, à juste titre, que c'était un bricolage ayant trop d'effets néfastes et, résultat, le NAT a quand même été largement déployé, de manière non standardisée. Le groupe de travail behave de l'IETF a été créé bien plus tard pour essayer de documenter ce bricolage et ses conséquences, et pour trouver des solutions partielles à certains de ses inconvénients.

Évidemment, pas mal de participants à l'IETF craignent que la même chose se produise avec IPv6. Selon un scénario possible, l'IETF, attachée aux principes de l'adresse IP unique, de la neutralité du réseau, et de la transparence de bout en bout (RFC 4924), refuserait fermement de normaliser des solutions de NAT IPv6 et celles-ci seraient déployées quand même, menant à une prolifération de routeurs NAT différents et gardant l'actuel cauchemar que vivent les applications, notamment pair-à-pair. Mais la situation est-elle la même qu'avec IPv4 ?

Les opposants à cette vision font remarquer que la motivation initiale du déploiement du NAT pour IPv4 était uniquement la pénurie d'adresses. (Je me souviens bien de mon émerveillement quand le premier routeur NAT utilisable, un PC Linux avec ce qui s'appelait à l'époque IP masquerading, est apparu vers 1995. Soudainement, le particulier pouvait avoir plusieurs machines IP chez lui.) Cette pénurie disparaissant avec IPv6, la motivation du NAT disparait aussi. Compte-tenu des défauts du NAT, où un équipement intermédiaire interfère avec la relation entre deux machines, il ne faudrait surtout pas déployer des NAT IPv6 et donc pas les normaliser.

Ce n'est pas et de loin la première fois que la question se pose. Ainsi, le RFC 4864 avait déjà discuté des avantages et inconvénients des NAT. Où en est-on aujourd'hui ?

Pour évaluer la possibilité que des systèmes de NAT soient déployés pour IPv6, même en l'absence de pénurie d'adresses, la section 2 du RFC étudie successivement les motivations possibles pour le NAT ou, en d'autres termes, les bénéfices perçus par certains utilisateurs.

Premier avantage perçu (section 2.1), dispenser de renumérotation. Avec un routeur NAT devant son réseau, celui-ci peut avoir des adresses IP stables, indépendantes des adresses vues de l'extérieur. Si celles-ci changent (par exemple parce qu'on a changé de fournisseur d'accès), il suffit de reconfigurer le routeur et tous les autres problèmes de renumérotation (RFC 5887) sont évités. Notre RFC 5902 note que cet argument saute si on dispose d'adresses PI mais que celles-ci posent d'autres problèmes, les mécanismes de routage actuels de l'Internet ne pouvant peut-être pas gérer un trop grand nombre de préfixes PI.

Autre motivation parfois citée pour déployer du NAT, le désir d'être multi-homé (section 2.2). Aujourd'hui, la seule solution qui isole le routage mondial du multi-homing est le NAT. Autrement, il faut utiliser des adresses PI qui sont routées globalement. Les techniques basées sur la séparation de l'identificateur et du localisateur ne sont pas encore prêtes. Donc, bien que la solution à base de NAT ne fournisse pas tous les services qu'on attend du multi-homing (par exemple, elle ne protège pas les sessions déjà établies d'une défaillance d'un des fournisseurs), elle reste tentante.

Pour un FAI, le NAT a un autre avantage : il permet d'homogénéiser la configuration des réseaux locaux des clients. Avec le NAT, tous les clients ont 192.168.0.0/24, tous les routeurs CPE ont l'adresse 192.168.0.1, etc. Cela peut simplifier le support utilisateur (section 2.3). En IPv6, un mécanisme équivalent serait d'utiliser les adresses locales au lien (section 2.5.6 du RFC 4291) mais il y a trop peu d'expérience pratique aujourd'hui pour juger de la validité de cette approche.

Lorsqu'on demande à un administrateur réseaux pourquoi il utilise du NAT alors qu'il dispose de suffisamment d'adresses, il répond souvent « la sécurité ». Cet argument est souvent vague et peu étayé. En creusant un peu, on peut trouver deux propriétés du NAT qui ont un rapport avec la sécurité. La première est le fait de dissimuler partiellement le réseau, sa structure et les machines qui s'y connectent (section 2.4). L'idée est que, sans faire reposer toute la sécurité du réseau sur cette dissimulation, on peut toutefois se dire qu'il n'y a aucune raison que le monde entier puisse analyser facilement le réseau, ce qui faciliterait la préparation d'une éventuelle attaque. Ainsi, le NAT permet de rendre plus difficile le recensement des machines (section 2.4.1). Cachées derrière le routeur NAT, les machines ne sont plus accessible à un comptage, par exemple. Dans ce domaine, la plupart des administrateurs réseau surestiment beaucoup les protections fournies par le NAT. Un article comme « A technique for counting NATted hosts » montre bien que le NAT n'empêche nullement le recensement des machines. Des mécanismes de NAT plus complexes pourraient permettre de limiter certaines des attaques que décrit Bellovin (pas celles par fingerprinting, par exemple) mais ils seront aussi plus difficiles à traverser pour des services comme SIP ou SCTP. La règle traditionnelle s'applique ici : les progrès de la sécurité se font presque toujours au détriment de la facilité d'usage. Notre RFC détaille les contre-mesures possibles mais il n'en existe aucune de miraculeuse. La machine derrière le NAT ne doit donc pas se sentir en complète sécurité.

À défaut de cacher les machines, peut-on cacher la topologie du réseau (section 2.4.2) ? Là encore, l'étude indique un résultat mitigé. On peut dans une certaine mesure rendre l'analyse du réseau interne plus difficile mais on ne peut pas la rendre impossible et ces améliorations de la dissimulation seront presque toujours au détriment des usages du réseau. Bref, comme le résume la section 2.4.3, le NAT fournit davantage une sécurité perçue qu'une sécurité réelle. Et les vrais gains de sécurité seront obtenus en empêchant les techniques de traversée de NAT comme STUN, ce qui diminuera l'utilité du réseau.

La deuxième propriété du NAT qui peut sembler augmenter la sécurité est l'impossibilité de faire une connexion depuis l'extérieur vers une machine NATtée (section 2.5). En fait, cette propriété n'a rien de spécifique au NAT : tout pare-feu à états en fait autant et il n'y a pas besoin du NAT pour avoir ce résultat.

Une fois examinées les bonnes (et moins bonnes) raisons de faire du NAT, même en IPv6, la section 3 de notre RFC prend de la hauteur et essaie de voir quelles sont les conséquences architecturales du NAT. Il n'y a pas de doute que le NAT a des avantages : si les gens le déploient, c'est bien qu'ils y trouvent des bénéfices. La vraie question est donc plutôt « Quel est le coût à payer, notamment pour les autres ? ». Le RFC ne mentionne pas cet exemple mais, aujourd'hui, le déploiement massif des NAT est payé essentiellement par les développeurs d'application (qui doivent consacrer beaucoup d'efforts et une grande partie de leur code réseau à contourner les NAT, à l'aide de solutions comme TURNRFC 5766) et par les utilisateurs (dont certaines applications marchent ou ne marchent pas selon le spécificités du système NAT rencontré). L'administrateur réseaux qui déploie le NAT pour se faciliter la vie transmet donc les coûts à d'autres. Les RFC 2993 et RFC 4924 discutent plus en détail ce point.

Donc, avant de décider de normaliser un service de NAT, il ne faut pas seulement considérer les avantages perçus par ceux qui les déploient (la section 2 couvrait ces avantages) mais aussi les conséquences globales. Le principe (qui est au cœur de l'architecture de l'Internet) est que deux machines qui veulent se parler (le pare-feu peut donc légitimement filtrer le trafic qu'on ne veut pas) doivent pouvoir le faire sans se soucier du NAT, c'est-à-dire sans avoir à déployer des solutions complexes comme ICERFC 8445. Le programmeur, au lieu de consacrer l'essentiel de son code à contourner les NAT, devrait pouvoir tenir pour acquise une connectivité de bout en bout. Des techniques comme la référence (j'indique l'adresse IP à laquelle la suite du trafic doit être envoyé) sont triviales avec l'architecture normale de l'Internet et cauchemardesques avec les NAT.

Bref, l'objectif est que le système NAT, s'il existe, n'aie un effet que purement local et pas, comme actuellement, des conséquences pour tous les utilisateurs. Est-ce possible ?

La section 4 regroupe les solutions qui permettent d'atteindre les avantages cités plus haut (notamment le multihoming et la non-nécessité de renuméroter) en trois classes :

  • Adresses PI systématiques : très simple et marchant très bien, cette approche a pour principal inconvénient de faire porter un gros effort sur le système de routage mondial, qui doit gérer les adresses de tout le monde, sans possibilité d'agrégation. Le sujet a fait l'objet de nombreux travaux comme, par exemple, « Extending the Life of Layer 3 Switches in a 256k+ Route World ».
  • Adresses uniques et stables en local, mais utilisation d'un tunnel pour communiquer avec le reste du monde. C'est l'approche de la plupart des techniques comme LISP et elle est rare aujourd'hui.
  • Adresses stables en local, avec traduction d'adresses avant d'atteindre l'Internet. C'est ce que fait le NAT et cette classe de solutions est la plus difficile à combiner avec la connectivité de bout en bout. C'est toutefois possible, si la traduction est réversible. (C'était le cas du NAT original, où toute adresse interne était mise en correspondance avec une et une seule adresse externe, mais c'est moins vrai avec les déploiements actuels, où les adresses IP globales sont partagées et où des numéros de port sont alloués dynamiquement pour désambiguer.)

Maintenant, place à la conclusion. La section 4.1 résume les pensées de l'IAB : le NAT est une mauvaise idée, car il est très difficilement compatible avec la transparence du réseau (RFC 4924), celle-ci étant la clé du succès de l'Internet. Mais certains problèmes (comme le Multihoming) ne sont pas encore traités par l'IETF. Il ne suffit donc pas de dire que le NAT est négatif, il faut encore travailler à fournir des solutions pour les problèmes qu'il semble traiter. Dans tous les cas, toute évaluation d'une nouvelle norme (que ce soit du NAT ou pas) devrait se faire en priorité sur le critère de la transparence du réseau aux applications.


Téléchargez le RFC 5902


L'article seul

RFC 5895: Mapping Characters in IDNA2008

Date de publication du RFC : Septembre 2010
Auteur(s) du RFC : P. Resnick (Qualcomm Incorporated), P. Hoffman (VPN Consortium)
Pour information
Première rédaction de cet article le 14 septembre 2010


Dans l'ancienne version de la norme IDN, en 2003, une étape obligatoire et uniforme de canonicalisation (ou normalisation) précédait le traitement des noms de domaine en Unicode. La nouvelle version d'IDN, sortie en 2010, a supprimé cette étape. Désormais, chaque application est libre de canonicaliser comme elle le souhaite les noms entrés par l'utilisateur. Il n'est toutefois pas interdit de donner des conseils aux programmeurs mais il n'a pas été possible, dans le groupe de travail idnabis, de trouver un consensus sur ces conseils. Il y aura donc un ou plusieurs RFC « pour information seulement » sur ce sujet. Celui-ci est le premier.

La section 1 du RFC rappelle ce problème de normalisation. Celle-ci se produit uniquement dans les applications, et n'a pas d'influence sur ce qu'on voit dans le réseau. Sur le câble, on voit passer uniquement des noms « punycodés » comme xn--acadmie-franaise-npb1a.fr. La norme IDNA bis (RFC 5890 et suivants) expose comment traduire un nom de domaine en Unicode (comme académie-française.fr) en cette forme punycodée (et retour). Le RFC 5891 impose que le nom Unicode soit déjà en forme normale C et n'accepte qu'un nombre restreint de caractères (par exemple les majuscules sont exclues). Imaginons qu'un utilisateur francophone travaille dans un environnnement Latin-1 et saisisse Académie-Française.fr. Ce nom est illégal pour IDNA bis et, pire, il n'est pas en Unicode. Il va donc falloir le traduire en Unicode, et le normaliser. Ici, c'est trivial, on remplace les octets de Latin-1 par ceux d'un encodage Unicode et on remplace chaque majuscule par sa minuscule équivalente. On a fait une normalisation. Mais, dans certains cas, l'opération est bien plus complexe. En français, il est difficile de trouver un exemple significatif. Mais d'autres langues posent des défis plus sérieux. Un exemple classique est celui du turc où la minuscule du grand I sans point (I) est le petit i sans point (ı) pas le petit i avec point (i). Mettre I en minuscule dépend de la locale.

Il est donc impossible de trouver une normalisation qui couvre proprement tous les cas, ne serait-ce que parce qu'elle dépend de la langue (alors que les RFC définissent des normes mondiales). Le choix de IDNA bis avait donc été d'abandonner le principe d'une normalisation standard (qui était définie dans le RFC 3491). Il y a donc désormais plusieurs normalisations possibles. Toutes devraient suivre un principe simple « surprendre l'utilisateur le moins possible ». Plus facile à dire qu'à faire... Notre RFC 5895 précise d'ailleurs modestement qu'il ne donne pas une solution complète. Mais, au moins, la normalisation est laissée au logiciel qui est le mieux placé pour connaître le contexte, le logiciel qui est directement en contact avec l'utilisateur.

À propos de la différence entre interface utilisateur et protocole réseau, la section 1.1 contient une intéressante discussion à ce sujet. Normalement, l'IETF ne s'occupe que des protocoles. L'interface utilisateur est certes une chose importante mais elle nécessite des compétences différentes, qui ne sont pas forcément très présentes à l'IETF. Résultat, beaucoup de programmeurs d'applications réseau sous-estiment la difficulté de réaliser une bonne interface utilisateur. Ainsi, des phrases qu'on trouve dans des normes IDN comme « l'utilisateur rentre un nom de domaine en Unicode » expédie en moins d'une ligne un processus très complexe, partant d'une décision de l'utilisateur de choisir tel symbole plutôt que tel autre, puis de le rentrer dans l'ordinateur par des moyens très divers (rien qu'avec un clavier, il existe d'innombrables manières de taper un sinogramme, par exemple ; et le clavier n'est pas le seul périphérique d'entrée), le tout suivi par le processus d'interprétation des entrées par l'ordinateur (très simple pour l'ASCII mais bien plus complexe avec d'autres écritures).

IDNA bis a supprimé complètement la partie « interface utilisateur ». Notre RFC 5895, sans la rétablir dans le protocole, expose des idées pour la gérer. Cette idée est résumée dans la section 1.2 : ce RFC 5895 propose des extensions à IDNA bis pour canonicaliser les noms d'une manière raisonnable dans la plupart des cas. Par définition, la normalisation de ce RFC ne conviendra donc pas à tout le monde, d'où son caractère « pour information » seulement.

La section 2 décrit la procédure de normalisation sous forme d'une suite d'étapes :

  • Passer les caractères en minuscule, en utilisant uniquement la base Unicode (propriétés Lowercase_Mapping dans le fichier SpecialCasing.txt puis Simple_Lowercase_Mapping dans la table principale).
  • Les caractères « pleine-chasse » et « demi-chasse » sont remplacés par leur équivalent (défini dans la table principale Unicode), le seul qu'accepte IDNA bis. Cette étape est utile car les mécanismes de saisie utilisés en Asie ne permettent pas toujours facilement de saisir la forme qu'attend le RFC 5891.
  • Les caractères sont normalisés en NFC. C'est la forme qu'attend IDNA bis. Il est raisonnable que l'application fasse cette normalisation car l'utilisateur n'en a pas toujours la possibilité. Si vous tapez sur la touche « à » de votre clavier, savez-vous si l'application enregistrera U+00E0 (petit a avec accent grave) ou bien U+0061 U+0300 (petit a suivi de l'accent grave combinant) ? NFC ne laissera subsister que la première forme.
  • Pour de très bonnes raisons, les règles d'IDNA bis ne s'appliquent qu'à un composant de nom de domaine isolé. Ainsi, dans www.académie-française.fr, académie-française est traité sans considération pour le composant précédent (www) ou pour le suivant (fr). Il y a de très bonnes raisons pour cela (même si certains amateurs de régulation auraient voulu faire des règles inter-composants) mais la canonicalisation, qui dispose du nom complet peut ajouter d'autres étapes notamment considérer comme séparateur d'autres caractères que le point de ASCII. Le 。 (U+3002) est recommandé.

Si j'appliquais cet algorithme, aurais-je une normalisation raisonnable ? La section 3 étudie ce point et répond clairement non. L'algorithme décrit en section 2 est uniquement un point de départ pour le programmeur et ne devrait pas être utilisé « sec ». La bonne démarche pour le courageux développeur est donc de bien lire la section 1 pour comprendre l'ampleur du problème, ensuite de partir de l'algorithme de la section 2 et de l'adapter.


Téléchargez le RFC 5895


L'article seul

RFC 5894: Internationalized Domain Names for Applications (IDNA): Background, Explanation, and Rationale

Date de publication du RFC : Août 2010
Auteur(s) du RFC : J. Klensin
Pour information
Réalisé dans le cadre du groupe de travail IETF idnabis
Première rédaction de cet article le 22 août 2010


Dans l'ensemble des RFC sur IDNA bis, celui-ci joue le rôle du document non officiel mais qui éclaire, explique et justifie les autres. Il n'est pas nécessaire de le lire pour mettre en œuvre les IDN mais il peut aider à comprendre la démarche des auteurs de IDNAbis. Mon compte-rendu va être un peu plus polémique que d'habitude car 1) ce RFC n'explique pas grand'chose, en fait et 2) il contient beaucoup de rhétorique et de FUD.

Officiellement, IDNAbis est nommé IDNA2008 (section 1), car c'était la date (totalement irréaliste, et qui avait été pointée comme telle par de nombreux participants) à laquelle le projet devait se terminer. La section 1 rappelle aussi quelques points sur lesquels IDNA 1 posait des problèmes, le changement de la gestion de la casse (IDNA 1 était insensible à la casse, comme le DNS) alors que IDNAbis résout le problème autrement, en interdisant les majuscules) ou comme la dépendance de IDNA 1 à une version spécifique d'Unicode (ce qui interdisait les écritures qui sont entrées dans Unicode plus tard, comme le Tifinagh).

Les objectifs d'IDNAbis sont détaillés dans la section 1.4 :

  • Indépendance vis-à-vis d'une version particulière d'Unicode (certainement l'objectif qui était le plus consensuel),
  • Régler quelques limites d'IDNA 1 qui interdisaient, en pratique, certaines langues comme le Yiddish, qui avaient besoin de certains caractères, qui étaient exclus,
  • Réduire (en fait, elle a même été supprimée) l'étape de canonicalisation (qui était faite avec nameprep, du RFC 3491),
  • Changer les règles du bidi (cf. le nouveau RFC 5893).

Pour le reste, le RFC est plutôt une collection assez décousue de divers points qui furent discutés lors du projet IDNAbis, points sur lesquels John Klensin tenait à faire connaître son opinion personnelle. Cela tient du blog plutôt que du RFC. Voyons quelques-uns de ces points.

Le terme même de « nom de domaine » peut entraîner des confusions car un nom dans le DNS n'est pas forcément une phrase ou même un mot dans une langue naturelle (section 1.3.1). Plusieurs règles du DNS interdisent certaines phrases ou certains mots (par exemple, la société C&A ne peut pas avoir de domaine à son nom, l'esperluette n'étant pas autorisée, avec ou sans IDN ; même chose avec le nom local de l'archipel d'Hawai'i, l'apostrophe n'étant pas acceptée). L'argument de Klensin est que, finalement, l'ancienne restriction à ASCII n'est pas si terrible puisque, de toute façon, on ne peut pas « écrire un roman dans le DNS ». Dommage qu'il se sente obligé de ridiculiser ceux qui ont une autre approche en les accusant de vouloir écrire du Klingon.

La section 1.5 concerne les limites d'IDNA, les points qu'il ne résoudra pas. Par exemple, le DNS ne permet pas de recherche floue, il faut indiquer le nom de domaine exact et cela ne change pas. L'augmentation du nombre de caractères admissibles, grâce à IDNA, peut rendre ce problème plus palpable (par exemple si on lit un peu trop vite un nom de domaine qu'on a vu sur le côté d'un bus).

Comme IDNA 1, IDNAbis ne nécessite pas de changement de l'infrastructure, comme l'aurait nécessité un hypothétique DNS Unicode. Une des conséquences est qu'il existe une forme ASCII de chaque IDN, le A-label et que ce nom (par exemple xn--pgbs0dh pour تونس) peut toujours être utilisé comme solution de secours.

La section 1.6 raconte qu'un des buts de IDNAbis était d'améliorer la « comprehensibilité » d'IDN. Qu'une personne normale, n'ayant pas forcément lu les RFC, comprenne mieux le fonctionnement d'IDN. D'où la suppression de l'étape de canonicalisation, jugée trop déroutante. Avec IDNAbis, les noms de domaine en Unicode (U-labels) seront tous déjà sous forme canonique (les autres étant interdits), ce qui devrait augmenter ladite compréhensibilité.

En fait, la canonicalisation (par exemple de CAFÉ vers café) sera faite dans l'interface utilisateur et plus dans le protocole et je ne crois pas que cela rende les choses plus prévisibles, d'autant plus que deux interfaces utilisateur différentes pourront canonicaliser différemment.

Traditionnellement, le DNS avait des règles différentes pour la résolution (qui utilisait des règles standard, comme l'insensibilité à la casse, mais aussi l'acceptation de tous les caractères, au delà de ASCII, cf. RFC 2181, section 11) et l'enregistrement (où les règles sont décidées localement par le registre et sont typiquement bien plus sévères, par exemple limitation à l'ASCII, interdiction des gros mots, etc). IDNAbis formalise cette distinction, pour refléter cette pratique (section 2 et RFC 5891).

Une des caractéristiques nouvelles et importantes de IDNAbis est que les caractères Unicode sont désormais interdits par défaut, alors qu'avec IDNA 1, ils étaient autorisés, sauf quand c'était indiqué explicitement. La section 3 revient sur ce choix. L'algorithme exact figure dans le RFC 5892. Une autre différence entre IDNA 1 et IDNAbis est que la validité d'un caractère dépend désormais du contexte. En effet, certains caractères notamment les « gluons », les caractères qui contrôlent le fait que deux caractères soient séparés ou pas, peuvent être jugés raisonnables ou pas, selon les caractères autour d'eux. C'est le cas par exemple de U+200D - le gluon de largeur nulle. En IDNA 1, tous ces caractères de la catégorie Unicode Join_Controls étaient interdits. Ils sont désormais autorisés conditionnellement (section 3.1.2)

Par défaut, en IDNAbis, les caractères tombent dans la catégorie IDN DISALLOWED (section 3.1.3). On y trouve des caractères qui ne sont typiquement pas considérés comme lettre ou chiffres et donc ne correspondent pas aux traditionnels critères pour les identificateurs. C'est le cas du ⁄ (U+2044) ou du ♥ (U+2665).

Les règles du protocole IDNAbis ne sont pas la totalité des règles applicables. En effet, le registre peut ajouter des règles supplémentaires. Par exemple, la plupart des registres interdisent l'enregistrement de noms comportant des caractères parfaitement valides dans le DNS comme le _ (U+005F). La section 3.2 discute des politiques des registres. Il serait plus juste de dire que cette section aboie des ordres, sur un ton paternaliste. On y trouve beaucoup d'opinions personnelles non étayées, déguisées en « bonnes pratiques » par exemple l'idée qu'il ne faut pas accepter les noms composés de plusieurs écritures (alors la plupart des utilisateurs d'alphabets non-latins acceptent en plus les caractères latins). Certaines recommandations sont intéressantes (comme celle du système des variantes, cf. RFC 3743, RFC 4290 et RFC 4713) mais d'autres relèvent plutôt d'une volonté de bras de fer, qui avait souvent été exprimée ouvertement dans les réunions du groupe de travail IDNAbis (par exemple, Klensin disant que « les registres pensaient uniquement à l'argent et qu'il fallait les contraindre à respecter l'intérêt général », intérêt qu'il exprimait, lui).

De même, cette section justifie la règle (section 4.1 du RFC 5891) comme quoi le demandeur doit envoyer à la fois le U-label (forme Unicode) et le A-label (forme Punycode) au registre, en prétendant que c'est pour vérifier la cohérence des deux. Pourtant, la forme Punycode n'est qu'une astuce technique pour déployer les IDN, ce que l'utilisateur veut, c'est la forme Unicode et il est tout à fait anormal de prétendre que le A-label aie un quelconque intérêt pour l'utilisateur !

Ces règles et bien d'autres ont souvent été justifiées au début du processus IDNAbis par de vagues arguments de sécurité (section 2.2.6 du RFC 4690). Cette baudruche s'est dégonflée assez vite et, aujourd'hui, la section 3.3 note à juste titre qu'il n'y a pas de solution technique à des questions comme celle de la confusabilité de deux caractères (par exemple le 0 - U+0030 - et le O - U+004F).

Traditionnellement, l'IETF travaille uniquement sur ce qui se passe sur le câble, loin des utilisateurs. Ici, toutefois, on ne peut pas ignorer les problèmes des applications, IDNA est faite pour elles (le A final du sigle). La section 4 se penche donc sur les logiciels que verra l'utilisateur. D'abord, contrairement au réseau, où les noms de domaines sont toujours transmis dans le même ordre (celui de la saisie au clavier), l'affichage des IDN peut être de droite à gauche ou de gauche à droite (section 4.1). Cela peut être d'autant plus complexe à gérer pour, par exemple, un navigateur Web, que le nom complet peut avoir des composants de gauche à droite et d'autres de droite à gauche (par exemple www.تونس.com). Ce cas est encore pire pour un IRI (RFC 3987) puisque celui-ci a forcément au moins un composant ASCII, le plan (par exemple http).

Saisir et afficher des IDN nécessite donc des choix délicats et des codes complexes (alors qu'un serveur de noms, par exemple, ou même une base de données d'un registre qui stocke des noms de domaine, n'ont rien de particulier à faire). La section 4.2 donne quelques conseils. Elle rappelle par exemple que les noms de domaine peuvent apparaitre dans un contexte où le fait qu'il s'agisse d'un nom de domaine est évident (par exemple lors d'un dialogue SMTP) mais aussi dans du texte libre, où le logiciel ne comprend pas forcément ce qu'il transmet. Les protocoles devraient donc bien préciser quand un nom de domaine est une partie du protocole (commande MAIL FROM de SMTP) et quand il ne l'est pas (le corps d'un message envoyé en SMTP).

Un problème en soi est celui de la canonicalisation (mapping, mise en correspondance) des caractères saisis par l'utilisateur avec ce que IDNAbis accepte. Dans IDNA 1, il existait une canonicalisation officielle, nameprep, normalisée dans le RFC 3491. Elle a été supprimée et, désormais, la canonicalisation est laissée à l'initiative de l'application. La seule obligation est de produire un nom conforme au protocole IDNAbis. Comme celui-ci, par exemple, exclus les majuscules (contrairement à la tradition du DNS, où majuscules et minuscules sont autorisées, tout en étant équivalentes), l'application doit mettre le nom en minuscules (une tâche triviale en ASCII mais bien plus complexe en Unicode, elle peut même dépendre de la langue). Le RFC 5895 décrit un exemple d'une telle canonicalisation.

A priori, cette canonicalisation locale, chacun faisant comme il veut, risque de dérouter et d'entrainer bien des problèmes : la même chaîne de caractères en Unicode, saisi dans deux navigateurs différents, pourra donner des noms de domaines (U-label) différents. L'idée est que chaque application prendra une décision conforme au contexte local (l'application connait l'utilisateur, connait sa langue) et que cela sera finalement moins surprenant. En outre, cela permet d'avoir, contrairement à IDNA 1, un aller-retour sans perte dans les conversions entre U-label et A-label.

D'autres attentes linguistiques peuvent poser un problème au développeur de logiciel IDNAbis. La section 4.3 fournit quelques exemples pittoresques :

  • Norvégiens et suédois peuvent considérer que æ et ä sont équivalents, ce qui dérouterait un utilisateur anglophone. Même chose avec oe et ö pour un allemand.
  • Un chinois regarde en général les formes simplifiées et traditionnelles d'un caractère comme équivalentes, or ces caractères sont aussi utilisés pour le japonais où cette opération n'aurait pas de sens.
  • Tout simplement, un anglophone pourrait s'étonner que theatre et theater, ou bien color et colour soient deux noms de domaine distincts... La frontière entre l'équivalence que doit faire le protocole et celle qui est laissée à la responsabilité de l'utilisateur n'est pas évidente à placer.

Autre cas de canonicalisation délicat : la distinction entre majuscules et minuscules. Pour les utilisateurs de l'alphabet latin, les deux casses sont souvent considérées comme sémantiquement équivalentes et c'est ce point de vue que reflète le DNS lorsque le RFC 1034 section 3.1 dit « domain name comparisons for all present domain functions are done in a case-insensitive manner ». Avec Unicode, un tel principe n'est plus tenable, comme le rappelle la section 4.4. Ni IDNA 1, ni IDNAbis n'obligent les serveurs à être insensibles à la casse et pour de bonnes raisons. Par exemple, certains caractères n'ont pas de majuscule propre comme le sigma final ς. Une conversion en majuscules en fait un Σ dont la forme minuscule est le sigma ordinaire σ. IDNA 1 résolvait la question en imposant aux applications une canonicalisation en minuscules via nameprep (RFC 3491), IDNAbis choisit d'ignorer le problème en n'acceptant que les minuscules et en laissant l'application canonicaliser à sa guise, en suivant les règles locales. À noter que ce changement peut entraîner quelques incompatibilités entre les deux versions d'IDN. Ainsi, en IDNA 1, strasse.de et straße.de sont le même nom de domaine (puisque nameprep canonicalise le second dans le premier) alors qu'ils sont différents en IDNAbis.

Le cas des écritures qui s'affichent de droite à gauche fait l'objet de la section 4.5. Pour limiter les risques d'ambiguité, IDNA 1 et IDNAbis imposent que, dans chaque composant d'un nom de domaine, il n'y aie que des caractères de la même directionnalité (ou des caractères neutres). C'est une des rares règles d'IDN qui examinent le composant entier, pas juste des caractères individuels.

La règle exacte dans IDNA 1 était trop stricte pour certaines langues qui ont besoin de marques vocaliques comme le yiddish écrit en hébreu ou le divehi écrit en thaana. Ces marques n'ont pas de directionalité et étaient interdites à la fin d'un composant. Ce n'est plus le cas et IDNAbis permet donc des noms qui étaient interdits en IDNA 1 (cf. RFC 5893).

En revanche, l'idée d'avoir des règles entre composants (étendre la règle ci-dessus à tout le FQDN) a été abandonnée. Elle aurait imposé une partie de bras de fer avec les registres de noms. (Le RFC ne mentionne pas cette très mauvaise idée, qui était pourtant promue par son auteur...) Il est donc toujours possible d'avoir un nom de domaine dont certains composants sont de gauche à droite et d'autres de droite à gauche.

La section 5 se réclame du fameux principe de robustesse (« soyez strict dans ce que vous envoyez et tolérant dans ce que vous recevez ») pour culpabiliser les registres de noms de domaine en leur faisant porter la responsabilité de contrôles plus étendus. En pratique, l'application qui accède à un IDN ne peut pas compter dessus, à la fois parce que tous les registres n'ont pas forcément les obsessions de John Klensin, mais aussi parce que des techniques comme les jokers (RFC 1034, section 4.3.3) font qu'un nom peut être résolu bien qu'il n'aie jamais été enregistré.

Encore plus délicate, la question des interfaces utilisateur (section 6). Il n'est évidemment pas possible de donner des règles applicables à tous les cas, vue la grande variété de ces interfaces. La section 6 se concentre surtout sur la nouveauté de IDNAbis ayant le plus d'implication pour l'interface : le fait que la canonicalisation standard (nameprep) du RFC 3491 aie disparu. Cette canonicalisation standard avait des avantages, notamment une meilleure interopérabilité, due au caractère plus prédictible des noms. Mais d'un autre côté, elle menait à des canonicalisations qui ne tenaient pas compte de la locale et pouvaient donc être surprenantes pour l'utilisateur humain. La nouvelle règle (chaque application canonicalise comme elle veut) permet aux applications (qui connaissent l'utilisateur, la locale, la langue...) de produire, à partir de ce qu'a tapé ou sélectionné l'utilisateur, des noms qui seront moins déroutants.

Pour ceux qui avaient déjà déployé les IDN avec l'ancienne norme IDNA 1, la section 7 fournit une description détaillée des mécanismes de migration possibles, et des pièges qui peuvent les guetter. Ainsi, comme le précise la section 7.2, des chaînes de caractères identiques en IDNA1 ne le sont plus en IDNAbis (strasse et straße ou bien les noms utilisant les gluons Unicode comme le U+200D) et donc deux noms de domaines qui étaient équivalents en IDNA 1 ne le sont plus (et ont donc des A-labels différents). Le choix n'a pas été évident. La section 7.2.3 résume les possibilités qui s'offraient au groupe de travail, dont certaines étaient très lourdes (changer le préfixe de l'encodage, actuellement xn--, par exemple, pour marquer clairement l'incompatibilité). Finalement, après de très longues discussions, le choix a été fait d'accepter cette légère incompatibilité. Une fois cette décision prise, quelle stratégie adopter pour accueillir ces « nouveaux » caractères ? La section 7.2.4 en décrit plusieurs, du refus des nouveaux, qui empêchera les anciens noms de fonctionner mais évitera toute confusion, à la période de transition (sunrise) pendant laquelle les titulaires des anciens noms auraient priorité pour enregistrer le nom incluant les nouveaux caractères. Par exemple, un registre germanophone pourrait donner la priorité au titulaire de strasse.de pour qu'il enregistre straße.de avant tout le monde. Il y a aussi l'éventualité d'un système de « variantes » où les noms « anciens » et « nouveaux » seraient liés en permanence et enregistrables uniquement par le même titulaire. Et la toute simple possibilité de ne pas s'en préoccuper, en considérant que le problème est mineur et disparaitra peu à peu. À l'heure actuelle (juin 2010), le registre du .AT prévoit de ne pas utiliser de variantes et de ne pas accepter immédiatement les nouveaux caractères. Lorsque ce sera fait, je suppose qu'il y aura une période de transition avec priorité aux anciens titulaires. C'est ce qu'a fait le registre du .DE, DENIC, qui fournit une période de transition.

La question du changement de préfixe fait même l'objet d'une section spécifique, 7.4. En effet, la question avait été sérieusement envisagée. Ce changement aurait créé deux familles d'IDN complètement séparées, celle dont les A-labels commencent par xn-- et la nouvelle. Le groupe de travail a considéré que le changement de préfixe aurait été nécessaire si les changements avaient créé un risque de confusion. La section 7.4.1 énumère précisèment les cas où cela se serait produit, par exemple si la conversion d'un A-label en U-label avait renvoyé deux chaînes Unicode différentes ; le cas inverse était jugé moins grave, et il s'est effectivement produit dans de rares cas, comme dans l'exemple du ß ci-dessus. Autre exemple, celui où l'encodage du A-label aurait été drastiquement modifié, par exemple pour inclure de l'information sur la langue utilisée.

En revanche, le groupe de travail avait considéré que des changements comme l'interdiction de caractères autrefois autorisés (section 7.4.2) ne justifiait pas un changement de préfixe. Cette interdiction rend des noms enregistrés inutilisables dans le DNS mais l'idée est qu'un refus clair est moins grave qu'un changement de sémantique et ne justifie donc pas de changement de préfixe. Un tel changement aurait eu des coûts considérables, détaillés en section 7.4.3. En effet, si un registre peut toujours changer tous les A-labels facilement (UPDATE Domains SET alabel TO idnabis_alabel(ulabel)), il n'aurait pas pu synchroniser ce changement avec celui des applications qui ont l'encodage en Punycode.

Et l'algorithme nameprep, normalisé dans le RFC 3491, que devient-il ? Il est complètement abandonné en IDNAbis mais nameprep n'est qu'un profil particulier de stringprep, normalisé dans le RFC 3454, et celui-ci est utilisé par bien d'autres normes IETF et il continue donc sa vie (section 7.5), sans que IDNAbis ne l'affecte.

Un des grands changements théoriques entre IDNA 1 et IDNAbis est l'interdiction des symboles comme U+2665 (♥), U+2605 (★) ou U+2798 (➘). C'est un changement surtout théorique car, en pratique, ils étaient souvent interdits par les règles d'enregistrement et on ne les trouve pratiquement pas en pratique. (Voir, par exemple, le IESG Statement on IDN.) Cette méfiance vis-à-vis des symboles vient entre autre du fait qu'il n'existe pas de nommage standard pour les désigner et que les variations de forme entre polices sont encore plus marquées que pour les lettres. Il n'est donc pas facile d'épeler un nom de domaine comme I♥NY.us sans ambiguité... D'autant plus que certains symboles ont beaucoup de caractères Unicode correspondants (comme le carré).

La même section 7 couvre le cas de la migration interne à IDNAbis lorsqu'une nouvelle version d'Unicode est publiée (section 7.7). En effet, IDNAbis n'est plus lié à une version spécifique d'Unicode et l'enregistrement de nouveaux caractères, ou bien certains changements dans les caractères déjà enregistrés, peuvent faire apparaitre « automatiquement » de nouveaux caractères légaux dans IDN.

Parmi les innombrables questions qu'avaient soulevé l'introduction des IDN en 2003, le comportement des logiciels serveurs de noms comme BIND (section 8). Le souci de ne pas leur faire faire des canonicalisations Unicode est la principale raison pour laquelle nous avons IDNA (IDN in Applications) et pas un DNS Unicode). Si le DNS a toujours prévu une canonicalisation minimale (les noms de domaine sont insensibles à la casse), celle-ci n'a jamais été normalisée pour Unicode (cf. RFC 4343). Ce point ne change pas en IDNAbis.

Donc, une des rares conséquences réelles pour les serveurs de noms est la longueur plus importante de beaucoup d'IDN. Ce point est mentionné en section 8.2, mais sans préciser que DNSSEC, bien plus gourmand, a été déployé sans trop de problèmes. Depuis la rédaction du RFC, l'introduction de quatre TLD IDN dans la racine du DNS a bien montré qu'il n'y avait aucun problème technique, malgré le FUD qui a été répandu à ce sujet.

Vu le sujet du RFC, la section facultative sur l'internationalisation se devait d'être présente (section 9). Elle rappelle que les noms dans le DNS, quoique mnémoniques, ne sont pas écrits selon les règles des langues humaines (par exemple, l'espace n'y est pas permis) et qu'il ne faut donc pas demander aux IDN de permettre l'écriture de n'importe quelle phrase, en respectant toutes les règles de la langue. Ceci dit, la même section oublie par contre de dire que, si les noms de domaine ne sont pas du texte en langue naturelle, ils ne sont pas non plus de purs identificateurs (c'est pour cela qu'ils ont une utilisation mnémonique) et c'est bien cela qui justifie IDN (personne ne demande l'internationalisation des adresses IP qui sont, elles, de purs identificateurs).

Une autre raison pour laquelle les règles des langues humaines ne peuvent pas être intégralement respectées dans le DNS est que le DNS est mondial et qu'un nom de domaine doit pouvoir être utilisé partout. D'autre part, le RFC rappelle également qu'un nom de domaine n'est pas écrit dans une langue particulière. Quelle est la langue de coca-cola.com ? (Certainement pas de l'anglais.)

Le développement de IDNAbis a nécessité la création de certains nouveaux registres à l'IANA. La section 10 revient sur ces registres. Elle rappelle que la liste des caractères autorisés n'est pas normative, seul l'est l'algorithme du RFC 5892. En revanche, la liste des règles contextuelles est normative. Plus délicate, la liste des politiques d'enregistrement, dont la section 10.3 rappelle qu'elle n'a aucune valeur, c'est juste un dépôt volontaire de leurs politiques par certains registres. Elle n'est spécifiée dans aucun RFC et ne découle que de considérations politiciennes à l'ICANN.


Téléchargez le RFC 5894


L'article seul

RFC 5893: Right-to-left scripts for Internationalized Domain Names for Applications (IDNA)

Date de publication du RFC : Août 2010
Auteur(s) du RFC : H. Alvestrand (Google), C. Karp (Swedish Museum of Natural History)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF idnabis
Première rédaction de cet article le 22 août 2010


Le fait que certains systèmes d'écriture soient de gauche à droite (comme celui utilisé pour ce texte) et d'autres de droite à gauche ne pose pas de problèmes lorsque le texte est entièrement dans un sens ou dans l'autre. Mais, si on les mélange, on arrive parfois à des résultats surprenants. Dans le contexte des noms de domaine, cela peut mener à rendre leur utilisation difficile. C'est pour cela que l'ancienne norme IDNA 1 limitait ce mélange (RFC 3491, section 6, qui référence RFC 3454, section 6). Les limitations étaient un peu trop strictes et sont légèrement libéralisées par ce nouveau RFC 5893, qui fait partie de la nouvelle norme IDNAbis. Le changement est faible en pratique, la plupart des noms autorisés restent autorisés. En dépit d'une fréquente utilisation de weasel words par ce RFC (comme « sûr » en section 1.3), il n'y a pas de conséquences, qu'elles soient positives ou négatives, pour la sécurité (malgré ce que raconte la section 9 du RFC).

On peut résumer l'ancienne norme (cf. section 1.2 de notre nouveau RFC) en disant que tout composant d'un nom de domaine ne devait pas inclure des caractères de directionnalité différente (par exemple de l'alphabet grec et de l'alphabet arabe) et qu'il devait commencer et se terminer par des caractères ayant une directionnalité déterminée (les chiffres arabes, par exemple, n'ont pas de directionnalité déterminée). Notons qu'il y a deux poids et deux mesures : les noms de domaine traditionnels en ASCII n'avaient pas cette limite et, par exemple, 7-septembre ou 3com sont des composants autorisés.

Il est prudent de relire la section 1.4 sur la terminologie, car tout le monde n'est pas expert BIDI. Soit on apprend par cœur le difficile UAX#9, la norme officielle du BIDI, soit on révise rapidement dans ce RFC les points importants :

  • Les caractères Unicode ont tous une propriété BIDI : directionnalité de gauche à droite (les caractères de l'alphabet grec, par exemple), directionnalité de droite à gauche (les caractères de l'alphabet arabe), chiffres arabes (qu'Unicode appelle EN pour European Number, comme 0, 1 ou 2, ils sont sans directionnalité puisqu'ils sont utilisés dans des alphabets des deux modèles), chiffres indo-arabes (qu'Unicode appelle AN pour Arabic Number, comme ١ (1) ou ʛ (7) et qui ont une directionnalité dite « faible »), etc.
  • Les chaînes de caractères ont deux ordres : l'ordre du réseau, qui est celui dans lequel les caractères de la chaîne ont été tapés, ou bien dans lequel ils sont transmis sur le réseau, et l'ordre d'affichage, qui est celui dans lequel ils sont présentés à des lecteurs humains. Lorsque le RFC parle d'ordre ou bien utilise des termes comme « premier » ou « dernier », c'est en général en référence à l'ordre du réseau,

Armé de ces définitions, on peut arriver au cœur du RFC, la section 2. Elle formalise les règles que doivent suivre des composants de noms de domaine internationalisés :

  • Le composant d'un IDN doit commencer par un caractère de directionnalité forte (donc pas par un chiffre, cf. section 4.3 et 7.1) ; ce caractère détermine si le composant est gauche-à-droite ou droite-à-gauche,
  • Dans un composant droite-à-gauche, seuls sont permis les caractères de directionnalité droite-à-gauche ou bien sans directionnalité (comme les chiffres). Ainsi, مدقق-XML-المدمج (tiré de la documentation en arabe de SPIP) serait interdit, à cause du sigle en caractères latins (même si la présence de tels sigles est très courante dans les textes techniques en arabe),
  • Le caractère final peut être sans directionnalité (on peut finir par un chiffre),
  • Le mélange des chiffres arabes et indo-arabes dans un même label est interdit (notons que cette règle était déjà dans le RFC 5564) : les chiffres indo-arabes sont interdits dans un composant gauche-à-droite,
  • Et je passe quelques règles plus subtiles.

Ce RFC 5893 propose également des justifications pour le choix de ces règles, sous forme de critères que devraient respecter tous les noms de domaine en Unicode (section 3) :

  • Unicité du composant : deux composants distincts, affichés dans le même paragraphe, ne doivent pas avoir le même affichage. Sans les règles plus haut, les composants 123 et 321, par exemple, pourraient s'afficher de manière identique, si le second est précédé de caractères droite-à-gauche. L'interdiction des chiffres (caractères sans directionnalité) au début d'un composant découle de ce critère.
  • Regroupement des caractères : les caractères d'un même composant doivent rester groupés, ce qui ne serait pas le cas si on permettait le mélange de caractères de directionnalité différentes.

Dans le cours de la discussion sur IDNAbis, d'autres critères avaient été suggérés mais n'ont finalement pas été retenus :

  • Constance de l'apparence : un composant doit être affiché de manière identique dans un contexte de gauche-à-droite et dans un contexte de droite-à-gauche : c'est un résultat trop difficile à obtenir dans le contexte de l'algorithme BIDI,
  • L'ordre des composants d'un nom doit rester identique quel que soit le contexte d'affichage ; ce critère aurait mené à des tests inter-composants, peu réalistes (puisque ce sont des registres différents qui sont impliqués pour chaque niveau du nom, avec des règles différentes),
  • Unicité du nom de domaine : deux noms différents ne devraient pas être affichés de manière identique ; objectif impossible à atteindre : ABC.abc sera affiché abc.CBA dans un contexte droite-à-gauche, et le nom différent abc.ABC sera affiché de manière identique dans un contexte gauche-à-droite.

Arrivé là, on a toutes les règles (la fin de la section 3 les reformalise de manière plus rigoureuse). La section 4 donne simplement des exemples de cas où les règles des RFC 3454 et RFC 3491 donnaient des résultats peu satisfaisants. Ainsi, la langue divehi, qui s'écrit avec un alphabet proche de l'arabe, le Thaana, a tous ses mots qui se terminent par un caractère Unicode combinant (un accent, disons en simplifiant). « Ordinateur » se dit en dhivehi « ކޮންޕީޓަރު » et le dernier caractère, U+07AA est l'ubu fili, un caractère (pas une lettre) sans directionnalité, qui aurait été rejeté par IDNA 1 (section 4.1).

Un problème analogue se pose en yiddish. Ainsi, l'organisation qui normalise les règles d'écriture du yiddish s'écrit « יִואָ » et le dernier caractère, U+05B8, n'est pas une lettre (section 4.2).

Il n'existe pas de solution technique aux problèmes d'affichage BIDI, l'ensemble des situations possibles étant trop vaste. Il ne faut donc pas croire qu'appliquer les règles de ce RFC suffira à être tranquille. La section 5 donne quelques exemples, par exemple un nom de plusieurs composants, où un composant un IDN (satisfaisant les règles de ce RFC), précède des noms ASCII commençant par un chiffre : المغربية.3com.com va ainsi être affiché d'une manière déroutante (cela devrait être ‏المغربية‎.3com.com). Ce nom n'est pas interdit (alors que c'était l'ambition initiale du groupe de travail idnabis) car il existe déjà beaucoup de noms ASCII commençant par un chiffre, et car la combinaison de composants pour former un nom est parfois réalisée automatiquement (par exemple via la directive search dans /etc/resolv.conf), ne laissant pas de possibilité de contrôle, et enfin parce que les jokers du DNS (encore eux) peuvent faire qu'un nom peut être résolu sans avoir été enregistré (et donc vérifié)...

La section 6 liste d'ailleurs quelques autres problèmes comme le fait que le mélange de chiffres arabes et de chiffres indo-arabes est interdit, mais que le mélange de chiffres bengalis et chiffres gujaratis n'est pas mentionné... Le cas doit être traité par le registre (par exemple celui de .IN).

Les règles de ce RFC étant nouvelles, il y a potentiellement des problèmes avec les anciens noms. La section 7.1 analyse les questions de compatibilité. La 7.2 se préoccupe au contraire du futur en constatant que les propriétés BIDI ne font pas partie des propriétés qu'Unicode s'engage à ne pas modifier et que donc, dans le futur, un changement de propriétés BIDI pourrait rendre invalides des composants valides et réciproquement.

Les IDN BIDI posent-ils des problèmes de sécurité particuliers ? C'est ce que laisse entendre Patrik Fältström dans son article « Mixing different scripts is hard », qui est franchement tendancieux. Si les exemples donnés d'affichage BIDI suprenants sont amusants intellectuellement, il n'est jamais démontré que cela puisse avoir des conséquences de sécurité. La section 9 de ce RFC 5893, consacrée à ce sujet, ne fournit pas d'éléments nouveaux, à part de vagues accusations.


Téléchargez le RFC 5893


L'article seul

RFC 5892: The Unicode code points and IDNA

Date de publication du RFC : Août 2010
Auteur(s) du RFC : P. Faltstrom (Cisco)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF idnabis
Première rédaction de cet article le 22 août 2010


Dans l'ensemble des RFC sur la version 2 des IDN (appelée IDNAbis ou IDNA2008), ce document normalise les propriétés Unicode utilisées pour calculer la catégorie à laquelle appartient un caractère donné, catégorie qui déterminera s'il est autorisé dans un nom de domaine en Unicode. (Il a depuis été partiellement mis à jour par le RFC 8753.)

Le concept de catégorie est défini dans la section 1 (avertissement : le vocabulaire de IDNAbis est très flou et on trouve « catégorie » ou « propriété » pour ce concept, des termes d'autant plus malheureux qu'ils existent aussi dans Unicode avec un sens différent ; j'ai donc plutôt utilisé « statut »). Ce RFC 5892 contient les tables complètes de tous les caractères Unicode et de leur catégorie. Mais ces tables ne sont présentes qu'à titre d'information : IDNAbis est en effet indépendant de la version d'Unicode utilisée et la vraie norme est l'algorithme utilisé pour créer les tables, algorithme qu'il faut faire tourner pour chaque version d'Unicode, pour trouver la table effective.

IDNAbis repose sur un principe d'exclusion par défaut. Tout caractère est interdit, sauf s'il est autorisé (cf. RFC 4690). Cette autorisation dépend de ses propriétés Unicode, propriétés qui font partie de la norme Unicode. Par exemple, le U+00E9 (petit e accent aigu) est dans la catégorie Unicode Ll (lettres minuscules, presque toutes autorisées).

Le fait d'être dans la bonne catégorie des tables ne suffit pas : dans certains cas, IDNAbis met des contraintes aux combinaisons de caractères.

Quelles sont les catégories (ou statuts) possibles ?

  • PROTOCOL VALID dit PVALID, les caractères acceptés.
  • CONTEXTUAL RULE REQUIRED, pour des caractères acceptés sous condition, par exemple sur leur position dans le composant du nom de domaine. Il est abrégé en CONTEXTJ (caractères qui contrôlent l'attachement de deux mots comme le U+200D, Zero-width joiner) ou CONTEXTO (les autres).
  • DISALLOWED, les caractères interdits.
  • UNASSIGNED, les points de code pas encore affectés dans la norme Unicode, interdits aujourd'hui mais qui, selon leurs propriétés, pourraient devenir autorisés dans le futur.

Le classement d'un caractère dans une de ces catégories dépend de l'algorithme décrit plus loin. Une liste d'exceptions maintenue manuellement (section 2.6) permet d'ajuster le résultat, une autre liste manuelle permet de maintenir la stabilité (d'empêcher un caractère de changer de catégorie).

La section 2 décrit les catégories utilisées pour classer les caractères (à ne pas confondre avec les catégories IDNA, comme PVALID, décrites plus haut) et les propriétés utilisées (elles ne sont pas mutuellement exclusives) :

  • Lettres & Chiffres (section 2.1) : le caractère a une catégorie Unicode dans l'ensemble {Ll, Lu, Lo, Nd, Lm, Mn, Mc}. Par exemple Ll désigne les lettres minuscules, ainsi le êta grec, ͱ (U+0371) est dans cette catégorie (sa définition dans la base Unicode étant 0371;GREEK SMALL LETTER HETA;Ll;0;L;;;;;N;;;0370;;0370).
  • Instables (section 2.2) : le caractère ne survit pas à une normalisation NFKC avec un changement de casse. La plupart de ces caractères ne seront pas autorisés.
  • Propriétés qu'on peut ignorer (section 2.3) : ces caractères ont des propriétés qui font qu'on peut les ignorer pour les noms de domaines (par exemple les caractères d'espacement, propriété Unicode White_Space).
  • Blocs qu'on peut ignorer (section 2.4) : des blocs entiers des tables Unicode peuvent être ignorés comme le bloc des symboles utilisés en musique qui va de U+1D100 (𝄀) à U+1D1FF.
  • LDH (Letters-Digits-Hyphens), les caractères ASCII traditionnellement utilisés dans les noms de machine (section 2.5).
  • Des exceptions, définies manuellement, pour le cas où les propriétés Unicode ne donnent pas le bon résultat (section 2.6). Ainsi, après de très longues discussions dans le groupe de travail, le ß allemand, le ς grec et le ་ tibétain (ce dernier, le tsheg, a été l'objet du débat le plus aveugle puisqu'aucun expert de cette écriture n'était présent) ont été manuellement autorisés (alors qu'ils auraient été interdits en appliquant l'algorithme). Par contre, les chiffres indo-arabes, qui auraient été autorisés inconditionnellement, sont maintenant autorisés uniquement dans certains contextes (voir le RFC 5564 pour une discussion sur ces chiffres).
  • Compatibilité (section 2.7) : cette catégorie est actuellement vide. Mais, dans les futures versions d'Unicode, des changements des propriétés pourraient faire passer des caractères de PVALID à DISALLOWED ou le contraire. Ils seront alors mis dans cette catégorie pour conserver leur ancien statut.
  • Contrôle du collage entre caractères (section 2.8). Cette catégorie regroupe les caractères « gluons » qui servent à coller des caractères ou des mots qui seraient normalement séparés. Certaines écritures (par exemple les indiennes) en font un grand usage.
  • Vieil Hangul (section 2.9), une catégorie très ad hoc pour des caractères utilisés en Corée.
  • Et enfin, la dernière catégorie, celle des caractères non actuellement affectés (section 2.10) mais qui pourraient l'être dans les futures versions d'Unicode.

Bien, on a dix catégories. Comment les utilise t-on pour déterminer si un caractère est acceptable ou pas ? C'est l'objet de la section 3, qui indique cet algorithme en pseudo-code. Je n'en donne qu'une partie ici :

SI le caractère est dans les Exceptions, sa propriété IDNA est donnée
par la table Exceptions
...
SINON SI le caractère est dans LDH, alors il est PVALID
...
SINON SI le caractère est dans les Blocs Ignorables alors il est
DISALLOWED
...
SINON SI le caractère est dans les Lettres & Chiffres, alors il
est PVALID

SINON SI (cas par défaut) il est DISALLOWED

La section 4 insiste sur le fait que la liste des caractères faisant foi est celle calculée par l'algorithme ci-dessus. La liste fournie dans ce RFC 5892, en annexe B, n'est là que pour information (en effet, chaque nouvelle version d'Unicode modifiera les tables).

On a vu que le sort d'un caractère dont le statut est CONTEXT nécessite de regarder une table. Celle-ci est définie dans la section 5.2 et sa syntaxe figure dans l'annexe A. Elle est hébergée à l'IANA.

Enfin, même si elle n'a pas de caractère normatif (cf. RFC 8753), la plus grande partie du RFC est formée par l'annexe B, qui donne l'état actuel des tables de caractères avec leur statut.

Comme indiqué plus haut, les tables figurant dans le RFC ne sont pas normatives, seul l'algorithme l'est. En pratique, les tables ont été produites par un programme écrit par l'auteur du RFC qui ne le distribue pas (malgré plusieurs demandes). J'ai refait une mise en œuvre incomplète (manque de temps) de l'algorithme qu'on peut récupérer en create-idnabis-tables.py.


Téléchargez le RFC 5892


L'article seul

RFC 5891: Internationalized Domain Names in Applications (IDNA): Protocol

Date de publication du RFC : Août 2010
Auteur(s) du RFC : J. Klensin
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF idnabis
Première rédaction de cet article le 22 août 2010


L'ensemble des RFC sur la deuxième version d'IDN couvre la terminologie (RFC 5890), les tables de caractères autorisés (RFC 5892), les justifications des choix effectués (RFC 5894) et, dans ce RFC 5891, le protocole lui-même, utilisé pour l'enregistrement et la lecture des noms de domaine.

Ces RFC « IDNAbis » remplacent donc les RFC 3490 et RFC 3491 mais pas le RFC 3492, Punycode continuant à être l'encodage utilisé pour les IDN, avec le même préfixe, xn--. Le principe reste le même : comme les règles pour les noms de machine (mais pas pour les noms de domaine) imposent l'utilisation des seuls caractères US-ASCII, comme il n'est pas question de mettre à jour toutes les plate-formes utilisées, IDN fonctionne en encodant les noms de domaines Unicode en ASCII, grâce à l'algorithme Punycode. L'infrastructure n'est donc pas modifiée mais on peut présenter aux utilisateurs le vrai nom en Unicode, quitte à le traduire lors du passage sur le réseau. (Officiellement, IDNAbis est nommé IDNA 2008 mais ce nom est incorrect, le protocole n'ayant pas été terminé en 2008.)

La section 3 précise ce fonctionnement en exigeant qu'un nom de domaine utilisé comme tel (i.e. comme élément d'un protocole, pas lorsqu'il est simplement cité dans du texte libre), doit être encodé en ASCII lorsqu'on parle aux applications non-IDN, et que la comparaison entre deux noms de domaine (pour voir s'ils sont égaux) doit se faire entre deux formes Unicode ou deux formes ASCII mais pas en mélangeant les deux. Dans IDNAbis, le passage de la forme Unicode (U-label) à la forme ASCII (A-label) et en sens inverse se fait sans perte d'informations. Les deux comparaisons sont donc équivalentes. Comme beaucoup de protocoles utilisent des noms de domaine, les IDN affectent potentiellement beaucoup de monde. Sauf si le protocole le prévoit explicitement (ce qui est le cas des IRI du RFC 3987), les IDN doivent donc être mis sous leur forme ASCII. Idem pour les requêtes et réponses effectives faites avec le DNS.

Petit détail au passage. On trouve souvent des noms de domaine dans la partie droite d'un enregistrement DNS, par exemple dans le champ RNAME d'un SOA, qui indique l'adresse de courrier du responsable de la zone). Comme le rappelle la section 3.2.2, IDN ne change pas ces champs qui restent actuellement en pur ASCII, en attendant un futur RFC (le RFC 6530 ne suffit pas).

Passons maintenant aux deux protocoles utilisés par IDNAbis, le protocole d'enregistrement et le protocole de résolution. Le premier est décrit dans la section 4. Il concerne l'enregistrement d'un nom de domaine Unicode auprès d'un registre (attention, un registre ne gère pas forcément un TLD, ce protocole concerne tous les registres, même, par exemple, celui de bortzmeyer.org).

Donc, première étape, le registre reçoit un nom en Unicode (section 4.1). Il doit être normalisé en NFC et peut être encore normalisé selon des règles locales (cf. RFC 5895). Ce nom peut être transmis directement en Unicode (« U-label ») ou bien encodé en Punycode (« A-label »). Le RFC recommande de joindre la forme Punycode (voire uniquement celle-ci) mais il n'y a aucune justification technique à ce choix, c'est juste du FUD anti-Unicode.

Le registre doit ensuite vérifier que le nom est correct techniquement (section 4.2). Ainsi, il faut tester que la conversion U-label -> A-label et retour redonne bien le meme nom et, si uniquement une forme Punycode est reçue, qu'elle est bien légale (toute chaîne de caractères commençant par xn-- n'est pas forcément du Punycode). Les caractères interdits doivent être absents (cf. RFC 5892).

À côté des règles absolues (« le caractère ; est interdit »), il existe également des règles contextuelles comme l'interdiction du caractère Katagana U+30FB sauf dans les écritures utilisées au Japon (cf. RFC 5892). Enfin, si le nom comporte des caractères dont la directionnalité est de droite à gauche (cas de l'écriture arabe), il faut également suivre les prohibitions du RFC 5893.

Notons que les interdictions de ce RFC 5891 ne sont qu'un minimum. Un registre peut toujours ajouter ses propres règles comme de n'accepter que les caractères qui sont utilisés pour la langue locale, ou bien pour interdire des mots considérés comme grossiers.

Après ce parcours du combattant, le nom est enregistré. Reste à le résoudre via une requête DNS. C'est l'objet de la section 5, sur le protocole de résolution. Ce dernier effectue moins de tests puisqu'ils sont censés avoir été faits à l'enregistrement. Notez toutefois que ce n'est pas un argument très solide : non seulement il peut exister des registres qui ne font pas les tests ou bien les font mal mais la seule existence des jokers dans le DNS (RFC 1034, section 4.3.3) permet à un nom non enregistré d'« exister » quand même.

Bref, pour résoudre un IDN, le client doit donc convertir en Unicode (en effet, l'environnement de départ n'utilisait pas forcément Unicode, cela pouvait être, par exemple, Latin-1) et le normaliser en NFC. Ensuite, il teste que les caractères Unicode présents sont bien autorisés (section 5.4). Il est à noter que le résultat de ce test dépend de la version d'Unicode utilisée par le client (probablement via des bibliothèques standard fournies par le système d'exploitation). Ainsi, un nom de domaine utilisant un caractère très récemment affecté par Unicode pourrait être refusé par beaucoup de clients IDN.

Enfin, le client IDN convertit le nom en Punycode et termine par une résolution DNS normale (sections 5.5 et 5.6).

La section sur la sécurité, obligatoire dans les RFC, mentionne le risque de confusion entre des caractères similaires (un FUD classique contre IDN) mais ne fournit pas de solution dans le protocole. Elle compte sur les registres pour ne pas accepter les noms problématiques.

L'annexe A dresse la liste des différences avec la première version d'IDN. Je cite notamment :

  • Au lieu de dépendre d'une version spécifique d'Unicode (la 3.2 pour IDNA 1), le protocole est désormais indépendant de la version : tout changement dans Unicode est automatiquement disponible.
  • Les protocoles pour l'enregistrement d'un nom et sa résolution sont désormais séparés (et légèrement différents).
  • Les caractères de ponctuation et les symboles sont désormais presque tous exclus.
  • Il n'y a plus d'étape de normalisation standard comme l'était le nameprep du RFC 3491. Seul reste le NFC. D'une manière générale, chaque application est désormais libre d'effectuer la correspondance (mapping) entre ce qu'a tapé ou sélectionné l'utilisateur et l'IDN (cf. RFC 5895 pour un exemple).
  • Le modèle de sélection des caractères autorisés est passé de « entièrement manuel, caractère par caractère » à « essentiellement algorithmique, fondé sur les propriétés Unicode - avec un peu d'exceptions manuellement ajoutées ». C'est ce qui permet l'indépendance par rapport aux versions d'Unicode.
  • La validité d'un caractère peut désormais dépendre du contexte (ce qui complique sérieusement la vérification).
  • Nouvelles règles « bidi ».
  • Largement compatible avec l'ancien IDN (même Punycode, même préfixe, beaucoup de règles communes) mais pas totalement (certains noms légaux deviennent invalides).

Pour un point de vue critique sur IDNA bis, on peut consulter le Unicode Technical Standard #46, « Unicode IDNA Compatibility Processing », qui remet notamment en cause le soi-disant rôle d'Unicode dans le hameçonnage. Une critique de cette critique a été publiée en Review of Unicode TR#46.


Téléchargez le RFC 5891


L'article seul

RFC 5890: Internationalized Domain Names for Applications (IDNA): Definitions and Document Framework

Date de publication du RFC : Août 2010
Auteur(s) du RFC : J. Klensin
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF idnabis
Première rédaction de cet article le 22 août 2010


La nouvelle norme pour les noms de domaine écrits en Unicode, nommée IDNA2008, modifie les règles qui s'appliquent à ces IDN. Elle est composée de plusieurs RFC dont ce RFC 5890, qui fixe la terminologie.

Dans cette nouvelle version, sur laquelle le travail a commencé en 2008 (d'où son nom officiel d'IDNA2008, cf. section 1.1), la norme est plus riche et plus complexe. Le seul RFC des définitions fait 29 pages. Elle remplace IDNA 1, ou « IDNA2003 » (l'ancienne norme, dans les RFC 3490 et RFC 3491). Elle crée notamment les nouveaux termes de U-label (composant de nom de domaine en Unicode) et de A-label (composant de nom de domaine internationalisé encodé selon l'algorithme Punycode du RFC 3492). Contrairement à d'autres normes de l'IETF, elle n'est pas indispensable que pour les programmeurs, mais aussi pour ceux qui, par exemple, décident des politiques d'enregistrement des registres.

Quels sont les RFC qui composent IDNA2008 ? La section 1.3 donne la liste officielle :

  • Ce document, le RFC 5890, qui donne les définitions.
  • Le RFC 5894, de justification des choix effectués, et qui fournit aussi des avis sur les politiques d'enregistrement. Il n'a pas statut de norme et reflète des opinions peu consensuelles sur les IDN.
  • Le RFC 5891 qui normalise le protocole.
  • Le RFC 5893, spécifique aux questions posées par les écritures de droite à gauche,
  • Le futur RFC sur les fonctions qui transforment un nom de domaine avant de le passer à IDNA, par exemple pour mettre en œuvre les équivalences entre deux caractères.
  • Et enfin la liste des caractères autorisés, dans le RFC 5892. C'est une des grandes nouveautés, puisque, contrairement à la précédente version, elle ne dépend plus d'une version particulière de la norme Unicode.

La section 2 est ensuite consacrée aux mots-clés de IDNA2008 (attention à ceux qui connaissaient l'ancienne norme, le vocabulaire est souvent nouveau). Les RFC de IDNA2008 utilisent également un vocabulaire non-spécifique aux IDN mais qui est rappelé en section 2.2. Ainsi, un registre désigne toute organisation qui enregistre des noms de domaine, même si elle ne gère pas un TLD (je suis le registre de bortzmeyer.org). LDH (Letters Digits Hyphen) désigne les caractères ASCII qui sont traditionnellement autorisés dans les noms de machine (RFC 1123). Notez bien que les noms de domaine, contrairement à ce qu'écrivent beaucoup d'ignorants, ne sont pas limités à LDH.

La section 2.3 introduit les termes spécifiques à IDN. Par exemple :

  • LDH label est le composant (label) d'un nom de domaine, qui s'écrit uniquement avec LDH (c'est le nom traditionnel comme example dans www.example.com, nom qui compte trois composants). Deux sous-ensemble de LDH label sont définis, Reserved LDH label (ceux dont le troisième et quatrième caractères sont des tirets) et les non-réservés (les noms de domaines pré-IDN comme bortzmeyer.org). Parmi les réservés, certains ont xn en premier et deuxième caractère. Ils forment les XN labels dont tous, c'est important, ne sont pas forcément des encodages valides en Punycode. Ceux qui sont valides sont les A-labels, les autre étant nommés d'un terme péjoratif absolument non justifié, fake A-labels (IDNA2008 contient beaucoup de réglements de compte via le vocabulaire). La figure 1 du RFC représente graphiquement les relations entre ces différents ensembles. Il est recommandé de la consulter en cas de migraine.
  • Les A-labels sont donc la forme ASCII des IDN, produite par Punycode (RFC 3492). Par exemple, xn--stphane-cya est un A-label.
  • Un U-label est un composant valide d'un nom de domaine en Unicode. Par exemple, stéphane est un U-label (dont le A-label est le xn--stphane-cya cité plus haut). Toute chaîne Unicode n'est pas forcément un U-label. Elle doit être normalisée en NFC et ne compter que des caractères autorisés. Tout U-label peut être converti en un A-label unique et réciproquement.

Notons que tous ces termes sont pour des composants d'un nom de domaine (label). Le nom lui-même, s'il contient au moins un A-label ou un U-label est un IDN.

Il y a plein d'autres détails sur les composants d'un nom. Par exemple, lorsque les normes IDNA2008 parlent de l'ordre d'un caractère, c'est une référence à l'ordre de transmission via le réseau. L'affichage peut être différent, puisque certaines écritures se font de droite à gauche.

Tout RFC doit comporter une section sur la sécurité et c'est ici la section 4. Avec IDN, il y a potentiellement des problèmes de débordement de tableau (le U-label peut avoir plus de caractères que son A-label, section 4.2). Mais cette section est aussi l'occasion d'une attaque erronée contre les IDN, accusés d'augmenter la confusion des utilisateurs. D'où des conseils tout à fait inappropriés comme de montrer d'une manière spécifique les noms composés de plusieurs écritures (une pratique pourtant courante dans certains pays).

Les discussions sur cette section avaient été acharnées, avant même la création du groupe de travail, et ont donc mené à des paragraphes déroutants, bourrés d'allusions que le lecteur débutant ne comprendra sans doute pas (comme les mystérieux « risques », jamais explicités, de la section 4.4). Au moins, cette section et la 4.8 disent franchement que la question des caractères visuellement similaires n'a pas de solution technique.


Téléchargez le RFC 5890


L'article seul

RFC 5889: IP Addressing Model in Ad Hoc Networks

Date de publication du RFC : Septembre 2010
Auteur(s) du RFC : E. Baccelli (INRIA), M. Townsley (Cisco)
Pour information
Réalisé dans le cadre du groupe de travail IETF autoconf
Première rédaction de cet article le 7 septembre 2010


Pendant longtemps, les normes TCP/IP ne traitaient que le cas de machines statiques, administrées par des professionnels, et dotées de connexions matérielles et d'adresses IP stables. Le paysage aujourd'hui est bien différent, entre autres à cause des réseaux ad hoc, ces réseaux non gérés, qui se constituent au hasard des rencontres, par exemple entre deux équipements portables dont les propriétaires se croisent. On trouve même aujourd'hui des routeurs pour ces réseaux et ce court RFC introduit le problème de leur adressage. Quelles adresses IP pour des routeurs ad hoc ?

Les sections 1 et 3 définissent le problème : soit un routeur connecté à au moins un lien dont la connectivité n'est pas vraiment connue. Le matériel marche parfaitement mais on ne sait pas à l'avance si les paquets passeront. Le réseau peut marcher très bien ou il peut mal marcher ou bien encore il peut marcher par intermittence, ce qui est courant avec le sans-fil. Et ce réseau n'est pas administré par un humain compétent (pas de plan d'adressage, par exemple). Quelle adresse IP doit choisir le routeur ?

Il existe plusieurs protocoles de routage pour de tels cas (comme, par exemple, le DSR du RFC 4728 ou l'OLSR du RFC 7181, ce dernier étant plus fréquent dans les réseaux sans-fil communautaires) mais pas de mécanisme standard pour choisir les adresses du routeur. Ce RFC expose les contraintes et demandes pour un tel mécanisme, en se focalisant sur les adresses utilisées par les protocoles de routage (les applications ont également besoin que des adresses IP soit attribuées mais leurs exigences ne sont pas forcément les mêmes).

Commençons par la configuration du préfixe des adresses IP (section 4). Puisque la connectivité du lien n'est pas connue, on ne peut pas savoir quelles adresses IP sont « sur le lien » (locales au lien), à part bien sûr celle de l'interface elle-même. Donc, on ne peut rien garantir quant à la possibilité de joindre une autre adresse en un seul saut. D'où le principe posé par cette section 4 : on ne configure pas de préfixe du tout.

Et l'adresse IP du routeur ? La section 5 analyse ce cas. Les protocoles de routage qui tourneront peuvent exiger, dans certains cas, des adresses IP uniques au sein du domaine de routage (cf. RFC 1136 pour une définition de cette notion). Comme avoir une adresse IP unique satisfait tous les protocoles de routage, même les plus exigeants, la section 5 pose le principe que l'adresse IP allouée soit unique, au moins dans le domaine de routage.

Une fois ces principes posés dans les sections 4 et 5, la section 6 en vient au concret : elle sépare IPv6 et IPv4. Pour le premier (section 6.1), adresses IP uniques dans le domaine de routage et pas de préfixe configuré sur les interfaces à connectivité inconnue. Les adresses IPv6 link-local (RFC 4291, section 2.5.6) sont explicitement déconseillées : elles ne sont uniques que par lien et ne peuvent donc pas identifier un routeur et le RFC 4291 interdit nettement de transmettre les paquets ayant ces adresses comme source d'un lien à un autre. Le but d'un routeur étant de faire passer les paquets d'un lien à un autre, cela élimine ces adresses.

À noter que notre RFC 5889 ne suggère pas de solution, il pose des principes. On peut penser aux adresses ULA (Unique Local Addresses, dans le le RFC 4193) mais elles ne sont pas citées (car il n'y a pas encore d'accord sur le fait qu'il faille obtenir une adresse routable globalement ou seulement routable localement ; dans ce second cas, l'ULA serait clairement un bon choix).

En second, IPv4 fait l'objet de la section 6.2. Les règles sont presque les mêmes sauf que IPv4 ne permettant pas de dire explicitement qu'il n'y a pas de préfixe configuré pour une interface, la règle dit à la place que ce préfixe doit être de longueur 32 (et donc ne comporter qu'une seule adresse).

Les adresses locales au lien (RFC 3927) sont tout aussi déconseillées que pour IPv6, d'autant plus que, avec la faible taille de l'espace d'adressage qui leur est réservée en IPv4, elles ont encore moins de chances d'être uniques.

Merci à Emmanuel Baccelli pour sa relecture et ses commentaires.


Téléchargez le RFC 5889


L'article seul

RFC 5887: Renumbering still needs work

Date de publication du RFC : Mai 2010
Auteur(s) du RFC : B. Carpenter (Univ. of Auckland), R. Atkinson (Extreme Networks), H. Flinck (Nokia Siemens Networks)
Pour information
Première rédaction de cet article le 28 mai 2010


Changer les adresses IP utilisées par un réseau a toujours été une plaie pour l'administrateur réseaux. Il faut modifier des tas de fichiers, plusieurs configurations et on en oublie toujours. Des années après, on retrouve encore les anciennes adresses IP à des endroits inattendus (dans les documentations, par exemple). Sans compter que le changement peut mettre en jeu des partenaires extérieurs à votre organisation, par exemple parce qu'ils ont autorisé vos adresses IP dans la configuration de leur pare-feu. Bref, tout ingénieur qui a fait l'opération sait très bien qu'elle est très coûteuse.

Résultat, les gens hésitent à changer. Ils souhaitent conserver leurs adresses IP en changeant d'opérateur (les adresses PI, l'équivalent Internet de la portabilité des numéros de téléphone), ils jouent avec les règles des RIR pour garder les adresses, ils contribuent ainsi à la fragmentation de la table de routage globale.

Un certain nombre de projets de nouvelles architectures pour l'Internet, ou bien de tentatives de réduction de la taille de la DFZ repose sur l'idée que la rénumérotation d'un réseau devrait devenir banale (cf. section 1), permettant ainsi de ne garder que les noms de domaine comme identificateurs stables, les adresses IP pouvant changer sans douleur. C'était certainement l'idée originale pour la séparation entre adresses et noms mais est-ce réaliste ? Ce RFC répond qu'en tout cas, il y a du travail avant que ce ne soit le cas...

Que contient ce document ? Une analyse des mécanismes permettant ou facilitant le rénumérotation, ainsi que de leurs limites. C'est un document très concret, nourri de beaucoup d'expériences pratiques, et qui devrait intéresser tous les administrateurs réseaux. À l'IETF , espérons qu'il injectera un peu de réalisme opérationnel dans les discussions. Il succède au RFC 1900, d'où son titre dérive. Plusieurs documents ont été publiés par l'IETF sur ce sujet (cf. section 1, qui cite notamment le RFC 4192). Depuis la publication du RFC 1900 en 1996, plusieurs techniques ont été développées, qui auraient dû faire disparaître le problème (par exemple DHCPRFC 2131 et RFC 8415 ou l'auto-configuration sans état d'IPv6RFC 4862). Pourtant, le diagnostic unanime des praticiens est que le renumérotage des réseaux demeure coûteux et délicat (renuméroter une machine individuelle, par exemple celle de M. Michu chez lui, alors qu'il est abonné à un FAI grand public est, par contre, en général une opération indolore).

Quelles sont les raisons pour renuméroter un réseau entier ? La section 1 fournit de nombreux cas où c'est nécessaire :

  • Changement d'opérateur, pour les malheureux qui ont des adresses PA, la cause la plus courante,
  • Renumérotation chez l'opérateur lui-même...
  • Changement de topologie (par exemple pour tenter de récupérer quelques adresses IPv4 au fur et à mesure qu'elles s'épuisent) ou d'organisation interne (par exemple fusion de deux entreprises),
  • etc.

Dans tous ces cas, le changement est planifié à l'avance (la renumérotation non planifiée est bien plus difficile).

Enfin, pour terminer cette introduction, le RFC note que certaines solutions techniques, en séparant les adresses locales et les adresses publiques, peuvent diminuer et peut-être supprimer le besoin de renumérotation. C'est le cas du NAT, bien sûr, mais aussi de toutes les solutions fondées sur la séparation de l'identificateur et du localisateur. Mais le NAT a d'énormes défauts (voir par exemple le RFC 5128) et les techniques de séparation sont encore peu déployées.

Quelles sont les solutions techniques aujourd'hui pour faciliter la rénumérotation ? La section 2 explore les techniques du côté des machines non routeuses. Par exemple, DHCP (section 2.1) a été un grand succès en terme de déploiement et il rend la renumérotation d'une machine « terminale » presque indolore. Même chose pour l'auto-configuration sans état de IPv6 (sections 2.2 et 2.3) ou pour PPP (section 2.4, RFC 1332 et RFC 5072), ce dernier étant bien plus riche puisqu'il fournit des possibilités de négociation des paramètres comme les adresses.

La très grande majorité des interactions entre machines, sur l'Internet, commencent par une requête DNS. En effet, les machines et les services sont en général référencés par leur nom et pas par leur adresse IP. La rénumérotation d'un réseau va donc nécessiter la mise à jour des enregistrement DNS (section 2.5). Sur les sites sérieux, ces enregistrements sont typiquement mis à jour à partir d'une base de données, ce qui rend la renumérotation relativement simple. Une solution alternative est que la machine (ou le serveur DHCP) mette à jour le DNS (RFC 3007) Cette solution est largement déployée, et des outils existent pour toutes les plate-formes (comme nsupdate pour Unix).

Une limitation à l'usage du DNS pour garder des identificateurs stables (les noms de domaine) afin de pouvoir changer facilement les adresses IP est la sécurité. Celle du DNS est traditionnellement imparfaite. Au moment de la publication de notre RFC 5887, toutefois, les choses changent nettement puisque le déploiement de DNSSEC bat son plein (la racine du DNS a ainsi été signée quelques semaines avant la publication du RFC).

Encore un cran au dessus de l'utilisation des noms de domaine se trouve la découverte de services dans le DNS. C'est ainsi que SLP (RFC 2608) ou bien des solutions non-standard comme Bonjour permettent de découvrir, par exemple, l'imprimante du réseau local.

Cette section 2 était consacrée aux mécanismes utilisés par les machines non-routeuses. Et sur les routeurs ? La section 3 les étudie. Par exemple, l'option Prefix Delegation de DHCP (RFC 3633) permet d'indiquer à un routeur le préfixe IPv6 qu'il va devoir router (section 3.1). Il existe aussi un mécanisme ICMP, normalisé dans le RFC 2894, mais qui semble n'avoir jamais été déployé. Et le RFC 4191 fournit également un service intéressant d'enrichissement des Router Advertisements d'IPv6.

Le cas spécifique d'IPv6 est traité également en section 4, qui note que, contrairement à son prédécesseur, IPv6 a été prévu dès le début pour une coexistence de préfixes d'adresses sur le même réseau. Cela permet théoriquement des renumérotations plus faciles, en installant le nouveau préfixe sans supprimer l'ancien immédiatement (cf. RFC 4192). En outre, le mécanisme des ULA (RFC 4193) permet d'avoir des adresses locales uniques (ce qui n'est pas possible avec les adresses privées IPv4 du RFC 1918). D'autre part, l'existence des adresses IP temporaires du RFC 8981 fait que les mises en œuvres d'IPv6 sont normalement préparées à des fréquents changements d'adresse, ce qui devrait, en théorie, faciliter les rénumérotations.

Avec tous ces mécanismes, comment se présente en pratique la renumérotation d'un réseau ? La section 5 descend dans le concret en étudiant ce point. Du côté des machines non-routeuses, une première série de problèmes concerne la couche 3 (section 5.1.1). La grande majorité de ces machines obtient son adresse par DHCP et la garde pour la durée du bail. L'administrateur réseau compétent, qui planifie à l'avance, peut donc abaisser la durée du bail lorsque le moment de la renumérotation approche, changer le préfixe, puis remonter la durée du bail. On peut ainsi renuméroter uniquement avec DHCP. Il existe aussi une extension DHCP IPv4, FORCERENEW (RFC 3203) pour forcer une mise à jour immédiate, si on a oublié de planifier. Mais elle semble peu disponible en pratique.

DHCP n'est pas qu'une aide, il peut aussi être lui-même une source de problèmes. Il a actuellement 170 options (!) et certaines transportent des adresses IP, et la configuration de ces options doit être changée en cas de renumérotation.

L'auto-configuration sans état d'IPv6 (SLAAC - StateLess Address AutoConfiguration) permet également une renumérotation facile, d'autant plus qu'elle a moins d'options. Par contre, si on utilise SLAAC et DHCP en même temps (RFC 8415), il faut prendre garde à leur interaction, qui n'est pas normalisée avec suffisamment de précision.

DHCP et SLAAC n'aident pas si les adresses sont marquées en dur dans la machine (par exemple pour éviter de dépendre du serveur DHCP), ou bien si la machine n'a pas de client DHCP. Cela arrive dans le monde de l'embarqué où l'adresse IP doit parfois se configurer par des commutateurs DIP.

DHCP (ou bien SLAAC) permettent de changer facilement l'adresse IP. Mais cela peut perturber les autres couches. Par exemple, TCP identifie une connexion par un tuple qui comprend entre autres les adresses IP source et destination (et la somme de contrôle les utilise donc on ne peut pas facilement les changer dans le dos de TCP). Renuméroter signifie qu'on casse les connexions TCP existantes (section 5.1.2). Ce n'est pas forcément un problème pour HTTP, où les connexions sont en général courtes, mais c'est bien plus gênant pour SSH. D'autres protocoles de transport permettent par contre la renumérotation (SCTP, RFC 4960) mais ils sont peu déployés.

Continuant à grimper vers les couches hautes, le RFC note que le DNS nécessite une attention particulière (section 5.1.3). Si les données servies par le DNS sont produites à partir d'une base de données centrale, l'opération de renumérotation est relativement simple. Il faut toutefois penser à abaisser le TTL à l'avance, pour éviter, une fois le changement fait, que les vieilles informations traînent dans les caches.

Si, par contre, le DNS est géré à l'ancienne, avec des fichiers de zone édités à la main, le DNS devient alors un problème de plus en cas de renumérotation. Si le DNS, comme c'est souvent le cas, est sous-traité, il y aura en plus une étape de coordination avec l'hébergeur.

Ensuite, il y a les problèmes liés aux applications proprement dites, la couche 7 (section 5.1.4). Tous les protocoles applicatifs n'ont pas les mêmes problèmes. Le RFC 3795 avait étudié 257 protocoles IETF et découvert que 34 stockaient explicitement les adresses IP, ce qui les rend peu utilisables en cas de renumérotation. (Le plus connu est FTP, qui passe l'adresse IP dans la commande PORT , section 4.1.2 du RFC 969.) Mais l'analyse des protocoles ne suffit pas, encore faut-il étudier le comportement des applications elle-mêmes. Celles-ci stockent souvent des adresses IP, sans penser qu'elles puissent changer.

Ainsi, beaucoup d'applications font du pinning : elles résolvent le nom en adresse IP une seule fois et ne modifient plus cette information, même si l'adresse IP a changé. À leur décharge, il faut préciser que la routine standard getaddrinfo() ne fournit pas d'information de durée de vie... (Le RFC suggère aux applications de respecter le TTL du DNS en oubliant que getaddrinfo ne le transmet pas. Suivre ce conseil nécessiterait donc que les applications fassent leur propres requêtes DNS.) Idéalement, l'application devrait vérifier la validité de l'adresse (par exemple en refaisant getaddrinfo() à chaque ouverture de connexion avec une machine distante).

Les applications les plus sensibles sont celles qui restent ouvertes longtemps, comme les navigateurs Web. Ceux-ci, en général, sont conscients du problème et ne gardent l'adresse IP que pendant un temps limité mais ils épinglent parfois délibérement cette adresse, pour des raisons de sécurité Javascript (cf. section 8). D'autres applications traitent le problème (ainsi que celui, plus général, d'une connectivité imparfaite) en essayant régulièrement et sur toutes les adresses possibles (les applications pair-à-pair font souvent cela). C'est non-trivial à développer.

Les dépendances des applications vis-à-vis des adresses IP sont souvent pires : par exemple, il existe des mécanismes de licence logicielle où la licence dépend de l'adresse IP... Plus légitimes, il y aussi les cookies HTTP liés à une adresse IP. (L'annexe A donne d'autres exemples.)

Mais le RFC note aussi que, par delà la limite de getaddrinfo() citée plus haut (pas d'information sur la durée de vie d'une adresse), le problème des API est plus général : celles-ci sont en général de trop bas niveau, obligeant les applications à stocker des adresses IP ce qui, en général, ne devrait pas être nécessaire. La traditionnelle API socket, conçue avant même le DNS, est ainsi en tort. Dans le futur, il faut espérer que les programmes utiliseront des API de plus haut niveau, n'exposant pas du tout les adresses IP. C'est typiquement le cas en Java et, en C, il existe des bibliothèques pour cela comme libcurl.

Après les machines non-routeuses, place aux routeurs (section 5.2). Depuis le RFC 2072, où en sommes-nous ? Il y a eu des progrès mais des points soulevés par ce vieux RFC sont toujours d'actualité. Par exemple, pour la configuration des tunnels, bien que l'utilisation d'un nom de domaine pour configurer IPsec soit normalisée (RFC 4306, section 3.5), elle reste peu utilisée. La configuration du routeur contient ainsi les adresses IP des extrémités des tunnels, gênant ainsi la renumérotation.

La section 5.3 parcourt d'autres questions qui ne sont pas liées aux routeurs ou aux machines terminales. Par exemple, la section 5.3.4 est un excellent et très concret examen des problèmes d'administration système. La situation idéale serait que l'information sur les machines, leurs connexions et leurs adresses soient dans une base de données centrale et que tous les fichiers de configuration soient fabriqués automatiquement à partir de cette base. C'est loin d'être la réalité partout et, en pratique, la renumérotation nécessite des grands coups de grep dans /etc (voire ailleurs) pour trouver toutes les occurrences des vieilles adresses IP avant de les changer. Faites l'essai sur votre site : dans combien de fichiers sont stockées vos adresses ? Pour les règles du pare-feu, ou le DNS, vous savez sans doute les trouver. Mais il y a aussi des adresses IP à plein d'endroits surprenants, parfois chez des tiers.

Pourquoi les fichiers de configuration utilisent-ils si souvent des adresses IP lorsque des noms de domaine conviendraient ? Le RFC 1958, section 4.1, disait déjà en 1996 que c'était une mauvaise idée. C'est souvent le pur conservatisme qui empêche d'adopter cette bonne pratique. Mais il y a plusieurs bonnes raisons, l'une d'elles étant que la traduction de nom en adresse IP ne se fait souvent qu'une fois (par exemple, pour un routeur, au démarrage) et qu'il faudra donc de toute façon au moins redémarrer en cas de renumérotation. Une autre raison (RFC 1958, section 3.11), est pratique : si la configuration du routeur utilise des noms, il dépendra du DNS qui lui-même dépend du routage, créant ainsi une dépendance circulaire, source de problèmes.

Autre raison pour laquelle beaucoup d'administrateurs utilisent des adresses et pas des noms : la sécurité (section 5.3.5). Le DNS n'étant pas sûr (cf. RFC 3833), configurer un outil de sécurité, comme le pare-feu, via des noms n'est pas logique. Le déploiement de DNSSEC, plutôt rapide en ce moment, pourrait résoudre cette question.

Il reste bien des questions de sécurité liées à la rénumérotation, dans cette section 5.3.5 (voir aussi la section 8), comme le risque d'annonces de fausses adresses (presque personne n'utilise le RFC 3971) pendant l'opération, le risque lié à un pare-feu mis à jour trop tôt (et il bloquerait les anciennes adresses à tort) ou trop tard (bloquant les nouvelles adresses), les certificats X.509 contenant une adresse IP (RFC 5280)...

Quels sont les mécanismes nouveaux qui sont proposés pour faciliter les futures renumérotations, se demande la section 6 :

  • SHIM6 (RFC 5533) est un mécanisme de multi-homing (avoir plusieurs adresses et les gérer correctement) situé sur la machine non-routeuse, comme HIP, SCTP ou d'autres,
  • Le groupe de travail MANET travaille à des solutions de mobilité pour les réseaux, ce qui résoudrait en même temps la question de la rénumérotation,
  • Des protocoles comme Netconf (RFC 6241) pourraient faciliter les choses, en permettant l'administration centrale et standard des équipements réseau.

Et quels sont les « trous », les points qui manquent pour faire de la renumérotation un évenement banal et simple ? La section 7 les étudie successivement.

Il serait souhaitable, comme indiqué plus haut, que l'API indique la durée de vie d'une adresse (section 7.1). Une interface qui ne manipulerait que des noms serait encore meilleure.

Un moyen standard de stocker et de récupérer la configuration des machines serait également une grande aide (il existe déjà plein de moyens ad hoc et non standards). Cela concerne aussi bien les routeurs que les machines ordinaires, et cela pourrait utiliser Netconf.

Et peut-être pourrait-on étendre UDP et TCP de manière à les rendre multi-adresses (comme l'est SCTP).

Pour les routeurs (section 7.2), déployer enfin les RFC 2894 et RFC 3633 aiderait beaucoup.

Enfin, puisque ce RFC prend soin de ne pas oublier les considérations opérationnelles, la section 7.3 identifie les manques actuels dans ce domaine. D'abord, comme déjà cité, tant que DNSSEC n'est pas largement déployé, il sera difficile d'exiger des administrateurs système qu'ils renoncent à l'usage des adresses IP dans les fichiers de configuration.

Ensuite, nous devons pousser au déploiement de techniques d'administration système plus modernes, dépendant moins de l'édition manuelle de dizaines de fichiers avec vi.

Finalement, il reste à documenter et à écrire de jolis HOWTO sur la renumérotation d'un réseau... (Un exemple est « Preparing network configurations for IPv6 renumbering ».)

Quelques conseils pratiques personnels, tirés de l'expérience de renumérotations réussies ou ratées :

  • Planifiez bien à l'avance, en écrivant un plan et un calendrier. Une maîtrise des aspects temporels est particulièrement nécessaire avec des protocoles comme le DNS, où la vieille information peut être gardée dans les caches.
  • Il peut être intéressant d'utiliser un système d'administration centralisé comme cfengine ou puppet,
  • Pour génerer des fichiers de configuration, si on n'a pas confiance dans le DNS et donc dans les noms, si on hésite à déployer un système complexe avec base de données centrale et tout le toutim, une solution simple et légère est simplement de passer par un préprocesseur, comme cpp ou m4. On peut alors définir la correspondance nom<->adresse au début du script (voire dans un fichier central) et utiliser ensuite des noms dans la configuration.

Sur beaucoup de sites, simplement déterminer tous les endroits où l'adresse IP est marquée peut être difficile. grep aide évidemment beaucoup mais, pour des recherches dans toute une arborescence, je préfère ack-grep, par exemple, avec l'adresse IPv4 actuelle de la machine qui héberge ce blog :

% sudo ack --all 208\.75\.84\.80
apache2/vhosts.d/drupal.example.net.conf
74:     Allow from 208.75.84.80 

conf.d/net
3:config_eth0=( "208.75.84.80 netmask 255.255.255.0 broadcast 208.75.84.255" )

nsd/nsd.conf
17:        ip-address: 208.75.84.80

Pas mal : une renumérotation ne devrait pas être trop dure. Vous noterez que l'adresse IP n'apparait pas dans la configuration du pare-feu : Shorewall la trouve tout seul, supprimant un problème de mise à jour.

En conclusion, une analyse personnelle : l'état de la technique aujourd'hui, avec les grandes difficultés de renumérotation qui existent, justifie amplement l'existence des adresses PI, même si les gros opérateurs, dans leurs forums comme le RIPE-NCC, les regardent souvent comme un luxe. Comme renuméroter est difficile, s'il n'existait que des adresses PA, les utilisateurs auraient beaucoup de mal à changer de fournisseur...


Téléchargez le RFC 5887


L'article seul

RFC 5881: BFD for IPv4 and IPv6 (Single Hop)

Date de publication du RFC : Juin 2010
Auteur(s) du RFC : D. Katz (Juniper), D. Ward (Cisco)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF bfd
Première rédaction de cet article le 1 juin 2010


Le protocole de détection BFD, normalisé dans le RFC 5880, permet plusieurs applications. La plus évidente est la détection de la panne d'une machine voisine et c'est celle que normalise notre RFC 5881.

Traditionnellement, la détection de la panne d'un voisin se faisait lorsqu'il arrêtait d'envoyer certains messages, par exemple les paquets Hello pour un voisin OSPF. Mais cette méthode est souvent lente. BFD (RFC 5880) spécifie un mécanisme générique de détection, indépendant des protocoles de routage et du lien physique. BFD permet plusieurs applications dont, pour notre RFC 5881, la connectivité avec un voisin immédiat (« immédiat » au sens IP, pas forcément au sens physique). Cette application fonctionne avec IPv4 ou IPv6, mais sur des sessions BFD séparées.

Si la fonction d'écho de BFD est employée, la section 2 note qu'il faut penser à désactiver les filtres du RFC 2827, incompatibles avec la façon dont cette fonction marche.

À quoi ressemblent les paquets de cette application ? Comme indiqué en section 4, ce sont des paquets UDP utilisant le port 3784 - et 3785 pour la fonction d'écho. BFD emploie IP de manière assez... créative et nécessite donc des précautions particulières, notamment pour éviter que des paquets de redirection (ICMP redirect) soient envoyés. Ainsi, la section 4 prévient que l'adresse IP source, paradoxalement, ne devrait pas être une adresse légale du sous-réseau utilisé (ni, en IPv6, une adresse locale au lien). Mettre en œuvre BFD, sur certains systèmes d'exploitation, peut donc être difficile, puisque ce protocole nécessite de court-circuiter pas mal de fonctions normales d'IP.

La section 5 précise les TTL à utiliser. Si on ne se sert pas des fonctions d'authentification de BFD, il faut limiter les risques d'usurpation en mettant un TTL de 255, la valeur maximale. Comme le TTL est diminué par chaque routeur, la réception d'un paquet avec ce TTL prouvera que le paquet vient bien du lien local (cf. section 9 et RFC 5082).


Téléchargez le RFC 5881


L'article seul

RFC 5880: Bidirectional Forwarding Detection

Date de publication du RFC : Juin 2010
Auteur(s) du RFC : D. Katz (Juniper Networks), D. Ward (Cisco Systems)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF bfd
Première rédaction de cet article le 1 juin 2010


Le tout nouveau protocole BFD est un protocole très générique de test de la liaison entre deux routeurs, de manière à ce qu'ils puissent déterminer qu'ils sont encore capables de se passer des paquets. Son originalité est d'être indépendant du type de liaison physique, ainsi que des protocoles de routage.

Les routeurs ont toujours besoin de savoir si les autres routeurs sur le même réseau sont joignables, afin de pouvoir calculer une route alternative. Certaines liaisons physiques fournissent très rapidement une indication en cas de panne (SONET), d'autres peu ou pas du tout (Ethernet). Les routeurs utilisent donc en général une fonction du protocole de routage, comme la fonction Hello de OSPF. Le principe est de s'envoyer des messages régulièrement. Si on n'a pas entendu un routeur voisin depuis deux ou trois périodes, c'est qu'il est en panne (section 1 du RFC). Mais ces mécanismes ne fonctionnent que s'il y a un protocole de routage (ce n'est pas toujours le cas, il existe des routes statiques), ils ne testent que la communication entre les control engines des routeurs, la partie qui gère les protocoles de routage, pas la communication entre les forwarding engines, la partie qui commute effectivement les paquets (ces deux parties sont souvent radicalement séparés sur un routeur et peuvent donc tomber en panne séparement). Enfin, ces mécanismes sont typiquement trop lents à détecter les pannes.

D'où BFD, présenté dans la section 2 de notre nouveau RFC. BFD est une fonction du forwarding engine pour être sûr qu'il teste la capacité des routeurs à transmettre les paquets, et pour survivre au redémarrage d'un protocole de routage. Il ne dépend pas de fonctions du lien physique comme la diffusion, pour pouvoir fonctionner sur tous les types de liens physiques.

La section 3 décrit le fonctionnement du protocole. Comme les autres systèmes de type Hello, chaque routeur BFD envoie périodiquement à ses voisins des paquets pour dire « Tout va bien ». Lorsqu'on ne les reçoit plus, on sait que le routeur est planté. La durée entre deux paquets est modifiable dynamiquement, afin de garantir un temps de détection de panne aussi court que possible, sans pour autant trop surcharger le réseau par des paquets Hello.

BFD a deux modes de fonctionnement (section 3.2), asynchrone, où chaque routeur envoie ses paquets Hello sans se préoccuper de l'autre et synchrone (Demand mode, cf. section 6.6) où le routeur n'envoie rien par défaut, il attend une sollicitation « Tu es toujours là ? ». En outre, BFD dispose d'une fonction Echo où le routeur qui reçoit un paquet BFD répond aussitôt. Cette fonction est utilisable avec les deux modes. Elle peut être coûteuse en nombre de paquets mais elle teste réellement tout le chemin à travers le forwarding plane (la machinerie qui commute et transmet les paquets) du routeur cible. La même section 3.2 discute les avantages et les inconvénients de chaque mode, ainsi que ceux d'une utilisation de la fonction Echo (sur cette fonction, voir aussi les sections 5 et 6.4, qui précise notamment qu'echo est asymétrique, elle peut être activée dans une direction seulement).

Les paquets BFD sont envoyés dans le contexte d'une session et l'établissement de cette session nécessite un mécanisme de contrôle. Le format des paquets qui le réalisent est exposé en section 4. Un paquet BFD a plusieurs champs (section 4.1) dont deux discriminateurs, des nombres qui identifient les sessions à bord des deux routeurs (chaque paquet comprend le discriminateur mis par la source et, s'il est connu, celui pertinent pour la destination ; le discriminateur identifie la session, pas le routeur). Une authentification simple est possible (sections 4.2 à 4.4 et 6.7).

Une fois le format défini, que doivent faire les deux routeurs pour envoyer et traiter correctement les paquets BFD ? C'est l'objet de la section 6. D'abord, il faut décider de lancer le service. Un des routeurs le sollicite, il est actif (l'autre est passif). L'actif envoie des paquets de contrôles, informant de son désir de commencer une session, et indiquant le discriminateur (cf. section 6.3). Des paramètres comme le mode (synchrone ou asynchrone) et le rythme d'envoi de paquets (section 6.8.2) sont alors négociés. L'envoi de paquets continue alors, selon les paramètres sélectionnés. La session est considérée comme en panne s'il n'y a pas de réponse.

La machine à états du protocole (très simple) est décrite en section 6.2.

Enfin, en pratique, l'expérience du déploiement d'autres protocoles justifie qu'une section, la 7, soit consacréee aux problèmes opérationnels. Par exemple, les paquets BFD circulant directement sur la couche 2, sans passer par un protocole de couche 3 (ce qui sera sans doute un cas courant), risquent d'être bloqués par certains pare-feux et il faut donc veiller à la configuration de ceux-ci. Il y a aussi un problème analogue pour tous les mécanismes de shaping. Limiter le rythme de transmission des paquets BFD (qui doivent normalement être considérés comme du trafic temps réel) pourrait interférer avec leur fonction de détection des pannes.

Autre question pratique de grande importance, la sécurité. Si tout se passe bien, BFD deviendra une partie essentielle de l'infrastructure réseau. Une attaque contre BFD pourrait donc avoir des effets très étendus, par exemple en réalisant une DoS si un attaquant peut bloquer la réception des paquets BFD. D'où la section 9 sur la sécurité. Ainsi, pour ne citer qu'un exemple, si on fait passer BFD sur un protocole de couche 3 comme IP, un paquet BFD imité, avec une fausse adresse IP source, serait trivial à fabriquer et à envoyer au routeur victime. Lorsque les routeurs parlant BFD sont adjacents (situés sur le même réseau physique), il faut donc mettre le TTL à la valeur maximale et vérifier qu'elle n'a pas été décrémentée (technique GTSM, décrite dans le RFC 5082).

Et les implémentations ? Les routeurs Juniper l'ont depuis longtemps (version 8.3 de JunOS), ainsi que les Brocade et les Cisco. Pour les deux premiers, BFD fonctionne aussi en multi-hop, cf. RFC 5883. Voici par exemple sur un Brocade :

telnet@ro=1#show bfd neighbors bgp
Total Entries:8 R:RxRemote(Y:Yes/N:No)H:Hop(S:Single/M:Multi)
....

Il y a aussi une implémentation dans Linux avec kbfd et une autre libre, OpenBFDd. Merci à Ludovic Boué pour ses précisions.


Téléchargez le RFC 5880


L'article seul

RFC 5870: A Uniform Resource Identifier for Geographic Locations ('geo' URI)

Date de publication du RFC : Juin 2010
Auteur(s) du RFC : A. Mayrhofer (IPCom), C. Spanring
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF geopriv
Première rédaction de cet article le 7 juin 2010
Dernière mise à jour le 7 juillet 2010


Ce RFC normalise un nouveau plan pour les URI, geo, qui permet de représenter l'information concernant la latitude et la longitude sous la forme d'un URI, par exemple geo:13.4125,103.8667.

Le projet « plan geo » est un vieux projet de normalisation des URI de localisation géographique. En l'absence d'un tel plan, beaucoup de gens utilisaient des URI http comme ceux de Google Maps, ou bien des mécanismes spécifiques à un certain format (cf. section 1 du RFC). Ainsi, la cathédrale Saint-Étienne à Vienne, qui se notait souvent http://maps.google.com/maps?f=q&source=s_q&hl=fr&sspn=0.355096,0.500565&ie=UTF8&ll=48.208223,16.372687&spn=0.00281,0.003911&t=h&z=18 sera désormais geo:48.208333,16.372778. Un tel URI est-il utilisable ? Oui, si on a l'extension Firefox appropriée (cf. http://geouri.org/2007/02/26/firefox-extension-handles-geo-uri/ mais la version actuelle est bien vieille et ne marche pas avec les Firefox récents). Comme expliqué par la section 5 du RFC, on pourrait imaginer d'autres applications. Un tel mécanisme va certainement aider tous ceux qui manipulent des informations géographiques sur l'Internet, par exemple le remarquable projet OpenStreetMap qui permettrait d'écrire le lien ci-dessus http://www.openstreetmap.org/?lat=48.208333&lon=16.372778&zoom=40.

D'autres exemples et scénarios d'usage figurent dans la section 6. Outre la création d'hyperliens classiques pointant vers un service de cartographie (section 6.2), on peut imaginer des code-barres 2D codant un URI geo (section 6.3) et permettant à un smartphone avec un GPS d'afficher l'itinéraire vers l'endroit indiqué.

Les sections 1 et 2 exposent les principes de base de ce plan, notamment le choix du système de coordonnées WGS 84, entre autre parce que c'est celui du GPS. La syntaxe des URI permettra l'indication d'autres systèmes plus tard mais, pour l'instant, WGS 84 est le système officiel. Dans WGS 84, un point est représenté par une latitude, une longitude et une altitude.

La section 3 est l'enregistrement officiel du plan auprès de l'IANA dans le registre des plans d'URI, suivant les règles du RFC 4395. Elle inclus la syntaxe formelle des URI (section 3.3). De manière résumée, un URI geo comprend la chaîne de caractères geo: suivie de deux ou trois nombres, séparés par des virgules. Le premier est la latitude (en degrés décimaux), le second la longitude (idem) et le troisième (optionnel) l'altitude (en mètres). Ainsi, geo:90.0,0.0,100 désigne un point à cent mètres au dessus du Pôle Nord (cf. section 3.4.2 pour les détails et, attention, WGS 84 mesure l'altitude par rapport au géoïde, pas par rapport au niveau de la mer, cf. section 3.4.5).

Un paramètre optionnel (et dont l'usage est actuellement déconseillé), crs=, permettra d'indiquer d'autres systèmes de coordonnées que WGS 84. Un autre paramètre optionnel, u= indique l'incertitude sur la mesure (section 3.4.3).

Une utilisation courante des URI est la comparaison. Ces deux URI sont-ils équivalents ? La section 3.4.4 répond à cette question, moins évidente qu'il n'y parait. La comparaison de deux URI geo ne signifie pas en effet qu'ils désignent le même point (ce qui serait trop compliqué à déterminer) mais est plus restrictive que cela : deux URI geo sont identiques si tous les nombres sont rigoureusement les mêmes. Donc, geo:45.0,-10.0 est identique à geo:45,-10 mais la fonction de comparaison n'essaie pas d'utiliser le paramètre u= (l'incertitude) pour considérer que deux points sont proches... (Voir aussi la section 6.4.)

À noter qu'il existe déjà des moyens de noter une position géographique dans un langage formel. Une des plus connues est GML et la section 7 indique comment convertir entre les URI geo et les éléments <Point> de GML. Ainsi, le code GML :


<gml:Point srsDimension="2" srsName="urn:ogc:def:crs:EPSG:6.6:4326">                                                       
                        <gml:pos>49.40 -123.26</gml:pos>
                  </gml:Point>

deviendrait l'URI geo:49.40,-123.26. Et, si vous vous demandez où c'est, voyez http://www.openstreetmap.org/?lat=49.4&lon=-123.26&zoom=10.

Même si le RFC ne le cite pas, il y avait aussi le mécanisme ICBM addresses, plus primitif (apparemment pas de norme écrite, pas d'indication de l'altitude, résolution plus faible...)

Deux nouveaux registres IANA créés (sections 4 et 8), pour stocker les paramètres possibles et les valeurs admises pour les paramètres : https://www.iana.org/assignments/geo-uri-parameters/geo-uri-parameters.xhtml.

Les mises en œuvre de ce RFC sont encore rares et une liste figure sur le site de référence. Mais les progrès que ce plan d'URI sont cruciaux : Comme le note Nicolas Krebs, utiliser geo: permet de s'affranchir d'un fournisseur. Ce plan d'adresse est neutre quand au service cartographique utilisé. C'est l'utilisateur qui fait ce choix. geo:48.208333,16.372778 est à http://maps.google.com/maps?ll=48.208223,16.372778 ce que news:hrctmq$ua8$1@news.le-studio75.com (RFC 5538) est à http://groups.google.com/group/fr.usenet.divers/msg/cf1d3bd076ba6559.


Téléchargez le RFC 5870


L'article seul

RFC 5867: Building Automation Routing Requirements in Low Power and Lossy Networks

Date de publication du RFC : Juin 2010
Auteur(s) du RFC : J. Martocci (Johnson Controls), Pieter De Mil (Ghent University), W. Vermeylen (Arts Centre Vooruit), Nicolas Riou (Schneider Electric)
Pour information
Réalisé dans le cadre du groupe de travail IETF roll
Première rédaction de cet article le 12 juin 2010


Nouveau « cahier des charges » du groupe de travail ROLL de l'IETF, ce RFC décrit les exigences du protocole de routage des réseaux difficiles (peu de courant et beaucoup de parasites), pour le cas des immeubles de bureaux. Le cas de la maison avait été traité dans le RFC 5826.

Les immeubles de bureaux sont remplis de systèmes techniques complexes, collectivement dénommés HVAC (pour Heating, Ventilation and Air Conditioning, même s'il faut ajouter les ascenseurs, les alarmes incendie, l'éclairage, etc). Ces systèmes tendent de plus en plus à être informatisés, puis à communiquer entre eux, ou bien avec une centrale de contrôle. Les exigences particulières de cet environnement (par exemple le fait que certains appareils fonctionnent sur batterie et ne doivent donc pas gaspiller l'énergie) font que les mécanismes de routage IP traditionnels ne sont pas forcément adaptés.

Autrefois, de tels systèmes étaient connectés, comme le rappelle le RFC, par un lien pneumatique, maintenant, c'est un réseau informatique local, qui doit pouvoir être partitionné en sous-réseaux, reliés par des routeurs. Notre RFC se penche donc sur le futur protocole de routage.

J'ai parlé d'une centrale de contrôle. En fait, il s'agit d'un système de contrôle bien plus complexe, en général dénommé FMS (pour Facility Management System, en Europe, on dit plutôt BMS pour Building Management System, et GTB en français) et qui a la lourde responsabilité de piloter des immeubles allant jusqu'au gratte-ciel de cent étages et de cent mille mètres carrés de surface totale (à noter que le RFC, suivant les mœurs du BTP états-unien, utilise encore les pieds carrés...) ou bien à des immeubles très complexes comme le Pentagone.

La section 3 du RFC décrit l'organisation générale d'un FMS. En 3.2, on découvre le bestiaire qui peuple un immeuble de bureaux (capteurs, contrôleurs, etc). En 3.3, les méthodes utilisées pour l'installation de cet équipement. Le réseau informatique traditionnel est installé en commençant par le câblage, puis les équipements actifs, puis enfin les terminaux. Le FMS, au contraire, croît à partir d'équipements installés immédiatement, puis connectés petit-à-petit et ensuite reliés aux systèmes centraux, voire au réseau informatique « normal » (voir aussi section 5.6). Les raisons de cette méthode sont en bonne partie organisationnelles : tous les corps de métier n'accèdent pas au bâtiment en même temps. D'autre part, certains systèmes de sécurité (comme la détection incendie) doivent être en place très tôt dans la vie de l'immeuble, avant qu'on ne branche l'électricité partout. Le système de détection du feu ne peut donc pas compter sur des serveurs DNS ou DHCP déjà en place.

Enfin, la section 3.4, très détaillée et où le lecteur informaticien qui n'a pas d'expérience du bâtiment apprendra bien des choses, explique les problèmes spécifiques liés à la densité des machines. Par exemple, la tendance actuelle à la vidéo-surveillance a nettement accru le nombre de caméras, et celles-ci sont inégalement réparties. Autrefois, de tels systèmes utilisaient des réseaux fermés mais, aujourd'hui, c'est de plus en plus souvent un bête réseau IP qui connecte les caméras. (Elles posent d'autres problèmes, comme le débit de données important qu'elles fournissent, par rapport aux équipements FMS traditionnels.)

Tiens, à propos de capacité nécessaire, quelles sont les caractéristiques du trafic des équipements de l'immeuble ? La section 4 analyse quantitativement (200 octets pour un message typique au contrôleur, envoyé toutes les minutes..., 30 % des paquets restent sur le réseau local et 70 % ont besoin d'être routés...) et qualitativement (lors d'une coupure de courant, le plus dur est la reprise, lorsque les machines alimentées par batterie vont tout à coup essayer de transmettre les données qu'elles avaient stockées) le trafic sur le réseau du FMS.

Puis le cœur de notre RFC, la section 5, expose le cahier des charges proprement dit. Comme l'installation est souvent faite par des non-informaticiens (des électriciens, par exemple), tout le réseau doit pouvoir être auto-configurable, sans aucune action humaine (section 5.1.1). Le routage doit pouvoir commencer tout de suite (section 5.1.2), sans intervention d'un administrateur réseaux.

Le réseau doit pouvoir fonctionner pour des immeubles de cent mille mètres carrés. Le RFC demande que les protocoles marchent avec des réseaux de deux mille machines, dont la moitié routent des paquets pour le compte des autres (section 5.2.1). Un sous-réseau (par exemple une pièce) doit accepter 255 machines. Et chaque machine doit pouvoir parler directement à n'importe quelle autre, en pair-à-pair. Par exemple, si les tours de refroidissement sont sur le toit et le refroidisseur dans le sous-sol, vue sa taille, ils doivent néanmoins pouvoir se parler (section 5.2.2).

La plupart des machines dans l'immeuble sont fixes, accrochés au mur ou dans un faux plafond. Il n'y a donc pas d'énormes exigences de mobilité (section 5.3). Toutefois, les équipements mobiles se répandent et le RFC ajoute donc quelques demandes pour eux :

  • Possibilité d'exclure les engins en déplacement des fonctions de routeur (section 5.3.1),
  • Moins de cinq secondes après un déplacement pour pouvoir parler sur le réseau à nouveau, si on est restés sur le même sous-réseau (et dix autrement),

Les équipements de l'immeuble sont souvent très limités dans leurs ressources matérielles. La section 5.4 liste donc les règles à suivre pour ne pas les épuiser :

  • Le logiciel doit pouvoir tourner sur un processeur 8-bits avec 128 ko de mémoire flash (section 5.4.1), et sur 256 ko si la machine sert à router les paquets (avec seulement 8 ko de RAM),
  • Un capteur typique doit pouvoir durer cinq ans avec une batterie de 2000 mAh (pour un transmetteur de 25 ma et une émission par minute, section 5.4.3). Le logiciel doit donc absolument être économe et ne pas provoquer des émissions inutiles. Le RFC demande de garder un message (et de retransmettre) pendant au moins 20 secondes si le destinataire ne répond pas (il peut être en train de dormir pour économiser sa batterie).

Il existe aussi des exigences pour la sélection des routes. Ainsi, le RFC demande que les applications prioritaires (alarme incendie, par exemple) puissent prendre le pas sur les autres (section 5.7.7).

Enfin, le cahier des charges se conclut par une longue section sur la sécurité (section 5.8). D'abord, s'il y a une configuration de la sécurité, celle-ci doit pouvoir être faite via le réseau (beaucoup d'équipements seront en effet peu accessibles). Cette configuration par le réseau est délicate à réaliser mais nécessaire puisque le même équipement peut être installé dans des immeubles aux règles de sécurité très variables (petite entreprise banale vs. bâtiment Seveso). Idéalement, toute communication devrait être chiffrée, puisqu'on ne peut pas espérer qu'il n'y ai jamais de méchant indiscret sur le trajet. Mais, d'un autre côté, les équipements installés dans l'immeuble ont souvent des moyens limités et la cryptographie coûte cher. Le RFC demande donc simplement que les deux arguments, de sécurité et d'économie, soient pris en considération.

Une autre règle sur le chiffrement (section 5.8.3) est que les protocoles développés par le groupe ROLL doivent inclure le chiffrement mais cela n'implique pas que l'implémentation le permette, ni que le responsable sécurité l'active obligatoirement.

Un cahier des charges tourne toujours facilement à la « lettre au Père Noël », où on accumule des dizaines de demandes toutes plus irréalistes que les autres. La valeur d'un bon cahier des charges n'est donc pas dans les demandes mais plutôt dans ce que les auteurs ont eu le courage d'écarter. Pour ce RFC, ces exigences non retenues ont fini dans l'annexe A : intéressantes idées mais qui ne sont pas considérées par le groupe de travail ROLL comme obligatoires. Par exemple, la section A.3.5 dit que cela serait sympa si le protocole de routage permettaient à certains routeurs, les plus limités en mémoire, de ne garder qu'une partie des routes. La A.4.1 voudrait bien imposer une limite basse de capacité à 20 Kb/s...

Merci à Nicolas Riou pour sa relecture (mais, bien évidemment, les erreurs sont de moi).


Téléchargez le RFC 5867


L'article seul

RFC 5863: DomainKeys Identified Mail (DKIM) Development, Deployment and Operations

Date de publication du RFC : Mai 2010
Auteur(s) du RFC : T. Hansen (AT&T Laboratories), E. Siegel, P. Hallam-Baker (Default Deny Security), D. Crocker (Brandenburg InternetWorking)
Pour information
Réalisé dans le cadre du groupe de travail IETF dkim
Première rédaction de cet article le 27 mai 2010


Le mécanisme de signature (et donc d'authentification) du courrier DKIM a été normalisé dans le RFC 4871 puis dans le RFC 6376. Ce nouveau RFC fait le point sur les aspects pratiques du déploiement de DKIM. Il ne s'agit pas encore vraiment d'un retour d'expérience (DKIM n'est pas encore assez utilisé pour cela) mais plutôt d'une collection de points auxquels il faut prêter attention quand on développe du logiciel DKIM ou quand on déploie DKIM.

La section 2 considère le problème générale d'authentification : que garantit DKIM exactement ? La lutte anti-spam aujourd'hui est unilatérale : le destinataire accepte ou refuse selon ses critères. Ces critères sont arbitraires, souvent absurdes (comme la vérification de l'enregistrement PTR) et produisent aussi bien des faux positifs que des faux négatifs. DKIM tente d'introduire une notion de confiance entre deux parties qui essaient de communiquer. L'expéditeur signe ses messages et, après vérification de sa signature, il peut espérer une délivrance déterministe de ses messages. Bon, cet objectif est loin d'être réalisé, mais c'est l'idée (exprimée en des termes très abstraits, qui sont la marque de l'auteur Philip Hallam-Baker, qui n'est pas toujours facile à suivre).

Donc, DKIM permet d'identifier et d'authentifier une organisation responsable (Responsible Identifier, dit le RFC). Celle-ci peut être précise et affecter une étiquette particulière à différents types de messages (par exemple, pour un vendeur en ligne, le courrier de confirmation des commandes peut etre étiqueté différemment du courrier publicitaire, ce dernier ayant probablement une moins bonne réputation). Bien sûr, cette authentification ne dit pas que le message est véridique, correct ou intéressant. Elle dit simplement que telle organisation en prend la responsabilité (et elle permet de vérifier qu'il n'y a pas d'usurpation). Le dessin de la section 2.1 illustre la complexité des relations entre les différents acteurs.

À noter que, pour DKIM, « le message » inclus les en-têtes comme From: donc DKIM ne garantit pas du tout que le courrier prétendant venir de faispaslemalin@elysee.fr vient vraiment de l'Élysée. (Ce point va probablement dérouter beaucoup d'utilisateurs, cf. section 2.4, qui insiste bien sur le fait que l'identité DKIM peut n'avoir aucun rapport avec les identités existantes dans le message.)

Alors, justement, qui est responsable du message ? Ce point est couvert dans la section 2.2, choix des paramètres. Il en existe plusieurs dans DKIM (s=, d= et i=) et la confusion avait même nécessité la sortie d'un RFC de correction, le RFC 5672. Donc, pour résumer, c'est le paramètre d= qui est le seul obligatoire et qui doit donc être rempli. Voici un exemple d'un message envoyé sur une liste de diffusion, par un utilisateur du domaine assysm.com :

DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=cru.fr;
        h=from:sender:reply-to:subject:date:message-id:to:cc:list-id:list-help:list-unsubscribe:list-subscribe:list-post:list-owner:list-archive:in-reply-to:references:resent-date:resent-from:resent-sender:resent-to:resent-cc:resent-message-id:mime-version:content-type:content-transfer-encoding:content-id:content-description; 
        s=lists; i=smtp-fr-request@cru.fr;
        bh=uoq1oCgLlTqpdDX/iUbLy7J1Wic=;
        ...

On n'y voit pas du tout le domaine expéditeur (qui ne signe probablement pas avec DKIM) mais par contre le service de listes de diffusion du CRU, Universalistes, a signé et engagé sa réputation. Le d=cru.fr indique que le CRU est responsable, le i=smtp-fr-request@cru.fr (facultatif) indique une responsabilité plus précise, celle de la liste smtp-fr. Attention, le fait qu'elle ressemble à une adresse de courrier ne doit pas faire illusion, ce n'est pas forcément une adresse utilisable. Il faut résister à la tentation d'analyser ce paramètre, il peut être différent selon les services. Il faut le traiter comme opaque.

Justement, quel nom de domaine choisir pour mettre dans les paramètres ? Comme dans l'exemple précédent, le signeur n'est pas forcément l'auteur, il peut être un fournisseur ou un intermédiaire. La section 2.3 explore en détail la question du choix du nom de domaine. Ainsi, pour une compagnie qui envoie des messages de différents types, la méthode recommandée est d'avoir plusieurs noms (par exemple transaction.example.com pour les messages de confirmation de commande mais newsletter.example.com pour la publicité) mais pas trop. Un seul nom (example.com) ne permettrait pas de distinguer entre la propagande du service Communication et les messages sérieux. Trop de noms et la situation devient confuse et un service ne peut plus bénéficier de la réputation des autres.

Si un fournisseur (ici example.net) gère le courrier et signe pour plusieurs de ses clients, il est logique d'utiliser un nom par client (bigbank.example.net, pornvendor.example.net, viagravendor.example.net, etc). Si l'un d'eux est un spammeur, cela n'affectera pas les autres. Une autre possibilité serait de les classer selon ce qu'ils ont payé (free.example.net, business.example.net et firstclass.example.net).

Après ces problèmes de haut niveau, la section 3 se consacre à une question récurrente dès que la cryptographie est en jeu : la gestion des clés. DKIM n'est pas une PKI classique car la distribution et la « certification » des clés sont toutes les deux faites par le DNS. L'existence d'une signature DKIM valide indique donc finalement que le gérant de la zone DNS en question a authentifié ce message. Mais cela suppose que les bonnes pratiques de sécurité et de cryptographie aient été utilisées partout. Par exemple, si le gérant de la zone DNS gère sa zone via une interface Web en PHP avec injection SQL incluse, son authentification ne vaut plus grand'chose. Même chose s'il laisse trainer la clé privée DKIM n'importe où. La section 3.1 couvre ce dernier cas : protégez vos clés, utilisez un HSM si possible, n'utilisez pas de système de séquestre, etc. À noter, bien que le RFC n'en parle pas, que le destinataire d'un message n'a aucun moyen de savoir si ces bonnes pratiques ont été suivies ou pas par l'expéditeur...

Ensuite, la distribution de la clé publique dans le DNS (section 3.2). Ici, le gérant de la zone doit s'assurer que la zone est raisonnablement sécurisée, et contient bien les bons enregistrements DKIM, ce qui est d'autant plus difficile que le serveur de courrier (qui signe avec DKIM) et le serveur DNS sont souvent gérés par des équipes distinctes. Les deux groupes doivent donc se coordonner soigneusement.

Le DNS n'étant lui-même pas sans failles, l'utilisation de DNSSEC (RFC 4034) est recommandée. Si on utilise les NSEC3 du RFC 5155, il ne faut pas choisir l'option opt-out, qui permettrait l'insertion de clés pirates, par exemple pour des sélecteurs DKIM choisis par l'attaquant.

La complexité est souvent le pire ennemi de la sécurité, or DKIM dispose d'un mécanisme complexe pour permettre des signatures par utilisateur et non plus juste par domaine. Les précautions à prendre lors de l'utilisation de ce mécanisme figurent en section 3.3. Là encore, un des pièges est que le destinataire ne connait pas la politique de gestion des utilisateurs du domaine expéditeur et ne peut donc pas savoir si elle est laxiste ou au contraire très rigoureuse.

Le processus de signature lui-même est ensuite couvert dans la section 4. Le module de signature peut être placé à de nombreux endroits, le plus évident étant le MTA de sortie de l'organisation, ce qui simplifie le déploiement. Par contre, cela offre moins de souplesse, moins de possibilités de réglages que si la signature se fait dans les MUA des utilisateurs. Dans les deux cas, comme la politique de l'organisation va changer au cours du temps, le RFC recommande que les choix (par exemple, quel sélecteur utiliser) soient disponibles dans la configuration plutôt que placés en dur dans le code.

Et la vérification, à l'autre bout, lorsque le message est reçu ? Quels sont les pièges à éviter ? Par exemple, la section 5.1 insiste sur un point : un message dont la signature est invalide doit être traité comme s'il n'avait pas de signature du tout. Il ne doit pas être moins bien traité car la signature invalide peut être due à bien des problèmes, pas toujours sous le contrôle de l'émetteur. (En outre, bien que le RFC n'en parle pas, les risques d'erreur lors de la signature étant nombreux, traiter moins bien les messages avec une signature invalide découragerait les premiers adopteurs de DKIM, en leur faisant payer cher une erreur, qui les ferai mettre après ceux qui n'essaient même pas de signer.) Et le message à signature invalide ne doit pas être mieux traité que celui sans signature car, dans ce cas, les méchants mettraient simplement des signatures invalides dans leurs messages. Donc, le programme de vérification peut traiter plus favorablement les messages à signature valide mais il doit être neutre pour ceux à signature invalide.

Un autre piège, traité très vite et de manière très sommaire par le RFC, est que l'option l= permet de ne signer qu'une partie d'un message et qu'une attaque possible est donc de rajouter du texte à un tel message. Le RFC ne propose pas de solution. On pourrait imaginer un MUA qui n'affiche pas du tout la partie non couverte par la signature, ou bien qui l'affiche d'une manière particulière (en violet sur fond rouge ?).

Un autre piège, conséquences des risques cités plus haut sur la sécurité du DNS et de la clé privée, est qu'un destinataire oublie que la sécurité de DKIM dépend d'un certain nombre de facteurs... qui ne sont pas forcément présents (section 5.3). Par exemple, une signature valide sur un message qui ne l'est pas est possible si l'expéditeur s'est fait copier sa clé privée, ou si son hébergement DNS s'est fait pirater, ou tout simplement si une des procédures de justice privée qui abondent dans le monde des noms de domaine, comme l'UDRP, lui a fait perdre son nom de domaine.

Enfin (mais il existe d'autres pièges, mentionnés dans le RFC), l'existence d'intermédiaires pas toujours respectueux du message (par exemple les MLM) complique encore la vérification, et les conclusions qu'on peut en tirer.

Pour aider les vérificateurs, la section 6 se lance dans une taxonomie des signatures, selon les cas les plus courants. Ainsi, on peut trouver le cas le plus simple et le plus évident, la signature mono-domaine (section 6.1), où l'organisation signe ses propres messages avec son propre domaine. Ainsi, la société Toto, qui détient le domaine toto.example, aura à la fois des From: USER@toto.example et une signature en d=toto.example. Mais il existe aussi des cas plus compliqués comme le cas où la signature est faite par une tierce partie (section 6.3, voir aussi la 7.5), par exemple un « fournisseur de réputation » qui, en signant les messages, « garantirait » la valeur de ces messages. À noter que, pour DKIM, la signature du courrier From: smith@company.example par un d=company.example (signature mono-domaine) ou bien par d=rep-provider.example (signature par un tiers) sont exactement équivalentes : DKIM lui-même ne privilégie pas un cas plutôt qu'un autre.

Puisque plusieurs cas sont possibles, peut-on les combiner et avoir plusieurs signatures DKIM pour un message ? Oui, dit la section 6.5 qui rappelle que, non seulement c'est légal, mais que cela peut être parfaitement raisonnable dans certains cas (par exemple, signature par l'organisation émettrice et par un fournisseur de réputation).

Cela vaut la peine de le répéter : DKIM fournit uniquement un moyen de s'assurer qu'une organisation (identifiée par un nom de domaine) valide un message. DKIM est un mécanisme, pas une politique, et ne dit pas qui doit signer (comme l'indique la section 6, il y a plusieurs possibilités raisonnables) ni ce que le récepteur doit faire lorsqu'un message est signé et valide. La section 7 illustre cette « neutralité » de DKIM par plusieurs exemples d'usages, incluant la publication des politiques de signature par ADSP (RFC 5617).

La très ancienne expérience de la cryptographie dans l'Internet indique qu'il y aura certainement des problèmes avec DKIM. La section 8 cite quelques cas qui seront probablement délicats comme le cas d'une personne en voyage professionnel qui essaie d'envoyer du courrier en passant par le MTA du FAI de son hôtel, qui n'a pas la clé privée de la société de cette personne... Un problème similaire survient avec les services du type « Envoyez cette information à un ami » où le service qui propose cette fonction n'a pas de clé privée correspondant au domaine que l'utilisateur indiquera dans son adresse. DKIM ne fournit pas de solution à ce problème.

Ainsi, même les cas qui semblent simples et banals peuvent provoquer des surprises. La section 8.2 mentionne le problème de l'authentification du courrier d'une organisation, par cette même organisation. Surement, une organisation qui signe tout avec DKIM peut rejeter le courrier entrant qui prétend venir d'elle, mais qui n'a pas de signature ? Mais c'est plus compliqué que cela, en raison des programmes qui modifient les messages (et peuvent invalider une signature), ainsi qu'en raison des messages envoyés par le VRP itinérant cité plus haut.

Certains choix peuvent rendre l'utilisation de DKIM encore plus difficile. Par exemple, l'authentification par utilisateur, quoique parfois citée par certains enthousiastes partisans de DKIM, risque fort d'être peu praticable, pour les raisons expliquées en section 8.3 : il y a peu d'intérêt à maintenir une base de réputation par utilisateur (on peut imaginer un récepteur qui fasse confiance au courrier d'amazon.com, on a plus de difficulté à concevoir un récepteur qui fasse confiance à smith@amazon.com mais pas à jones@amazon.com), et le coût d'une telle signature par utilisateur (distribuer les clés, garantir leur sécurité, les mettre à jour) serait énorme.

Et les logiciels ? Après tout, ils sont en première ligne dans le déploiement de DKIM et plus d'une mesure de sécurité a été annulée par un mauvais logiciel. Les sections 8.4 et 8.5 rassemblent les analyses sur le rôle desdits logiciels. Par exemple, l'usage des MUA pour signer est découragé, car les MUA ne sont pas en général sous le contrôle direct de l'organisation, contrairement aux MTA, et sont souvent situés sur des machines compromises.

Enfin, pour continuer dans les conseils pratiques, notons l'annexe A 3, qui détaille comment réaliser une migration DKIM propre, depuis un algorithme de signature DKIM (RSA est le seul normalisé dans le RFC 6376) vers un autre et l'annexe B qui rappelle les principes généraux de programmation d'une application cryptographique sûre. Par exemple, sur une machine à mémoire virtuelle, le programmeur devrait s'assurer que la clé privée, stockée en mémoire, ne se retrouve pas dans le swap à un endroit où d'autres processus pourraient la lire (pour cela, le programmeur peut, par exemple, utiliser mlock() sur Unix.) Notre RFC recommande fortement d'utiliser des bibliothèques cryptographiques existantes et éprouvées, plutôt que de se croire capable d'en inventer une nouvelle.

Le ricaneur notera que l'IETF ne s'est mise à utiliser son œuvre qu'en juillet 2011. Désormais, les messages émis par les serveurs de courrier de l'IETF arborent fièrement la signature DKIM :

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=

Téléchargez le RFC 5863


L'article seul

RFC 5855: Nameservers for IPv4 and IPv6 Reverse Zones

Date de publication du RFC : Mai 2010
Auteur(s) du RFC : J. Abley (ICANN), T. Manderson (ICANN)
Première rédaction de cet article le 24 mai 2010
Dernière mise à jour le 18 février 2011


Tous les RFC ne décrivent pas forcément une norme technique. Certains sont de nature plus opérationnelle et c'est le cas de de ce document, qui décrit le nouveau schéma de nommage des serveurs DNS de in-addr.arpa et ip6.arpa.

Bien qu'il n'existe aucun document décrivant l'usage qui peut être fait de la correspondance depuis l'adresse IP vers le nom de domaine (il y a eu plusieurs essais à l'IETF, tous ratés), il ne fait pas de doute que cette correspondance est utilisée. Par exemple, beaucoup de MTA, à l'exemple de Postfix, résolvent systématiquement l'adresse IP du client en nom, même s'ils ne se servent pas de ce nom. Pour cela, il font une requête de type PTR sur un nom spécial, formé à partir de l'adresse IP, et ajoutant un domaine spécial de .arpa à la fin. Avec l'option -x, dig fait tout cela automatiquement, ce qui permet de voir le processus, ici pour une adresse IPv6 :


% dig -x 2001:db8:dada::beef:1
; <<>> DiG 9.5.1-P3 <<>> -x 2001:db8:dada::beef:1
...
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 20846
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

;; QUESTION SECTION:
;1.0.0.0.f.e.e.b.0.0.0.0.0.0.0.0.0.0.0.0.a.d.a.d.8.b.d.0.1.0.0.2.ip6.arpa. IN PTR

;; AUTHORITY SECTION:
d.0.1.0.0.2.ip6.arpa.   10800   IN      SOA     ns1.apnic.net. read-txt-record-of-zone-first-dns-admin.apnic.net. 3005122290 7200 1800 604800 172800

...

On voit le domaine « spécial », ip6.arpa (RFC 3152), à la fin (pour IPv4, cela serait in-addr.arpa). Tout ceci est rappelé dans la section 1 du RFC.

Mais qui gère ces domaines spéciaux et avec quels serveurs ? Avant ce RFC, les serveurs de noms de ces domaines étaient un sous-ensemble des serveurs racine :

% dig NS in-addr.arpa 
...
;; ANSWER SECTION:
in-addr.arpa.           86400   IN      NS      a.root-servers.net.
in-addr.arpa.           86400   IN      NS      b.root-servers.net.
in-addr.arpa.           86400   IN      NS      c.root-servers.net.
in-addr.arpa.           86400   IN      NS      d.root-servers.net.
in-addr.arpa.           86400   IN      NS      e.root-servers.net.
in-addr.arpa.           86400   IN      NS      f.root-servers.net.
in-addr.arpa.           86400   IN      NS      g.root-servers.net.
in-addr.arpa.           86400   IN      NS      h.root-servers.net.
in-addr.arpa.           86400   IN      NS      i.root-servers.net.
in-addr.arpa.           86400   IN      NS      k.root-servers.net.
in-addr.arpa.           86400   IN      NS      l.root-servers.net.
in-addr.arpa.           86400   IN      NS      m.root-servers.net.

pour in-addr.arpa (qui, en décembre 2010, n'a pas encore changé) et des serveurs fournis par les RIR pour ip6.arpa :

% dig NS ip6.arpa    
...
;; ANSWER SECTION:
ip6.arpa.               84600   IN      NS      ns.icann.org.
ip6.arpa.               84600   IN      NS      sec1.apnic.net.
ip6.arpa.               84600   IN      NS      ns2.lacnic.net.
ip6.arpa.               84600   IN      NS      ns-sec.ripe.net.
ip6.arpa.               84600   IN      NS      tinnie.arin.net.

Le but du nouveau schéma est de séparer les domaines en .arpa du reste de l'infrastructure, pour pouvoir les déléguer éventuellement à d'autres serveurs. Le RFC ne spécifie que le nommage. La nomination des opérateurs de ces domaines est une question politique, laissé à l'ICANN, via la fonction IANA, suivant le RFC 2860 :

% whois -h whois.iana.org arpa

IANA Whois Service
Domain: arpa
ID: arpa

Sponsoring Organization:
    Organization: Internet Assigned Numbers Authority
...
    Country: United States
...
Administrative Contact:
    Organization: Internet Architecture Board (IAB)
                  c/o IETF Administrative Support Activity, ISOC
...
    Country: US
...
Technical Contact:
    Organization: Internet Assigned Numbers Authority
...

Donc, en quoi consiste le nouveau schéma ? Suivant de nombreuses zones (comme la racine mais aussi comme des TLD tels que .fr), les serveurs de in-addr.arpa sont désormais tous dans un domaine dédié et ont un nom d'une seule lettre (section 2 du RFC) :

  • A.IN-ADDR-SERVERS.ARPA
  • B.IN-ADDR-SERVERS.ARPA
  • C.IN-ADDR-SERVERS.ARPA
  • ...

Ces noms se terminant par les deux mêmes composants permettent la compression des données DNS (RFC 1035, section 4.1.4).

Les serveurs de in-addr-servers.arpa et de in-addr.arpa sont les mêmes (puisqu'ils servent le même but et peuvent donc partager le même sort en cas de problème). La colle (les adresses IP des serveurs) sera de toute façon présente dans la zone parente et l'utilisation d'un seul domaine ne pose donc pas de problème de fiabilité.

Même système pour les serveurs de ip6.arpa (section 3 du RFC) :

  • A.IP6-SERVERS.ARPA
  • B.IP6-SERVERS.ARPA
  • C.IP6-SERVERS.ARPA
  • ...

Le nouveau schéma a été déployé quelques mois après la publication du RFC (travail terminé le 7 décembre 2010 pour ip6.arpa et le 18 février 2011, après quelques cafouillages, pour in-addr.arpa) :

% dig NS ip6.arpa.
...
;; ANSWER SECTION:
ip6.arpa.		84600	IN	NS	a.ip6-servers.arpa.
ip6.arpa.		84600	IN	NS	b.ip6-servers.arpa.
ip6.arpa.		84600	IN	NS	c.ip6-servers.arpa.
ip6.arpa.		84600	IN	NS	d.ip6-servers.arpa.
ip6.arpa.		84600	IN	NS	e.ip6-servers.arpa.
ip6.arpa.		84600	IN	NS	f.ip6-servers.arpa.
% dig NS in-addr.arpa.
...
;; ANSWER SECTION:
in-addr.arpa.           29652   IN      NS      a.in-addr-servers.arpa.
in-addr.arpa.           29652   IN      NS      c.in-addr-servers.arpa.
in-addr.arpa.           29652   IN      NS      d.in-addr-servers.arpa.
in-addr.arpa.           29652   IN      NS      f.in-addr-servers.arpa.
in-addr.arpa.           29652   IN      NS      e.in-addr-servers.arpa.
in-addr.arpa.           29652   IN      NS      b.in-addr-servers.arpa.

La gestion de .arpa étant une affaire de gouvernance complexe, la section 4 doit expliquer que l'IAB a donné son accord pour le nouveau schéma, rôle que le RFC 3172 lui attribue.

Notez enfin que ce RFC ne concerne que les sous-domaines de .arpa. Le cas du TLD lui-même a été traité ultérieurement dans le RFC 9120.


Téléchargez le RFC 5855


L'article seul

RFC 5849: The OAuth 1.0 Protocol

Date de publication du RFC : Avril 2010
Auteur(s) du RFC : E. Hammer-Lahav
Pour information
Première rédaction de cet article le 3 mai 2010


Le protocole OAuth, déjà fréquemment déployé, voit son développement officiellement passer du côté de l'IETF, avec ce RFC 5849 qui reprend la description de la version 1 du protocole, pendant que le groupe de travail Oauth travaille à la version 2 (dont le premier document publié a été le RFC 6749, en octobre 2012).

OAuth, parent de OpenID, est 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. (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, Auto FollowFriday, Twibbon ou TwitterCounter - à noter que le premier des trois n'est pas encore passé à Oauth). 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é... OAuth fournit une meilleure solution : le serveur, en recevant la requête du client, demande au propriétaire l'autorisation : twitter-oauth.png

Tout se fait par redirections HTTP (RFC 2616, section 10.3). Bien sûr, pour que cela soit sûr, il y a de nombreux détails à prendre en compte, ce qui explique les quarante pages du RFC.

OAuth existe depuis plusieurs années et était géré par un groupe informel (voir la section 1 du RFC pour un historique). Il est désormais documenté dans ce RFC 5849 (la version documentée n'a pas subi de changement significatif à l'IETF, c'est surtout une officialisation, avec quelques corrections de bogues, l'annexe A détaille ces changements ; le plus gênant est la refonte complète de la terminologie) et les nouvelles versions sont maintenant développées à l'IETF.

Une fois que Twitter a adopté ce protocole et documenté son usage, la plupart des services tiers l'ont intégré (par exemple Twibbon).

Lisons maintenant le RFC. Premièrement, 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 que la terminologie OAuth a changé avec ce RFC (par exemple, le propriétaire était nommé « utilisateur » - user).

Pour voir le cheminement complet d'une authentification OAuth, on peut regarder la jolie image de Yahoo (mais attention, elle utilise l'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.

La requête initiale du client auprès du serveur pourra ressembler à :

POST /initiate HTTP/1.1
Host: photos.example.net
Authorization: OAuth realm="Photos",
        oauth_consumer_key="dpf43f3p2l4k3l03",
        oauth_signature_method="HMAC-SHA1",
        oauth_timestamp="137131200",
        oauth_nonce="wIjqoS",
        oauth_callback="http%3A%2F%2Fprinter.example.com%2Fready",
        oauth_signature="74KNZJeDHnMBp0EMJ9ZHt%2FXKycU%3D"

Si le serveur renvoie le token hh5s93j4hdidpola, la redirection de Jane vers le serveur pourra se faire via un URL comme :

     https://photos.example.net/authorize?oauth_token=hh5s93j4hdidpola

et, une fois l'authentification de Jane auprès du serveur et son autorisation de la requête effectuées, le client pourra demander son autorisation pour le token hh5s93j4hdidpola :

POST /token HTTP/1.1
Host: photos.example.net
Authorization: OAuth realm="Photos",
        oauth_consumer_key="dpf43f3p2l4k3l03",
        oauth_token="hh5s93j4hdidpola",
        oauth_signature_method="HMAC-SHA1",
        oauth_timestamp="137131201",
        oauth_nonce="walatlh",
        oauth_verifier="hfdp7dh39dks9884",
        oauth_signature="gKgrFCywp7rO0OXSjdot%2FIHF7IU%3D"

Et enfin, après encore un nouveau token, le client pourra demander la photo :

GET /photos?file=vacation.jpg&size=original HTTP/1.1
Host: photos.example.net
Authorization: OAuth realm="Photos",
        oauth_consumer_key="dpf43f3p2l4k3l03",
        oauth_token="nnch734d00sl2jdk",
        oauth_signature_method="HMAC-SHA1",
        oauth_timestamp="137131202",
        oauth_nonce="chapoH",
        oauth_signature="MdpQcU8iPSUjWoN%2FUDMsK2sui9I%3D"

Voici pour le principe. Le reste du RFC est consacré aux détails. D'abord, comment obtenir son token ? Comme indiqué dans l'exemple, la méthode la plus courante est la redirection HTTP, normalisée en détail dans la section 2. Elle nécessite trois URL à connaître par le client. Par exemple, ceux de Twitter (apparemment documentés uniquement dans le source) sont :

  • Demande d'un token initial (section 2.1 du RFC) : https://twitter.com/oauth/request_token (le terme de request token fait référence à l'ancienne terminologie, dans le RFC, vous trouverez le même concept sous le nom de temporary credentials, cd. section 1.1),
  • Renvoi du propriétaire vers la page d'autorisation (section 2.2) : http://twitter.com/oauth/authorize,
  • Accès à la ressource convoitée via un autre token (section 2.3) : https://twitter.com/oauth/access_token.

Comment authentifier toutes ces requêtes ? C'est le but de la section 3. À noter qu'il existe plusieurs méthodes, dépendant du serveur. Le paramètre oauth_signature_method indique celle choisie, cela peut utiliser de la cryptographie asymétrique - cf. RFC 3447 -, un condensat incluant un secret partagé - cf. RFC 2104 -, voire même du texte brut, qui doit alors évidemment être emballé dans https. Les sections 3.4 à 3.6 détaillent la canonicalisation à pratiquer et autres formalités.

Le but de Oauth étant la sécurité, il n'est pas étonnant que la section résumant les questions de sécurité (section 4) soit longue. Parmi les points passés en revue :

  • Le fait qu'un protocole, si parfait qu'il soit, ne protège pas contre les erreurs dues à de mauvaises procédures. Par exemple, si le serveur ne vérifie pas l'authenticité des propriétaires avant qu'ils donnent leur autorisation... (Cf. RFC 7235.)
  • Si on utilise la signature RSA, le secret partagé n'est pas utilisé et la sécurité dépend donc du secret de la clé privée RSA (section 4.1). Par contre, si on utilise les secrets partagés, ils doivent être stockés en clair chez le client et le serveur. Si on ne prend pas de précautions suffisantes, un craqueur peut donc les lire et se faire alors passer pour l'une des deux parties (section 4.5).
  • En lui-même, OAuth ne garantit que l'authentification, pas la confidentialité. Si les requêtes ne passent pas en https, elles sont visibles à tout espion (section 4.2).
  • L'existence sur le trajet d'un relais/cache HTTP peut compliquer les choses. Par exemple, si la requête à la ressource est faite sans le champ HTTP Authorization: (ce qui est permis : section 3.5.1), le relais ne peut pas savoir que la ressource est protégée et risque donc de la distribuer après à d'autres clients. Il faut donc, dans ce cas, utiliser Cache-control: pour l'en empêcher (section 4.4).
  • Le client s'authentifie (paramètre oauth_consumer_key et signature de la requête initiale), certes, mais le client peut être du logiciel distribué avec son code source et, de toute façon, un attaquant déterminé peut trouver les paramètres du client même sans le code source, puisqu'il tourne sur une machine que l'attaquant contrôle. Le serveur ne doit donc pas faire une confiance aveugle que le client est bien celui qu'il prétend être (section 4.6).
  • Comme tout système reposant sur la redirection HTTP (le cas a été largement discuté pour OpenID), OAuth peut être sensible au hameçonnage. En effet, un méchant client peut rediriger le navigateur vers un faux serveur. Le propriétaire va alors s'authentifier auprès de ce qu'il croit être le serveur et peut-être donner alors des secrets réutilisables (par exemple un mot de passe). Le propriétaire humain doit donc faire attention à ce qu'il est bien sur le serveur attendu (section 4.7).
  • OAuth, dans la phase d'autorisation par le propriétaire, est également vulnérable au clickjacking (section 4.14).

Un guide complet sur OAuth est disponible en http://hueniverse.com/oauth/guide/. Une autre bonne introduction 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 pour accéder à Twitter en Python figure dans mon article. Fin 2012, la version 2 de OAuth est en cours de finalisation à l'IETF, mais de grosses incertitudes demeurent. Le premier RFC de la nouvelle version est le RFC 6749.


Téléchargez le RFC 5849


L'article seul

RFC 5838: Support of address families in OSPFv3

Date de publication du RFC : Avril 2010
Auteur(s) du RFC : A. Lindem (Ericsson), S. Mirtorabi, A. Roy, M. Barnes (Cisco), R. Aggarwal (Juniper)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF ospf
Première rédaction de cet article le 25 avril 2010


Les relations du protocole de routage OSPF avec le fait qu'il existe plusieurs familles de protocoles IP (IPv4 et IPv6) ont toujours été compliquées. En pratique, la totalité des déploiements actuels d'OSPF dans un environnement mixte (v4 et v6) se font avec deux installations séparées, une utilisant OSPF v2 (RFC 2328) pour IPv4 et une utilisant OSPF v3 (RFC 5340) pour IPv6. Cela complique la tâche de l'administrateur réseaux et notre RFC propose donc une autre approche, un mécanisme simple pour utiliser le protocole le plus récent, OSPF v3, pour toutes les familles.

Ce n'est pas la première tentative pour faire d'OSPF v3 (normalisé dans le RFC 5340) un protocole de routage multi-familles. Mais, jusqu'à présent, OSPF v3 n'était utilisé que pour IPv6. Ce RFC 5838 vise la simplicité en minimisant les changements au protocole. Il s'appuie sur un mécanisme existant d'OSPF v3, les instances (section 2.4 du RFC 5340). En gros, chaque instance est une incarnation du protocole OSPF, avec sa propre base, mais gérée par le même routeur (ce qui minimise le travail pour l'administrateur).

La section 1 précise que chaque famille d'adresse (IPv4, IPv6 mais aussi des choses plus exotiques comme multicast IPv6) sera mise en correspondance avec une instance OSPF v3. Cela permet d'atteindre l'objectif de simplicité (section 1.1) puisqu'on n'introduit pas de nouveau mécanisme, les instances existant déjà) mais cela empêche les différentes familles de partager l'information, chaque instance ayant sa propre base de données. Si un lien qui sert à IPv4 et IPv6 tombe, il faudra le détecter deux fois et faire les calculs SPF deux fois (routage dit des « navires dans la nuit » car les différentes instances ne se voient pas : elles partagent le logiciel et une partie de la configuration, mais pas les bases).

La section 2 détaille l'affectation des numéros d'instance (Instance ID, un octet dans l'en-tête OSPF). L'idée est d'affecter des plages de numéros d'instances à chaque famille. Ainsi (section 2.1), l'unicast IPv6 a les numéros de 0 à 31, l'unicast IPv4 de 64 à 95, etc (128 à 255 sont actuellement libres, un RFC ayant le statut de norme étant nécessaire si on veut les utiliser). La liste complète des plages figure dans un registre IANA (cf. section 5).

À noter que OSPF v3 tourne uniquement sur IPv6, même lorsque les routeurs échangent de l'information sur des préfixes IPv4. Il faut donc activer IPv6 sur tous les liens, même si IPv6 n'est pas routé (un routeur OSPF v3 utilise les adresses « locales au lien » pour communiquer avec ses pairs).

Comme les routeurs OSPFv3 qui utilisent notre nouveau RFC coexisteront dans les réseaux avec les « vieux » routeurs, il est préférable d'avoir un mécanisme de signalisation pour les distinguer. C'est l'objet de la section 2.2 qui définit les bits du champ Options de OSPF (annexe A.2 du RFC 5340). Le bit v6, qui était déjà défini, est désormais ignoré (puisque la famille d'adresses est indiquée via l'Instance ID et un nouveau bit reçoit une signification, le n° 15, le bit AF (pour Address Family) qui, s'il est mis à un, indique un routeur conforme à ce RFC 5838. Un routeur configuré pour notre RFC doit ignorer les paquets où ce bit n'est pas mis (section 2.4) sauf pour l'unicast IPv6 (afin de pouvoir continuer à utiliser OSPFv3 comme avant). Cette heureuse coexistence entre anciens en nouveaux est décrite plus précisément en section 3.

En revanche, il n'y a pas de changement dans la définition des LSA (Link State Advertisements, les paquets qui portent la description d'un lien), OSPFv3 les avait déjà prévu « multi-protocoles » en indiquant explicitement la longueur du préfixe et la famille d'adresses (section 2.3). De même, l'adresse du routeur à utiliser n'est pas celle du pair OSPF (qui est forcément une adresse IPv6) mais est mise dans le LSA (section 2.5 ainsi que la section 4.4.3.8 du RFC 5340) et peut donc être une adresse IPv4.


Téléchargez le RFC 5838


L'article seul

RFC 5837: Extending ICMP for Interface and Next-hop Identification

Date de publication du RFC : Avril 2010
Auteur(s) du RFC : A. Atlas, R. Bonica (Juniper), C. Pignataro (Cisco), JR. Rivers, N. Shen (Cisco)
Chemin des normes
Première rédaction de cet article le 25 avril 2010


Depuis les débuts d'IP, les routeurs envoient des messages ICMP à l'émetteur lorsqu'ils ne peuvent pas transmettre un datagramme. Ces messages, normalisés dans les RFC 792 et RFC 4443, donnent un certain nombre d'informations sur le datagramme original mais ne contiennent pas les informations internes au routeur comme l'interface réseau par lequel le datagramme original est arrivé, ou bien l'adresse IP du routeur auquel il aurait été transmis. Ce RFC normalise des extensions pour transmettre cette information.

Donc, quand un routeur reçoit un datagramme qu'il ne peut pas ou ne veut pas faire suivre, il renvoie un message ICMP (RFC 1812, notamment la section 4.3). Parfois, l'interface réseau sur laquelle a été reçue le datagramme original (celui dont la non-transmission a nécessité l'émission d'un message ICMP) est identifiée par l'adresse IP source du message ICMP. Mais pas toujours (section 2 du RFC). Pour que cela marche, en effet, il faut que le routeur aie envoyé le message ICMP par l'interface où le datagramme original avait été reçu et que cette interface soit « numérotée » (aie une adresse IP en propre). Mais le routage peut être asymétrique (auquel cas le message ICMP sort par une autre interface que celle où le datagramme IP était entrée) et les interfaces n'ont pas forcément une adresse IP.

IPv6 fournit d'autres possibilités (RFC 4443) pour la sélection de l'adresse IP source du message d'erreur. Mais, dans les deux cas, IPv4 ou IPv6, il n'existe pas de moyen fiable d'indiquer l'interface d'entrée du datagramme original. D'où l'extension de notre RFC. Celle-ci permet d'indiquer le nom de l'interface (identique au ifName du RFC 2863), ses adresses IP, etc.

Pour cela, cette extension repose sur le concept de messages ICMP structuré, défini dans le RFC 4884.

La section 3 donne des exemples d'application de cette extension. Par exemple, elle peut être utilisée par traceroute pour améliorer l'information donnée à l'utilisateur (section 3.1). Malheureusement, je ne connais pas encore de mise en œuvre de traceroute qui utilise cette extension.

Même des informations a priori complètement opaques (comme le numéro - ifIndex - de l'interface où le routeur avait reçu le datagramme original) peuvent être utiles, par exemple pour voir si deux paquets étaient entrés par la même interface.

Comme cette extension permet également d'identifier quelle aurait été l'interface de sortie du datagramme original (s'il avait été transmis), elle peut servir à déboguer des problèmes de filtrage spécifiques à une interface, ou bien à résoudre les problèmes de MTU (section 3.2).

L'extension est formellement décrite dans la section 4. Elle a la forme d'un objet (RFC 4884), le Interface Information Object. Cet objet porte le numéro de classe 2 dans le registre IANA (cf. section 7). Il est joint aux paquets ICMP comme Time Exceeded ou Destination Unreachable. Le sous-type (section 4.1, c-type dans le RFC 4884) identifie le rôle de l'interface du routeur et quelles informations sont incluses (par exemple, le cinquième bit du sous-type indique si l'objet comprend l'information sur l'adresse IP de l'interface considérée). Quels sont les rôles possibles pour l'interface à propos de laquelle l'objet d'information est envoyé ? Par exemple, les deux premiers bits du sous-type à zéro indiquent que l'interface est celle d'entrée du datagramme originel. Le premier bit à 1 et le second à zéro indiquent que l'objet décrit au contraire l'interface de sortie (enfin, celle qui aurait été utilisée si le paquet avait été transmis).

Les sections suivantes décrivent le format des sous-objets d'information. Par exemple, si une adresse IP est présente (bit 5 du sous-type), son format figure en section 4.2 (la famille, IPv4 ou IPv6, puis l'adresse elle-même). Si le nom de l'interface est présent (bit 6 du sous-type), le format de ce nom est décrit par la section 4.3 (un octet pour la longueur, puis le nom en UTF-8, suivant la description de la MIB-II, dans le RFC 2863, par exemple eth1 ou Ethernet0/3).

Pour aider à la compréhension, la section 4.4 donne des exemples détaillés de paquets utilisant cette extension ICMP. Si vous n'avez pas compris mes explications, les exemples de cette section rendront tout cela plus clair.

Ces paquets ICMP étendus permettent de transmettre des informations d'un réseau à un autre, peut-être en traversant les frontières d'un espace d'adressage particulier. Si un routeur sur un réseau interne émet ces paquets ICMP, et qu'ils passent par un routeur NAT pour atteindre la machine de gestion, que va t-il se passer ? Les adresses IP contenues dans le paquet ICMP peuvent n'avoir plus aucun sens. La section 5 s'attaque à ce problème, déjà abordé dans le RFC 5508. La règle est simple : toute « traduction » de l'objet d'information est interdite. Le routeur NAT doit laisser passer cet objet intact ou le retirer mais jamais le modifier. Le destinataire du message ICMP et de l'objet qu'il contient est donc averti que les adresses IP de l'objet peuvent concerner un autre domaine d'adressage et peuvent donc ne pas être pertinentes.

Quels autres problèmes peut poser cette extension ICMP ? Comme elle distribue davantage d'information qu'avant, il existe des risques de confidentialité. Avant, un routeur ne révelait pas quelle était l'interface d'entrée ou de sortie du datagramme qu'il n'avait pas routé. Désormais, il peut le faire et certains administrateurs réseau peuvent estimer que cette information ne doit pas sortir. La section 6, sur la sécurité, leur donne raison en spécifiant que la diffusion de cette information devrait être configurable, par exemple pour permettre de ne pas diffuser certains points.

Enfin, dernier avertissement, rien n'authentifie le contenu des paquets ICMP. Il ne faut donc pas se fier aveuglément au contenu des ces objets d'information.

Je n'ai pas d'informations sur les implémentations de ce RFC. Peut-être faudra t-il attendre.


Téléchargez le RFC 5837


L'article seul

RFC 5835: Framework for Metric Composition

Date de publication du RFC : Avril 2010
Auteur(s) du RFC : A. Morton (AT&T Labs), S. Van den Berghe (Alcatel-Lucent)
Pour information
Réalisé dans le cadre du groupe de travail IETF ippm
Première rédaction de cet article le 13 avril 2010


Le groupe de travail IETF sur les performances, IPPM, définit un grand nombre de métriques, de grandeurs mesurables, par exemple dans son RFC 2330. Si ce RFC avait déjà abordé le problème de la composition des métriques, il n'avait pas répondu à toutes les questions sur cette composition, ce que fait désormais notre RFC 5835. Comment combiner des mesures dans le temps et l'espace ?

Une telle demande est fréquente chez les opérateurs (section 1.1). Une mesure isolée ne sert en général pas à grand'chose et il faut donc pouvoir les composer (récolter et distribuer un ensemble de mesures) et les agréger (réduire un ensemble de mesures à une seule).

Par exemple, l'administrateur réseaux a souvent besoin de mesures immédiates, obtenues rapidement, pour résoudre un problème précis (ceux qu'on débogue avec ping...). Mais celui qui planifie les évolutions futures du réseau a besoin de mesures répétées sur une longue période, par exemple pour détecter des tendances. Les mesures utiles au premier peuvent aussi l'être au second si on les compose sur cette longue période (section 1.1.2).

Quant à l'agrégation, son but principal est de diminuer la quantité de données (section 1.1.3). Cela facilite le travail de l'humain, qui a ainsi une donnée plus simple à lire et à comprendre et on peut même mettre ces mesures agrégées dans un SLA.

Toutes les données ne se prêtent pas forcément bien à la composition et à l'agrégation. La section 2 exclut donc des métriques comme le réordonnancement des paquets (RFC 4737) et la duplication (RFC 5560). Par contre, les métriques « perte de paquets » (RFC 7680) ou « variation de délai d'acheminement » (RFC 5481) sont parfaitement composables.

La section 3 décrit les mots utilisés dans le reste du RFC. Un terme est particulièrement important, celui de « vérité de base » (ground truth, section 3.7) qui désigne la « vraie » valeur agrégée, celle qu'on va essayer d'atteindre.

Armés de ces mots, on peut alors passer aux compositions elle-mêmes (section 4). Il y a d'abord l'agrégation temporelle (section 4.1), qui consiste à combiner des mesures faites au même endroit et dans les mêmes conditions, mais à des instants différents. Par exemple, si on a mesuré les maxima et minima d'un délai d'acheminement toutes les cinq minutes, on peut agréger à une mesure toutes les soixante minutes en prenant le maximum le plus élevée d'une série de douze mesures successives (et le minimum le moins élevée de la même série, pour trouver le minimum agrégé). Attention, le RFC 2330 parlait de « composition temporelle » pour désigner une opération assez différente, de prédiction de valeurs inconnue.

L'agrégation spatiale, elle (section 4.2), agrège des mesures du même type faites à des endroits différents. Par exemple, si on a mesuré des délais d'acheminement des paquets à plusieurs endroits d'un grand réseau, et qu'on veut déterminer un délai « moyen », le calcul naïf de la moyenne serait assez faussé par quelques liens peu utilisés et la bonne façon d'agréger est donc une moyenne pondérée par l'importance du trafic sur chacun des liens mesurés.

Autre exemple d'agrégation spatiale, un opérateur réseau veut connaître le délai d'acheminement d'un paquet dans son réseau. Comme ce dernier a beaucoup de points d'entrée et beaucoup de points de sortie, la liste des délais va être longue. L'opérateur peut la raccourcir par une agrégation spatiale : garder uniquement le délai maximum (qui sera ainsi une borne supérieure du temps passé dans le réseau).

L'agrégation spatiale diminue la résolution de l'information (c'est bien son but : simplifier les données). La composition spatiale, elle (section 4.3), combine plusieurs mesures faites à des endroits différents pour trouver une mesure globale. Un exemple typique est la mesure du délai d'acheminement du point A au point D si on connait les délais de A à B, de B à C et de C à D. Une simple addition donnera alors le délai total (approximatif : par exemple, il n'est jamais garanti que les délais soient parfaitement additifs).

Une fois qu'on a combiné des mesures, on peut continuer le processus dans d'autres combinaisons (section 4.5). Par exemple, les résultats d'une agrégation temporelle (qui diminue la résolution des mesures mais les rend plus faciles à analyser et plus légères à copier sur le réseau) peuvent faire l'objet d'une nouvelle agrégation qui va encore diminuer la résolution (et le volume des données).

Le principal but de notre RFC étant de paver la voie pour de futurs RFC définissant rigoureusement des métriques composées et agrégées, la section 5 donne les exigences auxquelles ces futures métriques devront obéir, par exemple une description claire des suppositions sur lesquelles elles reposeront, une explication de leur utilité pratique, une analyse des sources d'erreur, etc. Le premier de ces RFC a été le RFC 6049.

Il y a même une mention des risques liés à l'appropriation intellectuelle, en section 5.1, qui rappelle que, si une seule des métriques est plombée par un brevet ou une appropriation similaire, alors la composition entière l'est.

Enfin, la section 6 donne des conseils sur la composition de métriques, tournant en général autour de l'idée de « vérité de base ». Ainsi, lors d'une composition temporelle (section 6.1.1), la vérité de base est la mesure effectuée sur tout l'intervalle. Si je mesure le taux de perte de paquets (RFC 7680) sur trois intervalles contigus, de durées égales, T1, T2 et T3, et que je fais une composition temporelle (en prenant la moyenne) pour trouver le taux de pertes de l'intervalle T (= T1 + T2 + T3), une mesure directe pendant T nous aurait donné la vérité de base. La composition idéale devrait donc donner une valeur proche de la vérité de base.

Qu'est-ce qui empêche une composition de s'en tenir à cet idéal ? Comme le note la section 6.2, cela peut être la propagation d'erreurs de mesure, ou bien une légère différence dans ce qui est mesuré. Par exemple, lors d'une composition spatiale, le délai d'acheminement d'un paquet entre A et C (séparés par un routeur B) n'est pas réellement la somme des délais de A à B et de B à C car il y a un temps de traitement dans B.

Autre piège dans les mesures : le trafic sur l'Internet réel dépend souvent du temps. Par exemple, des variations sur un rythme quotidien sont très courantes. Composer des mesures prises à des moments différentes peut donc donner des résultats erronés (section 6.4). À noter que certaines métriques ne dépendent quasiment pas du moment de la mesure, par exemple le délai minimum d'acheminement des paquets.


Téléchargez le RFC 5835


L'article seul

RFC 5832: GOST R 34.10-2001 digital signature algorithm

Date de publication du RFC : Mars 2010
Auteur(s) du RFC : V. Dolmatov (Cryptocom)
Pour information
Première rédaction de cet article le 16 mars 2010


L'algorithme de signature GOST est une norme russe de cryptographie. Son utilisation est obligatoire en Russie pour les services publics. GOST est un algorithme purement local, qui n'avait été décrit qu'en russe et qui n'avait donc jamais suscité d'intérêt à l'étranger (ni, probablement, beaucoup d'essais de cryptanalyse). Ce RFC 5832 (et son compagnon, le RFC 5830, sur l'algorithme de chiffrement) semblent être les premières descriptions de GOST en anglais (il a depuis été remplacé par le RFC 7091). Les RFC précédents comme le RFC 4490 ou le RFC 4491 ne portaient que sur l'usage de GOST.

Le caractère très étatique de GOST est rappelé dès la section 1.1 du RFC qui note que l'algorithme a été développé par la FAGCI (ou FAPSI), la NSA russe « sous la direction du Président de la Fédération ». GOST étant obligatoire en Russie pour les services nationaux (section 2 du RFC) , les responsables du TLD .ru ont donc annoncé qu'ils ne pourraient pas déployer DNSSEC si celui-ci ne fournit pas un moyen d'utiliser GOST (en plus de DSA et RSA). Une des étapes nécessaires à l'utilisation de GOST dans DNSSEC était la disponibilité d'un texte stable décrivant GOST, ce qui est désormais le cas. (Et du RFC 5933 qui spécifie son intégration dans DNSSSEC.)

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

Je vous laisse découvrir ledit algorithme dans le RFC, personnellement, mes compétences en cryptographie sont bien trop faibles pour y comprendre quelque chose. Et le code source ? Pour OpenSSL, il existe une distribution de GOST.


Téléchargez le RFC 5832


L'article seul

RFC 5830: GOST 28147-89 encryption, decryption and MAC algorithms

Date de publication du RFC : Mars 2010
Auteur(s) du RFC : V. Dolmatov (Cryptocom)
Pour information
Première rédaction de cet article le 16 mars 2010


Les algorithmes de signature et de chiffrement GOST sont des normes russes de cryptographie. Leur utilisation est obligatoire en Russie pour les services publics. GOST est un algorithme purement local, qui n'avait été décrit qu'en russe et qui n'avait donc jamais suscité d'intérêt à l'étranger. Sauf erreur, ce RFC 5830 (et son compagnon, le RFC 5832, sur l'algorithme de signature) sont les premières descriptions « officielles » de GOST en anglais. Les RFC précédents comme le RFC 4490 ou le RFC 4491 ne portaient que sur l'usage de GOST. (Depuis, une nouvelle version de l'algorithme est sortie, spécifié dans le RFC 8891.)

GOST 28147-89, décrit dans notre RFC, est la norme russe de chiffrement et déchiffrement symétrique (GOST R 34.10-2001, décrit dans le RFC 5832, étant l'algorithme de signature).

La section 4 donne le cadre général de l'algorithme. On note que, s'il dépend de tables de substitution, aucune n'est définie dans la norme (on peut en trouver dans le RFC 4357). Classiquement, il existe plusieurs modes de chiffrement comme ECB (décrit en détail en section 5) ou CFB (section 7). GOST 28147-89 permet également de générer un MAC (section 8).

Ces deux RFC sur GOST ont suscité des débats agités à l'IETF, notamment face à la possibilité de leur incorporation dans DNSSEC. Les critiques portaient sur l'insuffisance de la description dans le RFC (bien des points sont laissés dans l'ombre et il semble difficile de mettre en œuvre GOST uniquement en lisant le RFC), sur le peu d'analyse de sécurité sérieuse faite sur GOST, et sur les vraies motivations du gouvernement russe pour insister à imposer un algorithme local (une des hypothèses étant, comme toujours avec les gouvernements fermés, qu'il y a une porte dérobée dans l'algorithme).

Ce RFC a été remplacé depuis par le RFC 8891, qui décrit une version plus récente de l'algorithme.


Téléchargez le RFC 5830


L'article seul

RFC 5829: Link Relation Types for Simple Version Navigation between Web Resources

Date de publication du RFC : Avril 2010
Auteur(s) du RFC : A. brown, G. Clemm (IBM, J. Reschke (greenbytes)
Pour information
Première rédaction de cet article le 7 avril 2010


Ce document spécifie des types de liens qui peuvent exister entre ressources Web, notamment si elles sont versionnées (voir la section 2 pour le vocabulaire spécifique du versionnage). Par exemple, un lien peut pointer vers la dernière version d'une ressource, ou vers son historique.

Ces liens sont notamment utilisés pour le format de syndication Atom (élement <atom:link>, section 4.2.7 du RFC 4287), ainsi que pour le système CMIS. Mais HTML peut en bénéficier aussi, pour son élément <link>. Ainsi, en HTML :


<link rel="latest-version" href="latest-thing.html">

sera désormais possible. Quant aux protocoles pour gérer les versions, beaucoup sont spécifiques à un VCS donné mais il y a eu aussi des normalisations, comme celle du RFC 3253.

La section 3 liste les nouveaux types de relations :

  • version-history, l'historique du document,
  • latest-version, la dernière version,
  • etc...

Tous ces types sont enregistrés dans le registre IANA.

Des exemples d'utilisation figurent en annexe A, notamment pour le champ Link: de HTTP (qui avait été normalisé dans la section 19.6.1.2 du RFC 2068, puis abandonné dans la norme actuelle, le RFC 2616, mais qui pourrait ressusciter).

Quelques petits avertissements de sécurité, en section 5 : un lien peut partir sur un autre site, et ne doit donc pas forcément être suivi automatiquement. Et l'historique peut réveler des choses sur une version, même si la ressource correspondant à cette version est interdite d'accès.


Téléchargez le RFC 5829


L'article seul

RFC 5826: Home Automation Routing Requirements in Low Power and Lossy Networks

Date de publication du RFC : Avril 2010
Auteur(s) du RFC : A. Brandt (Sigma Designs), J. Buron (Sigma Designs), G. Porcu (Telecom Italia)
Pour information
Réalisé dans le cadre du groupe de travail IETF roll
Première rédaction de cet article le 7 avril 2010


L'« Internet des objets » est un terme à la mode, pour désigner l'interconnexion d'équipements qui ne sont pas habituellement considérés comme des ordinateurs mais qui ont néanmoins une adresse IP et une connexion (souvent indirecte) à l'Internet. Dans un environnement de type domotique, par exemple, cela concerne le grille-pain et le réfrigérateur lorsqu'ils veulent échanger des recettes. Mais, s'ils sont trop éloignés l'un de l'autre et qu'ils ne peuvent communiquer que via le presse-purée ? C'est ici que rentre en jeu notre RFC, troisième document du groupe de travail ROLL de l'IETF, groupe de travail qui vise à définir des protocoles de routage permettant au grille-pain et au réfrigérateur de découvrir que le presse-purée est volontaire pour router leurs paquets IP. Ce document est le cahier des charges des futurs protocoles de ROLL.

Bien sûr, les exemples cités plus haut sont des cas trop faciles, car le grille-pain et le réfrigérateur disposent tous les deux de tellement d'énergie que les protocoles classiques de routage peuvent être utilisés. Mais si on prend des équipements non reliés au réseau électrique comme une alarme incendie planquée dans le plafond, la télécommande de la télévision, le compteur d'eau, etc, la situation devient plus délicate, on entre vraiment dans le monde des « Low power and lossy networks » qui ont donné leur nom au groupe ROLL. Ces engins ne peuvent plus communiquer que par radio et la portée de leurs émetteurs est souvent limitée (notamment afin d'économiser les batteries). Le routage est donc nécessaire, certaines machines relayant les communications des autres. D'autre part, la réception sera souvent mauvaise (le spectre hertzien est très encombré et la seule mise en route du four à micro-ondes peut perturber le réseau). Les pertes de paquets seront donc fréquentes. Le problème ressemble donc beaucoup à celui décrit dans le RFC 5548 (qui était davantage tourné vers l'extérieur, notre RFC 5826 visant la maison, alors que le RFC 5867 vise les immeubles de bureaux).

Pour allêcher le lecteur, la section 2 donne quelques exemples d'applications domotiques, chacune illustrant un ou deux points précis des exigences qui pèseront sur le protocole. À noter que beaucoup de ces exemples reprennent sans nuance le discours habituel des vendeurs de solution domotiques, qui font miroiter le côté high-tech de leurs gadgets, sans jamais se demander s'ils sont réellement utiles et si le même objectif ne pouvait pas être atteint autrement. C'est ainsi que le contrôle de l'air conditionné (section 2.2) est présenté comme permettant de réduire la consommation énergétique, sans même mentionner la possibilité de supprimer complètement ce gouffre d'énergie absurde qu'est l'air conditionné ! Bel exemple d'écoblanchiment.

L'exemple des systèmes d'alarme (section 2.8) est particulièrement détaillé. Comme certains des capteurs ont un rôle vital (par exemple les détecteurs de fumée), il n'est pas question de tirer inutilement sur leur batterie en leur faisant assurer des tâches de routage pour des équipements moins vitaux. Le protocole de routage doit donc permettre d'exclure de la corvée de routage certains systèmes.

Après ce voyage dans le Disneyland de la domotique, la section 3 liste les exigences concrètes :

  • Routage prenant en compte les contraintes, notamment de limitation de la consommation d'énergie de l'appareil (section 3.1). Les protocoles de routage actuels sur l'Internet ignorent complètement ce facteur.
  • Possibilité de mobilité, certains des équipements se déplacent en effet souvent (section 3.2). Certains équipements sont fixes mais arrêtés relativement souvent alors que d'autres, lorsqu'ils « disparaissent » à la vue du routage, réapparaissent à un autre endroit.
  • Passage à l'échelle (section 3.3), le chiffre envisagé étant de centaines (!) d'équipements actifs dans une maison. Cela semble incroyable aujourd'hui, où la domotique est souvent un luxe de riche, tout juste bon à permettre au milliardaire de la Silicon Valley d'impressionner ses visiteurs en leur infligeant une démo de ses derniers gadgets à chaque party. Mais ce chiffre pourrait être atteint dans des maisons plus ordinaires si la tendance actuelle à la multiplication du nombre d'appareils électriques se poursuit (regardez le nombre de prises de courant qu'il faut aujourd'hui, sans compter les appareils sur pile ou batterie). En mettant une limite arbitraire à « au moins 250 appareils », le RFC n'interdit quand même pas de stocker l'adresse des appareils sur un seul octet...
  • Convergence rapide (section 3.4) après un changement. Les équipements de la maison vont bouger et être allumés et éteints fréquemment. Les changements dans le routage seront donc fréquents et ne doivent pas bloquer le réseau pendant plusieurs minutes. Le RFC met des limites quantitatives : 0,5 secondes maximum si les nœuds du réseau n'ont pas bougé et 4 secondes s'ils se sont déplacés.
  • Autoconfiguration, car les utilisateurs n'auront pas envie d'être l'administrateur réseaux de leur propre mauson. Tout devra marcher tout seul (section 3.5).
  • Stabilité (section 3.6) ce qui implique une forme de mémoire : si un équipement est souvent en panne, il faut pouvoir s'en souvenir, pour ne pas le choisir comme routeur.

Bien sûr, un tel réseau à la maison, dont la taille et la complexité serait à peu près celle de l'Internet de 1975, poserait des problèmes de sécurité. C'est l'objet de la section 5. Les réseaux à la maison rendent beaucoup de solutions de sécurité irréalistes. Par exemple, difficile d'exiger d'une machine devant économiser chaque milliwatt d'énergie de faire des calculs cryptographiques compliqués à chaque paquet. Le RFC insiste donc sur la nécessité de développer des solutions de sécurité légères.

Autre problème de sécurité, l'auto-configuration. Elle rend difficile la mise en œuvre de politiques de sécurité et notre RFC 5826 demande donc des mécanismes permettant de refuser l'accès à une machine inconnue.


Téléchargez le RFC 5826


L'article seul

RFC 5812: ForCES Forwarding Element Model

Date de publication du RFC : Mars 2010
Auteur(s) du RFC : J. Halpern (Self), E. Deleganes (Intel)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF forces
Première rédaction de cet article le 19 mars 2010


Le protocole Forces s'affine au fur et à mesure des RFC. Ce protocole permettra aux différent éléments d'un routeur de communiquer entre eux de manière normalisée, permettant peut-être la réalisation de routeurs modulaires, obtenus en assemblant des composants standard.

Ce RFC décrit le modèle de données des FE (forwarding element) de Forces. Un FE est chargé d'effectuer le travail de transmission (forwarding) des paquets, sous le contrôle d'un CE (Control Element) avec lequel il communique en suivant le protocole Forces. Le modèle permet de décrire les capacités d'un FE (ce qu'il sait faire), son état (ce qu'il est en train de faire) et sa configuration (comment le CE peut-il le commander). Il s'inscrit dans la suite du cahier des charges de Forces, le RFC 3654 et dans celle du cadre de description de Forces, le RFC 3746.

Par exemple, parmi les capacités d'un FE, on pourrait trouver :

Le modèle utilise une entité plus précise que le FE, le LFB (logical functional block, décrit en détail en section 3.2). Un LFB assure une tâche élémentaire, la combinaison de ces tâches (les LFB sont typiquement chaînés) donnant le FE.

Par exemple, on peut imaginer qu'une fonction comme le forwarding soit mise en œuvre par la combinaison de deux LFB, Longest Prefix Match et Next Hop.

La section 4 du RFC décrit plus concrètement les schémas. Le langage de description utilisé est XML, avec utilisation des W3C Schemas. Un schéma Forces est essentiellement constitué de la descriptions des classes de LFB, comme par exemple un LFB Counter qui compte les données ou comme un LFB Dropper qui jetterait tous les paquets qu'il reçoit (permettant de modéliser des effets comme les null route d'IOS, où un routeur jette des paquets, par exemple pour arrêter une DoS). Ces descriptions de classes forment ensuite une bibliothèque de classes et tout FE Forces sera documenté par une telle bibliothèque (voir par exemple celle décrite dans le RFC 6956).

La complexité du modèle et l'utilisation des W3C Schema fait que ce RFC est particulièrement long : 122 pages à lire.


Téléchargez le RFC 5812


L'article seul

RFC 5810: ForCES Protocol Specification

Date de publication du RFC : Mars 2010
Auteur(s) du RFC : A. Doria (Lulea University of Technology), J. Hadi Salim (Znyx), R. Haas (IBM), H. Khosravi (Intel), W. Wang (Zhejiang Gongshang University), L. Dong (Zhejiang Gongshang University), R. Gopal (Nokia), J. Halpern
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF forces
Première rédaction de cet article le 19 mars 2010


Ce RFC conclut, après un très long travail, les efforts du groupe de travail Forces de l'IETF. Ce groupe était chargé de produire un protocole permettant la communication entre les différents éléments d'un routeur, afin de permettre d'acheter ces éléments chez des vendeurs différents. Un tel protocole pourrait permettre d'ouvrir le monde actuellement très fermé des routeurs de haut de gamme, mais il n'est pas sûr du tout qu'il soit un jour effectivement mis en œuvre.

Le travail de Forces avait commencé il y a de nombreuses années et le premier RFC, le RFC 3654 avait été publié en 2003. Maintenant, grâce à ce RFC 5810 (et quelques compagnons comme le RFC 5811 sur le protocole de transport), le travail est quasiment terminé et la partie Normalisation de Forces avec lui. Il reste à l'implémenter et à faire en sorte qu'il soit disponible dans les routeurs...

Conformément au cahier des charges du RFC 3654, et au cadre général de Forces exposé par le RFC 3746, ce nouveau protocole permet la communication entre deux catégories d'élements qui composent un routeur, les CE (Control Element) et les FE (Forwarding Element). (La section 3 rappelle le vocabulaire de Forces.) Les premiers, les CE, font tourner des algorithmes compliqués comme OSPF ou BGP, ils prennent des décisions « de haut niveau » et les seconds, les FE, font le travail « bête » mais ultra-rapide, de commutation de chaque paquet. Aujourd'hui, dans un routeur (Forces dit NE, pour Network Element, et pas routeur) haut de gamme, le CE est typiquement un processeur standard, avec un système d'exploitation (parfois un Unix),le FE est un ASIC aux capacités bien plus limitées mais aux performances fantastiques. Comme le protocole de communication entre le CE et le FE est privé, pas question de faire tourner du logiciel libre sur le CE, pas question d'acheter le processeur à un vendeur et les ASIC à un autre. C'est ce problème que Forces veut résoudre.

Dans Forces, la relation entre les CE et les FE est simple : le CE est le maître et le FE l'esclave. Les informations nécessaires au FE sont regroupées dans des LFB (Logical Function Block) dont la description est faite en XML (cf. RFC 5812 et un exemple dans le RFC 6956). Le protocole lui-même n'utilise pas XML. Le protocole ne spécifie que la communication entre FE et CE, pas celles qui pourraient exister entre FE ou bien entre CE, ni celle qui relie les CE à leur gérant (l'interface d'administration du routeur). (La section 4 rappelle le cadre général de Forces, exposé dans le RFC 3746.) Le protocole Forces est également responsable de l'établissement et de la terminaison des associations entre un routeur (NE) et des CE ou FE (section 4.4). Une fois l'association faite, le CE envoie des ordres au FE, ordres exprimés avec le protocole Forces, et encapsulés dans un protocole de transport, le TLM (Transport Layer Mapping) qui fait l'objet d'un RFC séparé (RFC 5811).

La section 4.3.1 du RFC détaille la question de l'atomicité des requêtes Forces. Le protocole permet des requêtes atomiques (toutes sont exécutées, ou bien aucune ne l'est, section 4.3.1.1.1) mais aussi des requêtes exécutées séquentiellement jusqu'au premier échec (section 4.3.1.1.3) ou encore des requêtes exécutées même si la précédente était un échec (section 4.3.1.1.2). Mieux, Forces permet des transactions ACID (section 4.3.1.2).

L'encodage des paquets sur le câble fait l'objet de la section 6. Tous les paquets ont un en-tête commun, suivi d'un ou plusieurs TLV. Parmi les champs de l'en-tête commun, un numéro de version sur 4 bits (actuellement 1), le type du message, sur 8 bits (les différents types sont décrits en section 7 et le tableau complet est dans l'annexe A.1) et les adresses (nommées ID) de l'expéditeur et du destinataire. Ces ID, ces adresses, sont codés sur 32 bits et doivent être uniques à l'intérieur du routeur (mais pas forcément pour tout l'Internet). Rappelez-vous qu'un des buts de Forces est de pouvoir gérer des équipements très complexes, où CE et FE ne sont pas forcément dans la même boîte. À noter que les adresses des CE et des FE sont séparées (les premières commencent toujours par 00 et les secondes par 01).

Une fois passé l'en-tête commun, viennent les TLV, décrits dans la section 6.2. Le choix de TLV permet de simplifier l'analyse des messages, certains FE n'apprécieraient en effet pas forcément de devoir analyser du XML. À noter que le champ Valeur d'un TLV peut contenir d'autres TLV.

Le contenu légal d'un message (quels TLV, en fonction de son type) est le sujet de la section 7. Par exemple (section 7.1.6), si le type est Config (créer ou bien mettre à jour un attribut du FE) ou Query (récupérer la valeur d'un attribut du FE), il ne peut pas y avoir de TLV de réponse dans le message (mais il y a un TLV PATH-DATA qui contient l'identificateur de l'attribut qu'on vise). Si le type est QueryResponse (réponse à une question posée), en revanche, le TLV de réponse (section 7.1.7) est obligatoire. Comme le protocole Forces est très asymétrique (les CE commandent et les FE obéissent), la plupart des messages ne peuvent être émis que dans une seule direction (par exemple, un GET ne peut être que d'un CE vers un FE, le FE, en bon subordonné, ne doit pas poser des questions à son supérieur). Les questions et réponses sont détaillées en section 7.7 et un registre IANA stocke les valeurs possibles. L'annexe C donne plusieurs exemples d'encodage.

La traditionnelle section sur la sécurité est la 9. Les menaces contre Forces ont été décrites dans le RFC 3746. Forces peut être configuré avec zéro sécurité (section 9.1), notamment si tous les composants, CE et FE, sont dans une seule boîte fermée (ce qui est le cas de la plupart des routeurs aujourd'hui). Autrement, la sécurité dépend essentiellement des services du TML (section 5).

Notre RFC 5810 ne normalise que les bits qui seront transportés entre CE et FE, pas la manière dont ils seront encapsulés dans un protocole de transport. La section 5 ne spécifie pas de telles règles mais expose le cahier des charges que devront respecter celles-ci (appelé le TML pour Transport Mapping Layer). Au moins une encapsulation est obligatoire pour Forces, celle du RFC 5811 mais d'autres sont possibles.

Parmi les exigences de cette section, la fiabilité de la délivrance des paquets (au moins pour certains d'entre eux), la sécurité (au minimum la possibilité d'authentifier CE et FE, de préférence avec des mécanismes existants comme TLS ou IPsec), le contrôle de congestion (cf. RFC 2914), la possibilité de haute disponibilité (section 8), etc.

Je ne connais pas encore d'implémentation de niveau « production ». Ce n'est pas un travail évident, Forces est riche et complexe, peut-être trop.


Téléchargez le RFC 5810


L'article seul

RFC 5804: A Protocol for Remotely Managing Sieve Scripts

Date de publication du RFC : Juillet 2010
Auteur(s) du RFC : A.Melnikov (Isode), T. Martin (BeThereBeSquare)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF sieve
Première rédaction de cet article le 14 juillet 2010


Le langage de filtrage du courrier Sieve permet d'écrire des scripts décrivant les actions à effectuer automatiquement en fonction du contenu d'un message électronique. Ces scripts peuvent évidemment être édités avec vi directement sur le serveur mais, très souvent, les utilisateurs de Sieve n'ont pas la possibilité de se connecter directement audit serveur. Ce RFC normalise donc un protocole, ManageSieve, qui permet de mettre à jour des scripts Sieve sur le serveur.

Comme résumé en sections 1.2 et 1.3, ManageSieve est un protocole texte, orienté ligne, analogue à de nombreux autres protocoles IETF comme IMAP. Le client ManageSieve se connecte au serveur, s'authentifie, envoie des commandes et le serveur répond par des codes (section 1.4) indiquant le succès ou l'échec de la commande.

Voici un exemple de session où les lignes préfixées par C: sont envoyées par le client et celles préfixées par S: sont les réponses du serveur :

S: "IMPLEMENTATION" "Example ManageSieved v001"
S: "SIEVE" "fileinto vacation"
S: "SASL" "PLAIN"
S: "STARTTLS"
S: "VERSION" "1.0"
S: "LANGUAGE" "fr"
S: OK
C: Authenticate "PLAIN" "QJIrweAPyo6Q1T9xy"
S: OK
C: Putscript "mysievescript" {110+}
C: require ["fileinto"];
C:
C: if envelope :contains "to" "tmartin+sent" {
C:   fileinto "INBOX.sent";
C: }
S: OK

L'utilisateur s'est authentifié, puis a déposé un script Sieve nommé mysievescript.

Une notion importante du protocole ManageSieve est celle de script actif (section 1.5). ManageSieve permet de déposer plusieurs scripts sur le serveur, chacun identifié par un nom (les noms sont décrits en section 1.7, ils peuvent être pratiquement n'importe quelle chaîne Unicode) mais un seul est script actif (est réellement exécuté lors de la délivrance du courrier). La commande SETACTIVE (section 2.8) sert à rendre un script actif.

Comme la plupart des protocoles, ManageSieve impose un certain nombre de fonctions qui doivent être mises en œuvre, et d'autres qui sont optionnelles (section 1.8). Un serveur ManageSieve annonce ces capacités à l'établissement de la connexion et en réponse à la commande CAPABILITY (section 2.4). Parmi elles, la possibilité de protéger la session par TLS (obligatoire), la liste des extensions Sieve acceptées (obligatoire), la langue utilisée pour les messages d'erreur (optionnelle), etc.

ManageSieve fonctionne sur TCP (section 1.9), le port par défaut étant 4190 (attention, pendant longtemps, c'était le 2000 et plusieurs logiciels ont encore cela par défaut). L'adresse IP du serveur est trouvée en résolvant d'abord les enregistrements SRV _sieve._tcp.$DOMAIN et, si le SRV n'existe pas, en essayant directement une adresse liée au nom de domaine.

La liste complète des commandes possibles figure en section 2. Deux examples :

  • PUTSCRIPT (section 2.6) permet de déposer un script en lui donnant un nom. À noter que le serveur doit tester la validité syntaxique du script avant de l'enregistrer.
  • LISTSCRIPTS (section 2.7) qui donne la liste des scripts Sieve déposés, en indiquant lequel est actif.

On peut désigner un serveur ManageSieve, ou bien un script sur un serveur, avec un URL (section 3). Un exemple est sieve://example.net/durand/mon-script qui identifie le script mon-script de l'utilisateur durand sur le serveur ManageSieve du domaine example.net.

Bien que le RFC vienne de paraître, ManageSieve est un ancien protocole et est déjà mis en œuvre, côté client dans SquirrelMail, Emacs, un simple script Perl, les programmes sieve-connect et sieveshell de Cyrus et, côté serveur, dans Archiveopteryx, Dovecot (voir aussi PigeonHole), Cyrus (programme timsieved)... Il existe aussi un serveur semi-autonome en Python, pysieved. Sur la question générale du filtrage du courrier, on peut consulter l'article « Filtres côté serveur ».


Téléchargez le RFC 5804


L'article seul

RFC 5798: Virtual Router Redundancy Protocol Version 3 for IPv4 and IPv6

Date de publication du RFC : Mars 2010
Auteur(s) du RFC : S. Nadas (Ericsson)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF vrrp
Première rédaction de cet article le 11 mars 2010


Lorsqu'on configure une machine connectée à l'Internet, on indique le routeur par défaut qu'elle doit utiliser. Que faire s'il tombe en panne ? Utiliser VRRP, le protocole que normalise notre RFC, qui permet à plusieurs routeurs de se surveiller mutuellement, et de se remplacer en cas de défaillance. (Le RFC a depuis été remplacé par le RFC 9568.)

Prenons par exemple une machine Unix. Sa table de routage va être :

% netstat -r -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
10.0.0.0        0.0.0.0         255.255.255.0   U         0 0          0 wlan0
0.0.0.0         10.0.0.1        0.0.0.0         UG        0 0          0 wlan0

Ici, 10.0.0.1 est le routeur par défaut (on utilise parfois l'ancien terme, incorrect, de passerelle par défaut). Que se passe t-il s'il tombe en panne ? La machine n'a plus accès qu'à une petite portion de l'Internet, son réseau local (ici 10.0.0.0/24) et ceux pour lesquels il existe une route via un autre routeur. En IPv6, des mécanismes comme la découverte de voisin (RFC 4861) peuvent aider à trouver un autre routeur, s'il existe, mais les délais sont souvent trop élevés.

C'est évidemment inacceptable lorsqu'on veut pouvoir compter sur son accès Internet. D'où le protocole VRRP, normalisé à l'origine dans le RFC 2338, puis dans le RFC 3768. Cette ancienne version était spécifique à IPv4 et notre RFC 5798 est la première version de VRRP à être commune à IPv4 et IPv6. Elle porte le numéro 3. (Bien à tort, je trouve, le RFC parle de « IPvX » lorsqu'il veut désigner les deux familles, au lieu de simplement dire « IP ».)

La section 1 du RFC commence par introduire le problème et par expliquer quelles sont les solutions possibles, avant VRRP. Ainsi (section 1.2), en IPv4, les méthodes classiques étaient de faire tourner un protocole de routage comme RIP (RFC 2453) en mode « écoute seule », où la machine reçoit les mises à jour de route, pour en déduire les routeurs possibles, mais n'en envoie pas elle même. C'est ainsi que, à une époque lointaine, toutes les machines Unix en réseau faisaient tourner le programme de routage routed. L'utilisation d'un protocole de routage par des machines non-routeuses a entraîné tellement de mauvaise surprises que cette méthode n'est plus recommandée.

Il reste donc la découverte de routeur par le biais de messages ICMP (RFC 1256), jamais réellement déployée, ou bien les routes statiques, mises à la main ou via DHCP. Cette solution a l'inconvénient de l'absence de résistance aux pannes. Si le routeur par défaut s'arrête, il n'y a pas de mécanisme de bascule automatique.

En IPv6 (section 1.3), il y a une possibilité supplémentaire, le protocole de découverte de voisin du RFC 4861 qui permet, via la fonction Neighbor Unreachability Detection (section 7.3 du RFC 4861) de s'apercevoir qu'un routeur est en panne et d'en chercher un autre. Avec les paramètres par défaut de la découverte de voisin, un tel changement prend environ 40 secondes, ce qui est trop pour la plupart des applications.

La section 1.6 décrit le vocabulaire de VRRP. Notons qu'un « routeur VRRP » est un routeur qui parle le protocole VRRP mais qu'un « routeur virtuel » est l'ensemble des routeurs (un maître et plusieurs remplaçants) qui contribuent au fonctionnement continu d'une adresse IP vers laquelle pointent les routes.

La section 2 est un résumé du cahier des charges de VRRP : service continu pour une adresse IP, avec minimisation du temps de bascule vers un autre routeur physique, possibilité d'exprimer une préférence entre les différents routeurs physiques d'un même routeur virtuel, minimiser les bascules inutiles (par exemple lorsqu'un ancien maître redémarre), fonctionnement sur un réseau local coupé par des ponts qui doivent apprendre l'adresse MAC (section 2.4, qui détaille ce problème), etc. VRRP fonctionne sur tout type de réseau local mais, en pratique, est surtout utilisé sur Ethernet (l'annexe A décrit les spécificités des autres protocole comme le Token Ring).

La section 3 donne une vision générale du protocole VRRP. C'est donc un protocole d'élection. Les routeurs physiques communiquent par la diffusion restreinte sur le réseau local. Pour chaque routeur virtuel, identifié par un nombre nomé VRID (virtual router identifier), un maître est élu, et il sera le seul à router. Les routes des machines non-routeuses pointeront vers le routeur virtuel (cf. section 4.1 pour un schéma). Si on veut faire de la répartition de charge, il faut plusieurs routeurs virtuels, avec des VRID différents, cf. section 4.2 pour un bon exemple. Chaque routeur virtuel a une adresse MAC (il n'y a donc pas de problème avec les caches ARP).

Le maître diffuse périodiquement des messages VRRP advertisement. Si le maître n'en envoie plus, un remplaçant le... remplace, avec la même adresse IP (celle du routeur virtuel) et la même adresse MAC.

Le protocole est normalisé en section 5. Le format des paquets est en section 5.1 et 5.2. À noter :

  • L'adresse IPv4 de destination des paquets de diffusion est 224.0.0.18 et la IPv6 est FF02:0:0:0:0:0:0:12.
  • Le TTL des paquets doit être à 255 (cf . RFC 5082).
  • VRRP n'utilise pas un des protocoles de transport classiques comme UDP, il a son propre protocole, numéroté 112.
  • Le VRID est sur huit bits et il n'existe pas de mécanisme pour son allocation sur un réseau local, c'est à l'administrateur réseau de s'assurer de son unicité.

La section 6 est consacréee à la machine à états du protocole. Dans l'état d'attente (Backup, section 6.4.2), le routeur VRRP écoute passivement les annonces du maître et ne répond pas aux requêtes ARP ou ND pour l'adresse IP du routeur virtuel, et ignore les paquets envoyés à cette adresse. Si le maître n'envoie plus d'annonces (par défaut, c'est après trois annonces non reçues), le routeur passe dans l'état Maître.

Inversement, le routeur dans l'état Maître (section 6.4.3), répond aux requêtes ARP et ND pour l'adresse IP du routeur virtuel, traite les paquets destinés à cette adresse, route les paquets qu'il reçoit et envoie des annonces périodiques pour manifester qu'il est toujours en service.

La section 7 décrit de manière très détaillée ce que doit faire un routeur VRRP lorsqu'il reçoit ou émet les paquets VRRP. C'est là qu'est spécifié le fait qu'un routeur maître doit utiliser l'adresse MAC du routeur virtuel (et non pas celle du routeur physique) lorsqu'il envoie les annonces de bon fonctionnement. C'est pour permettre aux ponts et commutateurs de trouver le routeur physique. Cette adresse MAC est calculée (sections 7.3 et 12) et vaut 00-00-5E-00-01-{VRID} en IPv4 et 00-00-5E-00-02-{VRID} en IPv6.

Comme souvent sur un réseau, le diable est dans les détails pratiques. Ils font l'objet de la section 8. Ainsi, la section 8.1.2 rappelle que, puisque le maître utilise toujours comme adresse MAC celle du routeur virtuel présentée au paragraphe précédent, le client ne peut pas découvrir qu'un routeur physique en a remplacé un autre.

Parmi ces problèmes opérationnels, celui de la sécurité a droit à une section entière, la 9. En gros, VRRP n'a aucune sécurité. Les versions précédentes avaient tenté de mettre en place quelques mécanismes mais ils n'ont eu aucun succès et notre version 3 de VRRP les supprime. Notons que le problème n'est pas créé par VRRP : sur le réseau local, un méchant a énormément de moyens de perturber bien des protocoles indispensables, à commencer par DHCP et ARP. Par exemple, le méchant peut toujours répondre aux requêtes ARP pour l'adresse IP du routeur et lui voler ainsi le trafic. VRRP, où le méchant peut se faire désigner comme maître, n'aggrave donc pas tellement la situation.

VRRP a toujours souffert d'une polémique récurrente sur un brevet que détient Cisco et qui est apparemment effectivement appliqué (des développeurs VRRP ou bien de protocoles similaires ont, semble t-il, reçu des menaces des avocats de Cisco). L'existence de ce brevet n'est pas en soi contraire à la politique de l'IETF. En effet, celle-ci accepte des protocoles brevetés (il est difficile de faire autrement, compte-tenu du membre, et du caractère ridiculement futile, de la grande majorité des brevets logiciels) et demande juste que les prétentions soient publiques, ce qui est le cas ici. D'innombrables messages, souvent courroucés, ont été échangé sur les listes IETF au sujet de ce brevet. Cette situation a mené les développeurs d'OpenBSD à développer un protocole concurrent, CARP. On peut lire un point de vue (très outrancier) sur cette polémique dans l'interview de Ryan McBride. La réalité est plus complexe : les développeurs d'OpenBSD ont adopté une attitude d'affrontement immédiatement (« comme souvent », disent ceux qui connaissent les gens d'OpenBSD) et la bureaucratie IETF n'a pas fait preuve de bonne volonté et a réagi par un blocage complet. Aujourd'hui, les positions semblent hélas figées, au point que CARP, n'ayant pas eu de numéro de protocole officiel (en raison de leur refus de se plier aux procédures IANA, procédures d'ailleurs incorrectement décrites par McBride), a tout simplement pris celui de VRRP. Sur un réseau local, si on voit des paquets du protocole 112, il peut donc s'agir de CARP ou bien de VRRP.

En raison du brevet Cisco sur HSRP (le précurseur de VRRP), brevet dont la licence n'est apparemment disponible que selon les conditions RAND (bien insuffisantes pour du logiciel libre), il n'est pas évident de faire une mise en œuvre libre de VRRP. Il existe toutefois vrrpd et keepalived (aucun des deux ne semble intégrer IPv6).

La configuration de VRRP sur un routeur Juniper est documentée en Configuring VRRP and VRRP for IPv6 et Configure Basic VRRP Support. Cela donne, par exemple :

address 192.0.2.0/25 {
                    vrrp-group 12 {
                        virtual-address 192.0.2.65;
                        priority 80;
                    }

Notez que vrrp-group est un terme purement Juniper, c'est ce que le RFC appelle VRID (ici 12). Quant au concept de priorité (ici 80, donc moins que la priorité par défaut), il est décrit en section 5.2.4. Avec vrrpd, la même configuration serait :

 ip address 192.0.2.2 255.255.255.128 
 vrrp 12 ip 192.0.2.1
 vrrp 12 priority 80

Téléchargez le RFC 5798


L'article seul

RFC 5797: FTP Command and Extension Registry

Date de publication du RFC : Mars 2010
Auteur(s) du RFC : J. Klensin, A. Hoenes (TR-Sys)
Chemin des normes
Première rédaction de cet article le 11 mars 2010


C'est un très vieux projet qui voit enfin le jour avec ce RFC : documenter les différentes commandes qu'a accumulé le vénérable protocole FTP, après vingt-quatre ans d'existence sous sa forme actuelle (spécifiée par le RFC 959), et d'innombrables extensions ajoutées sans trop de coordination. FTP, qui a commencé en 1971, sous le nom de Data Transfer Protocol (RFC 171), reste très utilisé un peu partout et l'absence d'un registre de ses commandes et extensions pouvait entrainer des problèmes de portabilité.

Certaines des extensions suivaient le cadre du RFC 2389, qui normalisait un mécanisme commun, souvent désigné sous le nom de FEAT (FEATure). Mais ce n'est pas le cas de toutes. Désormais, RFC 2389 ou pas, toutes les commandes et extensions sont dans un registre unique.

Ce registre est décrit en section 2. Nommé FTP Commands and Extensions, il comprend notamment, pour chaque entrée, les informations suivantes :

  • Nom de la commande (en MAJUSCULES), s'il y en a une (certaines extensions impliquent plusieurs commandes et, dans ce cas, il n'y a pas de nom de commande). Par exemple, LIST (obtenir la liste des fichiers distants) ou PROT+ (cette dernière étant, comme son nom l'indique, une modification de PROT, qui permet de spécifier le niveau de sécurité requis pour un transfert, voir RFC 4217, section 9).
  • Le nom de l'extension, par exemple MDTM (date de modification d'un fichier, cf. RFC 3659) ou hist (fourre-tout pour les vieilles extensions, abandonnées). Si l'extension suit le cadre du RFC 2389, pas de problème, ce nom est celui donné en réponse à la commande FEAT et il est noté en MAJUSCULES. Sinon un nom est inventé et indiqué en minuscules.
  • Le caractère obligatoire ou bien facultatif de cette extension. 'm' signifie mandatory (obligatoire), 'o' optional (facultatif) et 'h' historic (abandonné).

Notre RFC 5797 contient en section 3 le registre initial (on peut trouver la version actuelle en ligne). Il contient plusieurs codes « pseudo-FEAT » (qui n'utilisent pas réellement le système FEAT du RFC 2389 et sont donc écrits en minuscules), comme base (commandes obligatoires), secu (extensions de sécurité du RFC 2228), ou nat6 (extensions pour aider avec les NAT ou avec IPv6, dans le RFC 2428).

C'est ainsi que la commande AUTH est enregistrée comme AUTH+ pour tenir compte des extensions TLS qui avaient été normalisées dans le RFC 4217. On trouve aussi, par exemple, une commande LANG, normalisée dans le RFC 2640, et qui permet d'internationaliser FTP, entre autres en demandant des messages dans d'autres langues que l'anglais.

Les sections 2.4 et 2.5 donnent des explications sur la création du registre initial, à partir des commandes de base (RFC 959), toutes obligatoires (comme USER, ou RETR, l'équivalent du GET de HTTP) ou d'essais depuis abandonnés (par exemple par le RFC 1123).

Créer un registre est une chose, mais il faut le faire vivre ensuite : il est prévu que de nouvelles extensions à FTP soient enregistrées. Selon quels critères ? La section 2.3 (et la section 5) les formalise. L'idée est que le registre sert à éviter les conflits dans les codes utilisés. Il ne signifie pas que les extensions qu'il liste sont « approuvées » ou bien qu'elles représentent une « bonne idée ». Les vérifications faites avant l'enregistrement sont :

  • Qu'une spécification publique de l'extension existe, par exemple un RFC. Tout RFC convient. Pour les autres documents, l'expert appelé pour vérifier l'enregistrement devra s'assurer que l'autre document a bénéficié d'un examen sérieux.
  • Que l'extension a effectivement été mise en œuvre dans un client ou un serveur FTP (dans la tradition du running code de l'IETF).

C'est uniquement si l'extension doit être marquée comme obligatoire qu'il faudra un RFC de statut « Chemin des normes ».

Ces règles sont donc une légère variante des règles « Norme nécessaire » et « Examen par un expert » du RFC 5226.


Téléchargez le RFC 5797


L'article seul

RFC 5795: The RObust Header Compression (ROHC) Framework

Date de publication du RFC : Mars 2010
Auteur(s) du RFC : K. Sandlund, G. Pelletier (Ericsson), L-E. Jonsson
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF rohc
Première rédaction de cet article le 4 avril 2010


Quels que soient les progrès des technologies, il n'y a jamais assez de capacité. Même aujourd'hui, les vieux modems restent en service (y compris dans un pays riche, mais étendu, comme les États-Unis) et certaines technologies récentes offrent une capacité limitée (par exemple sur les téléphones mobiles). Il est donc utile de pouvoir comprimer les données et aussi les en-têtes des paquets émis, qui sont souvent très redondants, ouvrant ainsi de bonnes perspectives pour la compression. Plusieurs mécanismes de compression ont été inventés depuis les débuts de l'Internet et le projet ROHC (Robust Header Compression) a été créé pour mettre de l'ordre dans ces mécanismes, en développant un cadre commun. Ce RFC spécifie ce cadre.

La section 1 du RFC, l'introduction, donne quelques chiffres sur les gains qu'on peut tirer de la compression. Par exemple, si on utilise RTP (RFC 3550) pour transporter de la voix sur IP, il faudra transporter les 40 octets de l'en-tête (en IPv6), les 12 octets de l'en-tête UDP et les 8 octets de l'en-tête RTP (sans compter les en-têtes de la couche liaison). Ainsi, un paquet de données de 20 octets (une taille courante en voix sur IP) pourrait nécessiter 60 octets d'en-têtes TCP/IP.

Le RFC originel sur ROHC était le RFC 3095 qui incluait à la fois le cadre général et les profils de compression pour certains protocoles (un profil est un protocole de compression donné, adapté à un certain protocole). Une réforme générale de ROHC a eu lieu et il est désormais normalisé dans plusieurs RFC, notre RFC 5795 pour le cadre général, les RFC 4996 et RFC 5225 pour des profils pour, respectivement, TCP et les protocoles sans connexion comme IP ou UDP, le RFC 4997 pour le langage formel de définition des compressions, etc. (Le RFC 3095 n'est pas officiellement abandonné puisque le protocole est le même, il est juste mieux décrit.) Le cadre général de ROHC était initialement dans le RFC 4995, mais il comportait quelques bogues, corrigées par notre RFC qui remplace donc le RFC 4995.

La section 3 du RFC décrit les bases de la compression. Le principe est que le compresseur ne transmette pas certaines informations, car elles n'ont pas changé, ou bien peuvent être déduites automatiquement. Cela implique que le décompresseur puisse se souvenir de l'état de la compression, ce que ROHC nomme le contexte (la section 2.2 décrit toute la terminologie). Le maintien de ce contexte, même en présence de perturbations sur le réseau, est le principal défi de la compression. Sur des liens de mauvaise qualité (par exemple avec beaucoup de pertes), les mécanismes de compression pré-ROHC se comportaient plutôt mal (voir aussi la section 1).

Naturellement, rien n'est gratuit : le gain en capacité du réseau sera obtenu au détriment de la puissance de calcul, puisque compression et décompression nécessitent des calculs. La vitesse des processeurs des téléphones portables augmentant plus vite que leur capacité réseau, le choix de la compression semble raisonnable.

La section 3.2 rappelle l'histoire de la compression. Le premier grand travail dans le monde TCP/IP avait été la compression des en-têtes TCP par Van Jacobson en 1990 (RFC 1144), dont tous les utilisateurs de SLIP dans les années 1980 et 90 se souviennent (« Tu es sûr d'avoir activé la compression VJ ? »).

La section 4 décrit de manière relativement informelle le fonctionnement de ROHC, notamment (section 4.1), les différentes classes de changement dans les en-têtes, qui permettent leur prédiction par le décompresseur. Ainsi, la classe STATIC décrit les informations qui ne changent pas pendant la durée du flux de données (le numéro de version IP par exemple), la classe INFERRED étant composée des en-têtes qui peuvent se déduire ou se calculer à partir d'autres informations (comme la taille du paquet).

La vraie définition de ROHC est en section 5. C'est là qu'on trouve, par exemple, la description du mécanisme de rétroaction (section 5.2.4) qui permet au décompresseur de tenir le compresseur au courant du succès (ou de l'échec) de son travail. Autre exemple (section 5.1.2), chaque canal de communication ROHC a, parmi ses paramètres, un identificateur du profil utilisé (la liste des identificateurs possibles est dans un registre IANA, voir également la section 8). La section 5.4 normalise ainsi le profil d'identificateur 0x0000, le profil qui ne fait rien, les profils « actifs » étant définis dans d'autres RFC.

Les changements par rapport au RFC 4995 sont minimes mais peuvent affecter l'interopérabilité, puisqu'il y a correction d'une bogue : l'encodage de la rétroaction (section 5.2.4.1) a été refait (le RFC 4995 avait introduit une différence par rapport au RFC 3095) et une nouvelle section 5.4.3 a été faite pour décrire l'initialisation du contexte dans le cas où on utilise le profile 0x0000 (profil sans compression).

Des déploiements de ROHC sont déjà faits dans les téléphones portables. Il existe une implémentation libre, RObust Header Compression (ROHC) library (merci à Didier Barvaux pour cela), tirée d'une plus ancienne bibliothèque. La section 6 du RFC 3095 contient une excellent section sur les problèmes concrets de mise en œuvre de ROHC (section qui ne semble pas avoir été reprise dans les RFC plus récents).


Téléchargez le RFC 5795


L'article seul

RFC 5791: RFC 2731 ("Encoding Dublin Core Metadata in HTML") is Obsolete

Date de publication du RFC : Février 2010
Auteur(s) du RFC : J. Reschke (Greenbytes), J. Kunze (University of California)
Pour information
Première rédaction de cet article le 23 février 2010


Un ultra-court RFC pour dire simplement que l'IETF a abandonné tout travail sur la représentation en HTML de la norme de métadonnées Dublin Core (cf. RFC 5013).

Cette norme avait connu un RFC, le RFC 2731 mais, depuis, tout le travail d'évolution s'est fait au sein de la Dublin Core Metadata Initiative. C'est donc désormais sur le site Web de celle-ci qu'il faudra aller chercher des informations.


Téléchargez le RFC 5791


L'article seul

RFC 5789: PATCH Method for HTTP

Date de publication du RFC : Mars 2010
Auteur(s) du RFC : L. Dusseault (Linden Labs), J. Snell
Chemin des normes
Première rédaction de cet article le 19 mars 2010


Le célébrissime protocole HTTP (décrit dans le RFC 7230 et suivants) prévoit plusieurs méthodes pour interagir avec une ressource, identifiée par un URI. Dans le cas le plus connu, la ressource est une page en HTML et la méthode utilisée est GET, pour récupérer ladite page. Mais HTTP dispose d'autres méthodes, comme PUT ou DELETE. Ce RFC 5789 ajoute à la liste une méthode de modification partielle d'une ressource, PATCH.

Si GET sert à récupérer une ressource (par exemple un fichier), DELETE à détruire une ressource, et PUT à installer une nouvelle version toute neuve, PATCH permettra de modifier une ressource sans envoyer l'intégralité de la nouvelle ressource. L'intérêt principal est de transmettre des mises à jour de petite taille, au lieu de renvoyer une (peut-être très grosse) ressource complète. Pour l'instant, je ne connais pas de mise en œuvre disponible officiellement (voir à la fin de cet article pour quelques idées).

Il faut noter tout de suite que le format de la modification envoyée n'est pas spécifié : plusieurs formats seront possible, le client HTTP devra indiquer le format utilisé et espérer que le serveur l'accepte.

Pourquoi ne pas utiliser les méthodes existantes au lieu d'inventer PATCH ? La section 1 répond à cette question. PUT remplace complètement la ressource (et utiliser PUT pour envoyer une modification partielle, même si le serveur final comprend l'opération, sémerait la confusion chez les relais) et POST est trop mal spécifié (il sert un peu de méthode fourre-tout).

La nouvelle méthode est décrite en détail en section 2. Le client envoie le patch et indique l'URI de la ressource auquel il s'applique. Le patch est une série d'instructions indiquant comment modifier l'ancienne ressource pour atteindre l'objectif, la nouvelle ressource. Il existe plusieurs langages pour de telles instructions comme les patches XML du RFC 5261, comme le langage de patch traditionnel des programmeurs (type non officiel text/x-diff), etc. Au fur et à mesure de leur définition officielle, ces types seront enregistrés dans le registre.

Attention, comme rappelé à plusieurs reprises dans le RFC, PATCH n'est pas idempotent (pas plus que POST, voir le RFC 7231, section 9.1.2). La question a été vigoureusement discutée à l'IETF lors de l'élaboration de ce RFC et la conclusion générale était qu'assurer une telle sémantique serait très coûteux et pas toujours nécessaire.

De même, PATCH ne garantit pas forcément l'état final de la ressource : avec certains langages de patch, un patch, appliqué à une version différente de la ressource, peut engendrer des résultats inattendus (contrairement à PUT). C'est au client HTTP de s'assurer qu'il utilise bien la bonne version de la ressource. Comment ? Le plus simple est que le client demande un Etag (RFC 7232, section 2.3) par un GET, calcule les changements, avant d'envoyer le PATCH accompagné d'un en-tête If-Match: (RFC 7232, section 3.1). Ainsi, le client sera sûr de partir d'un état connu de la ressource. Cette méthode résout également le cas de deux clients tentant de patcher à peu près simultanément. (L'en-tête If-Unmodified-Since: est une alternative passable à If-Match:.) Avec certains langages de patch, ou bien pour certaines opérations (par exemple ajouter une ligne à la fin d'un journal), ces précautions ne sont pas nécessaires.

En revanche, PATCH garantit l'atomicité. La ressource sera complètement modifiée ou pas du tout (le logiciel patch d'Unix ne garantit pas cela).

PATCH ne permet de changer que le contenu de la ressource, pas ses métadonnées. Si la requête PATCH a des en-têtes, ils décrivent la requête, pas la ressource et des attributs comme le type MIME ne peuvent donc pas être modifiés via PATCH.

HTTP permet de traverser des caches et ceux-ci devraient évidemment invalider une ressource pour laquelle un PATCH est passé.

Voici l'exemple de PATCH de la section 2.1, utilisant un langage de patch imaginaire, indiquée par le type MIME application/example :

PATCH /file.txt HTTP/1.1
Host: www.example.com
Content-Type: application/example
If-Match: "e0023aa4e"
Content-Length: 100

[Le patch, au format "application/example"]

Et son résultat (rappel : 204 indique un succès mais où la ressource n'est pas renvoyée, contrairement à 200) :

HTTP/1.1 204 No Content
Content-Location: /file.txt
ETag: "e0023aa4f"

Et si ça se passe mal ? La section 2.2 décrit les cas d'erreur possibles parmi lesquels :

  • Patch invalide, inacceptable pour le langage de patch indiqué : réponse 400 (requête malformée),
  • Langage de patch inconnu : réponse 415 (type inconnu),
  • Requête impossible, par exemple parce qu'elle laisserait la ressource dans un état considéré par le serveur comme invalide : réponse 422,
  • État de la ressource différent de ce qui est demandé, lors de l'utilisation (recommandée) de If-Match:, ce qui est le cas si un autre processus a modifié la ressource entre temps : 409 ou 412 selon le cas,
  • Et naturellement les grands classiques de HTTP comme 403 (pas le droit de modifier cette ressource) ou 404 (pas moyen de patcher une ressource qui n'existe pas).

Pour interagir proprement avec les clients et les serveurs HTTP qui ne connaissent pas PATCH, la section 3 décrit l'information qu'on peut envoyer en réponse à la commande OPTIONS, pour indiquer qu'on accepte PATCH :

OPTIONS /example/buddies.xml HTTP/1.1
Host: www.example.com

[La réponse]

HTTP/1.1 200 OK
Allow: GET, PUT, POST, OPTIONS, HEAD, DELETE, PATCH
Accept-Patch: application/example, text/example

D'autre part, le nouvel en-tête Accept-Patch: (section 3.1 et 4.1 pour le registre IANA) sert à préciser les formats de patch acceptés.

Comme PATCH modifie une ressource Web, il n'est pas étonnant que la section de ce RFC 5789 sur la sécurité soit assez détaillée. Plusieurs problèmes peuvent se poser :

  • Les mêmes qu'avec PUT concernant l'autorisation de l'utilisateur à modifier la ressource. A priori, PATCH ne sera pas ouvert au public et nécessitera une authentification.
  • Le risque de corruption d'une ressource (inexistant avec PUT) qui peut être traité par les techniques de requêtes conditionnelles (If-Match:...).
  • Certains relais vérifient dans le corps de requêtes comme PUT ou POST la présence de contenus à problèmes, par exemple un virus. PATCH permettrait de contourner ces contrôles en envoyant le contenu en plusieurs fois. Mais le problème n'est pas très différent de celui posé par les contenus envoyés en plusieurs fois avec Content-Range: (le RFC cite aussi le cas des contenus comprimés, ce que je trouve moins convaincant).
  • Et, comme toujours, il y a un risque de déni de service si l'application du patch peut consommer beaucoup de ressources du serveur. Celui-ci doit donc définir des limites.

Pour implémenter PATCH, quelques idées :

  • Le livre de Lincoln D. Stein et Doug MacEachern, « Writing Apache modules with Perl and C » contient un exemple de module Perl (et de client) pour Apache,
  • Pour l'instant, c'est tout ce que je vois.

Un autre article en français sur cette technologie : http://pierre.dureau.me/billet/2011-04-06-http-patch.


Téléchargez le RFC 5789


L'article seul

RFC 5785: Defining Well-Known URIs

Date de publication du RFC : Avril 2010
Auteur(s) du RFC : M. Nottingham, E. Hammer-Lahav
Chemin des normes
Première rédaction de cet article le 7 avril 2010
Dernière mise à jour le 7 octobre 2014


Plusieurs normes du Web s'appuient sur l'existence d'un fichier à un endroit bien connu d'un site. Les deux exemples les plus connus sont robots.txt et favicon.ico. Jusqu'à présent, ces endroits « bien connus » étaient alloués sans schéma central. Notre RFC propose de mettre tous ces fichiers « sous » /.well-known/ pour construire des URI. (Il a depuis été remplacé par un document plus récent, le RFC 8615.)

Prenons l'exemple le plus connu, robots.txt, fichier stockant la politique d'autorisation des robots qui fouillent le Web. Si un robot examine le site Web http://www.example.org/, il va tenter de trouver ledit fichier en http://www.example.org/robots.txt. Même chose pour, par exemple, sitemap.xml ou P3P (section 1 du RFC). Ce système a plusieurs inconvénients, notamment le risque de collision entre deux noms (puisqu'il n'y a pas de registre de ces noms) et, pire, le risque de collision entre un de ces noms et une ressource normale du site. Cela fait donc des années que plusieurs personnes réclamaient un « rangement » de ces ressources bien connues. C'est désormais fait : les ressources bien connues doivent dorénavant être préfixées de /.well-known/. Ainsi, si le protocole d'autorisation des robots était normalisé aujourd'hui, on récupérerait la politique d'autorisation en http://www.example.org/.well-known/robots.txt.

À noter que le RFC spécifie uniquement un préfixe pour le chemin de la ressource, .well-known n'est pas forcément un répertoire sur le disque du serveur (même si c'est une mise en œuvre possible).

Le RFC 5785 note aussi qu'il existe déjà des mécanismes de récupération de métadonnées par ressource (comme les en-têtes de HTTP ou les propriétés de WebDAV) mais que ces mécanismes sont perçus comme trop lourds pour remplacer la ressource unique située en un endroit bien connu.

La section 1.1, par contre, met en garde contre un usage tous azimuts de .well-known. Compte-tenu de l'architecture du Web, il ne s'agit pas d'un mécanisme général de récupération d'information, juste d'une optimisation quand, par exemple, il faut évaluer une politique avant d'accéder à une ressource.

Le nom .well-known a été choisi car il avait peu de chances de rentrer en conflit avec un nom existant (traditionnellement, sur Unix, système d'exploitation le plus utilisé sur les serveurs Web, les fichiers dont le nom commencent par un point ne sont pas affichés). Une recherche sur Google avait confirmé que ce nom était largement libre.

Bref, passons à la section 3 qui donne les détails syntaxiques. Le préfixe est donc .well-known, les noms en « dessous » doivent être enregistrés (cf. section 5.1), et ils doivent se conformer à la production segment-nz du RFC 3986 (en clair, cela veut dire qu'ils doivent être une suite de caractères ASCII imprimables, avec quelques exclusions comme la barre oblique). À noter que l'effet d'une requête GET /.well-known/ (tout court, sans nom de ressource après), est indéfini (sur mon blog, cela donne ça ; devrais-je le configurer pour renvoyer autre chose ? Sur Mastodon, ça donne 404.)

La section 5 décrit les conditions d'enregistrement des noms bien connus à l'IANA. Le registre était vide au début mais a été ensuite rempli par exemple par les métadonnées du RFC 6415. Y mettre des noms supplémentaires nécessite un examen par un expert et une norme publiée (pas forcément un RFC). Dans les termes du RFC 5226, ce sera Specification Required et Expert Review. Il y aura un mini-formulaire à remplir et hop, le nom bien connu sera enregistré. Plusieurs existent désormais.

Notez qu'il est très difficile de savoir combien de sites ont des ressources /.well-known. Bien sûr, Google le sait, mais ne donne pas accès à cette information (une requête inurl:/.well-known ou inurl:"/.well-known" ignore hélas le point initial et trouve donc surtout des faux positifs). Si on n'a pas accès à la base de Google, il faudrait donc faire soi-même une mesure active avec un client HTTP qui aille visiter de nombreux sites.


Téléchargez le RFC 5785


L'article seul

RFC 5784: Sieve Email Filtering: Sieves and display directives in XML

Date de publication du RFC : Mars 2010
Auteur(s) du RFC : N. Freed, S. Vedam (Sun)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF sieve
Première rédaction de cet article le 11 mars 2010


Le langage de filtrage de courrier Sieve, normalisé dans le RFC 5228 a une syntaxe qui lui est propre et qui nécessite le développement d'outils spécifiques pour l'analyser. Or, il existe un format générique pour lequel d'innombrables outils ont été développés, XML. Ce RFC décrit donc un moyen de représenter les scripts Sieve en XML, ainsi que les règles de conversion de et vers le format traditionnel.

La syntaxe officielle de Sieve est celle d'un fichier texte, format simple et facilement traitable par des programmes. Mais la plupart des utilisateurs de Sieve, n'ayant pas d'expertise avec les langages formels, ne lisent et n'écrivent pas le Sieve dans ce format. Ils se servent d'outils spécialisés qui leur présentent le script sous une forme plus claire pour le non-spécialiste.

Le format XML étant très répandu, des facilités existent pour développer de tels outils, si la syntaxe d'entrée est du XML (section 1 du RFC). Comme ce n'est pas le cas de Sieve, notre RFC 5784 normalise une correspondance entre le format classique de Sieve et XML, permettant les conversions dans les deux sens. En outre, ce schéma XML ajoute la possibilité de donner des indications sur la présentation visuelle souhaitée, un point qui manquait dans la syntaxe Sieve classique (et qui était en général remplacé par des commentaires structurés spécifique à un logiciel d'édition).

La section 3 du RFC rappelle les particularités de la grammaire de Sieve : pour permettre les extensions futures, le langage n'a pas de mots réservés. La syntaxe est fixe (les extensions ne peuvent pas la modifier ou l'étendre). Toute extension peut ajouter des mots-clés. Et il existe déjà de très nombreuses extensions.

Un script Sieve est constitué de commandes, qui sont des actions ou des contrôles (mais la syntaxe ne fournit aucun moyen de distinguer les deux, seule la connaissance du mot-clé le permet). La commande est composée d'un mot-clé, suivi d'arguments, d'un test optionnel et d'un bloc de commandes optionnel. Voici quelques exemples :

stop;   /* Un contrôle tout nu, sans argument ou bloc */
require "fileinto"; /* Un contrôle avec un seul argument */
if true {stop;}   /* Un contrôle avec un test et un bloc de
   commandes */
discard;   /* Une action toute nue, sans argument */
fileinto "folder";  /* Une action avec un argument */

La section 4 définit la représentation en XML. Les contrôles sont représentés par l'élement <control> et les actions par l'élément <action>. Les exemples ci-dessus seraient donc, en XML :


   <control name="stop"/>
   <control name="require"><str>fileinto</str></control>
   <control name="if">
     <test name="true"/><control name="stop"/>
   </control>

   <action name="discard"/>
   <action name="fileinto"><str>folder</str></action>

Les directives permettant de contrôler la représentation visuelle du script Sieve sont en section 4.1. Par exemple, l'élement <displayblock> permet de groupe ensemble des commandes Sieve :


     <displayblock name="File filter list mail" order="1"
                   group="FILE_TO_FOLDER" enable="true">
       <control name="if">
         <test name="header">
           <tag>is</tag>
           <str>Sender</str>
           <str>owner-ietf-mta-filters@imc.org</str>
         </test>
         <action name="fileinto">
           <str>filter</str>
         </action>
       </control>
     </displayblock>

et l'élément <displaydata> d'indiquer du texte qui doit être montré à l'utilisateur lors de l'édition.

Pour permettre l'aller-retour dans les traductions de XML en Sieve, la section 4.2 spécifie des commentaires Sieve structurés permettant de garder l'information de présentation lors de la traduction. Ainsi, le code XML ci-dessus serait « sauvegardé » en :

/* [* name="File filter list mail" order="1" group="FILE_TO_FOLDER" enable="true" */
if header :is "Sender" "owner-ietf-mta-filters@imc.org"
...

où [* indique le début d'un displayblock.

Afin de permettre la validation des scripts Sieve en XML, notre RFC propose deux schémas, un en langage W3C Schema (annexe B), l'autre en Relax NG (annexe C). Prenons le schéma en RelaxNG (xmlsieve.rnc) et testons un script :

% rnv xmlsieve.rnc test2.xml
test2.xml

Parfait, il est bien valide.

L'annexe A contient un exemple complet d'un script Sieve (celui de la section 9 du RFC 5228) en XML. Sa version XML est disponible en rfc5228-sec9.xml et sa version sieve en rfc5228-sec9.sieve.

Voici autre un exemple de script Sieve en XML complet. Ce script jette tous les messages qui n'ont pas de champ Date: ou de champ From:, ainsi que les messages dont l'expéditeur est foobar@example.org :


<?xml version="1.0" encoding="utf-8"?>
<sieve xmlns="urn:ietf:params:xml:ns:sieve">
   <control name="if">
     <test name="anyof">
       <test name="not">
         <test name="exists">
           <list><str>From</str><str>Date</str></list>
         </test>
       </test>
       <test name="header">
         <tag>contains</tag>
         <str>from</str>
         <str>foobar@example.org</str>
       </test>
     </test>
     <action name="discard"/>
   </control>
</sieve>

Pour le traduire en script Sieve classique, on peut utiliser le programme XSLT qui figure dans l'annexe D du RFC (et qui est également disponible en xml2sieve.xslt) :

% xsltproc xml2sieve.xslt test.xml

if anyof ( not ( exists [ "From", "Date" ] ), 
   header :contains "from" "foobar@example.org" )
{
  discard;
}

En dehors de ce programme XSLT (qui ne va que dans un seul sens, depuis XML vers Sieve), je ne connais pas encore de mise en œuvre de ce RFC. Michel Sébastien me signale que JSieve semble avoir en projet une telle option.


Téléchargez le RFC 5784


L'article seul

RFC 5782: DNS Blacklists and Whitelists

Date de publication du RFC : Février 2010
Auteur(s) du RFC : J. Levine (Taughannock)
Pour information
Première rédaction de cet article le 19 février 2010
Dernière mise à jour le 25 février 2010


Le spam est un tel problème pour le courrier électronique d'aujourd'hui, que de nombreuses techniques ont été développées pour le limiter. Comme toujours en sécurité informatique, il n'y a pas de solution idéale, juste des compromis entre trop de sécurité (et on bloque du courrier légitime) et pas assez (et on est noyés par le spam). Dans cet arsenal de techniques, une des plus courantes et des plus contestées est la liste noire, ou DNSBL (DNS black list). Bien que très largement déployée, elle n'avait jamais fait l'objet d'une documentation formelle, ce qui est désormais le cas, avec ce RFC.

Le principe d'une DNSBL est de distribuer, via le DNS, de l'information sur des machines (identifiées par leur adresse IP) qui ont envoyé du spam, ou bien sont susceptibles de le faire. Le problème n'est pas tant dans la technique utilisée (même si certains déplorent qu'on charge la barque du DNS en lui confiant de plus en plus de missions) que dans la gestion de ces listes. La grande majorité sont gérées de manière opaque, par des gens irresponsables, qui inscrivent ou désinscrivent un peu comme ça leur chante.

Ce RFC a été développé par le groupe de travail IRTF ASRG. L'auteur du RFC, John Levine, est un des porte-paroles les plus fréquents des « éradicateurs », ceux qui sont prêts à faire beaucoup de dégâts collatéraux pour lutter contre le spam. Le RFC a le statut de « pour information », utilisé pour documenter les techniques qui sont utilisées et donc intéressantes à connaître, mais qui ne sont pas forcément approuvées par l'IETF. Il a failli être sur le chemin des normes, à la demande de l'ASRG, mais en a été retiré suite à une virulente discussion sur la liste principale de l'IETF.

Le document commence (section 1) par un peu d'histoire. En 1997, la première liste noire, RBL (Real-time blackhole list) avait été créée par Paul Vixie et Dave Rand. Elle était distribuée avec BGP, le DNS n'est venu qu'après. (Tout le monde a un client DNS, ce qui n'est pas le cas de BGP.) Elle existe toujours sous le nom de MAPS même si elle n'a plus grand'chose à voir avec l'effort du début.

Le terme de RBL étant désormais une marque déposée, le RFC suggère de parler plutôt de DNSBL (DNS Black List) et, pour celles qui sont utilisées pour autoriser plutôt que pour interdire, de DNSWL (DNS White List). Pour parler des deux simultanément, le RFC utilise DNSxL. (Notons que la différence entre les deux est uniquement dans l'usage que le client en fait, cf. section 2.2.)

Ce RFC décrit le fonctionnement technique des DNSxL et le protocole avec lequel elles communiquent leurs résultats. Il ne parle pas des questions de la maintenance de ces listes, ni de leur politique d'inscription/désinscription, qui font l'objet d'un autre document, le RFC 6471.

La section 2 attaque la technique : une DNSxL est une zone du DNS, où les noms sont formés à partir de la clé d'accès à la liste. Cette clé est presque toujours une adresse IP (la section 3 traite des listes de noms) et le mécanisme d'encodage est inspiré de celui de in-addr.arpa (section 2.1) : on inverse les octets et on ajoute le nom de la liste. Ainsi, pour chercher si 192.0.2.129 est listé dans la DNSxL list.example.com, on fera une requête DNS pour 129.2.0.192.list.example.com. Si 192.0.2.129 est listé, la zone doit contenir un enregistrement de type A (normalement, « adresse », mais utilisé dans un autre sens par les DNSxL) et peut contenir un enregistrement de type TXT qui stockera un message qu'on pourra afficher à l'utilisateur bloqué. Les données dans une DNBxL sont donc des données DNS ordinaires et on peut donc y accéder par des clients DNS comme dig, ici avec la liste sbl-xbl.spamhaus.org :

% dig A 129.2.0.192.sbl-xbl.spamhaus.org 
...
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 2015
...

Ici, on récupère le code NXDOMAIN (No Such Domain) donc cette adresse IP n'est pas sur la liste. Essayons avec une adresse qui est sur la liste :

% dig 158.2.0.192.sbl-xbl.spamhaus.org
...
;; ANSWER SECTION:
158.2.0.192.sbl-xbl.spamhaus.org. 684 IN A     127.0.0.4

La valeur de l'enregistrement DNS est typiquement 127.0.0.2 mais d'autres sont possibles (section 2.3).

En IPv6, pas de grosses différences, mais notons que, ici, le RFC fait œuvre créative car il n'existait pas encore de DNSxL IPv6 (pour IPv4, le RFC documente un état de fait). La section 2.4 précise les détails. Depuis, la liste Virbl a ajouté IPv6.

C'est tout pour le principe. Parmi les détails, la section 5 couvre le cas où une DNSxL arrête de fonctionner correctement et ne contient plus aucun enregistrement (ou au contraire répond systématiquement quelle que soit l'adresse, cas qui s'est déjà produit). La liste doit contenir une entrée pour 127.0.0.2 et ne pas en contenir pour 127.0.0.1. Tester ces deux clés permet de voir si le fonctionnement technique de la liste est correct.

Comment utilise t-on une DNSxl ? La section 6 couvre la configuration des clients. Par exemple, avec le MTA Postfix, la configuration se fait ainsi :

smtpd_recipient_restrictions = permit_mynetworks, reject_unauth_destination,
            reject_rbl_client sbl-xbl.spamhaus.org, ...

et l'examen du journal permet de voir les rejets de certains émetteurs :

Jan 20 21:28:02 lilith postfix/smtpd[7442]: NOQUEUE: reject: RCPT from unknown[192.0.2.158]: 554 5.7.1 Service unavailable; Client host [192.0.2.158] blocked using sbl-xbl.spamhaus.org; http://www.spamhaus.org/query/bl?ip=192.0.2.158; from=<dioxidep@pnc.com.au> to=<info@generic-nic.net> proto=ESMTP helo=<[192.0.2.158]>

La configuration ci-dessus est de tout ou rien. Si l'adresse IP du client SMTP est dans la DNSBL, il est rejeté. Comme le rappelle le RFC, une autre utilisation est de tester plusieurs listes noires et de faire un calcul de pondération entre elles, ne rejetant le message que si l'émetteur se trouve dans plusieurs listes. C'est ce que fait SpamAssassin, par exemple. Cela protège contre les listes excessivement zélées (ou contre les listes mortes, qui peuvent répondre positivement pour toutes les adresses soumises, entraînant des rejets systématiques).

Et comment savoir si on est dans une liste noire ou pas ? Il existe des outils pratiques et j'en recommande deux : rblcheck qui permet d'interroger plusieurs listes noires d'un coup et check-auth@verifier.port25.com, une adresse de courrier à laquelle on peut écrire, et qui vous renvoie automatiquement un rapport détaillé sur votre message et les machines qui l'ont transmis, y compris leur éventuelle présence dans les listes noires. Mais on peut aussi citer (accès Web uniquement) MultiRBL (qui permet de construire des URL REST comme http://multirbl.valli.org/lookup/198.51.100.1.html), Robtex (même remarque sur les URL) ou MXtoolbox ou encore Blacklist check.

La section 7, enfin, couvre le problème de sécurité général. Comme le résume bien le RFC, utiliser une liste noire externe à votre organisation, c'est sous-traiter la sécurité à un tiers. Celui-ci peut faire un meilleur travail que vous (la plupart des listes noires maintenues localement sont statiques et jamais mises à jour) ou au contraire un bien pire. Il faut donc être bien conscient de ses responsabilités. Contrairement à ce que prétendent les porte-paroles officiels des gros FAI, les listes noires ne sont pas parfaites : elles comprennent des faux négatifs (spammeurs non listés) et des faux positifs (innocents listés). Tenir à jour ces listes est un gros travail et personne ne peut croire à la vérité des affirmations d'un gros FAI, dont un porte-parole à l'IETF prétend lire et traiter tous les rapports de faux positifs envoyés par ses clients.

Idéalement, l'administrateur système qui configure son serveur de messagerie pour utiliser une liste noire devrait passer du temps à s'informer sur la ou les listes envisagées, étudier leur politique et leur pratique, et surtout suivre son évolution dans le temps puisque les listes changent. Mais très peu le font.

Ne nous faisons pas d'illusion : l'Internet n'est pas un monde de gentils Bisounours où tout le monde coopère pour le bien commun, c'est un espace de concurrence et la polémique à l'IETF reflétait simplement la différence entre d'une part les gros FAI, plutôt éradicateurs, qui connaissent et regardent les autres de haut (la remarque « vous ne gérez pas des millions de boîtes aux lettres, donc taisez-vous » était la plus fréquente lors de la discussion) et d'autre part les petits FAI et les utilisateurs, bien forcés de subir.

Un rapport intéressant, dû à Bruno Rasle et Frédéric Aoun, avait bien montré le manque de sérieux de tant de listes noires : « Blacklists anti-Spam : plus de la moitié des entreprises indexées ». Plus récemment, on peut aussi lire un intéressant article sur la mésaventure survenue à Gandi avec SORBS.

Notons pour terminer que les DNSxL posent d'autres problèmes de sécurité que les faux positifs : comme elles sont consultées à chaque message, le gérant de la DNSxL peut avoir une idée de qui sont vos correspondants, et le DNS n'étant pas très sûr, les DNSxL ne le sont pas non plus (aujourd'hui, aucune n'est signée avec DNSSEC).

Merci à Olivier Fauveaux et Serge Aumont pour leurs remarques et corrections.


Téléchargez le RFC 5782


L'article seul

RFC 5781: The rsync URI Scheme

Date de publication du RFC : Février 2010
Auteur(s) du RFC : S. Weiler (Sparta), D. Ward (Cisco Systems), R. Housley (Vigil Security)
Pour information
Première rédaction de cet article le 13 février 2010


Les URI, définis par le RFC 3986, sont des identificateurs qui commencent par le nom d'un plan (scheme). Celui-ci identifie parfois (mais pas toujours) le protocole de communication utilisé. Notre RFC enregistre le plan rsync pour l'application du même nom. Des URI comme rsync://rsync.samba.org/rsyncftp/ seront désormais légaux.

En effet, un URI standard doit avoir un plan enregistré dans le registre IANA, selon les procédures du RFC 4395. Bien que les URI de plan rsync soient très courants, ce plan n'avait jamais été formellement enregistré. La section 2 de notre RFC remédie à ce manque en fournissant le formulaire d'enregistrement. La syntaxe des URI rsync est donc :

rsync://[user@]host[:port]/source

par exemple, rsync://rsync.samba.org/rsyncftp/. Le port par défaut est 873. Contrairement à beaucoup d'autres plans, notamment http, il n'existe qu'une seule application qui utilise ce plan.


Téléchargez le RFC 5781


L'article seul

RFC 5780: NAT Behavior Discovery Using STUN

Date de publication du RFC : Mai 2010
Auteur(s) du RFC : D. MacDonald, B. Lowekamp
Expérimental
Première rédaction de cet article le 19 mai 2010


La norme STUN, à son origine en mars 2003 (RFC 3489), avait mis dans un seul RFC beaucoup de choses, comme la capacité à découvrir son adresse IP publique derrière le NAT, ou la capacité à découvrir le comportement du routeur NAT, et visait à être un mécanisme complet pour permettra la traversée d'un des engins qui enferment les machines situées derrière eux dans des adresses IP privées. Mais « qui trop embrasse mal étreint » et STUN avait été critiqué pour ne pas assez séparer ces différentes fonctions. Notamment, le mécanisme de découverte du comportement du routeur NAT a été jugé, avec l'expérience, trop fragile et peu fiable, vue la variété des comportements possibles (et l'absence de normes respectées sur ce point). Pire, dans certains cas, le comportement du routeur NAT variait dans le temps (par exemple parce qu'une table était pleine, cf. section 2). Le successeur du RFC 3489, le RFC 5389, a donc décidé de se concentrer sur le protocole de base, laissant des RFC comme notre RFC 5780, définir des usages (la section 1 résume ce choix). Notre RFC décrit donc comment utiliser STUN pour essayer de déterminer le comportement du routeur NAT.

Un routeur NAT alloue des bindings entre un couple {adresse IP, port} interne (l'adresse IP est généralement une adresses IP privée, telle que décrite dans le RFC 1918) et un couple {adresse IP, port} externe. Par exemple, si une machine sur le réseau local écrit depuis le couple {192.171.1.2, 45342}, le routeur dont l'adresse publique est 192.0.2.129, peut créer un binding de {192.0.2.129, 8662} vers {192.171.1.2, 45342}. Tout paquet envoyé depuis une machine de l'Internet à l'adresse 192.0.2.129, port 8662, va alors être transmis à l'adresse 192.171.1.2, port 45342.

Tous les routeurs NAT font cela. Mais ils diffèrent sur bien des points (la section 4 du RFC 4787 les énumère). Par exemple :

  • Combien de temps durera le binding si aucun paquet IP ne passe ? Dans les réseaux Wifi des hôtels, il est courant qu'il ne dure que quelques dizaines de secondes, ce qui ne pose pas de problème à HTTP mais est insupportable pour SSH. (Section 3.3)
  • Si la même machine interne écrit, depuis le même port, à une autre machine sur l'Internet, le même binding sera t-il utilisé ? Autrement dit, dépend t-il uniquement de l'adresse source (Endpoint-Independent Mapping, dit le RFC 4787) ou bien aussi de la destination ?
  • Est-ce que le routeur autorise les virages en épingle à cheveux, c'est-à-dire les cas où un paquet envoyé vers l'extérieur doit en fait être acheminé vers le réseau interne (car les deux machines ne savent pas qu'elles sont derrière le même NAT) ? (Section 3.4)
  • Est-ce que le routeur traduit les adresses IP présentes dans le flux de données (une idée catastrophique mais certains le font) ? (Section 3.6).
  • Etc

Notre protocole doit donc permettre de découvrir une réponse à ces questions. Il se base sur STUN (avec quelques attributs supplémentaires décrits dans ce RFC, section 7). L'application qui l'utilise peut alors se servir de ses découvertes pour ajuster son comportement. Par exemple, la découverte d'une très courte durée de vue des bindings peut l'amener à envoyer des paquets keepalive.

Pour tenir compte des critiques qui avaient été faites à STUN, le RFC précise bien (section 1) que ce protocole est expérimental, que l'application ne doit pas prendre au pied de la lettre les informations trouvées et qu'aucun procédé ne peut être complètement fiable dans ce domaine.

La section 2 décrit des cas où la découverte des propriétés du routeur NAT peut être utile, par exemple pour sélectionner les participants à un réseau pair-à-pair qui devront jouer un rôle particulier, par exemple de routage. La section 2.2, sur un protocole de pair-à-pair hypothétique qui utiliserait STUN, est particulièrement détaillée et donne un très bon exemple d'un mécanisme de « survie dans un monde de NAT ». Une lecture à recommander à tous les auteurs d'un protocole P2P.

La section 3 décrit le protocole en détail. Le serveur STUN est recherché dans le DNS via les enregistrements SRV (RFC 2782 et section 5.1). Chaque sous-section traite ensuite d'une question particulière de la liste donnée ci-dessus. Par exemple, pour déterminer si le binding dépend de l'adresses de destination, le client STUN écrit aux deux adresses IP du serveur STUN, en utilisant l'attribut OTHER-ADDRESS (c'est pour cela qu'un serveur STUN pour ce protocole ne peut pas avoir qu'une seule adresse, à noter que l'ancienne version de STUN imposait deux adresses IP dans tous les cas) et regarde si les résultats sont différents (section 3.2). Autre exemple, la section 3.3 est consacrée à la détermination de la durée de vie du binding en faisant un essai, attendant un certain temps, puis refaisant l'essai pour voir s'il marche toujours (inutile de dire que ce test est un des moins fiables, car la durée de vie d'un binding peut dépendre du remplissage des tables du routeur, section 4.6). Les virages en épingle à cheveux (paquets envoyés d'une machine située derrière le routeur à une autre machine située sur le même réseau, en passant par le routeur) sont exposés en section 3.4, qui explique comment déterminer si ces virages fonctionnent. La section 3.6 explique comment détecter la réécriture des adresses IP en comparant les attributs MAPPED-ADDRESS et XOR-MAPPED-ADDRESS. Oui, c'est une abomination, qui justifierait un rétablissement de la peine de mort mais certains routeurs examinent tous les octets qui passent et, lorsqu'ils trouvent quatre octets qui sont identiques à l'adresse IP NATée, les remplacent par l'adresse publique... C'est un des plus beaux exemples de délire d'un programmeur réseau.

La section 4 décrit en détail les algorithmes que doivent suivre clients et serveurs. Par exemple, 4.4 parle de la nécessité de faire tourner les tests en parallèle (certains peuvent être longs) et 4.5 explicite le mécanisme de découverte de la durée de vie des bindings (tout en notant que les clients doivent s'attendre à des résultats incohérents car cette durée de vie peut varier, par exemple selon la charge du routeur).

Pourquoi notre RFC 5780 sort-il si longtemps après le RFC 5389 ? Parce que sa genèse a été difficile : des points comme le tirage au hasard des ports utilisés (sections 4.1 et 9.2), ou comme les nouveaux enregistrements SRV (stun-behavior au lieu du traditionnel stun), ont suscité de longues discussions.


Téléchargez le RFC 5780


L'article seul

RFC 5773: Analysis of Inter-Domain Routing Requirements and History

Date de publication du RFC : Février 2010
Auteur(s) du RFC : E. Davies (Policy consulting), A. Doria (LTU)
Intérêt historique uniquement
Première rédaction de cet article le 19 février 2010


Ce RFC est essentiellement un document historique. Écrit il y a pas mal d'années, il est publié aujourd'hui (avec quelques mises à jour et annotations) dans le cadre des efforts de définition d'une future architecture de routage inter-domaine dans l'Internet.

Sur Internet, il existe en effet deux sortes de routage, l'intra-domaine qui concerne les opérations se déroulant à l'intérieur d'un unique système autonome, donc sous une direction commune, et l'inter-domaine, qui traite du routage entre systèmes autonomes (les « domaines »), lorsqu'il faut franchir des frontières administratives, ce qui est bien plus complexe que de simplement pousser des paquets. Aujourd'hui, l'essentiel du routage inter-domaine est fait avec le protocole BGP (RFC 4271, et BGP avait été originellement conçu, en 1989, en réponse aux exigences du RFC 1126) et l'architecture sur laquelle il repose montre des sérieuses limites, notamment en matière de passage à l'échelle : pourrons-nous faire ecnore croître l'Internet, et à un coût raisonnable ? (La section 2 du RFC résume l'état actuel du routage inter-domaine et de ses limites. Elle est complétée sur ce dernier point par la section 5. Le routage intra-domaine est, lui, considéré comme globalement satisfaisant.)

Il existe en ce moment beaucoup d'activité à l'IETF et à l'IRTF autour de ce thème d'une future architecture de routage. Elle porte, par exemple, sur des idées comme la séparation de l'identificateur et du localisateur. Le groupe de l'IRTF concerné est le Routing Research Group et ce groupe travaille à la définition d'un cahier des charges pour la future architecture. Parmi les travaux étudiés à cette occasion, figurent les discussions qui ont eu lieu il y a plusieurs années, à partir du RFC 1126, et qui sont désormais synthétisées dans ce RFC. (Attention, donc, en le lisant, une bonne partie a été écrite au tout début du siècle.)

La section 1 résume la longue genèse de ce document, qui prend sa source dans les travaux d'un groupe informel nommé Babylon en 2001. Le texte original a été préservé, des ajouts indiquent ce qui a pu changer dans l'Internet depuis.

La section 3 du RFC détaille chacune des exigences du RFC 1126, dans l'ordre du RFC original, en expliquant dans quelles mesures elles sont satisfaites aujourd'hui, avec un Internet radicalement différent de ce qu'il était en 1989, où sa taille était minuscule, selon les critères d'aujourd'hui, et où sa connectivité était encore très hiérarchique, avec NSFnet au sommet.

Ainsi, l'exigence indiquée en section 3.1 e) du RFC 1126, Provide paths sensitive to user policies est décrite dans notre RFC 5773 en section 3.1.2.1.5 comme toujours valide (selon le texte écrit en 2001 par Babylon) mais très imparfaitement faite (loose source routing, QoS) et les notes de 2006 à nos jours ajoutent qu'il faut plutôt parler d'échec complet que de déploiement insuffisant.

Mais il y a aussi des succès, le principal étant évidemment que l'Internet marche. Des points qui semblaient primordiaux en 1989 et même encore en 2001 ont sombré dans une relative indifférence (comme la QoS, justement).

Les plus gros problèmes sont peut-être quantitatifs. Le RFC 1126, section 3.4 c) demandait innocemment que le futur (à l'époque) protocole permette 10 000 systèmes autonomes et 100 000 réseaux. Ces nombres ont été largement dépassés mais il n'est pas garanti, loin de là, que cette croissance pourra durer éternellement. En 2001, Babylon s'inquiétait pour l'épuisement de l'espace de numérotation des systèmes autonomes (16 bits à l'époque) et cette inquiétude se retrouve dans notre RFC en section 3.1.2.4.3. Le RFC a finalement une note disant que le déploiement du RFC 6793 est en train de résoudre ce problème mais que ce déploiement prend plus de temps que prévu.

Dans tout exercice d'ingéniérie, le plus dur n'est pas en général de définir les buts (« Que ça marche bien ! Que ça ne soit pas cher ! Que n'importe qui puisse s'en servir ! Que cela fasse le café ! ») mais les « non-buts », ce qu'on renonce à obtenir car cela nous entrainerait trop loin et condamnerait le projet. Il est rare que les non-buts soient explicites, car cela focaliserait la critique. Mais le RFC 1126 avait une telle section, la numéro 4, analysée en section 3.1.3 de notre RFC 5773. Par exemple, le RFC 1126 expliquait que la connectivité de tous n'était pas un but. En effet, elle nécessite la coopération de systèmes autonomes intermédiaires, coopération qui ne peut pas être obtenue par des moyens techniques. Ce simple non-but déclenche une grande discussion dans le RFC 5773 en section 3.1.3.1. N'est-il pas contraire à la mission de connectivité totale de l'Internet ? Le RFC 1126 n'était-il pas excessivement prudent car il avait été écrit dans un monde où IP n'était pas encore le protocole universel qu'il était devenu en 2001 ? (Et qu'il n'est plus depuis que IPv4 et IPv6 coexistent.) Faut-il chercher la connectivité universelle (qu'on n'a pas, même avec IPv4 seul, notamment à cause du NAT) ou le « routage universel » ?

De même, la répartition de charges était considérée par le RFC 1126 comme un nom but, même si la section 3.1.3.3 du RFC 5773 fait observer que le désir de faire passer le trafic d'un domaine par plusieurs fournisseurs est une des causes de la désagrégation des préfixes annoncés, et donc de la croissance de la table de routage.

La section 3 remet les choses dans le contexte de l'époque. En 1989, lorsque le RFC 1126 a été écrit, la famille de protocoles OSI était encore considérée sérieusement par certains (elle sera abandonnée au début des années 1990, sans jamais avoir connu de déploiement significatif). Le développement de BGP s'est donc fait dans un contexte marqué par la présence d'un concurrent, IDRP (alias ISO 10747, section 3.2 de notre RFC). La section revient donc sur l'histoire tourmentée (et parfois contestée) de cette époque, marquée par l'émergence du concept de système autonome et par celle de l'idée de routage non-hiérarchique. Parmi les documents importants cités par le RFC, il y a, par exemple, Internet Architecture Workshop: Future of the Internet System Architecture and TCP/IP Protocols ou bien le chapitre 14 du livre Open Systems Networking. Le RFC considère que, si IDRP n'a jamais été réellement déployé, du moins certaines des idées qu'il contenait ont inspiré les développements dans le monde Internet. (Beaucoup d'autres ont été abandonnées : pensez au chapitre sur les non-buts. Comme tous les protocoles OSI, IDRP ne pouvait pas résister à la conception en comité, où toute fonction demandée était forcément incluse, de peur de fâcher quelqu'un.) D'autres idées d'IDRP, comme l'utilisation de certificats X.509 pour signer les annonces, n'ont pas encore percé, bien qu'elles soient régulièrement évoquées pour BGP.

BGP a donc suivi son bonhomme de chemin, première version dans le RFC 1105 en juin 1989, deuxième dans le RFC 1163, en juin 1990, troisième dans le RFC 1267 publié en octobre 1991 et enfin quatrième dans le RFC 1771 en mars 1995 (BGP-4 est désormais normalisé dans le RFC 4271). IDRP est, lui, bien oublié, il n'a même pas d'article dans Wikipédia .

Parmi les autres efforts pour développer un mécanisme de routage inter-domaine, une place particulière doit être faite à Nimrod (RFC 1753 et RFC 1992, section 3.3 de notre RFC). Le projet Nimrod, de 1994 à 1996, visait à créer une architecture de routage complètement nouvelle. S'il n'a pas débouché, les idées explorées à ce moment ont néanmoins beaucoup influencé les recherches ultérieures. Par exemple, Nimrod, contrairement à pas mal de projets « table rase » qui croient naïvement qu'on les laissera tout détruire et repartir de zéro, mettait explicitement au premier plan la nécessité d'être déployable progressivement, c'est-à-dire de ne pas rester bloqué dans le dilemme de l'œuf et de la poule, où personne n'adopte le nouveau système car il n'y a aucun intérêt à le faire, tant qu'on reste tout seul. Cette exigence de déploiement progressif reste essentielle aujourd'hui : l'Internet n'est plus un jouet de chercheurs, on ne peut plus l'arrêter pour voir, ni imposer un changement d'un seul coup, comme l'avait été l'abandon de NCP.

À noter que l'architecture de Nimrod faisait partie des projets concurrents pour le système « IPng », qui devait prendre la suite d'IPv4. Trop ambitieux, Nimrod avait été rejeté au profit du futur IPv6 qui se limitait au format des paquets IP et ne tentait pas de réformer l'architecture de routage inter-domaine (qui reste donc la même qu'avec IPv4).

Si Nimrod est relativement connu des gens de l'IETF, PNNI, résumé en section 3.4, l'est beaucoup moins. Il venait des travaux de l'ATM forum et n'avait guère eu de succès, peut-être parce que trop lié à une architecture vite dépassée, ATM.

Le travail des chercheurs sur le routage interdomaine ne s'est jamais arrêté. La section 4 est donc consacrée aux travaux récents en ce domaine. Ces recherches sur un objet très mouvant, le gigantesque Internet d'aujourd'hui, doivent s'adapter sans cesse. Ainsi, rappelle notre RFC, la connexion d'un site à plusieurs FAI devient de plus en plus fréquente et il est urgent de trouver un mécanisme qui permette de la faire dans de bonnes conditions.

Parmi les travaux de recherche des dernières années, le RFC cite NewArch (section 4.2). Datant de 2000-2001, financé par une agence gouvernementale états-unienne, NewArch avait, dans son cahier des charges, des préoccupations inquiétantes comme la protection des rapaces détenteurs de « propriété intellectuelle » ou comme la nécessité de développer des systèmes de surveillance plus perfectionnés.

Sans doute trop récents, puisque l'essentiel du RFC 5773 avait été fait avant 2006, les projets comme Clean Slate et GENI qui, pour l'instant, ont surtout produit du vent, ne sont pas mentionnés.

Quel est l'état de la réflexion sur les limites et défauts du modèle actuel de routage inter-domaine ? La section 5 répond à cette question, dans la suite du RFC 3221. Parmi les nombreux problèmes identifiés dans cette section, la propagation mondiale des erreurs locales (section 5.3), magnifiquement illustrée par l'attaque involontaire contre YouTube (depuis, une solution a été normalisée, mais pas encore massivement déployée), l'absence de solution satisfaisante à la forte demande des utilisateurs pour les connexions à plusieurs FAI (section 5.4 et RFC 4116), la question de la sécurité, puisque n'importe quel routeur BGP peut annoncer n'importe quelle route (section 5.11, RFC 4593 pour le cahier des charges des efforts actuels visant à normaliser une solution et, pour un exemple récent d'alerte de sécurité, la faille Kapela & Pilosov).

Comme toutes les listes de problèmes, celle-ci peut donner l'impression que BGP est fichu et on peut se demander, en la lisant, pourquoi l'Internet marche encore. C'est parce que les faiblesses de BGP, notamment la propagation mondiale de n'importe quelle annonce, même fausse, même mensongère, sont aussi ses forces. Elles permettent à tous de détecter le problème et de réagir rapidement. C'est bien à tort que le RFC prétend, dans sa section 5.14, qu'il n'existe pas d'outils de détection en temps réel des changements BGP, il y en a au contraire une pléthore !


Téléchargez le RFC 5773


L'article seul

RFC 5772: A set of possible requirments for a future routing architecture

Date de publication du RFC : Février 2010
Auteur(s) du RFC : A. Doria (LTU), E. Davies (Folly consulting), F. Kastenholz
Intérêt historique uniquement
Première rédaction de cet article le 19 février 2010


Ce RFC qui expose un cahier des charges pour le routage global de l'Internet est essentiellement un document historique. Écrit il y a pas mal d'années, il est publié aujourd'hui (avec quelques mises à jour et annotations) dans le cadre des efforts de définition d'une future architecture de routage. Il accompagne le RFC 5773 qui décrivait l'existant et se focalise sur les deux cahiers des charges qui avaient été redigés par deux groupes de travail en 2001. (Attention, donc, en le lisant, une bonne partie a été écrite au tout début du siècle.)

La section 1 résume la genèse compliquée de ce document. Il est issu d'un travail d'un groupe de l'IRTF qui devait travailler sur le routage « en partant d'une page blanche », c'est-à-dire sans être gêné par la nécessité de rester proche des mécanismes actuels. Un autre groupe, nommé Babylon, travaillait au même moment sur le même sujet, mais avec une perspective différente puisque Babylon se limitait aux solution incrémentales, ne nécessitant pas de tout jeter. Les contributions des deux groupes ont été réunis dans ce RFC 5772 (le « groupe A » est celui de l'IRTF et le « groupe B » est Babylon). Les deux groupes n'ont pas été fusionnés car ils partaient de principes trop différents pour qu'une fusion puisse marcher. La liste des membres des deux groupes figure dans la section 6.

Leurs contributions ont été un peu éditées pour la publication dans ce RFC mais, à part cela, elles reflètent en gros le point de vue du début des années 2000. Dans les deux cas (groupe A et groupe B), il s'agit d'une liste au Père Noël, de tout ce qu'il serait bien d'avoir dans le routage et la section 1 note qu'il n'est pas forcément possible de rééaliser toutes ces exigences (surtout simultanément).

La section 2 est rédigée par le groupe A, celui qui partait d'une feuille blanche. On y trouve tous les bons principes de conception, par exemple qu'une architecture doit être définie et bien documentée, avant de se plonger dans les détails des protocoles (section 2.1.1). Idéalement, les changements des composants de cette architecture devraient pouvoir se faire séparement pour chaque composant. Et, encore plus vœu pieux, l'adressage devrait être séparé de la topologie du réseau (actuellement, sans être complètement liés, les deux sont fortement connectés ; cela explique les bonnes performances de l'Internet, malgré sa taille, mais c'est aussi dans cette forte connexion que se trouvent souvent les conflits, par exemple autour des adresses PI, ces adresses qui ne suivent pas la topologie).

L'architecture vue par le groupe A doit passer à l'échelle, c'est-à-dire accepter des réseaux bien plus grands qu'aujourdhui (« idéalement, pour les vingt prochaines années »), par exemple pour plusieurs dizaines de milliers d'AS, chiffre qu'une note d'un éditeur en 2005 prévient qu'il a déjà été atteint. Une autre prévision est déjà dépassée dans la même section 2.1.3. Le texte de 2001 prenait le risque de pronostiquer que, en raison de certaines limites physiques, les 40 Gb/s d'OC768 seraient difficiles à dépasser alors qu'ils le sont déjà.

La section 2.1.6 demande que l'architecture nouvelle gère proprement le multi-homing. La 2.1.9, encore plus ambitieuse, demande que le nouveau système de routage soit sûr. Par exemple, une des exigences est la possibilité de dissimuler aux regards extérieurs la topologie de son réseau ce qui, pris au pied de la lettre, veut dire qu'il faut pouvoir empêcher traceroute de fonctionner.

Bien que le point de départ originel du projet du groupe A était de partir de zéro, une section, la 2.1.12 est quand même consacrée au déploiement incrémental de la nouvelle architecture, le considérant comme impératif. C'est compréhensible (l'expérience de beaucoup d'autres objets techniques complexes montre la vanité qu'il y a à vouloir faire table rase de l'investissement financier, technique et social) mais cela rend l'ensemble du cahier des charges encore plus... Comment dire ? Ambitieux ? Irréaliste ?

Le caier des charges du groupe A ne s'arrête pas là. Il demande encore une complète portabilité des adresses IP (section 2.1.14), que l'architecture soit simple à comprendre (« en moins d'une heure », dit la section 2.1.17 mais il est vrai que sa simplicité conceptuelle fut une des raisons de la victoire d'IP contre OSI). l'indépendance du système de routage par rapport aux autres composants de l'architecture (comme le DNS cf. section 2.1.20), et bien d'autres choses.

La liste est donc impressionnante. Et pourtant, tout n'a pas été inclus. La section 2.2 liste les non-buts, ce que le groupe A n'a pas considéré comme faisant partie des objectifs. On y trouve l'ingéniérie de trafic (section 2.2.2), terme très flou et trop vaste pour avoir été inclus dans les objectifs. la « sécurité absolue » (section 2.2.6), qui pourrait, en cas de problème, empêcher les opérateurs de faire leur travail, le routage dynamique en fonction de la charge du réseau (section 2.2.7), une vieille idée de l'Arpanet qui s'est toujours avérée très « casse-gueule », et, naturellement, la compatibilité avec l'existant (section 2.2.10) puisque l'idée de départ était une approche « table rase ».

La section 3 donne ensuite la parole au groupe (alias Babylon). Après un résumé du contexte, les exigences commencent en 3.2.3 qui note que tout cahier des charges laisse en général en blanc la question de l'évaluation des résultats : comment savoir qu'on a réussi ?

Parmi les demandes, l'exigence que le routage fournisse suffisamment d'informations pour pouvoir être utilisé par plusieurs services, autres que la délivrance de datagrammes au meilleur effort (section 3.2.3.2), le passage à l'échelle (section 3.2.3.3, où le RFC note que, dans ce secteur, l'échec est bien plus facile à détecter que le succès), etc. La sécurité fait l'objet de la demande 3.2.3.8,qui réclame une protection contre les DoS en notant que, dans l'Internet actuel, le fait de connaître une route sert également d'autorisation à y envoyer un paquet et qu'il faudrait changer cela (les notes récentes du RFC critiquent le groupe B en se demandant si ce ne serait pas une violation de la transparence du réseau).

Le groupe B souhaite également que les erreurs de configuration des routeurs (comme celle d'un routeur Microtik tchèque) ne puissent plus avoir des conséquences poiur l'Internet entier (section 3.2.3.10).

L'Internet n'est pas un objet purement technique. Il nécessite beaucoup de moyens humains et financiers, qui n'arrivent pas tout seuls. La section 3.4 se lance dans l'étude des contraintes extérieures, qui limitent les solutions possibles. Un des exemples le plus simple est celui de la très forte dépendance du soi-disant « cyberespace » vis-à-vis du monde physique (section 3.4.3). Combien d'entreprises ont acheté leur connectivité Internet à deux fournisseurs « pour la redondance » avant de découvrir que leurs câbles passaient dans la même tranchée et pouvaient tous être tranchés par la même pelleteuse ? (Comme ce fut le cas lors de la coupure égyptienne.)

Les exigences détaillées apparaissent ensuite en section 3.6. Groupées en sections, chacune reçoit un numéro, chaque section faisant l'objection d'une discussion groupée. Ainsi, l'exigence R(13) (Requirment 13), « Le routage doit pouvoir gérer différents chemins selon le service demandé » (nécessaire pour la QoS) fait partie de la section 3.6.2.2 sur les annonces de routes.

Il y a en tout 64 de ces exigences. Quelques exemples :

  • R(26) ne tranche pas entre les différentes familles d'adresses et demande que le futur système de routage sache gérer IPv4 et IPv6 et également des familles non-IP.
  • R(55) demande qu'il ne soit pas nécessaire de prévoir un flag day pour le déploiement du futur système de routage.
  • R(62) voudrait que le futur système de routage permette d'authentifier les annonces de route (un problème brûlant aujourd'hui).

La section 3.10 couvre ensuite les questions « contestables », celles où le consensus du groupe B est moins fort. Cela va de questions très vagues (3.10.1 regrette qu'on modélise toujours les réseaux sous forme de graphes et demande qu'on accepte d'autres modèles - sans donner aucune idée de ce qu'ils pourraient être) à des considérations sur des problèmes transversaux comme le général byzantin (section 3.10.10).


Téléchargez le RFC 5772


L'article seul

RFC 5766: Traversal Using Relays around NAT (TURN): Relay Extensions to SessionTraversal Utilities for NAT (STUN)

Date de publication du RFC : Avril 2010
Auteur(s) du RFC : J. Rosenberg (jdrosen.net), R. Mahy, P. Matthews (Alcatel-Lucent)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF behave
Première rédaction de cet article le 30 avril 2010


Le protocole TURN, que décrit notre RFC, est le dernier recours des applications coincées derrière un routeur NAT et qui souhaitent communiquer avec une application dans la même situation (cf. RFC 5128). Avec TURN, le serveur STUN ne se contente pas d'informer sur l'existence du NAT et ses caractéristiques, il relaie chaque paquet de données. (Depuis la parution de ce RFC, une nouvelle norme TURN est sortie, dans le RFC 8656.)

Être situé derrière un routeur NAT n'est jamais une situation enviable. De nombreuses applications fonctionnent mal ou pas du tout dans ce contexte. Le groupe de travail IETF behave a pour mission de spécifier des mécanismes permettant de faire fonctionner le plus d'applications possibles à travers un NAT. Le socle de tous ces mécanismes est STUN (RFC 5389), où le client STUN (notre machine bloquée par le NAT) communique avec un serveur STUN situé dans le monde libre pour apprendre sa propre adresse IP externe. Outre cette tâche de base, des extensions à STUN permettent d'aider davantage le client, c'est par exemple le cas de TURN que normalise notre RFC.

L'idée de base est que deux machines Héloïse et Abélard, chacune peut-être située derrière un NAT, vont utiliser STUN pour découvrir s'il y a un NAT entre elles (sinon, la communication peut se faire normalement) et, s'il y a un NAT, s'il se comporte « bien » (tel que défini dans les RFC 4787 et RFC 5382). Dans ce dernier cas, STUN seul peut suffire, en informant les machines de leur adresse extérieure et en ouvrant, par effet de bord, un petit trou dans le routeur pour permettre aux paquets entrants de passer.

Mais, parfois, le NAT ne se comporte pas bien et il n'existe aucune solution permettant le transport direct des données entre Héloïse et Abélard. La solution utilisée par tous les systèmes pair-à-pair, par exemple en téléphonie sur Internet, est de passer par un relais. Normalement, le serveur STUN ne sert qu'à un petit nombre de paquets, ceux de la signalisation et les données elles-mêmes (ce qui, en téléphonie ou en vidéo sur IP, peut représenter un très gros volume) vont directement entre Héloïse et Abélard. Avec TURN, le serveur STUN devient un relais, qui transmet les paquets de données. turn

TURN représente donc une charge beaucoup plus lourde pour le serveur, et c'est pour cela que cette option est restreinte au dernier recours, au cas où on ne peut pas faire autrement. Ainsi, un protocole comme ICE (RFC 8445) donnera systématiquement la préférence la plus basse à TURN. De même, le serveur TURN procédera toujours à une authentification de son client, car il ne peut pas accepter d'assurer un tel travail pour des inconnus (l'authentification - fondée sur celle de STUN, RFC 5389, section 10.2 - et ses raisons sont détaillées dans la section 4). Il n'y aura donc sans doute jamais de serveur TURN public.

TURN est défini comme une extension de STUN, avec de nouvelles méthodes et de nouveaux attributs. Le client TURN envoie donc une requête STUN, avec une méthode d'un type nouveau, Allocate, pour demander au serveur de se tenir prêt à relayer (les détails du mécanisme d'allocation figurent dans les sections 5 et 6). Le client est enregistré par son adresse de transport (adresse IP publique et port). Par exemple, si Héloise a pour adresse de transport locale 10.1.1.2:17240 (adresse IP du RFC 1918 et port n° 17240), et que le NAT réécrit cela en 192.0.2.1:7000, le serveur TURN (mettons qu'il écoute en 192.0.2.15) va, en réponse à la requête Allocate, lui allouer, par exemple, 192.0.2.15:9000 et c'est cette dernière adresse qu'Héloïse va devoir transmettre à Abélard pour qu'il lui envoie des paquets, par exemple RTP. Ces paquets arriveront donc au serveur TURN, qui les renverra à 192.0.2.1:7000, le routeur NAT les transmettant ensuite à 10.1.1.2:17240 (la transmission des données fait l'objet des sections 10 et 11). Pour apprendre l'adresse externe du pair, on utilise ICE ou bien un protocole de « rendez-vous » spécifique.

Ah, et comment le serveur TURN a t-il choisi le port 9000 ? La section 6.2 détaille les pièges à éviter, notamment pour limiter le risque de collision avec un autre processus sur la même machine.

TURN ne fonctionne que sur IPv4, car c'est pour ce protocole que des NAT sont présents. (Une extension pour relayer vers IPv6, afin de faciliter éventuellement la transition entre les deux familles, a été normalisée dans le RFC 6156.) TURN peut relayer de l'UDP ou du TCP (section 2.1) mais le serveur TURN enverra toujours de l'UDP en sortie (une extension existe pour utiliser TCP en sortie, RFC 6062). La section 2.1 explique aussi pourquoi accepter du TCP en entrée quand seul UDP peut être transmis : la principale raison est l'existence de coupe-feux qui ne laiseraient sortir que TCP.

Les données peuvent circuler dans des messages STUN classiques (nommés Send et Data, cf. section 10) ou bien dans des canaux virtuels (channels, sortes de sous-connexions, section 11) qui permettent d'éviter de transmettre les en-têtes STUN à chaque envoi de données.

Enfin, la section 17, très détaillée, note également que TURN ne peut pas être utilisé pour contourner la politique de sécurité : l'allocation ne se fait que pour une adresse IP d'un correspondant particulier (Abélard), TURN ne permet pas à Héloïse de faire tourner un serveur. Ce point permet de rassurer les administrateurs de coupe-feux et de leur demander de ne pas bloquer TURN.

Autre point important de cette section sur la sécurité : comme certains messages ne sont pas authentifiés, un méchant peut toujours envoyer au client des messages qui semblent venir du serveur et réciproquement. Le problème existe, mais c'est un problème plus général d'IP. TURN ne le résout pas mais ne l'aggrave pas (section 17.1.4).

Les implémenteurs seront sans doute intéressés par la section 12, qui explique comment traiter les en-têtes IP (voir aussi la 2.6). TURN travaille dans la couche 7, il n'est pas un « routeur virtuel » mais un relais applicatif. En conséquence, il ne préserve pas forcément des en-têtes comme ECN ou comme le TTL. Cela permet son déploiement sur des systèmes d'exploitation quelconque, où il n'est pas forcément facile de changer ces en-têtes. Pour la même raison, TURN ne relaie pas l'ICMP et la découverte traditionnelle de MTU (RFC 1191) à travers TURN ne marche donc pas.

À propos d'implémentations, il existe au moins une mise en œuvre libre de TURN, turnserver.

TURN a mis des années et des années à être publié. Certains débats, anycast pour trouver un serveur, cf. section 2.9, le fait de ne relayer qu'UDP et qu'IPv4, les allocations non-preserving, c'est-à-dire qui ne garantissent pas le respect des en-têtes IP comme ceux de DSCP, tous ces sujets ont été l'occasion de longs débats...


Téléchargez le RFC 5766


L'article seul

RFC 5746: Transport Layer Security (TLS) Renegotiation Indication Extension

Date de publication du RFC : Février 2010
Auteur(s) du RFC : E. Rescorla (RTFM), M. Ray, S. Dispensa (Phone Factor), N. Oskov (Microsoft)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF tls
Première rédaction de cet article le 13 février 2010


Les failles de sécurité font partie du folklore de l'Internet mais la plupart touchent une mise en œuvre particulière, qu'il suffit de corriger par un patch. La faille de renégociation de TLS, révélée en novembre 2009 était au contraire une faille d'un protocole. Il fallait donc modifier celui-ci pour la corriger, ce que vient de faire notre RFC (dont l'un des auteurs, Marsh Ray, est le découvreur de la faille). Ce RFC a été écrit et publié de manière particulièrement rapide, compte-tenu de l'urgence de combler cette faille. (Cette rapidité, inhabituelle à l'IETF, a d'ailleurs suscité des critiques.)

Un petit rappel : le protocole de sécurité TLS, normalisé dans le RFC 5246, contient une phase de négociation pendant laquelle les deux systèmes peuvent décider de choses comme les algorithmes de cryptographie à utiliser. Ils peuvent aussi présenter un certificat X.509 pour s'authentifier. Un point important de TLS est que la négociation ne survient pas uniquement au début de la session. À tout moment, chacune des deux parties peut renégocier (commande R si on utilise openssl s_client). Mais, et c'est le cœur de la faille, il n'existe pas de liaison (binding) entre l'état de la session avant renégociation et après. Un attaquant peut donc commencer une session avec un serveur, envoyer des données, lancer une renégociation, puis laisser la place au vrai client qui va s'authentifier. (Ce problème, et l'attaque qu'il rend possible, sont détaillés dans la section 1 du RFC.) Avec des protocoles utilisant TLS, comme HTTP qui ne fait pas la différence entre avant et après la renégociation, les données envoyées par l'attaquant seront considérées comme authentifiées par le vrai client... Même avec des protocoles comme SMTP et IMAP, où la transition entre état authenfifié et non authentifié est davantage marquée, certaines attaques restaient possibles. Bref, l'absence de toute liaison cryptographique fiable entre l'« ancienne » session et la « nouvelle » fait que le serveur et le client n'avaient aucun moyen de détecter l'attaque.

Qu'est-ce qu'une liaison, à ce sujet ? C'est une preuve cryptographique que deux éléments sont liés, qu'une attaque contre l'un invaliderait l 'autre. C'est un composant essentiel de tout protocole de cryptographie, dont l'oubli ou les défaillances sont à l'origine de plusieurs failles de sécurité. Un exemple de liaison est celle que fait SSH avec le MAC qui est calculé pour les paquets (RFC 4253, section 6.4). Sans ce MAC, l'authentification effectuée au début d'une connexion SSH ne servirait pas à grand'chose puisqu'il n'y aurait pas de liaison entre cette authentification et les paquets : un méchant pourrait laisser l'authentification se faire, puis injecter ses propres paquets. (Sur la question de la liaison cryptographique, on peut lire le RFC 5056 pour plus de détails.)

Bref, TLS manquait d'une liaison entre la session avant et après renégociation. Comment résoudre cette faille ? Le plus simple était de supprimer complètement la renégociation dans la serveur, et c'est ce qu'a fait OpenSSL en urgence. Mais cela ne résout pas le problème des utilisateurs qui ont besoin de la rénégociation (par exemple pour l'authentification X.509 sur HTTP, si on ne veut pas avoir deux machines, une pour les sessions authentifiées et une pour les autres).

Notre RFC 5746 crée donc une autre solution, qui va nécessiter la mise à jour des mises en œuvre de TLS. Son principe est d'avoir une extension TLS renegotiation_info qui lie cryptographiquement l'ancienne session (avant la rénégociation) et la nouvelle. Elle est décrite plus en détail en section 3. Elle nécessite que chaque pair TLS garde quelques informations supplémentaires :

  • Un booléen secure_renegotiation qui indique si la nouvelle option est utilisable sur cette connexion TLS,
  • Une valeur client_verify_data qui indiquait les données de vérification envoyées par le client à la dernière négociation (et que le client doit donc connaître, pour authentifier la renégociation),
  • Une valeur server_verify_data, l'équivalent pour le serveur.

L'extension elle-même figure en section 3.2. renegotiation_info est définie comme :

      struct {
          opaque renegotiated_connection<0..255>;
      } RenegotiationInfo;

où la valeur renegotiated_connection vaut zéro au début puis, en cas de renégociation, vaut *_verify_data.

Le changement à TLS est donc trivial. Mais il y a quelques détails pénibles. Par exemple, la section 3.3 fait remarquer que, bien qu'une extension inconnue doive être ignorée, certaines mises en œuvre de TLS avortent la connexion dans ce cas. Face à un TLS récent qui tente de leur envoyer une renegotiation_info,il y aura donc un problème. Une astuce a donc été créé : comme TLS permet d'indiquer les algorithmes de chiffrement acceptés, un algorithme bidon a été normalisé, TLS_RENEGO_PROTECTION_REQUEST. L'envoyer dans la liste des algorithmes ne plantera personne (les algorithmes inconnus sont légion et ne perturbent aucune implémentation) et permettra d'indiquer qu'on gère la nouvelle extension. (Oui, c'est un bricolage mais, dans le monde réel, on doit souvent utiliser de tels bricolages pour assurer un déploiement réussi, malgré la présence de logiciels bogués.)

Après ce petit détour sur la compatibilité, le RFC décrit en détail le comportement que doivent adopter clients et serveurs, aussi bien pour la connexion initiale (sections 3.4 et 3.6) que pour une éventuelle renégotiation (sections 3.5 et 3.7). Le client doit envoyer une extension renegotiation_info vide au début, pour indiquer sa volonté de protéger la rénégotiation (ou bien utiliser le truc de l'algorithme de chiffrement bidon). Si cette extension n'est pas dans la réponse, cela peut signifier que le serveur utilise un ancien logiciel, antérieur à notre RFC, ou bien qu'une attaque de l'homme du milieu est en cours. Le client doit donc décider s'il continue en notant juste que secure_renegotiation est faux, ou bien il doit être exigeant et couper la session (après tout, autrement, la nouvelle extension de sécurisation de la renégociation pourrait être rendue inutile par des attaques par repli). Mais la décision est difficile car, au début tout au moins, les clients TLS nouveaux n'auront guère de serveurs « sécurisés » à qui parler. La section 4.1 décrit plus en détail ce problème cornélien.

La situation est plus simple pour le serveur qui peut toujours, s'il rencontre un vieux client, refuser une éventuelle renégociation. La méthode recommandée en section 4.3 (et 4.4 et 5) est donc de n'accepter de renégociation qu'avec un client compatible avec ce RFC 5746.

La renégociation, même sécurisée par une liaison cryptographique avec l'état antérieur de la session, soulève d'amusants problèmes de sécurité, que traite la section 5. Ainsi, beaucoup de logiciels croient qu'en appelant getPeerCertificates(), ils obtiennent une liste de certificats immuable, qui est valide tout le temps de la session. Mais ce n'est pas le cas s'il y a renégociation.

Notre RFC recommande donc aux bibliothèques TLS de fournir un moyen d'autoriser ou d'interdire la renégociation (ce n'était pas le cas d'OpenSSL avant la découverte de la faille de sécurité.) Il y a d'autres recommandations comme celle d'offrir une possibilité de permettre la rénégociation mais sans changement des certificats (d'autant plus que, avec la plupart des bibliothèques existantes, il n'existe aucun moyen de savoir quelles données ont été transmises avant et après la renégociation).

Aujourd'hui, parmi les deux mises en œuvre de TLS en logiciel libre, OpenSSL a intégré le code pour notre RFC 5746 dans sa version 0.9.8m alors que GnuTLS l'a en développement (l'essentiel du code est dans lib/ext_safe_renegotiation.c et est écrit par un des auteurs du RFC).


Téléchargez le RFC 5746


L'article seul

RFC 5744: Procedures for Rights Handling in the RFC Independent Stream

Date de publication du RFC : Décembre 2009
Auteur(s) du RFC : R. Braden (ISI), J. Halpern (Ericsson)
Pour information
Première rédaction de cet article le 18 décembre 2009


L'infrastructure juridique des « nouveaux » RFC, désormais répartis en plusieurs voies selon leur source, continue à se mettre en place. Ce RFC 5744 décrit les procédures pour les droits liés aux RFC soumis par la voie « indépendante » (RFC soumis par un individu, ni l'IAB, ni un groupe de travail de l'IETF). Actuellement, il existe des dizaines de documents approuvés techniquement, qui attendent dans la file du RFC Editor car ils ont été soumis par cette voie et son statut n'a pas été clarifié depuis le déploiement des « nouveaux » RFC (RFC 5620). Sans doute vont-ils enfin être publiés mais on ne sait pas encore quand.

C'est que la publication d'un RFC, acte essentiellement technique au début, est devenue une grosse affaire juridico-politique. Des centaines de pages de discussions juridiques ont été noircies sur les problèmes de droits donnés par les auteurs (incoming rights, cf. RFC 5378) et les droits (forcément inférieurs ou égaux) que reçoivent les lecteurs (outgoing rights, cf.RFC 5377). Ces deux derniers RFC ne concernaient que les documents produits par l'IETF et, depuis, les documents produits par des individus languissaient sans statut et ne pouvaient être publiés.

Après tant de débats, il est ironique de constater que la procédure pour les RFC « indépendants » est finalement très proche de celle des RFC « IETF ».

Pour se saisir du contexte, la section 2 de notre RFC 5744 rappelle que le systèmes des voies (streams) a été défini dans les RFC 4844 (et RFC 4846, spécifiquement pour la voie indépendante). Cette dernière est une vieille tradition, et permet de publier des RFC qui sont proposés par des individus isolés, ou bien qui ont rencontré le veto de certaines parties à l'IETF (comme le RFC 4408). Tout RFC n'est donc pas le produit d'un groupe de travail IETF.

Depuis le RFC 5620, qui « éclatait » l'ancienne fonction de RFC Editor, la responsabilité des RFC soumis par voie indépendante revient au Independent Stream Editor, qui ne sera finalement désigné qu'en février 2010.

La section 3 pose les buts des nouvelles règles. Reprenant la politique traditionnelle, suivie informellement depuis l'époque de Jon Postel, elle pose comme principe que l'utilisation des RFC doit être la plus libre possible (« Unlimited derivative works »). Toutefois, tous les RFC de la voie indépendante ne sont pas équivalents. Certains sont des republications de documents édités ailleurs (par exemple par d'autres SDO) et les auteurs ont donc la possibilité de demander des restrictions supplémentaires. À noter que ces principes s'appliquent également au code inclus dans les RFC.

Enfin, les règles formelles elle-mêmes, en section 4. La procédure est proche de celle des autres RFC, l'auteur devant donner certains droits pour permettre la publication (par défaut, il donne presque tous les droits, en gardant évidemment l'attribution de son travail). Les termes exacts (le boilerplate) seront fixés par l'IETF Trust.

Le respect de la procédure par l'auteur ne préjuge pas de l'adoption du RFC. L'éditeur de la voie indépendante, l'ISE, reste seul juge de l'intérêt de publier le RFC. Le choix d'un auteur de ne pas permettre la réutilisation du RFC (« no derivative worlks ») peut, par exemple, être motif de rejet.

L'implémentation de cette politique nécessite une action de la part de l'IETF Trust, décrite en section 5. Celui-ci devra accepter la responsabilité de la gestion des droits de propriété intellectuelle pour ces RFC « indépendants » et devra écrire les termes exacts qui seront inclus dans chaque RFC.

Quant aux questions de brevets et de marques déposées, elles sont réglées dans la section 6. Les règles des RFC 2026 et RFC 8179 s'appliquent aux RFC de la voie indépendante comme aux autres : toute prétention de propriété intellectuelle doit être déclarée, de façon à ce que l'ISE puisse décider en toute connaissance de cause (notez bien qu'en pratique, cette règle est parfois violée). Comme d'habitude à l'IETF, il n'y a pas d'a priori sur les conditions de licence des brevets (tout est théoriquement possible) mais notre RFC précise que les termes de licence les plus favorables possibles seront privilégiés, notamment des licenses gratuites, voire implicites.


Téléchargez le RFC 5744


L'article seul

RFC 5742: IESG procedures for handling of independent and IRTF stream submissions

Date de publication du RFC : Décembre 2009
Auteur(s) du RFC : H. Alvestrand (Google), R. Housley (Vigil Security)
Première rédaction de cet article le 5 janvier 2010


Les RFC les plus connus sont ceux produits directement par l'IETF. Ils subissent alors tous un examen par l'IESG, garante de leur qualité et de leur cohérence. On l'ignore souvent mais ce n'est pas le cas de tous les RFC. Certains peuvent être soumis directement au RFC editor (Independent stream), d'autres soumis par d'autres organisations (comme l'IRTF). Que doit faire l'IESG avec eux ?

Le RFC 3932 répondait à cette question. Depuis le RFC 4844, qui formalise les différentes voies (streams) de soumission d'un RFC, il fallait le mettre à jour, ce qui a pris beaucoup de temps, entrainant le blocage d'un grand nombre de RFC indépendants, techniquement au point mais ne pouvant pas être publiés car on ignorait comment les gérer administrativement.

Deux des quatre voies sont traitées dans notre RFC 5742 : celle de l'IRTF et la voie indépendante, celle des documents soumis par des individus. Lorsqu'un document n'est pas passé par l'IETF, il n'a pas forcément été examiné sur les points où le protocole décrit peut causer des problèmes : sécurité, contrôle de congestion, mauvaise interaction avec les protocoles existants (section 1). L'IETF n'assume donc aucune responsabilité pour ces RFC indépendants.

Par contre, ils étaient traditionnellement (RFC 2026, section 4.2.3, puis RFC 3710) examinés par l'IESG. C'était un véritable examen, avec discussion des points techniques avec les auteurs, aller-retour, et discussions qui prenaient des ressources à l'IESG et retardaient sérieusement la publication du RFC. L'IESG avait décidé en mars 2004 de passer à une procédure plus légère (RFC 3932) où l'IESG vérifiait surtout qu'il n'y avait pas de conflit avec un travail en cours à l'IETF. Les commentaires de fond étaient envoyés au RFC editor qui les traitait comme n'importe quel autre commentaire. Quant aux documents de l'IRTF, ils étaient traités, soit comme venant de l'IAB, soit comme soumissions individuelles (ils ont maintenant leur propre voie, décrite dans le RFC 5743).

Notre RFC 5742 décrit la procédure qui est désormais suivie lorsque le RFC editor ou l'IRTF demande un examen plus complet à l'IESG (voir aussi le RFC 4846, qui détaille la voie indépendante).

Quels sont les changements par rapport au RFC 3932 ? La section 1.1 les résume :

  • Nouvel en-tête pour les RFC, indiquant explicitement la voie empruntée (RFC 5741, depuis remplacé par le RFC 7841),
  • Mécanisme de résolution de conflits si l'IESG demande l'ajout d'une note au RFC et que cette note soulève des objections. L'insertion de cette note était obligatoire auparavant (RFC 3932, section 4).

Les détails de l'examen par l'IESG sont désormais dans la section 3. Après étude du document, l'IESG peut décider, au choix :

  • Qu'il n'y a pas de conflit entre ce document et le travail de l'IETF,
  • Qu'il y a une relation avec le travail d'un groupe de l'IETF, sans que cela empêche la publication du document,
  • Qu'il y a risque de gêne du travail d'un groupe et que le document ne devrait pas être publié dans l'immédiat,
  • Que le document empiète sur un travail réservé à l'IETF (par exemple l'ajout d'un élément à un protocole lorsque la norme de ce protocole prescrit une procédure particulière pour de tels ajouts).

Des exemples concrets de conflits sont fournis dans la section 5. Par exemple, la publication d'un protocole « alternatif » (Photuris, RFC 2522) à celui de l'IETF (IKE, RFC 2409) devrait attendre pour laisser le protocole « officiel » être publié en premier. De tels protocoles alternatifs ne posent pas de problème en soi, le choix est une bonne chose, mais il est important qu'ils soient clairement différenciés du protocole de l'IETF. Un autre exemple est la réutilisation de bits « libres » dans un en-tête de paquet lorsque ces bits ont une autre signification dans la norme.

Et si les auteurs ou le RFC editor sont en désaccord avec la conclusion de l'IESG ? C'est la grande nouveauté de notre RFC 5742, une procédure de résolution des conflits, qui fait l'objet de la section 4. Même l'IETF, suivant la judiciarisation croissante de la société, a ses Dispute Resolution Procedures. En quoi consiste t-elle ici ? Dans l'introduction d'une tierce partie, l'IAB, qui sera chargée d'arbitrer tout conflit entre l'IESG et le RFC Editor, si les six semaines de dialogue obligatoire n'ont pas résolu le problème. L'IAB pourra donner raison à l'un ou l'autre et pourra donc, par exemple, imposer au RFC editor l'inclusion d'une note de l'IESG qu'il ne voulait pas.


Téléchargez le RFC 5742


L'article seul

RFC 5741: On RFC Streams, Headers and Boilerplates

Date de publication du RFC : Décembre 2009
Auteur(s) du RFC : L. Daigle, O. Kolkman
Pour information
Première rédaction de cet article le 5 janvier 2010


Les textes sacrés de l'Internet, les RFC, comprennent un certain nombre d'éléments obligatoires, souvent collectivement appelés boilerplates et comprenant, par exemple, les conditions légales d'utilisation du RFC. Ce RFC 5741 écrit par l'IAB les décrit et les précise. Il a depuis été remplacé par le RFC 7841.

Les éléments existants comme Category: Experimental ne suffisaient pas à transporter toute l'information nécessaire. Depuis la formalisation des voies dans le RFC 4844, les différents circuits de publication des RFC, il était devenu crucial de déterminer facilement de quelle voie venait un RFC. (Les anciens RFC étaient tous marqués comme provenant d'un mystérieux Network Working Group, cf. RFC 3.)

Donc, dans sa section 2, notre méta-RFC rappelle que, non seulement tous les RFC ne sont pas des normes (RFC 1796), mais que tous ne sont pas des documents issus de l'IETF, qui n'est qu'une voie parmi d'autres (quoique la plus prolifique). Ainsi, un RFC peut très bien être publié sans que l'IETF n'aie pu donner un avis sur des points comme la sécurité ou le contrôle de congestion, par le biais de procédures comme le IETF Last Call ou l'examen par l'IESG.

La section 3 liste les éléments qui forment la structure d'un RFC. Il y a l'en-tête général (section 3.1) qui, pour notre RFC, est :

Internet Architecture Board (IAB)                         L. Daigle, Ed.
Request for Comments: 5741                               O. Kolkman, Ed.
Updates: 2223, 4844                                          For the IAB
Category: Informational                                    December 2009

indiquant qu'il est issu de la voie IAB, qu'il porte le numéro 5741, qu'il est de la catégorie « Pour information » (les catégories sont décrites dans le RFC 2026), etc. Les autres voies sont IETF, IRTF et « soumission indépendante ».

Après cet en-tête vient un paragraphe (section 3.2.2) qui décrit clairement la voie par laquelle ce RFC est passé. Par exemple, pour une soumission indépendante, le texte (qui est sujet à évolution, en synchronisation avec la définition des voies) actuel est « This is a contribution to the RFC Series, independently of any other RFC stream. The RFC Editor has chosen to publish this document at its discretion and makes no statement about its value for implementation or deployment. ».

Je ne reprends pas ici tous les éléments, qui sont décrits dans cette section 3. Notons simplement le copyright, issu des RFC 5378 et RFC 4879, et l'ISSN des RFC, 2070-1721.

Question mise en œuvre, les programmes XSLT de Julian Reschke sont apparemment à jour pour ce RFC (voir l'annonce officielle). Par contre, xml2rfc ne semble pas encore adapté. (Rappelez-vous que, depuis, ce RFC a été remplacé par le RFC 7841.)


Téléchargez le RFC 5741


L'article seul

RFC 5738: IMAP Support for UTF-8

Date de publication du RFC : Mars 2010
Auteur(s) du RFC : P. Resnick (Qualcomm), C. Newman (Sun)
Expérimental
Réalisé dans le cadre du groupe de travail IETF eai
Première rédaction de cet article le 4 mars 2010


Presque toutes les normes produites par l'IETF sont désormais complètement internationalisées. Il reste quelques trous par-ci, par-là, qui sont comblés lentement. Par exemple, notre RFC 5738 normalise le support d'Unicode par le protocole IMAP d'accès aux boîtes aux lettres. (Il a depuis été remplacé par le RFC 6855.)

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 désormais 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). Ce RFC 5738 fait donc partie de la série de RFC du groupe de travail EAI qui normalise un courrier électronique complètement international.

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 crée une nouvelle, UTF8=ACCEPT (section 3). Par le biais de l'extension ENABLE (RFC 5161), le client peut à son tour indiquer qu'il va utiliser UTF-8. La section 3.1 détaille la représentation des chaînes de caractères UTF-8 sur le réseau.

Des commandes IMAP prennent désormais un paramètre UTF8. C'est le cas de SELECT et EXAMINE (section 3.2) qui permettent de manipuler les boîtes aux lettres. L'utilisation de ce paramètre par le client lors de la sélection d'une boîte change la sémantique de certaines commandes. Par exemple, toute commande qui indique la taille de la boîte aux lettres doit désormais compter en caractères Unicode et non plus en octets.

Les nouvelles capacités sont toutes décrites dans la section 10 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. Dans ce cas, elles ne doivent pas être indiquées par défaut dans le résultat d'une commande LIST (sauf extensions de celle-ci, cf. RFC 5258), puisqu'elles ne pourraient pas forcément être sélectionnées ensuite. À noter qu'IMAP disposait depuis longtemps d'une astuce pour représenter les boîtes aux lettres dont les noms comportaient des caractères non-ASCII, la IMAP Mailbox International Naming Convention (RFC 3501, section 5.1.3). Elle n'a jamais donné satisfaction et la section 3.3 de notre RFC 5738 recommande de l'abandonner.

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 (capacité UTF8=USER), et la section 5 spécifie ce point, en demandant que ces noms soient canonicalisés avec SASLprep (RFC 4013). Le RFC note (annexe A) 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.

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 7 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 en UTF-8 (un tel serveur, en 2010, n'aurait guère de clients...)

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. Si son client ne gère pas UTF-8, le serveur doit alors (section 9) dégrader le messages en ASCII seul, comme expliqué dans le RFC 5504.

Chose relativement rare dans un RFC, l'annexe A contient une discussion détaillée des choix effectués et des raisons de ces choix. Par exemple, le fait que l'accès aux boîtes en UTF-8 se configure boîte par boîte et pas pour tout le serveur, a pour but de permettre aux serveurs existants de ne pas avoir à convertir toutes les boîtes stockées en UTF-8, lors de la mise à jour du logiciel.

Je ne connais pas encore d'implémentation en logiciel libre. À noter que ce RFC a été mis à jour et que la nouvelle version est le RFC 6855.


Téléchargez le RFC 5738


L'article seul

RFC 5737: IPv4 Address Blocks Reserved for Documentation

Date de publication du RFC : Janvier 2010
Auteur(s) du RFC : J. Arkko (Ericsson), M. Cotton (ICANN), L. Vegoda (ICANN)
Pour information
Première rédaction de cet article le 15 janvier 2010


Pendant longtemps, les documentations ou cours sur TCP/IP utilisaient dans les exemples des adresses IP prises un peu au hasard, par exemple sur le réseau de l'auteur. Cela entrainait des problèmes si un lecteur prenait ces exemples trop littéralement et réutilisait ces adresses, rentrant ainsi en conflit avec les adresses existantes. C'est ce qui arrive par exemple au réseau 1. Le RFC 1166 avait donc commencé la bonne tradition de réserver des adresses pour la documentation, tradition que continue notre RFC 5737 (voir aussi le RFC 6890).

Comme le rappelle la section 1, la limite du préfixe 192.0.2.0/24 qui avait été réservé par le RFC 1166 était qu'il était tout seul : un cours sur OSPF ou BGP était assez difficile à faire avec des adresses commençant toutes par 192.0.2. Deux autres préfixes ont donc été ajoutés, 198.51.100.0/24 et 203.0.113.0/24 (section 3). IPv6, lui, a le 2001:db8::/32 du RFC 3849, les numéros de systèmes autonomes ont les plages 64496 à 64511 et 65536 à 65551, du RFC 5398, et les noms de domaine ont les example.org et autres example.net du RFC 2606.

Puisque ces trois préfixes IPv4 sont réservés à la documentation, ils ne devraient jamais apparaitre sur des vrais réseaux, par exemple via BGP (section 4). On peut donc les ajouter aux listes de bogons.

À noter enfin que, contrairement à ce qu'on lit parfois, le préfixe 128.66.0.0/16 n'est pas réservé (section 5) pour la documentation et peut être utilisé pour de vraies allocations.


Téléchargez le RFC 5737


L'article seul

RFC 5736: The IANA IPv4 Special Purpose Address Registry

Date de publication du RFC : Janvier 2010
Auteur(s) du RFC : G. Huston (APNIC), M. Cotton (ICANN), Leo Vegoda (ICANN)
Pour information
Première rédaction de cet article le 15 janvier 2010


Le RFC 5735 ayant réservé un préfixe d'adresses IPv4, 192.0.0.0/24 pour des allocations « spéciales », ce RFC 5736 définit les règles que devra suivre l'IANA pour la gestion du registre des allocations dans ce préfixe.

L'utilité principale de ce préfixe réservé est de permettre des allocations d'adresses IP pour certains protocoles qui ont besoin de coder en dur des adresses. (Il existe déjà un tel registre pour les adresses IPv6, registre décrit dans le RFC 4773.) La section 2 du RFC rappelle les généralités sur le rôle de l'IANA, ses relations avec l'IETF et l'accord qui les lie (RFC 2860).

La section 3 décrit le mécanisme d'allocation proprement dit. Prendre une adresse dans le préfixe 192.0.0.0/24 nécessitera une IETF review (le terme est défini dans le RFC 5226 et désigne une procédure relativement lourde, impliquant l'écriture d'un RFC).

Le registre doit indiquer l'adresse IP réservée, le RFC où son usage est documenté, le caractère routable ou non de cette adresse, etc. À noter que, même si le registre dit qu'une adresse est prévue pour être routée mondialement, le RFC précise qu'on ne peut rien garantir à ce sujet, vue la décentralisation des politiques de routage.

Le registre est vide, pour l'instant. Patience...


Téléchargez le RFC 5736


L'article seul

RFC 5735: Special Use IPv4 Addresses

Date de publication du RFC : Janvier 2010
Auteur(s) du RFC : M. Cotton (ICANN), Leo Vegoda (ICANN)
Première rédaction de cet article le 15 janvier 2010


Un certain nombre de préfixes IPv4 ont une signification spéciale et ce RFC les documente, pour éviter aux lecteurs de devoir fouiller dans les nombreux RFC originaux. (Ce RFC a depuis été remplacé par le registre décrit dans le RFC 6890.)

Normalement, les préfixes des réseaux IPv4 sont attribués par l'IANA aux RIR qui les allouent ensuite aux LIR (qui sont en général des FAI). Ces allocations et les affectations aux utilisateurs finaux sont enregistrées par les RIR et sont publiquement accessibles via des protocoles comme whois. Le premier RFC sur le rôle de l'IANA est le RFC 1174 et la description actuelle du rôle de l'IANA est le RFC 2860.

Mais certains préfixes sont spéciaux et échappent à ce mécanisme. Ils ont été réservés par tel ou tel RFC et sont donc dispersés à plusieurs endroits. Notre RFC, successeur du RFC 3330, écrit par l'IANA, rassemble toutes ces réservations en un seul endroit.

Voici quelques exemples de préfixes ainsi documentés :

  • 10.0.0.0/8, réservé pour les adresses privées par le RFC 1918,
  • 169.254.0.0/16, réservé pour les adresses locales au lien (cette réservation a été documentée dans le RFC 3927),
  • 192.0.0.0/24, réservé pour les protocoles qui ont besoin d'adresses IP spécifiques. Pour l'instant, aucune affectation dans ce nouveau registre n'a été faite, le RFC 5736 décrit les règles que ces affectations suivront,
  • 192.0.2.0/24, 198.51.100.0/24 et 203.0.113.0/24, réservés pour la documentation. Les deux derniers préfixes sont une nouveauté du RFC 5737. Le seul utilisé jusqu'à présent, le 192.0.2.0/24, était trop petit pour certains usages (par exemple, pour un cours BGP, c'était pénible de devoir distinguer 192.0.2.0/25 et,192.0.2.128/25),
  • 198.18.0.0/15, réservé pour les mesures, suivant le RFC 2544,
  • Et bien d'autres, énumérés dans la section 3 et résumés dans la 4.

Si vous avez une idée géniale qui nécessite de réserver un autre préfixe, la marche à suivre est expliquée dans la section 5. Au minimum, vous aurez à écrire un RFC.

Les fanas de la sécurité noteront la section 7, qui précise les filtrages qui devraient faire les routeurs (par exemple, 169.254.0.0/16 ne devrait jamais être routé), et avertit qu'il ne faut pas forcément compter sur ces filtres : tous les routeurs ne sont pas forcément bien configurés. Donc, si vous recevez un paquet IP avec une adresse source en 169.254.0.0/16, cela ne signifie pas forcément qu'il vienne d'une machine locale.

L'annexe A liste les principaux changements par rapport au RFC précédent, le RFC 3330. En raison de l'extrême pénurie d'adresses IPv4, des préfixes ont été définitivement remis dans le circuit normal d'allocation et n'apparaissent donc plus comme spéciaux (par exemple le 24.0.0.0/8). Et deux nouveaux préfixes apparaissent pour la documentation.

Un RFC équivalent existe pour IPv6, le RFC 5156.

Des nouveaux préfixes sont de temps en temps ajoutés à cette liste des préfixes spéciaux, comme le 100.64.0.0/10 du RFC 6598.


Téléchargez le RFC 5735


L'article seul

RFC 5734: Extensible Provisioning Protocol (EPP) Transport over TCP

Date de publication du RFC : Août 2009
Auteur(s) du RFC : S. Hollenbeck (Verisign)
Chemin des normes
Première rédaction de cet article le 22 octobre 2009
Dernière mise à jour le 30 octobre 2009


Ce court RFC spécifie comment utiliser le protocole d'avitaillement EPP au dessus d'une simple connexion TCP.

EPP, décrit dans le RFC 5730 est à sa base uniquement un format XML pour les requêtes d'avitaillement (création, mise à jour et destruction d'objets) et leurs réponses. Ces éléments XML peuvent être transmis de différence façon (au dessus de HTTP, de BEEP, par courrier électronique, etc), et notre RFC normalise la plus commune aujourd'hui, une simple connexion TCP. Il remplace le RFC 4934, avec uniquement des modifications de détail, portant notamment sur l'utilisation de TLS (section 9).

Le RFC est court car il n'y a pas grand'chose à dire, juste l'utilisation des primitives de TCP (ouverture et fermeture de connexion, section 2 du RFC), l'ordre des messages (section 3), le port utilisé (700, 3121 ayant été abandonné, section 7) et le fait que chaque élément EPP soit précédé d'un entier qui indique sa taille (section 4). Sans cet entier (qui joue le même rôle que l'en-tête Content-Length de HTTP), il faudrait, avec la plupart des implémentations, lire les données octet par octet (sans compter que la plupart des analyseurs XML ne savent pas analyser de manière incrémentale, il leur faut tout l'élément). En outre, sa présence permet de s'assurer que toutes les données ont été reçues (voir l'excellent article The ultimate SO_LINGER page, or: why is my tcp not reliable).

L'entier en question est fixé à 32 bits. Si on programme un client EPP en Python, l'utilisation brutale du module struct ne suffit pas forcément. En effet :

struct.pack("I", length)

force un entier (int) mais pas forcément un entier de 32 bits. Pour forcer la taille, il faut utiliser également, comme précisé dans la documentation, les opérateurs < et >, qui servent aussi à forcer la boutianité (merci à Kim-Minh Kaplan pour son aide sur ce point). Voici une démonstration (un "l" standard fait 4 octets alors que le type long de C peut faire 4 ou 8 octets) :

# Machine 32 bits :

Python 2.4.4 (#2, Apr  5 2007, 20:11:18) 
[GCC 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import struct
>>> print struct.calcsize("l")
4
>>> print struct.calcsize(">l")
4
# Machine 64 bits :

Python 2.4.5 (#2, Mar 11 2008, 23:38:15) 
[GCC 4.2.3 (Debian 4.2.3-2)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import struct
>>> print struct.calcsize("l")
8
>>> print struct.calcsize(">l")
4

Si on a quand même un doute, on peut tester la taille obtenue mais ce code est probablement inutile (merci à David Douard pour son aide ici) :


# Get the size of C integers. We need 32 bits unsigned.
format_32 = ">I"
if struct.calcsize(format_32) < 4:
    format_32 = ">L"              
    if struct.calcsize(format_32) != 4:
        raise Exception("Cannot find a 32 bits integer")
elif struct.calcsize(format_32) > 4:
    format_32 = ">H"                
    if struct.calcsize(format_32) != 4:
        raise Exception("Cannot find a 32 bits integer")
else:
    pass
...
def int_from_net(data):
    return struct.unpack(format_32, data)[0]

def int_to_net(value):
    return struct.pack(format_32, value)

L'algorithme complet d'envoi est :

epp_as_string = ElementTree.tostring(epp, encoding="UTF-8")
# +4 for the length field itself (section 4 mandates that)
# +2 for the CRLF at the end
length = int_to_net(len(epp_as_string) + 4 + 2)
self._socket.send(length)
self._socket.send(epp_as_string + "\r\n")

et la lecture :

data = self._socket.recv(4) # RFC 5734, section 4, the length 
                            # field is 4 bytes long
length = int_from_net(data) 
data = self._socket.recv(length-4)
epp = ElementTree.fromstring(data)
if epp.tag != "{%s}epp" % EPP.NS:
     raise EPP_Exception("Not an EPP instance: %s" % epp.tag)
xml = epp[0]

Le code Python complet (qui ne met en œuvre qu'une petite partie de EPP, le but était juste de tester ce RFC 5734), utilisant la bibliothèque ElementTree, est disponible en ligne. Le code ci-dessus comporte une grosse faiblesse (mais classique) : rien ne garantit que recv(n) retournera autant d'octets que réclamé. Il en renverra au plus n mais peut-être moins. Pour de la programmation sérieuse, il faut donc le réécrire avec une fonction du genre :

   def safe_recv(s, n):
       data = ''
       while (n > 0):
           tmp = s.recv(n)
           data += tmp
           n -= len(tmp)
       return data

(Merci à Kim-Minh Kaplan pour son aide sur ce point.)

Pour Perl, ce code ressemblerait (merci à Vincent Levigneron), pour envoyer un élément EPP stocké dans la variable $out, à :

print pack('N', length($out) + 4).$out;

et pour lire un élément EPP :

my $length = unpack "N", $buf;
...
$rc = read STDIN, $buf, $length;

Puisque le format N désigne un entier non signé gros boutien (cf. http://perldoc.perl.org/functions/pack.html).

À noter que cette lecture du champ longueur présente un risque de sécurité : si le serveur malloque aveuglément la taille indiquée dans ce champ, comme il fait quatre octets, le serveur naïf risque de consommer quatre giga-octets de mémoire.

La section 8, consacrée à la sécurité, et surtout la nouvelle section 9, consacrée à TLS, détaillent le processus d'authentification du client et du serveur. L'utilisation de TLS (RFC 5246) est obligatoire, ne serait-ce que pour protéger les mots de passe qui circulent en clair dans les éléments EPP. TLS permet également au client d'authentifier le serveur et au serveur d'authentifier le client, par la présentation de certificats X.509. Leur présentation et leur usage sont désormais obligatoires dans EPP. Notons que, comme toujours avec X.509, la difficulté est de déterminer ce qu'on vérifie. La section 9 détaille le cas où on vérifie un nom et celui où on vérifie une adresse IP. Il serait intéressant de savoir quels registres et quels bureaux d'enregistrement effectuent réellement ces validations...

La liste des changements par rapport au RFC 4934 se trouve dans l'annexe A. Le principal changement consiste en une meilleure spécification des règles de vérification du certificat X.509 lorsque TLS est utilisé (cf. la nouvelle section 9).


Téléchargez le RFC 5734


L'article seul

RFC 5733: Extensible Provisioning Protocol (EPP) Contact Mapping

Date de publication du RFC : Août 2009
Auteur(s) du RFC : S. Hollenbeck (Verisign)
Chemin des normes
Première rédaction de cet article le 14 octobre 2009


Le protocole d'avitaillement EPP ne spécifie pas comment représenter les objets qu'on crée, détruit, modifie, etc. Cette tâche est déléguée à des RFC auxiliaires comme le nôtre, consacré aux contacts, c'est-à-dire aux personnes physiques ou morales responsables d'un objet de la base et qui peuvent être contactées à son sujet. (L'objet étant typiquement un nom de domaine ou bien un préfixe IP.)

EPP permet à un client de créer, détruire et modifier des objets de types différents. En pratique, EPP n'est utilisé que dans l'industrie des noms de domaine mais, en théorie, il pourrait être utilisé pour n'importe quel type d'objets.

Le type n'est donc pas spécifié dans le protocole EPP de base, normalisé dans le RFC 5730, mais dans des RFC supplémentaires. Par exemple, celui qui fait l'objet de cet article spécifie le type, la classe (EPP dit le mapping) pour les contacts. Il remplace le RFC 4933, avec très peu de changement, et marque l'arrivée de cette norme au statut de « norme complète », la dernière étape du chemin des normes de l'IETF.

Ce type est spécifié (section 4 du RFC) dans le langage W3C XML Schema.

Un contact est donc composé d'un identificateur (type clIDType du RFC 5730). Cet identificateur (on l'appelait traditionnellement le handle) est, par exemple, SB68-GANDI (section 2.1).

Les contacts ont également un statut (section 2.2) qui est toujours mis par le client EPP, typiquement le bureau d'enregistrement. Ce mapping ne permet pas aux contacts d'être maîtres de leur propre information et de la changer directement (ce qui est cohérent avec l'approche d'EPP où un intermédiaire, le bureau d'enregistrement, a l'exclusivité des changements).

Les contacts ont aussi évidemment des moyens d'être contactés, via numéro de téléphone, adresse postale, etc. Par exemple, l'adresse de courrier du contact est spécifiée en section 2.6. La syntaxe formelle est celle du RFC 5322, par exemple joe.o'reilly+verisign@example.com. (Mais le schéma XML a une syntaxe plus bien laxiste, presque tout est accepté.)

Les contacts pouvant être des personnes physiques, pour protéger leur vie privée, la section 2.9 du RFC décrit aussi un format pour spécifier si ces informations doivent être publiées ou pas. Insuffisant pour tous les cas, ce format est en général remplacé, chez les registres européens, par un mapping spécifique (par exemple, EPP parameters for .pl ccTLD pour les polonais qui utilisent un élément <individual> pour indiquer si le contact est une personne physique, et a donc droit à la protection des lois européennes sur les données personnelles).

La section 3 normalise ensuite l'usage des commandes standards d'EPP (comme <create>) pour les objets de notre classe « contact ». À titre d'exemple, voici la réponse d'un serveur EPP à une requête <epp:info> (section 3.1.2) pour le contact SB68-GANDI :


<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
  <response>
    <result code="1000">
      <msg>Command completed successfully</msg>
    </result>
    <resData>
      <contact:infData
       xmlns:contact="urn:ietf:params:xml:ns:contact-1.0">
        <contact:id>SB68-GANDI</contact:id>
        <contact:roid>SH8013-REP</contact:roid>
        <contact:status s="clientDeleteProhibited"/>
        <contact:postalInfo type="int">
          <contact:name>John Doe</contact:name>
          <contact:org>Exemple SA</contact:org>
          <contact:addr>
            <contact:street>123 rue de l'Exemple</contact:street>
            <contact:city>Trifouillis-les-Oies</contact:city>
            <contact:cc>FR</contact:cc>
          </contact:addr>
        </contact:postalInfo>
        <contact:voice x="1234">+33.7035555555</contact:voice>
        <contact:fax>+33.7035555556</contact:fax>
        <contact:email>jdoe@example.com</contact:email>
        <contact:crDate>1997-04-03T22:00:00.0Z</contact:crDate>
        <contact:upDate>1999-12-03T09:00:00.0Z</contact:upDate>
        <contact:trDate>2000-04-08T09:00:00.0Z</contact:trDate>
        <contact:authInfo>
          <contact:pw>2fooBAR</contact:pw>
        </contact:authInfo>
        <contact:disclose flag="0">
          <contact:voice/>
          <contact:email/>
        </contact:disclose>
      </contact:infData>
    </resData>
  </response>
</epp>

L'espace de noms XML pour les contacts est urn:ietf:params:xml:ns:contact-1.0.

Comme rappelé par la section 5, EPP utilise XML dont le modèle de caractères est Unicode depuis le début. Logiquement, on devrait donc pouvoir enregistrer des noms et prénoms comportant des accents (comme « Stéphane ») mais je ne suis pas sûr que cela marche avec tous les registres : c'est une chose de transporter la chaîne de caractères Unicode jusqu'au registre et une autre de la stocker dans la base et de la ressortir proprement.

La classe « Contact » permet de représenter certains éléments (comme l'adresse postale) sous deux formes, une en Unicode complet (en indiquant type="loc" et l'autre sous une version restreinte à l'ASCII (en indiquant type="int", notez que ces labels doivent être lus à l'envers, la forme restreinte en labelisée int pour « internationale » et la forme complète loc pour « locale » alors que le contraire aurait été plus logique.)

Ce RFC remplace son prédécesseur, le RFC 4933 mais ce ne sont que des modifications légères, détaillées dans l'annexe A.


Téléchargez le RFC 5733


L'article seul

RFC 5732: Extensible Provisioning Protocol (EPP) Host Mapping

Date de publication du RFC : Août 2009
Auteur(s) du RFC : S. Hollenbeck (Verisign)
Chemin des normes
Première rédaction de cet article le 13 octobre 2009


La représentation des serveurs de noms (host, dans ce contexte) dans un registre de noms de domaine a toujours été une source de confusion et de désaccords. Le protocole EPP d'avitaillement (provisioning) d'un registre a tranché arbitrairement et décidé que la bonne méthode était d'avoir des objets « serveur de noms » (host) explicitement mis dans le registre. C'est ce que normalise notre RFC, successeur du RFC 4932, qui lui-même succédait au RFC 3732.

Un registre de noms de domaine stocke en effet au moins deux classes d'objets : les domaines, bien sûr, et les contacts, les entités (personnes physiques ou organisations) qui gèrent les domaines. Mais cela laisse ouverte la question des serveurs de noms. Pour pouvoir déléguer un domaine, le registre a besoin de ces serveurs, qui se retrouveront en partie droite des enregistrements de type NS, comme ici, dans le registre de .org :

example.org.      IN     NS    ns1.example.org.
                  IN     NS    galadriel.lothlorien.net. 

Comme souvent lors de l'élaboration d'un schéma de données, on peut se poser la question : objet ou attribut ? Les serveurs de noms doivent-ils être des objets « de première classe », gérés en tant que tels, accessibles via whois ou bien doivent-ils être de simples attributs des objets de la classe domaine ?

Les deux approches sont possibles. .com utilise la première. Un serveur de noms est un objet de première classe, vous pouvez le voir avec whois :

% whois ns.kimsufi.com 
...
   Server Name: NS.KIMSUFI.COM
   IP Address: 213.186.33.199
   Registrar: OVH

D'autres registres ont choisi de faire des serveurs de noms de simples attributs. Quelle approche fallait-il retenir pour le protocole d'avitaillement EPP, normalisé dans le RFC 5730 ? Celui-ci sépare le protocole proprement dit de la définition des classes d'objets (classes nommées, dans EPP, mappings. Il existe une classe (un mapping) pour les domaines (RFC 5731), une pour les contacts (RFC 5733) et notre RFC 5732 pour les serveurs de noms. Toutes sont optionnelles. Un registre n'est pas obligé de mettre en œuvre tous ces mappings et peut donc, s'il ne gère pas les objets hosts, ignorer le RFC 5732.

Si un registre choisit, par contre, de gérer des objets « serveur de noms » comme dans ce RFC, la section 1 décrit les relations entre ces objets et les domaines. Ainsi, tout serveur de noms est subordonné à un domaine (le parent) : ns1.example.org est subordonné à example.org et la relation doit être conservée par EPP (par exemple, l'objet host ne peut être créé que par le client EPP qui gère l'objet domaine parent). À noter que le parent peut être externe au registre (par exemple galadriel.lothlorien.net pour le registre de .org).

La section 2 de ce RFC énumère ensuite les attributs de l'objet « serveur de noms ». Le serveur a un nom (par exemple ns2.example.net), conforme aux règles syntaxiques du RFC 1123. Comme tous les objets manipulés avec EPP, il a un identificateur unique spécifique à EPP, le client identifier (voir le RFC 5730). Il a aussi un état (status), qui peut être une combinaison par exemple ok combiné avec linked (qui indique qu'il est utilisé dans au moins un domaine).

Il a enfin une adresse IP facultative. Le RFC recommande de ne la stocker que si elle est nécessaire pour publier la colle, les enregistrements qui permettent de trouver l'adresse IP d'un serveur de noms qui sert la zone dont il fait lui-même partie par exemple dans :

example.org.      IN     NS    ns1.example.org.
                  IN     NS    galadriel.lothlorien.net.

Ici, ns1.example.org est dans la zone qu'il sert (example.org), il faut donc transmettre au registre son adresse IP, pour qu'il puisse publier la colle :

ns1.example.org.          IN   AAAA    2001:db8:314::1:53

alors que cela n'est pas nécessaire pour galadriel.lothlorien.net. Les RFC 2874 et RFC 3596 contiennent des détails sur cette question. La section 3.2.1 de notre RFC, sur la commande <create> revient également sur ce point en insistant que cette commande n'impose pas de transmettre des adresses IP, bien au contraire.

Le cœur d'EPP est décrit dans le RFC 5730, qui inclus une description des commandes possibles (comme <create> ou <delete>). Toutes ne s'appliquent pas à tous les objets et chaque norme d'un mapping doit donc décrire quelles commandes ont un sens pour lui. C'est ici l'objet de la section 3. Par exemple (section 3.1.3), le passage d'un registrar à un autre (transfer) n'a pas de sens pour un objet « serveur de noms » et n'est donc pas défini. L'espace de noms XML du host mapping, de notre classe « serveur de noms » est urn:ietf:params:xml:ns:host-1.0 (voir section 6).

Les commandes <check> et <info> ont leur sens habituel (section 3.1), celui de récupérer des informations sur un objet, ici en donnant son nom. Voici l'exemple donné par le RFC pour la réponse à une commande <info> pour le serveur ns1.example.com :


<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
  <response>
    <result code="1000">
      <msg>Command completed successfully</msg>
    </result>
    <resData>
      <host:infData
       xmlns:host="urn:ietf:params:xml:ns:host-1.0">
        <host:name>ns1.example.com</host:name>
        <host:roid>NS1_EXAMPLE1-REP</host:roid>
        <host:status s="linked"/>
        <host:status s="clientUpdateProhibited"/>
        <host:addr ip="v4">192.0.2.2</host:addr>
        <host:addr ip="v4">192.0.2.29</host:addr>
        <host:addr ip="v6">1080:0:0:0:8:800:200C:417A</host:addr>
        <host:clID>ClientY</host:clID>
        <host:crID>ClientX</host:crID>
        <host:crDate>1999-04-03T22:00:00.0Z</host:crDate>
        <host:upID>ClientX</host:upID>
        <host:upDate>1999-12-03T09:00:00.0Z</host:upDate>
        <host:trDate>2000-04-08T09:00:00.0Z</host:trDate>
      </host:infData>
    </resData>
    <trID>
      <clTRID>ABC-12345</clTRID>
      <svTRID>54322-XYZ</svTRID>
    </trID>
  </response>
</epp>

Les informations spécifiques à notre classe sont dans l'espace de noms urn:ietf:params:xml:ns:host-1.0 dont le préfixe est ici host.

La syntaxe formelle complète de cette classe figure dans la section 4, sous la forme d'un schéma W3C.

L'annexe A rassemble les changements depuis le RFC 4932. Les changements, à part la mise à jour des RFC cités en référence, consistent surtout en une nouvelle licence pour le schéma XML et une précision sur le code de retour 2201 (permission refusée).


Téléchargez le RFC 5732


L'article seul

RFC 5731: Extensible Provisioning Protocol (EPP) Domain Name Mapping

Date de publication du RFC : Août 2009
Auteur(s) du RFC : S. Hollenbeck (Verisign)
Chemin des normes
Première rédaction de cet article le 14 décembre 2009


Le protocole d'avitaillement EPP ne spécifie pas comment représenter les objets qu'on crée, détruit, modifie, etc. Cette tâche est déléguée à des RFC auxiliaires comme le nôtre, consacré aux noms de domaine.

EPP permet à un client de créer, détruire et modifier des objets de types différents. En pratique, EPP n'est utilisé que dans l'industrie des noms de domaine mais, en théorie, il pourrait être utilisé pour n'importe quel type d'objets.

Le type n'est donc pas spécifié dans le protocole EPP de base, normalisé dans le RFC 5730, mais dans des RFC supplémentaires. Par exemple, celui qui fait l'objet de cet article spécifie le type (EPP dit le mapping, on pourrait aussi l'appeler une classe) pour les noms de domaine.

Ce type est spécifié (section 4 du RFC) dans le langage W3C XML Schema.

On note que ce schéma, se voulant adaptable à de nombreux registres différents, ne colle parfaitement à la politique d'aucun. Par exemple, <infData> est spécifié ainsi :


    <sequence>
      <element name="registrant" type="eppcom:clIDType"
       minOccurs="0"/>
      <element name="contact" type="domain:contactType"
       minOccurs="0" maxOccurs="unbounded"/>
      <element name="ns" type="domain:nsType"
       minOccurs="0"/>

ce qui veut dire que des « règles métier » très courantes comme « un titulaire et un seul » ou bien « au moins deux serveurs de noms » ne sont pas respectés avec le schéma EPP seul.

Ce RFC remplace son prédécesseur, le RFC 4931 mais ce ne sont que des modifications de détail, résumées en annexe A. Elles vont en général dans le sens d'une plus grande latitude laissée aux implémenteurs.

Voici un exemple d'une réponse à une requête <epp:info> (section 3.1.2) pour le domaine example.com (comme avec whois mais, typiquement, non public) :


<response>
  <result code="1000">
    <msg>Command completed successfully</msg>
  </result>
  <resData>
    <domain:infData
     xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
      <domain:name>example.com</domain:name>
      <domain:roid>EXAMPLE1-REP</domain:roid>
      <domain:status s="ok"/>
      <domain:registrant>jd1234</domain:registrant>
      <domain:contact type="admin">sh8013</domain:contact>
      <domain:contact type="tech">sh8013</domain:contact>
      <domain:ns>
        <domain:hostObj>ns1.example.com</domain:hostObj>
        <domain:hostObj>ns1.example.net</domain:hostObj>
      </domain:ns>
      <domain:host>ns1.example.com</domain:host>
      <domain:host>ns2.example.com</domain:host>
      <domain:clID>ClientX</domain:clID>
      <domain:crID>ClientY</domain:crID>
      <domain:crDate>1999-04-03T22:00:00.0Z</domain:crDate>
      <domain:upID>ClientX</domain:upID>
      <domain:upDate>1999-12-03T09:00:00.0Z</domain:upDate>
      <domain:exDate>2005-04-03T22:00:00.0Z</domain:exDate>
      <domain:trDate>2000-04-08T09:00:00.0Z</domain:trDate>
      <domain:authInfo>
        <domain:pw>2fooBAR</domain:pw>
      </domain:authInfo>
    </domain:infData>
  </resData>
...

On y voit les serveurs de noms du domaine, ns1.example.com et ns1.example.net, son titulaire, identifié par un code, ici jd1234, sa date de création, le 3 avril 1999, etc.

De même, pour créer un domaine, on appele <epp:create> (section 3.2.1) avec des éléments de l'espace de nom urn:ietf:params:xml:ns:domain-1.0, par exemple :


<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
  <command>
    <create>
      <domain:create
       xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
        <domain:name>example.com</domain:name>
        <domain:period unit="y">2</domain:period>
        <domain:ns>
          <domain:hostObj>ns1.example.com</domain:hostObj>
          <domain:hostObj>ns1.example.net</domain:hostObj>
        </domain:ns>
        <domain:registrant>jd1234</domain:registrant>
...

La liste complète des commandes EPP utilisables pour ce type « domaine » figure dans la section 3.

La syntaxe utilisable pour un nom de domaine est celle du RFC 1123, bien plus restrictive que celle utilisée dans le DNS (section 2.1). Ce type « domaine » ne peut donc pas être utilisé pour tout nom de domaine légal.

Chaque domaine a un « statut », ceux mis par le client (typiquement un registrar) étant préfixés par client (section 2.3). Par exemple, clientHold indique que, à la demande du registrar, ce nom, quoique enregistré, ne doit pas être publié dans le DNS.


Téléchargez le RFC 5731


L'article seul

RFC 5730: Extensible Provisioning Protocol (EPP)

Date de publication du RFC : Août 2009
Auteur(s) du RFC : S. Hollenbeck (Verisign)
Chemin des normes
Première rédaction de cet article le 23 novembre 2009


Les registres, par exemple les registres de noms de domaine fonctionnent parfois sur un modèle registry/registrar c'est-à-dire où le client final doit passer par un intermédiaire, le bureau d'enregistrement (registrar) pour enregistrer son nom de domaine. Le registrar souhaite en général avoir un protocole de communication avec le registre afin d'automatiser ses opérations, dans son langage de programmation favori. EPP, décrit dans ce RFC, est un de ces protocoles d'avitaillement (provisioning, et merci à Olivier Perret pour la traduction). (EPP n'emploie pas le terme de registrar mais celui de sponsoring client, plus neutre. EPP peut donc en théorie être utilisé en cas de vente directe.)

Notre RFC remplace le second RFC sur EPP, le RFC 4930, mais les changements sont mineurs (cf. annexe C, le principal étant que le RFC rend plus clair le fait que la liste des codes de retour est limitative : un registre ne peut pas créer les siens, ce qui est une des plus grosses limitations de EPP). EPP est désormais une norme complète (Full Standard).

EPP a été réalisé sur la base du cahier des charges dans le RFC 3375. Au lieu de s'appuyer sur les protocoles classiques de communication comme XML-RPC ou SOAP, ou même sur l'architecture REST, EPP crée un protocole tout nouveau, consistant en l'établissement d'une connexion (authentifiée) puis sur l'échange d'éléments XML, spécifiés dans le langage W3C Schemas.

Par exemple, l'ouverture de la connexion se fait en envoyant l'élément XML <login> (section 2.9.1.1) :


<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="urn:ietf:params:xml:ns:epp-1.0
     epp-1.0.xsd">
  <command>
    <login>
      <clID>ClientX</clID>
      <pw>foo-BAR2</pw>
      <newPW>bar-FOO2</newPW>
      <options>
        <version>1.0</version>
        <lang>fr-CA</lang>
      </options>
      <svcs>
        <objURI>urn:ietf:params:xml:ns:obj1</objURI>
        <objURI>urn:ietf:params:xml:ns:obj2</objURI>
        <objURI>urn:ietf:params:xml:ns:obj3</objURI>
      </svcs>
    </login>
    <clTRID>ABC-12345</clTRID>
  </command>
</epp>

Les espaces de noms utilisés, comme urn:ietf:params:xml:ns:epp-1.0 sont enregistrés dans le registre IANA (cf. section 6). Le <clTRID> est un identifiant de transaction (celui-ci est choisi par le client) et il facilite la traçabilité des opérations EPP. L'exécution de ces éléments doit être atomique (section 2 du RFC).

Chaque commande EPP entraîne une réponse (section 2.6) qui inclus notamment un code numérique à quatre chiffres (section 3) résumant si la commande a été un succès ou un échec (reprenant le schéma expliqué dans la section 4.2.1 du RFC 5321). Le premier chiffre indique le succès (1) ou l'échec (2) et le second la catégorie (syntaxe, sécurité, etc). Par exemple 1000 est un succès complet, 1001 un succès mais où l'action n'a pas encore été complètement effectuée (par exemple parce qu'une validation asynchrone est nécessaire), 2003, une erreur syntaxique due à l'absence d'un paramètre obligatoire, 2104 une erreur liée à la facturation (crédit expiré, par exemple), 2302, l'objet qu'on essaie de créer existe déjà, etc.

EPP est donc typiquement un protocole synchrone. Toutefois, il dispose également d'un mécanisme de notification asynchrone. La commande EPP <poll> (section 2.9.2.3) permet d'accéder à des messages qui avaient été mis en attente pour un client, et lui donnaient l'état des traitements asynchrones.

Le RFC 5730 spécifie une dizaine de commandes EPP comme <check>, qui permet de s'assurer qu'un objet peut être créé, <info>, qui permet d'accéder aux informations disponibles à propos d'un objet existant (comme whois sauf que whois est typiquement public et EPP typiquement réservé aux bureaux d'enregistrement), <create> pour créer de nouveaux objets (par exemple réserver un nom de domaine), etc.

Comme tout objet géré par EPP a un « sponsoring client », l'entité qui le gère (dans le cas d'un registre de noms de domaine, il s'agit typiquement du bureau d'enregistrement), EPP fournit une commande pour changer ce client, <transfer> (section 2.9.3.4). Des options de cette commande permettent d'initier le transfert, d'annuler une demande en cours, de l'approuver explicitement (pour le client sortant), etc.

La syntaxe formelle des éléments XML possibles est décrite dans la section 4, en utilisant le langage W3C schema.

Le transport de ces éléments XML sur le réseau peut se faire avec différents protocoles, s'ils respectent les caractéristiques listées en section 2.1. Par exemple, le RFC 5734 normalise EPP reposant directement sur TCP.

Un des points délicats de la conception d'un tel protocole est que chaque registre a sa propre politique d'enregistrement et ses propres règles. Quoi que dise ou fasse l'ICANN, cette variété va persister. Par exemple, l'expiration automatique d'un domaine existe dans .com mais pas dans .eu ou .fr. Le protocole EPP ne prévoit donc pas d'éléments pour gérer telle ou telle catégorie d'objets (les domaines mais aussi les serveurs de noms ou les contacts). Il doit être complété par des mappings, des schémas définissant une classe d'objets. Certains de ces mappings sont spécifiés pas l'IETF comme le domain mapping (gestion des domaines) dans le RFC 5731. L'annexe A fournit un exemple de mapping. Plusieurs registres utilisent des mappings non-standard, pour s'adapter à leurs propres règles d'enregistrement, ce qui limite la portabilité des programmes EPP (le cadre d'extension de EPP fait l'objet de la section 2.7). C'est ce qu'ont fait les français, les brésiliens ou les polonais.

Dans tous les cas, chaque objet manipulé avec EPP reçoit un identificateur unique (par exemple SB68-EXAMPLEREP), dont les caractéristiques sont normalisées dans la section 2.8. Les dépôts possibles sont enregistrés dans un registre IANA.

Complexe, EPP n'a pas été reçu avec enthousiasme chez les registres existants, sauf ceux qui refaisaient complètement leur logiciel comme .be. On notera que certains gros TLD comme .de n'utilisent pas EPP (Denic utilise son protocole MRI/RRI). Il existe d'autres protocoles d'avitaillement comme :

et beaucoup d'autres qui ne semblent pas forcément documentés publiquement.

Il existe plusieurs mises en œuvres d'EPP en logiciel libre par exemple le serveur EPP OpenReg de l'ISC, le logiciel Fred du registre de .cz ou bien le client EPP Net::DRI de Patrick Mevzek. Si vous voulez expérimenter avec EPP, vous devez installer votre propre serveur, il n'existe pas de serveur public pour tester.


Téléchargez le RFC 5730


L'article seul

RFC 5724: URI Scheme for Global System for Mobile Communications (GSM) Short Message Service (SMS)

Date de publication du RFC : Janvier 2010
Auteur(s) du RFC : E. Wilde (UC Berkeley), A. Vaha-Sipila (Nokia)
Chemin des normes
Première rédaction de cet article le 9 mars 2010


Il existe des plans d'URI pour tout. Alors, pourquoi pas pour les SMS ? C'est ce que prévoit notre RFC qui ajoute la possibilité d'avoir des liens hypertexte dont la sélection déclenche l'envoi d'un SMS...

D'abord, avec la section 1 du RFC, révisons : le réseau GSM est un réseau de téléphonie mobile très répandu dans certaines parties du monde (en Europe, par exemple), et fonctionnant sur des fréquences comme 900 Mhz, 1800 Mhz, etc. SMS est un service des réseaux GSM qui permet d'envoyer de courts messages texte. Son succès social a été tel que des réseaux non-GSM comme le RNIS l'ont également adopté, et un service de microblogging comme Identi.ca a emprunté bien des points au SMS, comme la longueur maximale d'un message.

Le SMS a en effet une taille maximale, fixée selon des critères un peu complexes (section 1.2.1 du RFC). La norme dit « 160 caractères » mais, limités à sept bits, ce ne sont pas des caractères Unicode. La vraie limite est en fait de 140 octets. Il existe diverses méthodes (typiquement non-standards) pour stocker dans ces 140 octets de l'UTF-16 ou bien des choses rigolotes comme les émoticons.

La délivrance des SMS se fait via un, et parfois plusieurs, serveur, le SMSC (Short Message Service Center).

La section 1.2.4 explique ensuite l'intérêt de spécifier un plan sms pour le Web. Ce dernier est aujourd'hui l'interface principale d'accès à l'information, notamment grâce à l'invention des URI. Parmi les URI, mailto: (RFC 6068) est devenu très populaire, en permettant d'envoyer un message « depuis » une page Web. L'idée est donc de faire pour les SMS ce que mailto: a permis pour le courrier. (Il existe aussi un tel: pour le téléphone, cf. RFC 3966.)

Le RFC note toutefois que, si la plupart des navigateurs permettent d'associer un programme externe à un contenu de type MIME inconnu (sans toucher au code source du navigateur), cette possibilité n'existe en général pas pour les plans d'URI inconnus. Ceux-ci nécessitent en général de modifier le navigateur, ou bien d'utiliser ses fonctions d'accueil de greffons (c'est le cas de Firefox).

Bref, venons en maintenant à la vraie normalisation ; la section 2 définit ce nouveau plan sms. Il s'appuie sur le RFC 3966 pour la syntaxe des numéros de téléphone (en incluant l'erratum 203). La syntaxe formelle des nouveaux URI figure en section 2.2. Un exemple simple est sms:+15105550101. Un exemple plus complexe est sms:+15105550101?body=hello%20there (d'autres exemples figurent en section 2.5). Ce second exemple illustre l'utilisation de champs (ici, un seul champ, body, qui indique le contenu du message) permettant d'étendre l'URI. Pour que l'ajout de champs ultérieurs soit possible, le RFC impose que les champs inconnus soient ignorés.

Pendant qu'on parle du champ body, la section 2.2 précise également son encodage : de l'UTF-8 avec le surencodage pour-cent, comme l'illustre le %20 ci-dessus.

Un RFC décrivant un plan d'URI n'est pas complet sans le formulaire d'enregistrement formel (RFC 4395, section 5.4), qui figure en section 3. sms: est donc désormais dans le registre IANA.

Et naturellement, le RFC se conclus par la section sur la sécurité (section 4), qui rappelle notamment que, l'envoi d'un SMS étant souvent payant pour l'abonné, le navigateur ne doit pas déclencher cet envoi sur un simple clic, il doit demander confirmation ! D'autre part, cette section attire l'attention des utilisateurs sur le fait que le SMS ne présente aucune confidentialité et aucun mécanisme d'authentification, contrairement au courrier électronique.


Téléchargez le RFC 5724


L'article seul

RFC 5715: A Framework for Loop-free Convergence

Date de publication du RFC : Janvier 2010
Auteur(s) du RFC : M. Shand, S. Bryant
Pour information
Réalisé dans le cadre du groupe de travail IETF rtgwg
Première rédaction de cet article le 19 janvier 2010


Le groupe de travail rtgwg de l'IETF travaille entre autre à définir des protocoles et des méthodes pour éliminer les micro-boucles lors d'un changement des routes dans un réseau IP. Une micro-boucle est la boucle temporaire qui se forme entre deux (parfois davantage) routeurs lorsqu'ils n'ont pas mis à jour leur table de routage pile en même temps. Pendant quelques secondes, le routeur A envoie les paquets à B, qui les envoie à A, qui les envoie à B... Notre RFC 5715 explique le problème, ses causes et ses effets, et expose les solutions existantes.

La section 1 rappelle le fonctionnement du routage IP. Les routeurs n'ont pas une vue commune du réseau. Lorsque celui-ci change, que ce soit suite à une « mauvaise nouvelle » (la rupture d'un câble) ou suite à une « bonne nouvelle » (l'ajout d'un nouveau lien), il faut un temps fini pour propager l'information à tous les routeurs et pour que ceux-ci mettent à jour leur FIB. Pendant ce temps de convergence, les routeurs ne fonctionnent pas sur une vision commune et les micro-boucles apparaissent. Les paquets vont alors tourner en rond, consommant de la capacité du réseau, avant d'être jetés lorsque leur TTL (Hop Count en IPv6) est terminé.

Ces micro-boucles sont-elles graves ? En général, les protocoles situés au dessus corrigent automatiquement. Mais de nouveaux services Internet pourraient être plus sensibles et souhaiteraient une transition sans douleur, sans délai et sans perte de paquets.

Cet idéal est évidemment utopique mais il existe quand même des méthodes pour améliorer les choses comme celles du RFC 4090 pour MPLS ou du RFC 5714 pour IP.

Parmi les voies possibles pour traiter le problème des micro-boucles, il y a des techniques de convergence suffisamment rapides pour que le problème soit minimal, ou bien des topologies du réseau qui rendent les micro-boucles rares ou impossibles.

La section 2 est consacrée à étudier plus en détail ce qu'est une micro-boucle et dans quelles conditions elles se forment. La micro-boucle est un phénomène temporaire, inévitable dans un paradigme de routage « saut après saut » qui est celui d'IP (chaque routeur ne se préoccupe que du saut suivant). Elle est « micro » par sa durée et par le petit nombre de routeurs en jeu (souvent seulement deux). La création d'une boucle nécessite au moins une des conditions suivantes :

  • Liens dont les coûts sont asymétriques,
  • Existence entre deux routeurs de deux chemins, de coût égal, avec des routeurs qui tranchent de manière différente lorsque deux chemins sont possibles et équivalents,
  • Et surtout, ce qui est la cause des micro-boucles, changement de topologie du réseau, pendant la phase de transition. Ce changement est souvent une panne mais ce peut aussi être un ajout d'un nouveau lien, ou bien une action délibérée de l'administrateur réseaux, par exemple parce qu'il change le coût d'un lien.

Les micro-boucles ont deux conséquences :

  • Consommation inutile de la capacité du réseau (un paquet peut passer 128 fois dans chaque sens, avant que son TTL n'expire),
  • Risque pour la convergence des routeurs car le trafic des protocoles de routage, s'il est pris dans la boucle, risque de ne pas atteindre son destinataire, l'empêchant de mettre sa table à jour.

Que peut-on faire contre les micro-boucles ? C'est un travail pour la section 4 et des suivantes. Il existe plusieurs stratégies, limiter les dégâts, empêcher les boucles de se former, les supprimer quand elles apparaissent ou bien minimiser le risque d'occurrence (par exemple par des réseaux avec davantage de maillage). Elles sont détaillées dans les sections suivantes. D'abord, la section 5 explique comment limiter les dégâts, soit en accélérant la convergence du réseau, soit avec la méthode PLSN (Path Locking with Safe Neighbors), non encore décrite dans un RFC (mais résumée en section 7), qui consiste à tenir compte de l'état du réseau avant et après le changement avant de choisir d'envoyer dorénavant du trafic à un voisin. La simulation montre que cette méthode est efficace mais elle ne fait que limiter les micro-boucles, pas les empêcher.

Et la prévention ? La section 6 est là pour ça. Elle ne liste pas moins de huit méthodes pouvant empêcher les micro-boucles de se former. Mais toutes ne sont pas réalistes. Parmi elles :

  • Au lieu de faire passer d'un coup le coût d'un lien coupé de N à « infini », l'incrémenter doucement. L'analyse montre que cela suffira (section 6.1).
  • Divers systèmes d'overlays ou de tunnels (sections 6.2 à 6.4). Cela aurait évidemment les inconvénients habituels des tunnels (comme la faible performance de beaucoup de routeurs avec ce type de trafic).
  • La cause fondamentale des micro-boucles étant le manque d'information, on pourrait aussi marquer les paquets pour indiquer par où ils sont passés, ce qui permettrait de détecter facilement qu'un paquet est déjà passé et qu'il y a donc une boucle (section 6.5). Mais cela compliquerait les routeurs de manière non-standard.
  • On pourrait enfin introduire davantage de synchronisation entre les mises à jour des FIB de chaque routeur (sections 6.7 et 6.8). Actuellement, le changement de FIB se fait dans chaque routeur indépendamment. On pourrait imaginer que chaque routeur calcule la nouvelle FIB (sans l'installer), qu'un algorithme permette de sélectionner le moment du changement et, si tous les routeurs sont à l'heure avec NTP, ils basculeraient au même moment.

Et la suppression des boucles, une fois qu'elles sont formées ? Pour détecter la micro-boucle, La section 8 examine deux possibilités, une forme de mémoire des paquets déjà vus, dans le routeur (très consommatrice en ressources) et une méthode plus simple : détecter une boucle au fait qu'un paquet entre par l'interface où on le ferait sortir (mais cela ne marche que pour les boucles simples, symétriques).

Quel que soit le mécanisme adopté, il va falloir le déployer dans l'Internet existant et la section 9 rappelle donc l'importance de la compatibilité avec cet existant.

Enfin, une comparaison des différentes méthodes occupe la section 10. Plusieurs méthodes semblent réalistes pour les protocoles futurs.


Téléchargez le RFC 5715


L'article seul

RFC 5714: IP Fast Reroute Framework

Date de publication du RFC : Janvier 2010
Auteur(s) du RFC : M. Shand, S. Bryant (Cisco)
Pour information
Réalisé dans le cadre du groupe de travail IETF rtgwg
Première rédaction de cet article le 19 janvier 2010


IP a une propriété très utile : la route entre deux points n'est pas fixée à l'avance et peut être modifiée même en cours de conversation. Cela permet aux réseaux IP de continuer à fonctionner même lorsque des coupures surviennent, s'il existe un chemin alternatif. Par contre, trouver ce chemin alternatif et l'utiliser prend du temps et ce délai peut être fatal à certaines applications plus ou moins temps-réel. D'où la nécessité de développer une méthodologie et des mécanismes pour un reroutage rapide. Ce RFC 5714 est consacré à décrire le cadre général de ce reroutage rapide.

De tels mécanismes existent déjà pour certains protocoles de couche 2, comme SONET, ou de couche « 2,5 » comme MPLS. Mais le but du travail sur le reroutage rapide IP est d'avoir une solution générale pour tous les réseaux IP.

Donc, après une section 1 de terminologie, commençons par décrire le problème (section 2). Lorsqu'un lien physique tombe en panne, même si des liens alternatifs sont disponibles, il s'écoule une période non nulle pendant laquelle les paquets ne peuvent plus être transmis. Ces paquets sont alors souvent jetés par les routeurs. Traditionnellement, dans un réseau IP, les durées de ces périodes atteignaient facilement plusieurs secondes. Pour certains applications (par exemple SMTP) ce n'est pas un problème. Mais certains services récents ont davantage de mal à tolérer ces courtes coupures. Calculer de nouvelles routes, dans un environnement distribué comme l'Internet, ne peut pas être « temps-réel ». Mais il existe une autre solution : calculer à l'avance les routes de secours ce qui permettrait de remplacer la route passant par le lien en panne en un temps bien plus court. C'est l'approche utilisée par le mécanisme Fast Reroute de MPLS (RFC 4090) et le but du projet IP Fast Reroute est de spécifier des mécanismes analogues dans un environnement purement IP.

Ces mécanismes sont loin d'être complètement définis, notre RFC 5714 se contenant de définir un cadre général pour leur élaboration. D'autre part, le projet se limite pour l'instant aux IGP à état des liaisons (section 3), une extension aux autres IGP ou bien aux protocoles de routage externes comme BGP étant possible dans le futur.

La section 4 du RFC analyse le problème. D'où vient le délai avant que la route alternative soit utilisable ? Il y a plusieurs sources de retard :

  • Le temps de détection de la panne. Lorsque celle-ci peut être détectée physiquement (câble Ethernet débranché, avec perte du signal de lien), ce temps est parfois de quelques milli-secondes. Mais, lorsque la détection se fait par l'absence, pendant une certaine période, d'un message (par exemple le paquet Hello d'OSPF), alors, des durées de plusieurs dizaines de secondes sont possibles.
  • Le temps pour le routeur de se reconfigurer.
  • Le temps pour le routeur de passer l'information à ses voisins (de dix à cent milli-secondes par saut entre deux routeurs).
  • Le temps de recalculer les tables de routage (quelques milli-secondes avec un algorithme comme celui de Dijkstra).
  • Le temps de recharger les nouvelles tables, par exemple en reconfigurant les ASIC. Il peut atteindre des centaines de milli-secondes.

Toutes ces opérations n'étant pas instantanées et devant être effectuées par plusieurs routeurs, le réseau sera dans un état incohérent pendant un moment et on verra des micro-boucles temporaires se former (une micro-boucle est le ping-pong entre deux routeurs, chacun croyant que l'autre est la meilleure route, cf. RFC 5715).

Quels sont les mécanismes disponibles pour faire mieux ? La section 5 les expose. Pour la détection de la panne (section 5.1), l'aide du matériel est bien pratique : si la fibre est coupée, la disparition de la lumière indique le problème immédiatement. Mais il existe aussi des protocoles indépendants du protocole de routage, et dédiés à la détection de pannes, comme BFD.

Pour réparer la panne, l'idée de base est de pré-calculer les chemins alternatifs, ce qui permettra de les installer rapidement (section 5.2). La plupart des pannes devraient pouvoir être réparées avec les techniques du RFC 5286, qui ne nécessitent pas de marquage spécial des paquets IP. Pour les autres, des techniques plus avancées sont nécessaires comme le calcul et le stockage à l'avance de plusieurs FIB dans les routeurs, combinés avec un mécanisme de signalisation permettant d'indiquer que le paquet doit prendre la route de secours. Des mécanismes reposant sur un routage explicite, par exemple avec des tunnels, sont également possibles.

Au fait, j'ai utilisé des termes vagues comme « la plupart ». Peut-on les quantifier ? La section 5.2.2 analyse le succès de chaque mécanisme en fonction de la topologie.

Enfin, pour la prévention des micro-boucles, la section 5.3 renvoie au RFC 5715 qui liste les possibilités.


Téléchargez le RFC 5714


L'article seul

RFC 5706: Guidelines for Considering Operations and Management of New Protocols and Protocol Extensions

Date de publication du RFC : Novembre 2009
Auteur(s) du RFC : D. Harrington (Huwaei / Symantec)
Pour information
Première rédaction de cet article le 8 décembre 2009


Ce n'est pas tout de normaliser des protocoles. Pour qu'ils ne rendent pas la vie impossible aux administrateurs réseaux, il faut encore qu'ils soient faciles à administrer. Cela peut être plus facile si ces questions opérationnelles ont été prises en compte dès le début. Ce RFC 5706 demande donc que tout nouveau protocole fait à l'IETF reçoive, dès le début, une sérieuse attention pour ses problèmes de gestion. Le faire a posteriori est en effet souvent moins efficace.

Ce RFC est essentiellement composé d'une liste de recommandations (très détaillées) aux auteurs de nouveaux protocoles, expliquant les étapes qu'ils doivent suivre pour que leur protocole soit « gérable ». Cette liste est résumé dans l'annexe A, qu'il suffit normalement de suivre pas-à-pas pour que le protocole soit complet.

La section 1.1 resitue la question : cela fait longtemps que l'IETF demande aux auteurs de protocole de prévoir les mécanismes de gestion pratique dès le début. Un cadre existe pour cela, autour du SMI (modèle décrivant les variables du protocole) du RFC 2578 (et du protocole qui lui est le plus souvent associé, SNMP ; voir le RFC 3410). Mais ce modèle est trop étroit et ne couvre pas l'intégralité de ce qu'il faut savoir pour le déploiement et l'administration d'un protocole. Sans aller jusqu'à formellement imposer une section Management Considerations dans les RFC (comme il existe une Security Considerations obligatoire), notre RFC 5706 demande une attention sérieuse portée, dès le début, aux questions de gestion et d'opération des réseaux.

La différence entre « gestion » (management) et « opération » (operation) est décrite en section 1.2. Les opérations, c'est faire fonctionner le réseau, même sans mécanisme de gestion. La gestion, c'est utiliser des mécanismes qui ont été créés dans le but d'améliorer les opérations.

Contrairement à l'idée dominante à l'IETF depuis quinze ans, et depuis les grandes luttes entre SNMP et CMIP, il n'est plus envisagé (section 1.3) d'atteindre le Graal du mécanisme unique. Toutes les solutions sont désormais acceptables, pourvu qu'elles marchent. (Parmi les échecs du SMI, on peut noter celui décrit par le RFC 3197. Aujourd'hui encore, les serveurs DNS sont gérés par des mécanismes non-standard comme la commande rndc de BIND.)

Le RFC 5706 va donc donner des lignes directrices et des conseils, plutôt que des obligations. C'est donc un assouplissement par rapport à l'ancienne politique de l'IESG qui exigeait une MIB (description des variables en suivant le SMI) pour tout protocole, au grand désespoir de certains auteurs.

Les sections 1.4 et 1.5 rappellent l'histoire tourmentée des mécanismes de gestion des réseaux TCP/IP. Par exemple, une date importante avait été le RFC 1052 en 1988, qui séparait le langage de modélisation (celui qui sert à écrire la MIB) du protocole d'accès aux données (aujourd'hui SNMP). Une autre avait été le RFC 3139 en 2001,