Je suis Charlie

Autres trucs

Accueil

Seulement les RFC

Seulement les fiches de lecture

Mon livre « Cyberstructure »

Ève

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


RFC 7826: Real-Time Streaming Protocol Version 2.0

Date de publication du RFC : Décembre 2016
Auteur(s) du RFC : H. Schulzrinne (Columbia University), A. Rao (Cisco), R. Lanphier, M. Westerlund (Ericsson AB), M. Stiemerling (NEC)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF mmusic
Première rédaction de cet article le 28 décembre 2016


Voici la version 2 du protocole bien connu RTSP, protocole servant à accéder à des flux vidéo. Comme c'est ce que j'utilise pour regarder la télévision sur l'écran de mon PC, je suis ravi que l'IETF se préoccupe de l'améliorer.

Comme beaucoup de protocoles dans le monde du multimédia (SIP, par exemple), RTSP est en fait uniquement un protocole de contrôle, permettant de déclencher ou d'arrêter des flux audio ou vidéo. Ces flux peuvent être temps-réel ou bien avoir simplement été stockés sur le disque d'un serveur. Donc, RTSP est une zapette logicielle. RTSP fait le contrôle et plusieurs protocoles peuvent être utilisés pour le transport des données, UDP, TCP, RTP, etc. À noter la taille impressionnante de ce RFC, avec plus de 300 pages. Ce n'est pas que le protocole soit si compliqué que cela, mais il y a beaucoup d'options et de choix.

La section 2 du RFC résume le protocole : RTSP est client/serveur, le client RTSP se connecte au serveur, un certain nombre de choix techniques sont faits et ensuite l'envoi des données commence. Physiquement, les messages sont du texte (la syntaxe de RTSP ressemble beaucoup à celle d'HTTP) bien que du binaire soit parfois possible. La ressource convoitée est identifiée par un URI de plan rtsp (ou rtsps pour TLS) et cet URI contient le nom de la machine qui sera utilisée comme serveur. Par exemple, si je dis à mon logiciel RTSP d'utiliser rtsp://mafreebox.freebox.fr/fbxtv_pub/stream?namespace=1&service=658&flavour=ld, la connexion RTSP sur TCP (ou TCP avec TLS) se fera avec mafreebox.freebox.fr. La requête RTSP inclus un certain nombre d'en-têtes comme dans HTTP, et parfois un corps (toujours comme en HTTP). Voici un exemple avec le client VLC. Je le lance avec vlc 'rtsp://mafreebox.freebox.fr/fbxtv_pub/stream?namespace=1&service=897' et on voit (tcpdump ne sait pas apparemment décoder le RTSP mais Wireshark y arrive très bien) :

Internet Protocol Version 4, Src: 192.168.2.1 (192.168.2.1), Dst: 212.27.38.253  (212.27.38.253)
Transmission Control Protocol, Src Port: 45854 (45854), Dst Port: rtsp (554), Seq: 563, Ack: 873, Len: 204
Real Time Streaming Protocol
    Request: PLAY rtsp://mafreebox.freebox.fr/fbxtv_pub/stream?namespace=1&service=897 RTSP/1.0\r\n
    CSeq: 5\r\n
    User-Agent: LibVLC/2.0.3 (LIVE555 Streaming Media v2012.05.17)\r\n
    Session: pokf6CQWbA8CUyC
    Range: npt=0.000-\r\n
    \r\n

Dans l'exemple ci-dessus, le protocole était RTSP version 1.0 (rappelez-vous que ce RFC décrit la version 2), la requête était PLAY (dont le nom dit bien ce qu'elle fait et vous ne serez pas surpris d'apprendre qu'il existe une commande PAUSE) et l'un des en-têtes, User-Agent: montre que j'utilise bien vlc.

Quand au trafic lui-même, on voit (ici avec tcpdump) d'abord du RTSP sur TCP puis un gros flux UDP :

21:34:36.179830 IP (tos 0x10, ttl 64, id 20888, offset 0, flags [DF], proto UDP (17), length 1356)
    212.27.38.253.46099 > 192.168.2.1.34324: [udp sum ok] UDP, length 1328
21:34:36.180040 IP (tos 0x10, ttl 64, id 20889, offset 0, flags [DF], proto UDP (17), length 1356)
    212.27.38.253.46099 > 192.168.2.1.34324: [udp sum ok] UDP, length 1328
21:34:36.180738 IP (tos 0x10, ttl 64, id 20890, offset 0, flags [DF], proto UDP (17), length 1356)
    212.27.38.253.46099 > 192.168.2.1.34324: [udp sum ok] UDP, length 1328

Les contenus auxquels on accède avec RTSP peuvent être de type très variés. Il faut donc une description formalisée des caractéristiques de ce contenu. RTSP peut utiliser plusieurs formats pour cela, le plus répandu étant sans doute SDP (RFC 4566). C'est en tout cas celui utilisé entre mon VLC et ma Freebox. La description peut inclure le nombre de flux (souvent un flux vidéo et plusieurs audios), le protocole de délivrance (RTPRFC 3550 - dans l'exemple ci-dessous), le format (MPEG-2 ici), etc :

    Session Description Protocol
        Session Description Protocol Version (v): 0
        Owner/Creator, Session Id (o): leCDN 1395332443 1395332443 IN IP4 kapoueh.proxad.net
...
        Media Description, name and address (m): video 0 RTP/AVP 33
            Media Type: video
            Media Port: 0
            Media Protocol: RTP/AVP
            Media Format: MPEG-II transport streams
        Media Attribute (a): control:rtsp://mafreebox.freebox.fr/fbxtv_pub/stream?namespace=1&service=658&flavour=ld
            Media Attribute Fieldname: control
            Media Attribute Value: rtsp://mafreebox.freebox.fr/fbxtv_pub/stream?namespace=1&service=658&flavour=ld

Quels sont les changements par rapport à RTSP version 1, la version du RFC 2326 ? Les deux versions, quoique identiques dans leurs principes, ne sont pas compatibles (par exemple, la commande PLAY n'a plus le même comportement, des en-têtes ont changé de syntaxe sans changer de nom, etc). C'est toujours un choix difficile que de casser la compatibilité d'un protocole mais, là, c'était nécessaire vu le nombre de modifications. En outre, RTSP 1 ne permettait pas de déployer facilement des extensions (en-têtes à la syntaxe trop rigide) et le modèle d'extension a changé. L'annexe I de notre RFC résume ce qu'il faut savoir sur ces différences : suppression des requêtes RECORD et ANNOUNCE, suppression de l'option qui permettait de faire passer RTSP (le contrôle, pas les données) sur UDP, gestion complète d'IPv6 (qui manquait en version 1), refactorisation du RFC (les en-têtes qui sont proches de ceux de HTTP sont désormais décrits par un texte spécifique, sans renvoyer au RFC HTTP), etc.

Il y a apparemment au moins une mise en œuvre de RTSP qui a la version 2, et plusieurs des nouveautés de la version 2 ont été mises en œuvre de manière séparée.


Téléchargez le RFC 7826


L'article seul

RFC 7997: The Use of Non-ASCII Characters in RFCs

Date de publication du RFC : Décembre 2016
Auteur(s) du RFC : H. Flanagan (RFC Editor)
Pour information
Première rédaction de cet article le 16 décembre 2016


Les RFC sont forcément écrits en anglais, qui restera la langue officielle (cf. RFC 7322). L'anglais peut s'écrire avec uniquement les caractères ASCII (avec quelques exceptions : resume et résumé ne sont pas le même mot). Mais on pourra désormais inclure des caractères non-ASCII, par exemple pour le nom des auteurs (chic, je pourrais écrire correctement mon prénom dans les RFC). Cette possibilité permettra aussi aux exemples de protocoles Internet utilisant Unicode (la grande majorité) d'être plus lisibles.

Cette nouvelle possibilité fait partie de celles qu'offre le nouveau format des RFC, décrit dans le RFC 7990. Il n'y a quand même pas d'autorisation générale d'inclure n'importe quel caractère Unicode dans les RFC, à n'importe quel endroit. Le RFC Editor pourra toujours refuser tel ou tel caractère, par exemple parce qu'il n'existe pas de police permettant de l'afficher. Et le « non-ASCII » n'est autorisé que dans certains cas, décrits plus loin. La grande majorité du texte sera donc du pur ASCII (RFC 20).

L'encodage de ces caractères sera bien sûr UTF-8.

Il ne suffit pas de proclamer « on a droit à Unicode ». Il faut aussi adapter les outils. Par exemple, notre RFC impose (section 2) que les outils de recherche dans les RFC gèrent correctement la recherche Unicode. (C'est pour traiter le cas des outils imparfaits que le RFC demande aussi que les noms d'auteurs en Unicode soient accompagnés d'une version en ASCII.) Et que le RFC soit affichable correctement sur un bon nombre de plate-formes (d'où la possibilité de rejeter les caractères les plus rares).

Ce problème du repli (vers une version en ACSII pur) est souvent cité dans le RFC. Ainsi, lorsqu'on veut mentionner un caractère Unicode (mettons le thorn islandais), le RFC permet désormais de l'afficher proprement, mais il demande qu'on l'accompagne du numéro du point de code, et, si possible, de son nom Unicode. Cela donnerait, par exemple « For instance, U+00FE, "LATIN SMALL LETTER THORN", þ, is interesting because... ». Notez que cette façon de désigner des caractères Unicode que tout le monde n'arrivera pas forcément à afficher n'est pas vraiment standardisée. Dans les RFC actuels, on trouve des variantes (voir cette discussion). Le RFC contient plusieurs exemples sur la façon d'écrire la phrase « Temperature changes in the Temperature Control Protocol are indicated by the U+2206 character (∆, "INCREMENT") », tous acceptés (le nom Unicode n'est pas obligatoire, il peut être placé avant ou après le caractère lui-même, etc.) Autre cas, ce texte du RFC 8264, « For example, the characters U+13DA U+13A2 U+13B5 U+13AC U+13A2 U+13AC U+13D2 from the Cherokee block look similar to the ASCII characters "STPETER" » deviendrait « For example, the characters U+13DA U+13A2 U+13B5 U+13AC U+13A2 U+13AC U+13D2 (ᏚᎢᎵᎬᎢᎬᏒ) from the Cherokee block look similar to the ASCII characters "STPETER" ». Des tables comme celles des identificateurs et mots de passe Unicode légaux (RFC 8265) seraient ainsi bien plus lisibles.

Pour les noms, par exemple ceux des auteurs. On aurait du « non-ASCII » et un texte de repli, comme (en utilisant le vocabulaire XML du RFC 7991) :

    
<author fullname="רוני אבן" asciiFullname="R. Even"/>
<author fullname="吴钦" asciiFullname="Q. Wu"/>
<author fullname="J. Smith" asciiFullname="J. Smith"/> <!-- Oui, dans
ce cas, il faut le dire deux fois -->

  

Cela permettra enfin d'écrire correctement les noms des auteurs de RFC.

La bibliographie d'un RFC est également un bon endroit où mettre des caractères Unicode, par exemple lorsqu'on cite des textes non-anglo-saxons. Ainsi, la bibliographie du RFC 5933 pourrait inclure :

[GOST3410] "Information technology. Cryptographic data security.
           Signature and verification processes of [electronic]
           digital signature.", GOST R 34.10-2001, Gosudarstvennyi
           Standard of Russian Federation, Government Committee of
           Russia for Standards, 2001. (In Russian)

           "Информационная технология. Криптографическая защита
           информации. Процессы формирования и проверки
           электронной цифровой подписи", GOST R 34.10-2001,
           Государственный стандарт Российской Федерации, 2001.

Le second texte étant l'original russe.

Les règles exactes figurent dans la section 3. D'abord, on peut mettre du « non-ASCII » comme on veut quand il fait partie d'un exemple. Ainsi, la communication XMPP pourrait être décrite de manière plus naturelle. Au lieu de cet exemple de communication en tchèque (RFC 6121) :

  
   <message
       from='juliet@example.com/balcony'
       id='z94nb37h'
       to='romeo@example.net'
       type='chat'
       xml:lang='en'>
     <body>Wherefore art thou, Romeo?</body>
     <body xml:lang='cs'>
        Pro&#x010D;e&#x017D; jsi ty, Romeo?
      </body>
   </message>

On pourra écrire la forme lisible :

  
   <message
       from='juliet@example.com/balcony'
       id='z94nb37h'
       to='romeo@example.net'
       type='chat'
       xml:lang='en'>
     <body>Wherefore art thou, Romeo?</body>
     <body xml:lang='cs'>
        PročeŽ jsi ty, Romeo?
      </body>
   </message>

Ensuite, on peut utiliser le « non-ASCII » pour les cas cités plus haut (noms d'auteurs, textes non-anglophones dans la bibliographie, etc). Pour les exemples utilisant un langage de programmation, notre RFC spécifie qu'il faut suivre les règles du langage en question. Ainsi, Python 3 autorisant l'Unicode même dans les noms de variables, on peut écrire :

    
a = "chocolat" 
b = "café"       # Accentué
ç = "lait"
print(a+b+ç)

  

Enfin, un petit mot sur la normalisation Unicode, pour rappeler que le format des RFC ne garantit rien à ce sujet (on aurait pu décider que NFC serait systématiquement utilisée...) et que les auteurs de RFC ne doivent donc pas compter dessus.

Le premier RFC publié avec des caractères Unicode a été le RFC 8187, en septembre 2017.


Téléchargez le RFC 7997


L'article seul

RFC 7991: The "xml2rfc" Version 3 Vocabulary

Date de publication du RFC : Décembre 2016
Auteur(s) du RFC : P. Hoffman (ICANN)
Pour information
Première rédaction de cet article le 16 décembre 2016


Contrairement à beaucoup de SDO, l'IETF n'avait pas de format standard pour l'écriture de ses documents. Désormais, avec le nouveau cadre décrit dans le RFC 7990, c'est fait. XML, avec le vocabulaire décrit dans ce nouveau RFC, est le format canonique des RFC.

Vous voulez écrire un RFC ? Il est fortement recommandé d'utiliser dès le début le format standard XML, fondé sur un vocabulaire spécifique aux RFC, et mis en œuvre dans la future version de l'outil xml2rfc. Voici donc le vocabulaire « XML2RFC version 3 », succédant à deux versions qui n'étaient pas officiellement standard (les changements depuis la v2, spécifiée dans le RFC 7749, ne sont pas énormes). Notez que le vocabulaire XML et les outils continuent à évoluer, donc ce RFC n'est pas éternel. Et que la version 2 restera sans doute en service pendant encore des années : cela prend du temps de changer les habitudes !

Voici le squelette d'un Internet-Draft écrit avec ce XML :

      
    
<?xml version="1.0" encoding="utf-8"?>
<rfc docName="draft-ietf-dnsop-qname-minimisation-09" submissionType="IETF"
     ipr="trust200902">
<front>
<title abbrev="Qname minimisation">DNS query name minimisation to improve privacy</title>
...
<middle>
<section anchor="intro" title="Introduction and background">
<t>The problem statement is described in <xref
target="RFC7626"/>. [...]
...
</back>
</rfc>

    

Sur ce squelette simple, on voit l'élément racine (<rfc>), l'utilisation des attributs (comme submissionType qui indique la voie prise par le document, ici, l'IETF, cf. RFC 7841), la séparation en trois parties, <front>, qui regroupe les métadonnées, <middle>, qui est le texte principal, et <back>, où se trouvent la bibliographie, les annexes, etc.

Parmi les attributs de cet élément racine <rfc>, notez ipr, qui indique les conditions légales d'utilisation de ce RFC. Dans cet example, la valeur est la plus couramment utilisée : trust200902 (cf. l'annexe A.1) indique les règles de l'IETF Trust datant de 2009 (qui disent en gros que le texte du RFC peut être librement copié, reproduit, distribué et mis en œuvre dans des programmes). L'annexe A de notre RFC détaille ce qu'on appelle le boilerplate, ces textes juridiques obligatoires qui sont ajoutés automatiquement par le logiciel xml2rfc. Ainsi, si on met ipr="trust200902" dans l'élément <rfc>, xml2rfc va automatiquement ajouter « Copyright (c) 2015 IETF Trust and the persons identified as the document authors. All rights reserved. \ This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents [...] »...

Le gros morceau du RFC est la section 2, qui donne la liste des éléments XML acceptés. Je ne vais pas reproduire ici cette liste, juste parler de quelques éléments qui me semblent rigolos.

<section> contient une partie du RFC. Cet élément est hiérarchique : on crée des sous-sections en les mettant sous les sections existantes, et ainsi de suite, récursivement. (Contrairement à ce qui se passe avec HTML, où on indique explicitement le niveau de la section, <h1>, <h2>, etc.) On a aussi <abstract>, qui indique le résumé au début du RFC.

<t> contient un paragraphe et est donc l'équivalent du <p> de HTML.

<artwork> permet de spécifier du texte qui sera représenté comme tel, sans aucune justification, mise à la ligne, etc. (Les tabulations sont interdites, ce qui règle le vieux débat « tabs vs. spaces ».) <artwork> permet de mettre de l'art ASCII dans un RFC, mais la méthode préférée pour les images est désormais SVG, voir le RFC 7996. Le SVG peut être mis directement dans le source XML ou bien inclus par différentes méthodes, dont l'attribut src. Cet attribut src permet de spécifier un fichier externe, l'art ASCII ne servant alors que de solution de secours, pour le format en texte seul. Un attribut type permet d'indiquer le type du dessin (par exemple svg pour les images en SVG). La liste des types possibles sera en ligne. Voici un exemple d'art ASCII :


<artwork type="ascii-art">
 +--------------+				     +----------------+
 |  Alice       |------------------------------------|      Bob	      |
 | 2001:db8::1  |                                    |   2001:db8::2  |
 +--------------+				     +----------------+
</artwork>

    

Le code source, lui, se fait avec l'élément <sourcecode>, un attribut type permettant d'indiquer le langage utilisé (une liste des valeurs possibles sera en ligne). Voici un exemple :

      
<sourcecode type="python">
	  print("Hello, world")
</sourcecode>
      
    

Comme le langage utilisé peut utiliser des caractères qui sont spéciaux pour XML (comme < ou &), il est souvent préférable de mettre le code source dans une section CDATA.

<eref> permet de faire un lien hypertexte vers l'extérieur :


      <t>More text and a <eref
      target="http://www.rfc-editor.org/">lien vers le site du RFC Editor</eref>.</t>
    
    

<ul> permet de représenter les traditionnelles listes à puces :


<t>There are three sorts of DNS requests being issued:</t>
<ul>
<li>Primary request: [...]</li>
<li>Secondary requests: [...]</li>
<li>Tertiary requests: [...]</li>
</ul>
    
    

<references> permet d'indiquer une bibliographie. Il y en a typiquement deux dans un RFC (cf. la section 4.8.6 du RFC 7322), la bibliographie normative (ce qu'il faut absolument avoir lu et compris car le RFC en dépend) et l'informative (ce qu'on peut sauter si on est pressé). Pour aider, le RFC Editor distribue des fichiers XML contenant les références aux RFC publiés, comme http://www.rfc-editor.org/refs/bibxml/reference.RFC.7626.xml.

Le nom d'un auteur de RFC se met avec l'attribut <author>. Comme il peut être en caractères non-ASCII, des attributs permettent d'indiquer une variante en ASCII seul. Par exemple :

      
<author fullname="Patrik Fältström" asciiFullname="Patrik Faltstrom">
	 <organization>Netnod</organization>
</author>

    

Ce format de RFC s'appuie sur XML et il faut donc suivre les règles de XML, notamment sur les caractères spéciaux. Ainsi, le chevron ouvrant doit être remplacé par une séquence d'échappement (&lt; au lieu de <). Si cette contrainte est trop forte, on peut aussi enclore les parties à « échapper » dans une section CDATA.

Le format des RFC permet d'autres caractères que ceux du jeu ASCII, mais avec certaines restrictions (voir RFC 7997).

Le format actuel permet l'inclusion d'autres documents, via des attributs comme l'attribut src pour le code source :

      
<sourcecode type="python" src="hello.py"/>

    

On peut aussi utiliser les mécanismes génériques d'inclusion de XML, comme XInclude (cf. annexe B.1) ou les entités, et c'est souvent utilisé pour la bibliographie :


   <!DOCTYPE rfc [
     <!ENTITY rfc7830 PUBLIC
     "http://xml.resource.org/public/rfc/bibxml/reference.RFC.7830.xml">
   ]>

[...]
     <references>
       &rfc7830;
     </references>
	     
    

À noter qu'il existe un type MIME pour les sources XML de RFC, application/rfc+xml (section 8 de notre RFC).

Si vous voulez voir le schéma XML complet, il est en annexe C (j'en ai exporté une version utilisable telle quelle, sans les sauts de page des RFC, en rfc-v3.rnc). Comme il est écrit en Relax NG, il permet l'utilisation de tous les outils Relax NG, comme le mode emacs nxml-mode et comme rnv. Ainsi, une fois le fichier rfc-v3.rnc chargé dans emacs (menus XML puis Set schema puis File), on dispose de fonctions d'édition bien pratiques (par exemple, on tape un < puis une tabulation et emacs propose de compléter uniquement avec les éléments autorisés à cet endroit). Cela évite bien des erreurs.

À noter que ce RFC ne décrit que les éléments et attributs XML, pas de processing instructions (PI), qui ne sont plus acceptées.

Avec un logiciel comme rnv, on peut tester la syntaxe (uniquement la syntaxe : certaines contraintes dans le RFC ne sont pas exprimables dans le schéma, il a fallu les formuler en langue naturelle dans le texte du RFC) :

% rnv rfc-v3.rnc rfc-v3-sample.xml 
rfc-v3-sample.xml
    

Parfait, ici, tout est bon. S'il y avait eu une erreur :

% rnv rfc-v3.rnc rfc-v3-sample-wrong.xml      
rfc-v3-sample-wrong.xml
rfc-v3-sample-wrong.xml:9:6: error: element ^t not allowed
required:
	element ^section
rfc-v3-sample-wrong.xml:11:2: error: unfinished content of element ^middle
required:
	element ^section
error: some documents are invalid
    

Si le RFC contient des références externes (que rnv ne sait pas traiter), on peut utiliser xmllint pour les remplacer :

%  xmllint --dropdtd --noent draft-dupont-my-protocol.xml | rnv rfc-v3.rnc 
    

On peut aussi utiliser Jing (annexe C.1). Mode d'emploi très court, on télécharge :

% wget https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/jing-trang/jing-20091111.zip
% unzip jing-20091111.zip
% java -jar ./jing-20091111/bin/jing.jar  -c rfc-v3.rnc draft-dupont-my-protocol.xml
%
     

Les changements depuis le texte précédent, le RFC 7749, qui décrivait la version 2 (notre RFC est la version 3), sont décrits dans l'annexe D et résumés en section 1.3. L'idée était notamment d'avoir un vocabulaire plus facile à utiliser, sans pour autant trop changer par rapport au format v2, qui était bien connu des auteurs.

Le changement le plus spectaculaire concerne les listes, qui sont désormais faites, comme en HTML, avec des <dl>, <ul> et <ol>. Dans une liste, le contenu est marqué par <li> et plus <t>. Autre inspiration HTML, l'apparition des tables, avec <table> (et éléments associés comme <tr> et <td>). D'autre part, de nouveaux éléments apparaissent pour marquer du texte, par exemple s'il est important (<em>, qui n'avait pas d'équivalent en v2, dont le seul format de sortie était le texte brut). Il y a aussi un <blockquote> pour les citations. Bien que l'IETF se vante souvent de pratiquer le culte du « running code », il n'y avait pas d'élément XML particulier pour indiquer du code source dans un RFC (on se contentait d'<artwork>). C'est désormais fait avec <sourcecode>. Quelques autres éléments XML nouveaux (je ne les cite pas tous, le RFC fait 159 pages !) : <displayreference> pour associer un chouette texte aux références, <link> pour les liens externes (contrairement à <eref>, qui existait déjà, <link> est spécifique à certains types de documents, par exemple les Internet-Drafts) ou encore <br> pour forcer des sauts de ligne (mauvaise idée que de mettre des éléments de présentation, si vous voulez mon avis).

Il y a aussi de nouveaux attributs XML aux éléments existants. Pour remplacer les PI (processing instructions comme <?rfc toc="yes"?>), on a tocInclude et tocDepth dans l'élément <rfc>, afin de contrôler la table des matières. De même, pour gérer l'internationalisation, il y a désormais un attribut ascii pour les éléments qui acceptent du contenu non-ASCII, afin de fournir une alternative pour les anglophones. Il y a aussi des attributs plus orientés présentation comme keepWithNext ou keepWithPrevious, attributs de <t>, qui expriment un souhait de garder ce paragraphe avec le suivant ou le précédent, pour mieux contrôler la pagination.

En revanche, certains éléments et attributs sont retirés de la circulation. Ils seront encore acceptés par les outils, mais temporairement. <list> subit ce trist sort (remplacé par les éléments HTMLisant comme <ul> et <ol>). <facsimile> disparait également, victime des évolutions technologiques. Parmi les attributs, title disparait (il était utilisé dans des éléments comme <section>) au profit de name (changement assez gratuit, je trouve).

Les autres changements sont bien sûr l'acceptation de caractères non-ASCII, et plein de modifications de détail.

Question mise en œuvre, il faudra patienter. S'il y a déjà eu des mises en œuvre expérimentales et partielles, les vrais logiciels officiels ne sont pas encore, en octobre 2016, développés.


Téléchargez le RFC 7991


L'article seul

RFC 7993: Cascading Style Sheets (CSS) Requirements for RFCs

Date de publication du RFC : Décembre 2016
Auteur(s) du RFC : H. Flanagan (RFC Editor)
Pour information
Première rédaction de cet article le 16 décembre 2016


Le nouveau format des RFC, décrit dans le RFC 7990, prévoit un format canonique, XML, à partir duquel seront automatiquement produits des versions texte brut, PDF, etc. Il y aura évidemment la possibilité de produire une version HTML (RFC 7992) et celle-ci sera bien sûr « stylée » avec CSS. Ce RFC décrit donc le cahier des charges de la feuille de style CSS à développer, avec tous les mots-clés du moment (comme responsive design).

Cette future feuille de style sera le style par défaut (le lecteur pourra toujours la redéfinir). Son but (section 2 du RFC) est de respecter le contenu du RFC (ceux-ci sont parfois des normes : pas question de toucher au texte !) tout en permettant une accessibilité maximale, pour tous les lecteurs, quelle que soit la machine qu'ils utilisent pour accéder au Web.

Plus précisément, la section 3 exige de :

  • Coller aux marquages sémantiques du RFC 7992,
  • Permettre l'accessibilité même aux gens en situation de handicap, comme décrit dans les « Best Practices for Authoring HTML »,
  • Permettre l'utilisation de petits écrans (ce qu'on appelle à tort les mobiles, alors que certains mobiles ne posent aucun problème particulier, car ils ont de grands écrans). Normalement, depuis le tout début du Web, c'est fait automatiquement, car le Web a toujours été prévu pour spécifier un contenu, pas une apparence. Mais certains pratiques ont mené à des pages Web très encombrées, difficiles à réduire automatiquement, ce qui a mené au mouvement du responsive design,
  • Permettre l'utilisation d'écritures diverses, pas juste l'alphabet latin, les RFC permettant désormais des caractères non-ASCII (cf. RFC 7997).

La section 4 donne ensuite les principes de présentation à suivre. Je ne vais pas les reprendre ici dans leur intégralité mais on y trouve :

  • Le code source et les exemples de déroulement d'un protocole réseau seront en chasse fixe, ainsi que l'art ASCII,
  • Le texte devra se réagencer selon la taille de l'écran (ce qui devrait quand même aller de soi quand il s'agit de Web !),
  • Les paragraphes auront un identificateur qui devra être affiché lorsque le pointeur (par exemple la souris) passe au-dessus d'eux,
  • La police par défaut pour l'écran sera sans empattement, inclura Unicode, et sera disponible pour tous les navigateurs importants, avec une licence la rendant disponible.

Il y aura également une feuille de style pour l'impression (comme pour le blog que vous êtes en train de lire, d'ailleurs.) La police par défaut sera cette fois avec empattement.

Enfin, la section 7 et l'annexe A de notre RFC font la liste des classes CSS employées. Par exemple, .pilcrow sera utilisé pour les marques de paragraphe, qui ne seront affichées que lorsque le pointeur passera dessus. .url servira à marquer les URL de manière visuellement distinctive. La classe .cref ne servira que dans les Internet-Drafts, pour afficher les commentaires, mais pas dans les RFC (où les commentaires des auteurs sont supprimés).

La merveilleuse feuille de style qui met en œuvre ces exigences n'est pas encore finie. Un appel d'offres a eu lieu (après relecture). Et on peut voir la feuille temporaire en ligne (pour le développement et les commentaires, c'est sur Github).


Téléchargez le RFC 7993


L'article seul

RFC 7996: SVG Drawings for RFCs: SVG 1.2 RFC

Date de publication du RFC : Décembre 2016
Auteur(s) du RFC : N. Brownlee (University of Auckland)
Pour information
Première rédaction de cet article le 16 décembre 2016


Dans la longue liste de RFC décrivant le nouveau format des RFC (commencez par le RFC 7990), ce document décrit l'utilisation de SVG pour faire (enfin) des graphiques dans les RFC.

Traditionnellement, en effet, seul le texte était possible dans les RFC. (On pouvait toutefois faire des graphiques en art ASCII, dont on imagine bien que ce n'était ni très pratique à écrire - malgré l'excellent mode Emacs picture-mode, ni très facile à lire.) Il y avait de bonnes raisons à cet état de fait, notamment le manque d'un format d'images ouvert et largement répandu. Je parle bien sûr d'images vectorielles car, a priori, dans un RFC, il y aura beaucoup plus de schémas que de photos.

Le processus de décision a été long et compliqué. En 2013, le RFC 6949 notait déjà la décision de permettre des images, en indiquant « Graphics may include ASCII art and a more complex form to be defined, such as SVG line art ». C'est désormais possible. Au fait, c'est quoi, SVG ? Il s'agit d'une norme d'un format d'images vectoriel, gérée par le W3C, et fondée sur XML. Voici un exemple d'un simple dessin en SVG :


<svg xmlns="http://www.w3.org/2000/svg" version="1.2">
  <rect x="25" y="25" width="200" height="200" fill="white" stroke-width="4" stroke="black" />
  <circle cx="125" cy="125" r="75" fill="black" />
  <polyline points="50,150 50,200 200,200 200,100" stroke="black" stroke-width="4" fill="none" />
  <line x1="50" y1="50" x2="200" y2="200" stroke="white" stroke-width="4" />
</svg>

Et voici son rendu : simple-rfc-picture

Les RFC n'utiliseront qu'un sous-ensemble de SVG, spécifié ici. Il existe d'autres sous-ensembles de SVG comme SVG Tiny, prévu pour des équipements contraints, genre smartphones. Ce SVG Tiny a servi de base au SVG des RFC, sous-ensemble limité car on n'attend pas de dessins artistiques et compliqués dans les RFC.

SVG RFC est donc SVG Tiny moins les éléments permettant le multimédia et l'animation (pas de vidéos dans les RFC), l'interaction (pas d'interface utilisateur active dans un RFC), l'utilisation de langages de programmation (pas de JavaScript actif dans un RFC). Plusieurs autres restrictions ont été apportées : pas de couleur (RFC 6949, section 3.2), pas d'IRI, seulement des URI, et pas de choix arbitraire de police.

Comment on écrit du SVG ? S'il est évidemment possible de le faire entièrement à la main avec un éditeur ordinaire, gageons que peu de gens le tenteront. Notre RFC cite des éditeurs graphiques, produisant du SVG, comme les logiciels libres Inkscape et Dia. (Et, si on aime programmer en Python, il y a svgwrite, que je présente plus en détail à la fin.) Attention, Inkscape et Dia produisent du SVG généraliste, pas du SVG RFC, qui est plus restreint. (Je ne connais personnellement pas d'outil pour produire du SVG RFC, ou pour « réduire » un fichier SVG généraliste en enlevant tout ce qui n'appartient pas à SVG RFC. Un tel outil était prévu mais je ne sais pas où il en est. C'était une des fonctions attendues du futur svgcheck.)

Et l'accessibilité (section 4) ? Il est crucial que les RFC soient accessibles à tou·te·s, non seulement que que soit le matériel utilisé, mais également quels que soient les handicaps dont souffre leur propriétaire. C'est bien joli de vouloir ajouter des tas de choses dans les RFC mais encore faut-il ne pas creuser ainsi davantage le fossé entre les utilisateurs. Ainsi, accepter de la couleur (le RFC 6949 limite les futurs RFC au noir et blanc) fait courir le risque que les daltoniens ne puissent pas comprendre un RFC. De même, les graphiques, qui ont l'air comme ça d'être une bonne idée, peuvent aggraver la situation des malvoyants. Le texte seul peut toujours être lu à voix haute par un synthétiseur de parole mais pas le graphique. Comme le note le RFC avec humour, « lire le source SVG à voix haute ne va pas le faire ».

Le texte « Tips for Creating Accessible SVG » donne des bons conseils pour faire du SVG accessible. Et il y a bien sûr la norme ARIA, dont il existe une introduction et de bons exemples. (Désolé, je n'ai pas suivi ces excellents principes dans les exemples ci-dessous, mais j'accepte les patches.)

Si vous voulez voir des exemples concrets, regardez https://www.cs.auckland.ac.nz/~nevil/SVG_RFC_1.2/. Ainsi, l'exemple de schéma d'un en-tête TCP donnera : tcp-header Et le schéma de la communication SIP du RFC 4321 fera rfc4321-fig3.svg

L'annexe A de notre RFC donne un schéma complet (formulé en Relax NG) du SVG des RFC. Il est extrait ici dans le fichier svg-rfc.rnc, que vous pouvez utiliser pour tester la conformité de vos SVG. Par exemple, avec rnv :

% rnv files/svg-rfc.rnc files/tcp-header.svg  
files/tcp-header.svg
    

En revanche, avec du SVG trop « riche » (ici, utilisant les couleurs), on aurait :

% rnv files/svg-rfc.rnc /tmp/test1.svg 
...
/tmp/test1.svg:2:267: error: attribute ^fill with invalid value "red"
required:
	value ^token "none"
	value ^token "black"
	value ^token "white"
	value ^token "#000000"
	value ^token "#FFFFFF"
	value ^token "#ffffff"
	value ^token "inherit"
    

Une alternative, pour tester la validité des SVG conformes à ce profil, sera svgcheck quand il sera développé.

Avec Inkscape, il faut veiller à sauver le fichier en Plain SVG (autrement, on a des ennuis avec les éléments spécifiques d'Inkscape, ex-Sodipodi). Mais il reste malgré cela deux ou trois trucs à corriger manuellement, avant que le document produit par Inkscape soit accepté. Pour Dia, il faut utiliser l'action Export (par défaut, Dia n'enregistre pas en SVG), mais Dia produit alors un document avec une DTD. Si on la retire (manuellement, ou bien avec xmllint --dropdtd), tout se passe bien, le document SVG est alors conforme au profil demandé pour les RFC.

Autre solution que j'aime bien pour faire du SVG, dès qu'on a des éléménts répétitifs et qu'on veut donc automatiser (en Python), svgwrite. Ce schéma en art ASCII :

 +--------------+				     +----------------+
 |  Alice       |------------------------------------|      Bob	      |
 | 2001:db8::1  |                                    |   2001:db8::2  |
 +--------------+				     +----------------+
    

aurait pu être créé avec svgwrite avec network-schema-svgwrite.py, qui donne network-schema-svgwrite

Bien sûr, pour un schéma aussi simple, le gain n'est pas évident, mais il le devient pour les schémas comportant beaucoup d'éléments récurrents. Mais notez que svgwrite ne connait pas le profil « SVG pour RFC » et, par défaut, peut donc produire des SVG invalides (par exemple avec de la couleur). Le programmeur doit donc faire attention.


Téléchargez le RFC 7996


L'article seul

RFC 7994: Requirements for Plain-Text RFCs

Date de publication du RFC : Décembre 2016
Auteur(s) du RFC : H. Flanagan (RFC Editor)
Pour information
Première rédaction de cet article le 16 décembre 2016


Dans la grande série des nombreux RFC spécifiant le nouveau format de ces documents (avec XML étant désormais la référence), ce court RFC décrit le format de publication « texte brut » des RFC.

En effet, si le format « texte brut » n'est plus la référence des RFC, ce format reste toujours utile. Dans le nouveau mécanisme (RFC 7990), il y a désormais plusieurs formats de publication, obtenus à partir du format canonique (celui qui est en XML). Le texte brut est l'un d'eux. Ce format, historiquement le seul utilisé par les RFC, ne disparait pas, mais perd de son importance. Il n'est plus qu'un des formats de publication parmi d'autres (comme HTML, voir le RFC 7992). Le RFC 6949 expliquait ce choix.

À noter que les RFC produits avant ce changement ne sont pas affectés : leur format de référence reste le texte brut (et en ASCII seul).

Bon, désormais, on aura un format de sortie (parmi d'autres) en « texte seul » ou « texte brut ». Mais c'est quoi, le texte brut ? Notre RFC reprend la définition du consortium Unicode : « du texte encodé pour les ordinateurs composé uniquement de points de code d'une norme donnée, sans instructions de format ou de structure ». Bref, les caractères indiqués ne valent que pour eux-mêmes, ils n'indiquent jamais de formatage ou de style. Selon cette définition, HTML, LaTeX et Markdown (RFC 7763) ne sont donc pas du texte brut. (La définition n'est pas 100 % parfaite. La norme Unicode, par exemple, inclut des caractères qui influencent le format.) Le texte brut est donc ce qui est le plus portable : tous les acteurs qui connaissent la norme de jeu de caractères sous-jacente (aujourd'hui, quasiment toujours Unicode) peuvent lire et écrire du texte brut. C'est d'ailleurs une des raisons pour lesquelles les RFC ont si longtemps gardé ce format comme format canonique.

Mais si le texte brut n'est pas idéal comme format de référence, il reste un format de sortie très utile, notamment pour son interopérabilité, ou en raison de l'existence de nombreux outils qui peuvent le traiter (à commencer par grep...) Désormais, donc, le format canonique est le XML décrit dans le RFC 7991 et le texte brut sera produit automatiquement par les nouveaux outils. Mais ce texte brut a des règles qui sont légèrement différentes du texte brut original (« RFC canal historique ») et notre RFC 7994 les décrit. Il est très court, car le format « texte brut » est un format simple.

D'abord, le jeu de caractères (section 2). Ce sera bien sûr Unicode, mais avec les restrictions indiquées dans le RFC 7997. En pratique, là où les caractères non-ASCII ne sont pas autorisés, il faudra utiliser l'ASCII équivalent, donné dans les attributs XML prévus à cet effet (ascii, RFC 7991 en section 2.23.1, asciiFullname en 2.7.1, etc). L'encodage sera obligatoirement UTF-8 (RFC 3629). Curieusement, il est prévu de mettre une BOM au début du document.

Que faire avec les graphiques, désormais autorisés par le RFC 7990, et écrits en SVG (RFC 7996) ? Ces graphiques sont, dans le source XML, à l'intérieur d'un élément <artwork>. Comment les rendre dans du texte brut (section 3 de notre RFC) ? D'abord, si le graphique n'est pas en SVG mais dans le traditionnel art ASCII (indiqué par type=ascii-art), on utilise cet art ASCII. Autrement, notre RFC ne propose pas de solution générale. Il est recommandé aux auteurs de diagrammes et schémas de prévoir une alternative en art ASCII, même quand ils font du SVG.

Enfin, la section 4 du RFC couvre le problème de la « mise en page ». Un caractère de fin de page (U+000C) sera inclus automatiquement toutes les 58 lignes (les outils auront probablement une option pour ne pas inclure de telles marques). L'outil devra gérer le délicat problème des veuves et des orphelines. Les lignes feront 72 caractères, suivies de deux caractères marquant la fin (U+000D U+000A).

Les textes de début du RFC (RFC 5741) seront automatiquement mis comme avant, mais les en-têtes et pieds de page disparaissent. Autre disparition, il n'y aura plus, dans le format de sortie en texte brut, de numéros de pages dans la table des matières (dommage, je trouve, mais c'est au nom de la cohérence avec les autres formats de sortie).


Téléchargez le RFC 7994


L'article seul

RFC 7992: HTML Format for RFCs

Date de publication du RFC : Décembre 2016
Auteur(s) du RFC : J. Hildebrand (Cisco Systems), P. Hoffman (ICANN)
Pour information
Première rédaction de cet article le 16 décembre 2016


Depuis la sortie du RFC 7990 et ses copains, le format canonique (le format de référence) des RFC n'est plus le texte seul mais un langage XML, normalisé dans le RFC 7991. Les formats « de publication » seront produits automatiquement à partir de ce XML. C'est ainsi que notre RFC 7992 décrit la sortie HTML, qui permettra de publier des beaux RFC sur le Web.

HTML, trop riche et trop mouvant, est en effet mal adapté à l'écriture et à la maintenance de documents. Il n'était donc pas envisageable de le choisir comme format canonique. En revanche, il est incontournable comme format de publication. C'est en effet le langage du Web, et il y a donc logiquement une forte demande pour pouvoir lire les RFC en HTML. Avant, lorsque le format canonique était le texte brut, des versions non officielles étaient publiées en HTML (voir un exemple) mais, le texte brut n'ayant pas de formatage précis, ces versions n'avaient pas vraiment l'air de vraies pages Web...

(Notez que ce blog que vous êtes en train de lire est produit par un mécanisme analogue à celui que les RFC suivront désormais : tapé en XML, avec le HTML produit automatiquement.)

La section 1 de notre RFC résume les principes de l'HTML utilisé. D'abord, ce sera un sous-ensemble de HTML (HTML a bien trop de fonctions). Ensuite, la présentation sera largement délégué à une feuille de style CSS, dont les caractéristiques sont mentionnées dans le RFC 7993.

La section 2, elle, est le « cahier des charges » du HTML des RFC. Elle précise les exigences du RFC 6949. Elle concerne les auteurs du ou des logiciels de production des RFC (pour ces logiciels, voir le RFC 7998). Les auteurs de RFC, eux, n'ont pas à s'en soucier, ils écrivent du XML, et le HTML sera produit par les outils.

Le but principal est que l'HTML produit soit parfaitement lisible sur la grande majorité des navigateurs utilisés. Pas question bien sûr d'ajouter une de des ridicules mentions « optimisé pour Internet Explorer » qui étaient si communes sur les sites Web d'amateurs, dans les années 2000. Notre RFC mentionne explicitement l'exigence que les textes soient lisibles avec au moins un navigateur « texte », comme Lynx, certaines personnes accédant au Web ainsi (par obligation ou par goût). C'est l'une des raisons de la décision de ne pas accepter la totalité de HTML.

Le fichier HTML devra être autonome (ne pas dépendre de fichiers extérieurs), de manière à pouvoir être transmis facilement par des mécanismes tels que rsync ou le courrier électronique.

Le JavaScript est accepté mais à condition qu'il ne modifie en aucun cas le texte du RFC. (Il peut, par exemple, ajouter des éléments de navigation, ou afficher des métadonnées.)

On l'a dit, CSS sera utilisé pour la présentation, mais le cahier des charges exige qu'on puisse facilement remplacer la feuille de style par une de son choix, pour s'adapter aux goûts locaux.

Le Web étant fondé sur la notion de lien hypertexte, il y aura évidemment des liens, aussi bien ceux mis explicitement par l'auteur (« ce point est développé en section N »), que ceux ajoutés automatiquement (de la table des matières vers les différentes sections, par exemple).

Un point crucial est évidemment l'accessibilité. Comme le savent tous ceux et toutes celles qui vont régulièrement à Paris Web, c'est un point essentiel mais souvent oublié. Notre RFC note donc que les publications en HTML des futurs RFC devront être accessibles aux malvoyants, aux daltoniens, et aux utilisateurs de petits écrans, par exemple les smartphones. (Note personnelle : ce dernier point ne devrait pas être dans une section sur l'accessibilité. Le Web est prévu - contrairement aux formats du monde du papier, comme PDF - pour être visible sur tous les périphériques.)

Au fait, quelle version de HTML sera utilisée (section 3 de notre RFC) ? Ce sera HTML5 (et pas, et je le déplore, XHTML ; l'inconvénient, souvent cité contre XHTML, de la difficulté à l'écrire n'a pas de sens ici, puisque le HTML sera produit automatiquement).

La section 4 précise la syntaxe utilisée (rappelez-vous qu'on n'accepte pas la totalité de HTML5) : encodage en UTF-8, sauts de ligne en style Unix (un U+000A et rien d'autre), pas de caractères de contrôle comme la tabulation (U+0009). Les éventuels commentaires du source XML ne seront pas mis dans le HTML (l'idée est qu'ils sont pour les auteurs, pas pour les lecteurs).

Il y a des objets divers qu'on retrouve souvent dans le source XML. Ils sont rassemblés dans la section 5. Par exemple, on trouve les identificateurs qui seront mis comme valeur des attributs id dans le HTML produit. Ce sont parfois des identificateurs mis explicitement par l'auteur, et parfois des identificateurs produits par le logiciel, par exemple pour que les entrées de la table des matières pointent vers la section correspondante.

Autre objet récurrent, la marque de paragraphe (pilcrow pied-de-mouche, caractère Unicode U+00B6, celui-ci : ¶), qui sera mise automatiquement derrière chaque paragraphe, mais pas affiché par défaut (il faudra promener le pointeur dessus pour le voir).

Maintenant, attaquons les différentes parties du RFC rendu en HTML. D'abord (section 6), les premiers objets HTML qu'on rencontrera, notamment les métadonnées du RFC. Il y aura évidemment un DOCTYPE identifiant le document comme du HTML5. L'élément racine sera <html>, avec une étiquette de langue qui sera bien sûr en, l'anglais. L'élément <head> qui suivra contiendra une déclaration de jeu de caractère, un titre, et diverses métadonnées :

    

   <meta charset="utf-8">
   <title>The Mother of all RFCs</title>
   <meta name="author" content="Joe Hildebrand">
   <meta name="author" content="Heather Flanagan">
   <meta name="description" content="This document defines...">
   <meta name="generator" content="xmljade v0.2.4">
   <meta name="keywords" content="html,css,rfc">

(Rappelez-vous que le HTML produit n'est hélas pas du XHTML donc il est normal que les <meta> ne soient pas explicitement fermés.) Il y aura aussi un lien vers la licence des RFC, en utilisant le cadre général des liens (RFC 8288) :


   <link rel="license" href="https://www.rfc-editor.org/copyright/">

   

Cette première partie du RFC produit contiendra aussi une feuille de style, ainsi qu'un lien vers une éventuelle feuille locale, au cas où un lecteur souhaiterait lire le RFC selon un style différent :


   <style>
     body {}
     ...
   </style>
   <link rel="stylesheet" type="text/css" href="rfc-local.css">

    

Le début de la partie visible du RFC sera composée d'une <dl> pour les métadonnées affichées, et d'une table des matières. Les métadonnées seront donc du genre :


   <dl id="identifiers">
     <dt>Workgroup:</dt>
       <dd class="workgroup">rfc-interest</dd>
     <dt>Series:</dt>
       <dd class="series">Internet-Draft</dd>
     <dt>Status:</dt>
       <dd class="status">Informational</dd>
     <dt>Published:</dt>
       <dd><time datetime="2014-10-25"
                 class="published">2014-10-25</time></dd>
     ...

    

La partie principale du RFC sera, elle, rendue selon les principes décrits en section 9 pour chacun des éléments XML qui composent le source.

La dernière partie du RFC incluera un index (si le source XML avait un attribut indexInclude dans l'élément <rfc>), les adresses des auteurs (formatées en hCard), et les métadonnées considérées comme les moins importantes (les autres ayant été mises au début).

La section 9 de notre RFC est particulièrement longue car elle décrit le rendu en HTML de tous les éléments du vocabulaire XML du RFC 7991. Je ne vais pas tout décrire ici, juste donner quelques exemples. Ainsi, <artwork> sera rendu dans un élément HTML <pre>, si le schéma était en art ASCII, sera inclus tel quel dans le HTML si le schéma était en SVG (RFC 7996), et sera mis sous forme d'un <img> (avec contenu de plan data:) dans les autres cas. <sourcecode>, lui, est toujours restitué sous forme d'un <pre> HTML.

La traduction de certains éléments en HTML est plus directe. Par exemple, <em> est simplement rendu par le même élément HTML.

Et, pour finir, un petit mot sur la sécurité (section 11) : comme les RFC en HTML ne sont pas forcément téléchargés depuis le Web mais peuvent être lus depuis un fichier local (après, par exemple, synchronisation via rsync), on ne bénéficie pas forcément des protections du navigateur. Donc, prudence.


Téléchargez le RFC 7992


L'article seul

RFC 7998: "xml2rfc" Version 3 Preparation Tool Description

Date de publication du RFC : Décembre 2016
Auteur(s) du RFC : P. Hoffman (ICANN), J. Hildebrand (Cisco)
Pour information
Première rédaction de cet article le 16 décembre 2016


Depuis la sortie du RFC 7990, le format canonique des RFC est le format XML. C'est un texte écrit en XML, selon le vocabulaire du RFC 7991 qui sera la version de référence, archivée et faisant autorité, pour tous les RFC. Comme les auteurs enverront souvent un XML imparfait, un outil de préparation sera nécessaire, pour compléter ce XML imparfait et permettre au RFC Editor de travailler sur une base sérieuse. Ce nouveau RFC décrit ce futur outil de préparation.

Ainsi, les outils qui travailleront sur le format canonique des RFC (par exemple les outils qui produiront le PDF, le HTML, etc) pourront compter sur un document complet et n'auront pas à gérer les écarts des auteurs : seul l'outil de préparation devra s'en soucier.

Cet outil de préparation servira aux RFC une fois qu'ils seront soumis au RFC production center (cf. RFC 8728) mais aussi aux Internet-Drafts pendant leur élaboration.

Dans le second cas (section 3 de notre RFC), le futur outil de préparation prendra un Internet-Draft en entrée et produira un document complet (par exemple avec addition des boilerplates).

Et ce sera à peu près la même chose lorsque le RFC sera presque fini. On passera la version finale dans l'outil de préparation, qui résoudra les références externes et ajoutera les éléments obligatoires manquants.

Bon, et en quoi vont consister exactement ces modifications ? Elle sont décrites dans la section 5, qui forme le gros de ce RFC. Contrairement à l'outil actuel idnits qui se contente de vérifier les Internet-Drafts, le nouvel outil va également corriger le texte, ajoutant des éléments, et changeant les valeurs erronées.

C'est ainsi que l'outil de préparation va traiter les éléments XInclude, les remplaçant par la valeur incluse. Il va traiter les DTD pour les supprimer ensuite (donc, remplacer les entités par leur valeur, et inclure les fichiers inclus par ce mécanisme). Ces deux actions peuvent aujourd'hui être faites par l'outil xmllint, avec xmllint --xinclude --noent --dropdtd NOMDUFICHIER.xml.

Outre ces mécanismes d'inclusion de XML, l'outil de préparation va aussi traiter les inclusions spécifiques au vocabulaire du RFC 7991. Ainsi, <artwork> a un attribut src indiquant la source du graphique, et l'outil de préparation va donc inclure ce graphique. (Idem avec <sourcecode> pour inclure le code source.)

Les instructions XML (PI, Processing Instructions) seront supprimées (ça, je ne sais pas le faire avec xmllint).

L'outil va valider le résultat produit, en utilisant la grammaire Relax NG du RFC 7991. Ça peut aujourd'hui se faire avec xmllint mais aussi avec rnv :

% rnv rfc-v3.rnc rfc-v3-sample.xml
rfc-v3-sample.xml
    

ou bien avec jing :

% java -jar ./jing-20091111/bin/jing.jar  -c rfc-v3.rnc rfc-v3-sample.xml
    

Parmi les nombreuses transformations possibles, citons l'ajout (s'il n'était pas déjà présent) de l'élément <seriesInfo> qui indique s'il s'agit d'un Internet-Draft ou d'un RFC, l'ajout d'un élément <date> s'il manque (sa valeur étant la date du traitement), changement de l'ancien attribut title en name, le retrait des commentaires XML...

Il est fréquent dans les Internet-Drafts de voir des paragraphes qui ne devront pas être inclus dans le futur RFC. C'est le cas s'ils contiennent des exemples réels qui risquent de ne pas être éternels (les RFC peuvent durer longtemps et ne sont jamais modifiés). C'est également le cas s'il s'agit de l'état actuel des mises en œuvre d'un RFC, comme décrit dans le RFC 7942. Dans le système actuel, ces paragraphes sont marqués par un texte en langue naturelle. Dans le nouveau vocabulaire du RFC 7991, ce sera fait avec un attribut removeInRFC. L'outil de préparation pourra enlever automatiquement ce paragraphe quand il préparera un RFC.

L'outil de prépartion devra également arranger le XML. Cela peut se faire aujourd'hui avec xmllint (ses options --format ou bien --pretty). Par contre, il n'est pas prévu de mettre le XML sous sa forme canonique.

Il y aura d'autres opérations faites par l'outil de préparation, voir le RFC pour les détails.

L'outil n'est pas encore développé, un appel d'offres a été lancé et les gagnants ont été les sociétés SeanTek et Elf Tools.


Téléchargez le RFC 7998


L'article seul

RFC 7990: RFC Format Framework

Date de publication du RFC : Décembre 2016
Auteur(s) du RFC : H. Flanagan (RFC Editor)
Pour information
Première rédaction de cet article le 16 décembre 2016


Voici enfin la série de RFC décrivant le nouveau format des RFC. Ce projet a commencé il y a plusieurs années, mais les discussions ont été longues. Ce nouveau RFC et les huit autres qui l'accompagnent, marquent un changement important dans ces « textes sacrés » de l'Internet : l'ancien format « texte brut » n'est plus le format de référence. Désormais, tout RFC sera fait en XML, format d'où seront produits automatiquement des versions texte brut, HTML, PDF, etc.

Les RFC sont des documents cruciaux pour l'Internet. C'est sous forme de RFC que sont publiées les normes techniques de la famille de protocoles TCP/IP. Et il y a bien d'autres RFC qui ne sont pas forcément des normes (cf. RFC 1796). Librement disponibles en ligne (contrairement aux normes techniques des organisations traditionnelles du mésozoïque), dans un format ouvert, la disponibilité des RFC est l'une des raisons du succès de l'Internet.

Parlons de format, justement. Les RFC, jusqu'à maintenant, étaient sous forme de texte brut, et en ASCII seul. (Certes, des versions PDF et HTML non-officielles étaient diffusées mais on voyait bien qu'elles avaient été produites à partir du texte brut... Certes, il était possible depuis dix ans d'écrire les RFC en XML, cf. RFC 2629, mais ce n'était pas le format de référence.) Pourquoi donc se limiter à ce format ? Il y avait plusieurs bonnes (et d'autres moins bonnes) raisons mais il ne faut pas de cacher qu'une des raisons les plus importantes était qu'il est difficile de faire changer un processus de production bien établi, même s'il comprend des archaïsmes, comme l'utilisation de troff pour traiter des documents. L'actuelle éditrice des RFC, Heather Flanagan, a donc eu bien du mérite à faire aboutir ce projet de changement. Il a fallu beaucoup de discussions, dans une communauté souvent divisée. (Que les informaticiens pensent aux grands débats du genre « vi ou emacs ? »)

Le projet de réforme des RFC avait sérieusement commencé en 2013 avec le RFC 6949, le véritable cahier des charges du nouveau format. La décision formelle de migrer vers le nouveau format, et donc de décider que le format de référence serait désormais le XML et non plus le texte brut a été prise en mai 2013. Avant et pendant cette décision, d'innombrables messages ont été échangés sur la liste de diffusion rfc-interest.

Il est important de noter que cette discussion portait sur le processus de publication des RFC terminés. L'élaboration des Internet-Drafts, la décision de les publier ou pas (qui dépend de chaque voie, cf. RFC 8729) ne sont pas concernées.

La section 2 de notre RFC résume le problème que veut résoudre le nouveau format. Le monde a bien changé depuis que seuls une poignée de Californiens anglophones venait aux réunions IETF. Les participants viennent aujourd'hui de 45 pays, situés dans le monde entier, les lecteurs des RFC sont plus divers que jamais, utilisent des engins très variés, et il est toujours aussi crucial que les RFC soient largement disponibles et accessibles, et sur une très longue période (mon favori est le RFC 768, publié en 1980 et toujours d'actualité). Le format de référence en texte ASCII brut ne permettait clairement pas cela.

Mais choisir un successeur n'était pas facile : notre RFC insiste sur le fait qu'il y a aujourd'hui plusieurs groupes qui utilisent les RFC (pas seulement des techniciens, juristes et chefs accèdent aujourd'hui à des RFC), et sur le fait qu'il fallait un compromis entre les besoins actuels et l'importance d'une disponibilité à long terme (par exemple, adopter le format à la mode du moment pourrait se payer cher plus tard lorsque ce format n'intéressera plus personne).

Un peu de terminologie (section 3) est nécessaire pour bien comprendre le choix effectué :

  • Format canonique : le format de référence, archivé, utilisé en cas de conflit (XML, donc). Il est important d'en avoir un, au cas où une bogue dans les logiciels change une partie d'un RFC.
  • Formats de publication : les divers formats sous lesquels est publié le RFC (détaillés en section 7). Peu de gens liront le RFC en XML (quoique cela soit possible, une propriété qui est importante pour la conservation à long terme). Ils liront de l'HTML, du PDF, voire du texte seul pour les traditionnalistes. Tous ces formats seront produits (de préférence automatiquement) à partir du format canonique. Chacun a ses avantages et inconvénients (section 5). Par exemple, HTML avec JavaScript fournit des capacités de navigation bien meilleures que le texte brut.
  • Format révisable : le format que le RFC Editor utilisera pour son travail interne. Ce sera XML.
  • Format de soumission : le format sous lequel le texte sera transmis initialement par les auteurs au RFC Editor. Aujourd'hui, le texte brut est obligatoire, le XML autorisé en prime. Demain, ce sera du XML, mais avec des exigences moins strictes que pour le format canonique.

Et aussi un terme important : texte réagencable (ou réajustable, reflowable text). C'est du texte qui s'ajuste automatiquement à la largeur du dispositif de lecture. C'est banal dans le monde HTML, où c'est fait automatiquement depuis toujours. Mais c'était un des principaux inconvénients de l'ancien format des RFC : le texte avait une largeur fixe.

Quel sera donc exactement le format canonique ? La section 6 répond à cette question :

  • Le langage sera du XML avec le vocabulaire spécifié dans le RFC 7991 (nommé « v3 »). Il est normalement meilleur que les précédents vocabulaires utilisés depuis le RFC 2629.
  • Les auteurs pourront envoyer leur draft en suivant le format dit « v2 » (celui du RFC 7749), voire en texte brut, mais il sera ensuite converti dans le format v3 ci-dessus.
  • Le SVG sera autorisé dans le source XML.
  • Comme en v2, DTD est abandonné, la description officielle du schéma XML est en Relax NG.
  • Les textes obligatoires (RFC 5741) seront automatiquement insérés.
  • Le source XML du format canonique sera autonome. Cela veut dire qu'il n'aura pas de références à des sources extérieures. Ainsi, si un auteur référence un code source externe avec <sourcecode src="[un URI externe]"... (RFC 7991, section 2.48), le code en question sera inclus dans la version canonique. Idem si l'auteur a utilisé XInclude.
  • Il n'y aura pas de commentaires ou de processing instructions dans le source XML. Si l'auteur en a mis, ils seront retirés.

Notez donc que les images (en SVG) seront désormais possibles (voir le RFC 7996).

Le guide du style des RFC (RFC 7322) avait été révisé pour tenir compte de ce nouveau format. Notamment, il se concentre désormais sur le contenu du texte, ne demandant plus aux auteurs des efforts de présentation. (La section 5 résume les changements importants pour les auteurs.)

Enfin, la section 7 décrit les formats de publication. À partir du source XML, seront automatiquement produits HTML, PDF, texte brut et peut-être plus tard d'autres. Le HTML est évidemment la cible évidente. Son utilisation pour les RFC est décrite dans le RFC 7992. Le résultat sera certainement bien meilleur que les versions HTML non-officielles actuelles, qui sont produites à partir du texte brut, qui ne contient pas assez de structure pour faire du bon HTML. La mise en page sera évidemment assurée par CSS (RFC 7993), il y aura une feuille de style standard, que chacun sera bien sûr libre de remplacer. Le SVG sera inclus dans l'HTML (il faudra donc un navigateur qui gère bien SVG). Il y aura même du JavaScript mais avec de sévères restrictions. Notamment, le code JavaScript ne devra pas changer le texte, ou supprimer du texte.

PDF, quant à lui, est spécifié dans le RFC 7995. Il devra suivre le profil PDF/A-3, spécialement prévu pour de l'archivage à long terme, et pour pouvoir être relu par des logiciels PDF n'ayant pas tous les derniers gadgets.

Naturellement, le texte brut n'est pas abandonné. Comme indiqué dans le RFC 7994, il y aura une version en texte brut produite automatiquement à partir du XML, même si elle ne sera plus la version canonique. Parmi les nouveautés par rapport à l'ancien format, UTF-8 sera désormais autorisé, même si c'est de façon limitée (voir les limitations dans le RFC 7997). Il pourra y avoir une variante non découpée en pages.

Dans le futur, il est possible que le format EPUB soit ajouté à cette liste.

Au passage, comment a été décidé cet important changement dans le format des RFC ? La section 4 résume cette histoire. Comme indiqué plus haut, cela a pris très longtemps et nécessité beaucoup de discussions, qui ont notamment eu lieu sur la liste de diffusion rfc-interest, et au cours des réunions physiques de l'IETF. Le cahier des charges a été formalisé en 2013 dans le RFC 6949. Une fois le cahier des charges décidé, une équipe spécialisée a été désignée par le RFC Editor pour mettre au point les détails, notamment en adaptant le langage XML utilisé, partant de la dernière version (RFC 7749), pour arriver au futur langage, RFC 7991. Des éditeurs professionnels ont également été consultés, ainsi d'autres SDO et même des juristes (oui, car aux États-Unis, rien n'est désormais à l'abri d'actions en justice, même pas les RFC, le choix du format de sortie PDF/A-3 venait en partie de la nécessité de répondre aux subpoenas). Le tout était bien sûr fait sous la supervision du RFC Series Oversight Committee. Certaines décisions furent consensuelles, les autres tranchées par le RFC Editor (cf. RFC 8728). Le tout a été approuvé par l'IAB en août 2016.

Après ce tour du passé, le futur. Comment se fera la transition vers le nouveau système (section 10) ? C'est qu'il va falloir créer de nouveaux outils (cf. RFC 7998). L'appel d'offres pour leur développement a été fait en septembre 2016. La description des outils est une très intéressante lecture (l'appel d'offres formel est sur la page des Request For Proposal). L'appel d'offres a été gagné par les sociétés SeanTek et Elf Tools.

Pendant une période intermédiaire, le texte seul sera toujours utilisé comme format canonique, mais les nouveaux RFC passeront également par le nouveau workflow, pour vérifier que tout se passe bien et que le résultat est correct. Double travail, donc, mais nécessaire pour s'assurer que tout est en place.

Notez que, même une fois la transition finie, les auteurs ne seront pas forcés de soumettre leur document sous forme d'un fichier XML (ils seront simplement très fortement encouragés à le faire). S'ils envoient le texte seul comme avant, le RFC Editor devra produire le XML lui-même, et c'est ce XML qui sera la version canonique. Rappelez-vous que beaucoup de RFC sont des documents normatifs et que chaque mot, voire chaque virgule peut compter ! Voici pourquoi il faudra s'assurer que tout est parfait, même si, au début, cela entrainera certainement des retards dans la publication.

Dans le cas où l'auteur envoie du XML suivant le RFC 7991, il y aura moins de travail pour le RFC Editor, juste convertir ce XML au XML canonique (résoudre les références extérieures, par exemple) et passer ce XML canonique dans les nouveaux outils.

Notez que le RFC Editor maintient une FAQ très utile sur toutes les questions que pose le nouveau format. Et la RFC Editor avait fait un très drôle Pecha Kucha à Séoul en novembre 2016, sur le cahier des charges du nouveau format.

Le premier RFC au nouveau format a été le RFC 8651, sorti en octobre 2019.


Téléchargez le RFC 7990


L'article seul

RFC 7995: PDF Format for RFCs

Date de publication du RFC : Décembre 2016
Auteur(s) du RFC : T. Hansen (AT&T Laboratories), L. Masinter, M. Hardy (Adobe)
Pour information
Première rédaction de cet article le 16 décembre 2016


Parmi les nombreux formats de publication des RFC prévus suite à l'adoption du nouveau format (RFC 7990), ce RFC décrit l'utilisation de PDF. On pourra donc, en suivant ces règles, avoir une jolie version papier des RFC.

Actuellement, les RFC peuvent bien sûr être imprimés mais c'est un peu tristoune (cf. annexe A). Avec le nouveau cadre de gestion des RFC, le format canonique du RFC sera du XML (RFC 7991), à partir duquel seront produits automatiquement (par des outils qui ne sont pas encore développés) divers formats. HTML sera sans doute le principal pour une publication en ligne (RFC 7992), mais il y a des partisans de PDF, surtout pour l'impression sur le bon vieux papier. Ce RFC 7995 décrit donc l'utilisation de PDF comme format de sortie pour les RFC. À noter que ce format, créé et piloté par une entreprise privée n'est pas à proprement parler un « format Internet » et est sans doute moins connu des participants à l'IETF que ne l'est HTML.

La norme PDF est déposée à l'ISO (ISO 32000-1) mais l'archaïque ISO ne distribue toujours pas librement ces documents. Si on veut apprendre PDF, il faut donc le télécharger sur le site d'Adobe.

Première question (section 2 de notre RFC), quelle version de PDF choisir ? PDF a évolué dans le temps, chaque version ajoutant de nouvelles fonctions. C'est aujourd'hui un format très complexe, difficile à mettre en œuvre complètement. C'est pour cela qu'il existe des profils de PDF, restreignant ce format pour des usages spécifiques. Ainsi, PDF/X est conçu pour l'échange de fichiers avec l'imprimeur. Pour les RFC, documents souvent normatifs, et à longue durée de vie, les exigences principales sont l'accessibilité et la stabilité. C'est ce que fournissent les profils PDF/UA (accessibilité) et PDF/A-3 (archivage à long terme).

Pour les RFC, les profils choisis sont la version 1.7 de PDF, suffisamment ancienne pour être gérée par la plupart des logiciels, le profil PDF/A-3 pour limiter le nombre de fonctions à gérer, et PDF/UA pour l'accessibilité.

La section 3 de notre RFC détaille ensuite toutes les exigences particulières des RFC, pour le format de sortie PDF. Je ne les commente pas toutes ici, seulement celles qui me semblent importantes. Par exemple, la délicate question des polices. PDF permet d'inclure une police dans le document, ou bien de se référer simplement à une police par son nom. Dans ce dernier cas, si le logiciel qui lit le PDF ne trouve pas exactement cette police, il se rabat sur une police « proche », avec un résultat qui n'est pas forcément satisfaisant. De toute façon, PDF/A, le profil « archivage » impose d'inclure la police utilisée, pour éviter de dépendre de logiciels futurs. À noter que cela peut impliquer de payer : peu de polices sont gratuites pour l'auteur. L'annexe C.4 discute des polices acceptables. Il y a les gratuites, mais sans support Unicode complet, comme Source Sans Pro, Source Serif Pro ou Source Code Pro. Bien meilleure du point de vue de la couverture Unicode, mais payante, est Skolar. L'idéal sera peut-être la nouvelle police Noto. Les RFC ayant maintenant le droit d'utiliser des caractères non-ASCII, mais avec des restrictions (cf. RFC 7997), il est possible que des caractères soient refusés par le RFC Editor uniquement parce qu'ils ne sont pas présents dans les polices utilisées.

Le choix des caractéristiques des polices (chasse fixe ou variable, empattement ou pas) devra suivre les mêmes règles que pour HTML et CSS, règles qui figurent dans le RFC 7993. À propos de HTML, notons d'ailleurs que notre RFC sur PDF demande que le PDF ressemble visuellement autant que possible au document HTML. Si vous écrivez un logiciel qui produit le PDF pour un RFC et que vous hésitez sur tel ou tel aspect graphique, consultez le RFC 7992 sur la sortie HTML.

Parmi les autres exigences pour la production de PDF, notre RFC demande qu'on évite les césures.

PDF permet de mettre des liens hypertextes. L'intérêt est faible puisque PDF est surtout utilisé pour le papier (si on regarde sur un écran PDF n'a aucun avantage par rapport au format bien plus ouvert qu'est HTML), mais le RFC prévoit quand même cette possibilité. Il y aura donc des liens, à la fois externes (vers des URL, y compris vers d'autres RFC et, dans ce cas, le RFC 7322 requiert que cela soit vers la page d'information officielle du RFC Editor) et internes (une section du RFC référençant une autre). Les liens internes sont parfois produits automatiquement (par exemple depuis la table des matières vers les sections du texte).

Un problème délicat est celui de la façon dont le texte est stocké dans le document PDF. PDF permet en effet plusieurs façons de réaliser ce stockage. Elles donnent le même résultat visuel mais se comportent différemment pour des fonctions comme la recherche de texte. Ainsi, le mot « IETF » peut être stocké comme une image, comme quatre lettres positionnées indépendamment, ou comme un mot unique. Le stockage en image posera évidemment des problèmes aux outils comme pdftotext (mais ce n'est pas forcément grave pour les RFC, on a toujours le source XML) ou aux outils de synthèse vocale, nécessaires aux malvoyants. Pour la recherche de texte, la solution du mot unique est certainement meilleure, même si elle ne permet pas une typographie aussi subtile. Mais il y a aussi le placement des phrases. La phrase « The IETF supports the Internet » peut être stockée comme cinq mots différents stockés indépendamment (y compris dans un ordre différent de celui de la phrase) et positionnés ensuite, ou bien comme un objet unique.

Notre RFC recommande d'au moins garder les mots dans l'ordre du texte (PDF/UA l'impose).

Pour les images, si le source XML contenait à la fois de l'art ASCII et du SVG, notre RFC impose bien sûr qu'on utilise le SVG pour produire le PDF. Le texte alternatif aux images, indispensable pour l'accessibilité, doit être mis dans le PDF (dans la propriété /Alt).

Les métadonnées (noms des auteurs, date, etc) sont très utiles pour l'indexation et la recherche et doivent donc être mises dans le PDF. PDF a plusieurs façons d'embarquer des métadonnées, et la recommandation est d'utiliser XMP.

Parmi les zillions de fonctions de PDF, il peut agir en container d'autres fichiers (oui, comme tar ou AVI). Tous les logiciels PDF ne savent pas extraire ces fichiers embarqués dans le PDF mais c'est une fonction utile, au cas où. Le RFC recommande donc que des fichiers utiles soient ainsi embarqués : le source XML du RFC, les codes sources (dans les éléments <sourcecode> du RFC), les images (dont les sources SVG)...

Dernier point, les éventuelles signatures. Pour l'instant, il n'y a pas de mécanisme standard pour signer les RFC et en garantir l'authenticité mais, lorsque ce sera le cas, PDF permettra d'inclure une signature dans le fichier produit. (Cette fonction existe dans PDF depuis longtemps.)

Le RFC contient aussi trois annexes intéressantes. L'annexe A est un historique de la relation compliquée entre les RFC et PDF. Depuis longtemps, une version PostScript du RFC était acceptée par le RFC Editor et publiée, même si très peu d'auteurs en ont profité. Cela concernait surtout les RFC ayant des images ou des formules mathématiques comme les RFC 1119 ou RFC 1142. Le PDF produit par le RFC Editor pour tous les RFC (ou par https://tools.ietf.org/) n'était, lui, qu'une simple « impression » du RFC en texte brut.

L'annexe B rappelle ce que doit faire un bon logiciel de production de contenu imprimé, avec découpage en pages. C'est plus dur que cela n'en a l'air, car il faut gérer les veuves et les orphelines, ne pas couper juste après le titre d'une section, ne pas couper les dessins en art ASCII, placer les tableaux intelligemment, etc.

Enfin, l'annexe C décrit une partie des outils disponibles pour le producteur de documents PDF. Si les logiciels de visualisation sont nombreux, il faut noter que tous n'ont pas la totalité des fonctions qu'utilise le format de sortie des RFC (par exemple les liens hypertexte). Du côté des imprimantes (le papier étant le but final de la plupart des documents PDF), certaines savent même gérer le PDF directement (dans les autres cas, ce sera au logiciel de visualisation de produire le format attendu par l'imprimante, souvent PostScript).

Et pour produire le PDF à partir du XML des RFC ? Une solution possible, puisqu'il existe une feuille de style XSLT (disponible en ligne) est de produire du FO qui sera ensuite transformé en PDF, par exemple avec FOP (je n'ai personnellement eu que des expériences décevantes avec FO). Mais il existe plein de bibliothèques qui produisent du PDF, et qui pourraient être utilisées.

Comme notre RFC impose l'utilisation de profils de PDF comme PDF/A, un outil important est le logiciel de vérification qui s'assure que le résultat est bien conforme aux exigences de ce profil. Pour l'instant, il semble qu'il n'existe pas grand'chose dans ce domaine. Il faudra donc compter sur l'outil de production de PDF pour qu'il fasse un travail correct.


Téléchargez le RFC 7995


L'article seul

BCP 38, ne pas laisser des adresses IP usurpées sortir de son réseau

Première rédaction de cet article le 7 décembre 2016


Qu'est-ce que ça peut bien être, « BCP 38 » ? Ce terme désigne un ensemble de documents de bonnes pratiques pour les acteurs de l'Internet, plus spécialement les opérateurs réseaux : il ne faut pas laisser sortir de son réseau des paquets ayant une adresse source usurpée. Le respect de ce principe permettrait de lutter contre certaines attaques par déni de service sur l'Internet. Ce principe est formalisé dans deux RFC, les RFC 2827 et RFC 3704.

« BCP » veut dire « Best Current Practice ». Le but de cet étiquetage est de pointer vers le ou les RFC qui décrivent la pratique en question. En effet, un RFC, une fois publié, n'est jamais modifié, alors que le monde, lui, change. C'est ainsi que le RFC 7525, parlant de TLS est décrit par l'étiquette BCP 195 : les bonnes pratiques, en matière de cryptographie, changent vite. Une étiquette BCP peut pointer plusieurs RFC. Un bon exemple est le BCP 47, sur les étiquettes de langue, qui pointe vers les RFC 5646 et RFC 4647.

C'est également le cas de BCP 38, qui désigne le RFC 2827, avec les additions du RFC 3704.

Le problème que vise à résoudre ce BCP est celui de l'usurpation d'adresse IP par un attaquant qui voudrait faire du déni de service sans révéler son adresse, ou bien en faisant une attaque par réflexion. Par défaut, dans l'Internet, il est trivial d'émettre des datagrammes avec une adresse source mensongère. BCP 38 dit que les opérateurs réseaux devraient interdire cette pratique, en configurant leurs routeurs à cette fin. Par exemple, si un FAI a deux préfixes IP, 192.0.2.0/24 et 2001:db8::/32, il n'y a aucune raison valable de laisser sortir du réseau du FAI des paquets ayant comme adresse IP source, mettons, 203.0.113.65.

Notons qu'un déploiement systématique de BCP 38 résoudrait un certain nombre de problèmes de sécurité sur l'Internet, mais pas tous. Ainsi, si l'attaquant dispose d'un botnet, et fait une attaque directe (pas par réflexion), il n'a pas vraiment besoin de mentir sur ses adresses IP source, ce ne sont pas les siennes, de toute façon (usurper l'adresse source aurait quand même quelques avantages, ça dépend des cas).

Aujourd'hui, le déploiement de BCP 38 dans l'Internet n'est pas inexistant mais il est très inégal. Par exemple, la situation est bien meilleure en Europe qu'en Asie. Un attaquant qui veut faire de l'usurpation d'adresses IP a donc encore pas mal de réseaux à sa disposition.

Pourquoi est-ce que tout le monde n'a pas déployé BCP 38, malgré le très large consensus qui existe parmi les professionnels ? La principale raison est économique. Un opérateur qui déploie BCP 38 (tous les routeurs permettent de le faire, soit en n'autorisant que ses propres préfixes, soit par des astuces comme RPF) aide les autres. Imaginez l'ingénieur allant voir le directeur financier et lui disant « on va dépenser de l'argent, et le ROI ira entièrement à nos concurrents »... Comme en écologie, c'est donc un cas typique où le sacro-saint marché ne peut pas aboutir à une bonne solution.

Notez que tester si un FAI donné met en œuvre ou pas BCP 38 est un peu plus compliqué que cela peut sembler au premier abord. Je connais par exemple une box très utilisée en France qui bloque les paquets IPv4 ayant une adresse IP source usurpée (par effet de bord du NAT) mais qui ne le fait que pour des flots existants ou pour des paquets de début d'un flot. Si on envoie un paquet TCP sans bit SYN, il passe malgré son adresse usurpée...

Quelques lectures pour approfondir :


L'article seul

Fiche de lecture : The Internet of money

Auteur(s) du livre : Andreas Antonopoulos
Éditeur : Merkle Bloom
9781537000459
Publié en 2016
Première rédaction de cet article le 5 décembre 2016


Ce petit livre rassemble le texte de plusieurs conférences d'Andreas Antonopoulos au sujet de Bitcoin. Les textes ont été édités, les erreurs corrigées, mais le ton reste celui des conférences de l'auteur, passionnantes et brillantes. Sa thèse principale est que le Bitcoin n'est pas juste une monnaie, c'est un mécanisme sur lequel on va pouvoir bâtir plein de nouvelles relations économiques, c'est l'Internet of money. Et les vieux dinosaures du monde actuel peuvent toujours critiquer, et prétendre que le Bitcoin n'a pas d'avenir, Antonopoulos démonte tous leurs arguments. (Les conférences elles-mêmes sont visibles en ligne.)

C'est donc vraiment le bouquin à faire lire aux gens qui expliquent doctement que le Bitcoin n'est pas une monnaie réelle, ou bien que ce n'est qu'une expérience d'une poignée de gusses dans leur garage. Antonopoulos est très pédagogue... et très militant.

Il n'a pas de mal à rappeler que les arguments contre le Bitcoin sont à peu près les mêmes que ceux employés par les messieurs sérieux et les experts médiatiques contre l'Internet (ou, puis-je ajouter, contre Unix et contre le logiciel libre) : c'est juste une expérience, ce n'est pas sérieux, c'est un truc de hippies libertariens, cela ne durera pas. Pourquoi croirait-on aujourd'hui ces mêmes experts ? D'où le titre du livre, qui fait allusion au fait que l'auteur prédit au Bitcoin le même succès que l'Internet : déranger les systèmes en place, permettre de nouvelles possibilités, reposer les questions. « Dire que le Bitcoin est une monnaie numérique, c'est aussi réducteur que dire que l'Internet est un téléphone amélioré. »

Un concept intéressant dans une des conférences est celui d'inversion de l'infrastructure. Au début, la nouvelle technologie utilise une infrastructure conçue pour la technologie précédente, et a donc bien du mal. Les premières voitures roulaient sur des routes prévues pour les chevaux. Ceux-ci ont quatre pattes et un bon équilibre, les trous ne les dérangeaient donc pas trop, alors qu'ils étaient redoutables pour les voitures. Petit à petit, les choses ont changé, l'infrastructure s'est inversée, et ce sont aujourd'hui les chevaux qui marchent sur une route goudronnée conçue pour les voitures. De même, l'Internet à ses débuts devait emprunter une infrastructure conçue pour le téléphone (et on avait besoin de modems, pour faire passer IP pour de la voix) alors qu'aujourd'hui, l'infrastructure s'est inversée, c'est la voix qui n'est plus qu'une des nombreuses applications qui utilisent l'infrastructure de l'Internet.

De la même façon, estime Antonopoulos, les services bancaires traditionnels continueront à exister, mais seront simplement des applications au-dessus de Bitcoin.

L'auteur est bien conscient que les adversaires du Bitcoin ne vont pas se contenter de le ridiculiser ou de le critiquer. Ils vont activement tenter de l'interdire. Il est très optimiste sur les chances du Bitcoin de résister à cette censure (dans le pire des cas, les transactions seront encodées en smileys dans les discussions des articles Wikipédia et ne pourront donc pas être stoppées...) Après tout, Bitcoin a déjà été testé au feu, d'innombrables attaques ont déjà visé cette monnaie, et le Bitcoin a toujours survécu. (Voir à ce sujet l'hilarant site « Bitcoin Obituaries » et l'amusante vidéo « Not this time ».)

Antonopoulos insiste sur le caractère « sans permission » du Bitcoin. Il n'y a pas de Président du Bitcoin, chacun avec une idée peut la mettre en œuvre sur la chaîne de blocs tout de suite, sans demander de permission. En tant que « programmable money », Bitcoin n'a pas seulement un usage (payer) mais tous les usages qu'on peut imaginer. (Le Bitcoin est neutre, au sens de « neutralité du réseau ».)

Antonopoulos fait remarquer que toutes les innovations ont été la cible d'innombrables critiques à leur début. (Il oublie de dire que certaines critiques étaient justifiées. Par exemple, il cite des déclarations anti-voiture des débuts de l'automobile, pointant les dangers mortels de cette technologie, dangers qui existent toujours.) Ces critiques semblent bien ridicules avec le recul, comme celles contre le Bitcoin sonneront moyenâgeuses dans le futur. Antonopoulos remarque avec justesse que ces critiques portaient souvent sur des points de détail, qui allaient évoluer avec le temps. Ainsi, les premières critiques des automobiles portaient sur la difficulté à les faire démarrer, problème réel mais qui a été vite résolu avec l'invention du démarreur. (Personnellement, je me souviens bien des premières démonstrations de l'Internet que je faisais au début des années 1990, où la plupart des remarques des gens portaient sur le caractère « peu convivial » des logiciels utilisés. Peu de gens étaient capables de voir l'intérêt de cette technologie, au-delà de problèmes ergonomiques temporaires.)

Dans une autre conférence, Antonopoulos revient sur la monnaie : de quand date t-elle ? Et, d'ailleurs, qu'est-ce qu'on appelle « monnaie » ? (Beaucoup de messieurs experts refusent de considérer le Bitcoin comme une monnaie car ils donnent de la monnaie une définition arbitraire et anti-historique du genre « la monnaie est le moyen de paiement décidé par un État, et régulé ».)

L'auteur insiste aussi sur l'importance pour les acteurs du monde Bitcoin de ne pas copier bêtement le vocabulaire du passé. Ainsi, il s'énerve (à juste titre) contre les articles mentionnant le Bitcoin et qui sont illustrés par... des pièces de monnaie. Il reconnait que c'est d'ailleurs en partie la faute du terme « bitcoin » qui est trompeur. De même, le terme de « portefeuille », souvent utilisé pour les logiciels de gestion de ses bitcoins, est erroné : on ne peut pas copier un portefeuille traditionnel, alors qu'il n'y a aucun problème à le faire avec un portefeuille Bitcoin (il ne stocke pas d'argent, mais des clés).

Autre exemple de l'erreur qu'il y a à copier aveuglément les anciennes techniques, les places de marché Bitcoin. Ces places n'ont rien de Bitcoin, ce sont des établissements financiers traditionnels et, notamment, leur modèle de sécurité n'est pas du tout celui de Bitcoin.

Compte-tenu de la marée médiatique anti-Bitcoin (et anti-cryptomonnaies en général), on a bien besoin d'un livre comme celui-ci, qui redresse la barre. Par contre, il ne faut pas y chercher une analyse balancée. On ne voit aucune critique sur les aspects problématiques du Bitcoin. Il faudra un autre livre pour cela. Un volontaire pour écrire une critique sérieuse du Bitcoin ? (Qui ne se limite pas à des points de détail spectaculaires comme l'identité de Nakamoto, ou à du simple conservatisme du genre « les banques n'en veulent pas » ?) En attendant, lisez le livre, et écoutez les conférences d'Andreas Antonopoulos, vous ne le regretterez pas.


L'article seul

RFC 8027: DNSSEC Roadblock Avoidance

Date de publication du RFC : Novembre 2016
Auteur(s) du RFC : W. Hardaker (USC/ISI), O. Gudmundsson (CloudFlare), S. Krishnaswamy (Parsons)
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 4 décembre 2016


Normalement, en 2016, tous les résolveurs DNS sérieux devraient valider avec DNSSEC. Mais ce n'est pas le cas. Il y a plusieurs raisons à cela, mais ce nouveau RFC se focalise sur un problème précis : le cas d'un résolveur connecté via un réseau pourri, non-neutre, et qui se permet d'interférer avec le transport des paquets IP, menant le résolveur à de sérieuses difficultés. Comment détecter ces réseaux pourris ? Et que faire pour valider quand même ?

Si le résolveur est une grosse machine dans un centre de données, connectée directement à des opérateurs neutres, il n'y a pas trop de problème. C'est le cas des résolveurs des FAI, par exemple. Mais la situation est bien moins favorable à M. Michu. Si celui-ci veut, à juste titre, avoir son propre résolveur DNS sur sa machine, il dépend des réseaux où on laisse M. Michu se connecter, et ceux-ci sont rarement neutres. (Le RFC couvre le cas où ce résolveur local fait suivre - forwarde - les requêtes à un autre résolveur, et celui où il parle directement aux serveurs faisant autorité.)

La section 1.2 du RFC décrit les cas où la validation DNSSEC va être difficile ou impossible :

  • Résolveur qui ne connait pas DNSSEC (évidemment),
  • Intermédiaires (relais DNS dans la box, par exemmple), qui viole le protocole DNS au point de gêner le fonctionnement de DNSSEC (ce cas est décrit en détail dans le RFC 5625),
  • Équipements réseau actifs qui modifient ou bloquent les messages DNS, par exemple en supprimant les signatures DNSSEC (beaucoup de « firewalls » sont dans ce cas),
  • Réseau qui ne gère pas correctement les fragments, ce qui est plus fréquent avec DNSSEC.

Bien des outils ont été développés pour contourner ces problèmes, comme dnssec-trigger.

Pour faire des tests des résolveurs et de tous les équipements intermédiaires qui peuvent poser des problèmes de validation DNSSEC dans certains cas, le RFC parle d'une zone de test nommée test.example.com. Elle n'existe pas en vrai mais, aujourd'hui, la zone test.dnssec-tools.org fait la même chose (elle est par exemple utilisée pour les travaux pratiques lors de la formation DNSSEC chez HSC). Cette zone est délibérement peuplée avec des noms mal signés. Ainsi, le nom badsign-aaaa.test.dnssec-tools.org a un enregistrement AAAA dont la signature a été modifiée, la rendant invalide. Testons (pour tous les tests, comme le but était de voir le comportement DNSSEC, j'ai utilisé un fichier de configuration ~/.digrc contenant +dnssec +multiline, merci à Landry Minoza de l'avoir remarqué) :


% dig AAAA badsign-aaaa.test.dnssec-tools.org
; <<>> DiG 9.9.5-9+deb8u8-Debian <<>> AAAA badsign-aaaa.test.dnssec-tools.org
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 60910
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;badsign-aaaa.test.dnssec-tools.org. IN AAAA

;; Query time: 3759 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Sun Dec 04 17:12:28 CET 2016
;; MSG SIZE  rcvd: 63


% dig +cd AAAA badsign-aaaa.test.dnssec-tools.org
; <<>> DiG 9.9.5-9+deb8u8-Debian <<>> +cd AAAA badsign-aaaa.test.dnssec-tools.org
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 29404
;; flags: qr rd ra cd; QUERY: 1, ANSWER: 2, AUTHORITY: 3, ADDITIONAL: 5

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;badsign-aaaa.test.dnssec-tools.org. IN AAAA

;; ANSWER SECTION:
badsign-aaaa.test.dnssec-tools.org. 86400 IN AAAA 2001:470:1f00:ffff::1
badsign-aaaa.test.dnssec-tools.org. 86400 IN RRSIG AAAA 5 4 86400 (
				20170101064820 20161202054820 19442 test.dnssec-tools.org.
				nZ8bPLBleW/sW6x135+Iz4IhO6Lr04V8C9fC1bMVfCVY
				3rKqbOoBk1i+wnnGDCTWQ5iCicWTKLIpbDmCSW9C33pj
				P2j7C/ensspbdwpD/7Ia8zN+XUSN+ThLU6lgYGKFuoVL
				QmIG/vr1lOn6xdjXY2E4mStAjaGuertvKKDYy/I= )

;; AUTHORITY SECTION:
test.dnssec-tools.org.	280 IN NS dns1.test.dnssec-tools.org.
test.dnssec-tools.org.	280 IN NS dns2.test.dnssec-tools.org.
test.dnssec-tools.org.	280 IN RRSIG NS 5 3 86400 (
				20170101064820 20161202054820 19442 test.dnssec-tools.org.
				AK95JOAuvfZ1ZwEsrKiR8DP1zluoBvBkXHRXa78rrK5U
				UuZdLnZwnYlnNplrZZOrQNuUaPyb4zI0TGfw/+aa/ZTU
				qyx8uQODSHuBTPQTlcmCFAfTIyd1Q+tSTEs2TuGUhjKe
				H9Hk+w6yOjI/o52c2OcTMTJ4Jmt2GlIssrrDlxY= )

;; ADDITIONAL SECTION:
dns1.test.dnssec-tools.org. 280	IN A 168.150.236.43
dns2.test.dnssec-tools.org. 280	IN A 75.101.48.145
dns1.test.dnssec-tools.org. 86400 IN RRSIG A 5 4 86400 (
				20170101064820 20161202054820 19442 test.dnssec-tools.org.
				zoa0V/Hwa4QM0spG6RlhGM6hK3rQVALpDve1rtF6NvUS
				Sb6/HBzQOP6YXTFQMzPEFUza8/tchYp5eQaPBf2AqsBl
				i4TqSjkIEklHohUmdhK7xcfFjHILUMcT/5AXkEStJg7I
				6AqZE1ibcOh7Mfmt/2f0vj2opIkz6uK740W7qjg= )
dns2.test.dnssec-tools.org. 86400 IN RRSIG A 5 4 86400 (
				20170101064820 20161202054820 19442 test.dnssec-tools.org.
				hGq7iAtbHrtjCYJGMPQ3fxijhu4Izk8Ly+xZOa0Ag24R
				lqpFgdd2amDstFVLTRs3x15UqQIO+hmFdlbSOterDkbg
				/o2/FhtZOJr7c75Pu3EWi/DDbT9pULk4Uwjlie1QBopv
				LLZ94SlqKO7eQ02NRyy5EL4gD2G5rSffsUqEkj8= )

;; Query time: 206 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Sun Dec 04 17:12:44 CET 2016
;; MSG SIZE  rcvd: 885

    

Le second test, celui fait avec le bit CD (Checking Disabled), montre que le problème vient bien de DNSSEC. Autre test, avec une signature expirée :


% dig A pastdate-a.test.dnssec-tools.org
...
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 46319
...


% dig +cd A pastdate-a.test.dnssec-tools.org
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 49547
;; flags: qr rd ra cd; QUERY: 1, ANSWER: 2, AUTHORITY: 3, ADDITIONAL: 5
...
;; ANSWER SECTION:
pastdate-a.test.dnssec-tools.org. 86400	IN A 64.90.35.104
pastdate-a.test.dnssec-tools.org. 86400	IN RRSIG A 5 4 86400 (
				20161201224321 20161101234821 19442 test.dnssec-tools.org.
				lIL0zcEZpG/4uG5hImvpivH1C/D3PFI3RNYHlPbZ [...]

    

La liste de tous les noms à tester est en ligne.

Le but de ce RFC est de lister tous les tests que peut et devrait faire un validateur local, pour arriver à valider malgré des résolveurs amont, ou bien un réseau, hostile. Ces stratégies sont mises en œuvre, par exemple, dans dnssec-trigger.

En détectant la non-conformité (compliance, un terme à la mode dans les organisations), le validateur situé sur la machine terminale, ou bien dans le réseau local, peut alors adopter la meilleure stratégie de contournement (ou, dans le pire des cas, prévenir loyalement l'utilisateur qu'on ne pourra pas faire de validation DNSSEC). Les tests doivent être faits au début d'une nouvelle connexion réseau, ou bien lorsque celle-ci change.

La section 3 du RFC est consacrée à ces tests de non-conformité. Je ne vais pas décrire la totalité de ces tests, un sous-ensemble suffira. Ainsi, le premier test, le plus trivial, est que la machine puisse parler en UDP à son résolveur attitré (celui typiquement reçu en DHCP). On lui demande good-a.test.dnssec-tools.org et on doit avoir une réponse sous forme d'une adresse IP (comme son nom l'indique, ce nom est correctement signé). Si un test aussi trivial ne marche pas, ce n'est sans doute pas la peine d'aller plus loin. Un peu plus subtil, on teste le même résolveur en TCP.

Après, on passe à EDNS (RFC 6891), qui est indispensable pour DNSSEC. Une requête pour ce même nom, mais avec une option EDNS, doit passer. Si EDNS ne marche pas, on peut arrêter, DNSSEC ne marchera pas non plus. Mais s'il marche ? On teste alors avec le bit DO (DNSSEC OK) qui indique au serveur qu'il doit envoyer les données DNSSEC, notamment les signatures. La réponse doit inclure ce même bit DO. (C'est plus tard qu'on teste qu'on a bien reçu des signatures. Rappelez-vous que la plupart des middleboxes sont horriblement boguées. Certaines acceptent le bit DO et le renvoient, sans pour autant transmettre les signatures.)

On teste alors des zones qu'on sait signées et on regarde si le résolveur met le bit AD (Authentic Data), au moins pour les algoritmes RSA + SHA-1 et RSA + SHA-256. Si cela ne marche pas, ce n'est pas forcément une erreur fatale, puisque, de toute façon, on voulait faire la validation nous-même. Il faut aussi penser à faire le test inverse : un résolveur validant doit mettre le bit AD pour une réponse signée correctement, et doit répondre avec le code de retour SERVFAIL (Server Failure) si la réponse devrait être signée mais ne l'est pas, ou bien l'est mal. Cela se fait en testant badsign-a.test.dnssec-tools.org.

Dans les enregistrements DNSSEC, il n'y a pas que les signatures (RRSIG), il y a aussi les enregistrements servant à prouver la non-existence, NSEC et NSEC3. Il faut donc également tester qu'ils sont reçus car, en pratique, on voit en effet des middleboxes qui laissent passer les RRSIG mais bloquent stupidement les NSEC et les NSEC3. On demande donc non-existent.test.dnsssec-tools.org, et on doit récupérer non seulement une réponse avec le code NXDOMAIN (No Such Domain) mais également les NSEC ou NSEC3 permettant de valider cette réponse :


% dig AAAA non-existent.test.dnsssec-tools.org
[...]
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 40218
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 8, ADDITIONAL: 1
[...]
;; AUTHORITY SECTION:
h9p7u7tr2u91d0v0ljs9l1gidnp90u3h.org. 900 IN NSEC3 1 1 1 D399EAAB (
				H9PARR669T6U8O1GSG9E1LMITK4DEM0T
				NS SOA RRSIG DNSKEY NSEC3PARAM )
iruevfos0vs8jssfj22me5p458p0qj1e.org. 900 IN RRSIG NSEC3 7 2 86400 (
				20161222153046 20161201143046 3947 org.
				kgCZC/gE4ySP7eZUb1+2ORYRhTrvL5YBIHLCBK5F8pqK
				MXGJXJ/hX+8LLrg4jHJaER2AelUgUGywRn4uY80ajYpg
				eTuSGzRX1aVCKAR8UB80bX/YLUPUPKWOdfgxTekD4nZk
				eoi/9JNmIMZRc0cmMGp8LSVMqX98F2bVJnZro8U= )
iruevfos0vs8jssfj22me5p458p0qj1e.org. 900 IN NSEC3 1 1 1 D399EAAB (
				IRVVBMC65HCBCFQNQS8NQFTAB943LCFU
				NS DS RRSIG )
vaittv1g2ies9s3920soaumh73klnhs5.org. 900 IN RRSIG NSEC3 7 2 86400 (
				20161222153046 20161201143046 3947 org.
				Nj/zvU0GB8vQ7bFfpSSWW+inE7RiOFjOpNc1K/TMnQqG
				QsKTLD9gBM8vgh3K1WdPXOCzthf/isDJAy2xLA/oRFFq
				KZ+Coo+33FManVmuyndGJ5bdgQqnpa0xGP7yOgjTfUsh
				Ff9HkX0mkzqYtWYzw0J7WnMPcOjmrlg26WsfwlU= )
vaittv1g2ies9s3920soaumh73klnhs5.org. 900 IN NSEC3 1 1 1 D399EAAB (
				VAJB898DELVT5UJ4I9D1BRD2FRTBSCM1
				NS DS RRSIG )

    

Certains serveurs DNS (ou, plus exactement, certains ensembles serveur+réseau+middlebox) n'acceptent que certains types d'enregistrement DNS (les plus connus, comme A, AAAA, MX, parfois SRV, etc). Il faut donc tester que le serveur accepte bien tous les types d'enregistrement,

Jusqu'à présent, on n'a testé que le résolveur « normal ». Même s'il ne valide pas, tant qu'il transmet fidèlement toutes les données DNS, on pourra au moins l'utiliser comme relais et cache. Par contre, dans certains cas, si on veut valider avec DNSSEC, il faudra complètement le court-circuiter. Ainsi, s'il ne transmet pas les signatures, on n'a pas d'autre choix que d'aller les demander à un autre résolveur, ou bien directement aux serveurs faisant autorité. Il faut donc tester qu'on puisse interroger ces serveurs, avec UDP et avec TCP. (Ce n'est pas toujours possible, certains réseaux violent tellement la neutralité de l'Internet qu'ils bloquent le port 53, celui du DNS.)

Avec DNSSEC, les réponses sont souvent de grande taille, et parfois fragmentées. Il faut donc tester que les fragments passent (ils sont souvent bloqués par des administrateurs réseau incompétents).

Une fois ces tests faits, il reste à synthétiser les résultats (section 4). L'idée est de pouvoir dire si le résolveur « normal » est :

  • Un validateur (on peut alors tout lui déléguer, en tout cas si on a confiance en lui),
  • Un résolveur DNSSEC (même s'il ne valide pas, il passe bien tous les enregistrements DNSSEC),
  • Une horreur à fuir.

En pratique, tous les résolveurs (ou plutôt l'ensemble du résolveur et du réseau situé devant, avec ses middleboxes qui cassent tout) ne rentrent pas parfaitement dans une de ces trois catégories. Ainsi, certains vont bloquer les fragments mais accepter TCP (ce qui permettra de quand même faire passer les données de grande taille), tandis que d'autres n'auront pas TCP mais qu'UDP fonctionnera bien, même en cas de fragmentation.

Une fois ces données collectées, et le résolveur correctement classé, on pourra alors déterminer comment contourner les éventuels problèmes (section 5 du RFC). Par exemple :

  • Si le résolveur officiel est un validateur ou bien un résolveur DNSSEC, on l'utilise comme forwarder pour transmettre les requêtes, profitant ainsi de son cache et réduisant la charge sur les serveurs faisant autorité.
  • Si le résolveur officiel est une horreur, mais que les requêtes DNS vers l'extérieur marchent, alors, ne pas faire appel au résolveur officiel et parler directement aux serveurs faisant autorité.
  • Si le résolveur officiel est une horreur, et que les requêtes DNS vers l'extérieur sont bloquées, tenter de joindre un résolveur extérieur de confiance, en utilisant DNS sur TLS (RFC 7858), ce que fait dnssec-trigger (dans son fichier de configuration, des lignes comme tcp80: 185.49.140.67 ou ssl443: 185.49.140.67 ...).
  • Sinon, si rien ne marche, laisser tomber, prévenir l'utilisateur et pleurer.

La section 6 du RFC sert de voiture-balai, en mentionnant les cas spéciaux qui peuvent être embêtants. Par exemple, DNSSEC dépend de l'horloge, puisqu'il faut vérifier que les signatures n'ont pas expiré. Mais la synchronisation de l'horloge dépend de NTP donc parfois du DNS si on a mis des noms de domaine dans son ntp.conf. Si la machine a une horloge assez stable pour garder l'heure entre un arrêt et un démarrage, ce n'est pas trop grave. Mais si la machine est un engin bon marché avec une horloge qui dévie beaucoup (genre le Raspberry Pi), que faire ?

Autre problème, les affreux portails captifs. Tant qu'on n'a pas cliqué sur « j'accepte cinquante pages de conditions d'utilisation que je n'ai pas lues, je veux recevoir du spam, et je promets de ne pas partager de la culture », on n'a pas un vrai accès Internet et le port 53 est sans doute bloqué. Il faudrait donc refaire les tests après le passage par le portail captif.

Face à ce genre de problèmes, une première solution est de ne pas tenter de faire du DNSSEC tant qu'on n'a pas synchronisé l'horloge, passé le portail captif (c'est ce que fait dnssec-trigger), au détriment de la sécurité. Au moins, on peut prévenir l'utilisateur et lui proposer de réessayer plus tard.


Téléchargez le RFC 8027


L'article seul

RFC 7970: The Incident Object Description Exchange Format Version 2

Date de publication du RFC : Novembre 2016
Auteur(s) du RFC : R. Danyliw (CERT)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF mile
Première rédaction de cet article le 1 décembre 2016


Pour rendre plus facilement analysables les innombrables rapports d'incidents de sécurité qui circulent sur Internet tous les jours, ce RFC spécifie un format standard XML, nommé IODEF, pour décrire ces incidents. Ici, il s'agit de la version 2 de ce format IODEF, la version 1 était dans le RFC 5070.

Tous les jours, des organisations comme les CERT et CSIRT, mais aussi les OIV, envoient et reçoivent des rapports détaillés concernant une attaque sur un réseau informatique ou un serveur. Ces rapports sont longs et détaillés mais, la plupart du temps, ce n'est pas une attaque isolée qui est intéressante, c'est l'image qui apparait lorsqu'on synthétise tous les rapports, et qu'on voit alors les tendances, par exemple l'arrivée d'un nouveau ver ou bien une attaque concertée contre un pays donné. D'où l'importance de pouvoir analyser automatiquement ces rapports, ce qui impose un modèle de données et un format standard, ce que fournit ce RFC.

Le modèle de données est proche des modèles objet, par exemple dans la descriptions des classes d'objets manipulés (comme la classe Incident en section 3.2, avec la cardinalité des attributs). Ces classes sont composés avec des données élémentaires (booléens, entiers, dates) décrites dans la section 2. Par exemple, parmi les attributs de la classe Incident, on trouve l'heure de début et de fin de l'incident, l'heure de détection, etc. Le schéma XML complet, écrit en W3C Schema, figure dans la section 8.

On trouve énormément de choses dans ce schéma (le RFC fait plus de 160 pages), pour traiter tous les cas prévus. Par exemple, on peut exprimer une liste de ports comprenant à la fois des ports individuels et des intervalles : 22,53,80,1024-2047. De nombreuses classes existent pour utiliser ces informations élémentaires. Ainsi, la classe Discovery, une nouveauté de la version 2, permet d'indiquer comment l'incident a été découvert (avec un attribut source qui a vingt valeurs possibles, comme avantivirus, os-logjournal, passive-dns - un système comme DNSdb, etc). Et BusinessImpact permet de décrire les conséquences de l'incident sur l'activité (breach-privacy, loss-of-service, theft-financial, etc). Ça peut même se quantifier financièrement avec la classe MonetaryImpact. Si on met les incidents de sécurité dans une base de données (ça s'appelle un SIEM, comme Prelude), on peut donc imaginer de regarder d'abord les incidents qui ont coûté le plus cher...

Voici un exemple d'un rapport d'incident, tiré du RFC (section 7), et qui décrit et qui décrit les systèmes de C&C (quatre serveurs) d'une campagne donnée (dans le RFC 5070, l'exemple était une simple reconnaissance avec nmap...). Cet exemple a l'avantage d'illustrer la classe IndicatorData, une nouveauté de la version 2 :


   <?xml version="1.0" encoding="UTF-8"?>
   <!-- A list of C2 domains associated with a campaign -->
   <IODEF-Document version="2.00" xml:lang="en"
      xmlns="urn:ietf:params:xml:ns:iodef-2.0"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation=
      "https://www.iana.org/assignments/xml-registry/schema/
       iodef-2.0.xsd">
     <Incident purpose="watch" restriction="green">
       <IncidentID name="csirt.example.com">897923</IncidentID>
         <RelatedActivity>
           <ThreatActor>
             <ThreatActorID>
             TA-12-AGGRESSIVE-BUTTERFLY
             </ThreatActorID>
             <Description>Aggressive Butterfly</Description>
           </ThreatActor>
           <Campaign>
             <CampaignID>C-2015-59405</CampaignID>
             <Description>Orange Giraffe</Description>
           </Campaign>
         </RelatedActivity>
         <GenerationTime>2015-10-02T11:18:00-05:00</GenerationTime>
         <Description>Summarizes the Indicators of Compromise
           for the Orange Giraffe campaign of the Aggressive
           Butterfly crime gang.
         </Description>
         <Assessment>
           <BusinessImpact type="breach-proprietary"/>
         </Assessment>
         <Contact type="organization" role="creator">
           <ContactName>CSIRT for example.com</ContactName>
           <Email>
             <EmailTo>contact@csirt.example.com</EmailTo>
           </Email>
         </Contact>
         <IndicatorData>
           <Indicator>
             <IndicatorID name="csirt.example.com" version="1">
             G90823490
             </IndicatorID>
             <Description>C2 domains</Description>
             <StartTime>2014-12-02T11:18:00-05:00</StartTime>
             <Observable>
               <BulkObservable type="fqdn">
               <BulkObservableList>
                 kj290023j09r34.example.com
                 09ijk23jfj0k8.example.net
                 klknjwfjiowjefr923.example.org
                 oimireik79msd.example.org
               </BulkObservableList>
             </BulkObservable>
           </Observable>
         </Indicator>
       </IndicatorData>
     </Incident>
     </IODEF-Document>

Le RFC note sagement que le partage d'informations n'est pas uniquement une question technique, mais qu'elle dépend aussi des procédures bureaucratiques de chaque organisation, des contraintes légales, de la confiance (ou de l'absence de confiance, souvent justifiée) et enfin de la simple bonne ou mauvaise volonté. (Mon opinion personnelle est que, en France, le partage d'informations précises sur les incidents de sécurité est très insuffisant.)

Les changements depuis la version 1 (celle du RFC 5070) sont listés dans la section 1.4. Beaucoup de détails, beaucoup d'ajouts, parmi lesquels je note :

  • Meilleure internationalisation (voir à ce sujet la section 6 du RFC), comme le fait que la classe Contact permette désormais d'indiquer une adresse postale en un jeu de caractères quelconque,
  • Nouvelles classes (comme IndicatorData ou Discovery cités plus haut, ou comme DomainData, pour des informations sur un nom de domaine), et nouveaux attributs dans les classes existantes (par exemple, Incident y gagne observable-id, un identificateur qui peut être utilisé dans des références croisées).

Si l'ajout de nouvelles classes ne rendent pas les anciennes descriptions IODEF incorrectes, en revanche, certains changements cassent la compatibilité et un fichier IODEF version 1 parfait ne sera pas forcément légal pour la version 2 (cf. section 4.4). Par exemple, la sous-classe NodeRole (qui permet de décrire si on est attaqué par une caméra de vidéosurveillance ou bien par un routeur) a changé de classe parente.

Et les mises en œuvre d'IODEF ? Un résumé de l'état de ces mises en œuvre figure dans l'Internet-Draft draft-ietf-mile-implementreport, et qui référence une liste des programmes IODEF (j'ai aussi trouvé celle-ci). Parmi d'autres, on peut noter la bibliothèque de Prelude (et qui a une version pour l'IODEF v2 de notre RFC), un module Perl, un autre en PHP, et un troisième en Python. On trouve aussi des moyens de connecter IODEF à des logiciels existants par exemple au logiciel de suivi de tâche Mantis, avec ce connecteur.

Pour des articles ou présentations sur IODEF, vous pouvez voir la Rump (session rapide) de Thomas Andrejak au SSTIC 2016 (vidéo en ligne).

Notez en France l'existence du projet SECEF (SECurity Exchange Format) qui a pour objectif de promouvoir et de faciliter l’usage des deux formats de fichier IDMEF (RFC 4765) et IODEF. Vous pouvez consulter leur Wiki, et leur tutoriel IODEF. Il y a aussi un article de synthèse sur SECEF, et un compte-rendu d'une de leurs réunions (mais vite fait et avec des erreurs). Enfin, le RFC 8274 donne quelques conseils sur la mise en œuvre d'IODEF.


Téléchargez le RFC 7970


L'article seul

RFC 8023: Report from the Workshop and Prize on Root Causes and Mitigation of Name Collisions

Date de publication du RFC : Novembre 2016
Auteur(s) du RFC : Matthew Thomas, Allison Mankin, Lixia Zhang (UCLA)
Pour information
Première rédaction de cet article le 27 novembre 2016


Ce nouveau RFC est le compte-rendu d'un atelier qui s'était tenu du 8 au 10 mars 2014 à Londres sur le thème des « collisions ». Ce terme exagéré et sensationnaliste désigne le phénomène qui peut se produire quand un acteur de l'Internet a bêtement choisi de se créer un TLD à lui dans le DNS, et que ce TLD est ensuite créé par l'ICANN.

Supposons que l'entreprise Bidon décide de nommer ses ressources internes (site Web réservé aux employés, etc) sous le TLD inexistant .bidon. C'est une mauvaise idée mais elle est fréquente. L'entreprise Bidon compte sur le fait que ses employés utiliseront les résolveurs DNS internes, qui ont été configurés pour reconnaître .bidon. Par exemple, avec Unbound, et un serveur faisant autorité en 2001:db8:666::1:541f, les résolveurs ont été configurés ainsi :

    stub-zone:
     name:   "bidon"
     stub-addr: 2001:db8:666::1:541f
    

Si un employé tente accidentellement d'accéder à une ressource en .bidon, alors qu'il n'utilise pas les résolveurs de la boîte, la requête filera vers la racine du DNS, qui répondra NXDOMAIN (No Such Domain). C'est ainsi que la racine voit souvent des requêtes pour des noms se terminant en .local, .home ou .belkin. Si, quelques années après, l'ICANN délègue effectivement ce TLD à une autre organisation, ces requêtes à la racine donneront désormais un vrai résultat. Au lieu d'un message d'erreur, le malheureux employé sera peut-être redirigé vers un autre site Web que celui attendu. C'est ce phénomène que Verisign avait baptisé « collision » (name collision), terme conçu pour faire peur.

C'est dans ce contexte qu'il y a plus de deux ans s'était tenu le « Workshop on Root Causes and Mitigation of Name Collisions », dont ce RFC est le compte-rendu tardif. Le premier rapport de l'ICANN qui mentionnait ce phénomène était le SAC 045 en 2010. Il pointait le risque que la délégation effective d'un nouveau TLD change la réponse obtenue, pour les clients mal configurés (qui interrogeaient à tort un résolveur extérieur, et donc la racine, au lieu de leurs résolveurs internes).

L'ICANN a même créé une page Web dédiée à cette question, dont la source réelle est le recouvrement de deux espaces de noms, l'interne et l'externe. La bonne pratique idéale serait de ne pas utiliser de noms qui n'existent pas ou, pire, qui existent avec une autre signification dans l'arbre public des noms de domaine (et, là, relire le RFC 2826 peut aider). Pour reprendre l'exemple de l'entreprise Bidon, si elle est titulaire de bidon.fr, elle devrait nommer ses ressources internes avec des noms se terminant en privé.bidon.fr ou interne.bidon.fr. Si on ne veut pas faire les choses proprement, et qu'on utilise quand même le TLD inexistant .bidon, alors il faut veiller très soigneusement à séparer les deux espaces de nommage et à éviter qu'ils ne se rencontrent un jour (ce qui est difficile à l'ère des mobiles, avec des appareils qui rentrent et qui sortent du réseau de l'entreprise). Sinon, on verra ces fameuses collisions.

En pratique, pas mal d'administrateurs système surestiment leurs compétences et croient qu'ils vont réussir à empêcher toute fuite vers le DNS public. C'est ce qui explique une partie des requêtes pour des noms inexistants que reçoit la racine (ces noms inexistants forment la majorité du trafic des serveurs racine du DNS). Un des problèmes de fond de l'Internet est en effet que l'administrateur de base ne se tient pas au courant et n'est pas informé des problèmes du monde extérieur. « Après moi, le déluge »

Autrefois, le problème était surtout théorique. Le nombre de TLD n'avait pas bougé depuis de très nombreuses années, et personne ne pensait que des TLD comme .pizza ou .green verraient le jour. Mais, en 2012, l'ICANN a lancé officiellement son programme d'ajout d'un grand nombre de TLD, et le risque est soudain devenu une question pratique. D'où l'atelier de 2014.

La section 2 du RFC revient en détail sur l'arrière-plan de ce problème de collision. Outre le rapport SAC 045 cité plus haut, il y avait eu une déclaration de l'IAB, puis un autre rapport du SSAC (Security and Stability Advisory Committee, un comité de l'ICANN), le SAC 046, une déclaration du RSSAC et plein d'autres textes sur les conséquences d'un agrandissement important de la zone racine. Par exemple, le rapport SAC 057 faisait remarquer que les AC attribuaient souvent des certificats pour des noms de domaine dans des TLD purement locaux. Cela montrait le déploiement de ces TLD privés et cela inquiétait. Si la société Bidon exploite .bidon et obtient d'une AC un certificat pour www.compta.bidon, après la délégation de ce même TLD dans la racine publique, ce certificat pourrait être utilisé pour usurper l'identité d'un autre serveur.

J'ai parlé plus haut des fuites vers le DNS public. Quelle est leur ampleur exacte ? Ce n'est pas si évident que cela de le savoir. Contrairement à un raccourci journalistique fréquent, l'ICANN ne gère pas la racine. Chaque opérateur d'un serveur DNS racine se débrouille indépendamment, supervise son serveur mais ne rend pas forcément compte à d'autres acteurs ou au public. En pratique, les opérateurs des serveurs racine ont un niveau d'ouverture très variable. (Cf. l'analyse de l'ICANN à ce sujet.) Un des moments où plusieurs opérateurs de serveurs racine collectent en même temps de l'information est le Day in the Life of the Internet et c'est sur la base de ces données qu'a été fait le rapport d'Interisle « Name Collision in the DNS ». Entre autres, ce rapport classait les futurs TLD selon qu'ils présentaient un risque de collision élevé ou faible (.home, .corp et .site se retrouvaient en tête du classement). L'ICANN a alors publié un plan pour gérer ce risque de collisions, notant que .home et .corp étaient de loin les plus « risqués », car ils sont fréquemment utilisés comme TLD locaux. Bien d'autres documents ont été publiés par l'ICANN, qui a une productivité extraordinaire lorsqu'il s'agit de faire de la paperasse. Le dernier mettait en place le système dit de « controlled interruption » qui, en gros, impose à tous les nouveaux TLD de résoudre, pendant les premiers temps de leur délégation, tous les noms de domaine vers l'adresse IP 127.0.53.53. Voici l'exemple de .box en novembre 2016 (ce cas avait fait l'objet d'un article de Heise en allemand, car le routeur Fritz!Box, très populaire en Allemagne, utilisait ce TLD) :



% dig ANY box.

; <<>> DiG 9.10.3-P4-Debian <<>> ANY box.
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 14573
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 24, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;box.			IN ANY

;; ANSWER SECTION:
box.			3600 IN	A 127.0.53.53
box.			3600 IN	SRV 10 10 0 your-dns-needs-immediate-attention.box.
box.			3600 IN	TXT "Your DNS configuration needs immediate attention see https://icann.org/namecollision"
box.			3600 IN	MX 10 your-dns-needs-immediate-attention.box.
box.			900 IN SOA a.nic.box. support.ariservices.com. (
				1478481375 ; serial
				1800       ; refresh (30 minutes)
				300        ; retry (5 minutes)
				1814400    ; expire (3 weeks)
				1800       ; minimum (30 minutes)
				)
box.			172800 IN NS b.nic.box.
box.			172800 IN NS d.nic.box.
box.			172800 IN NS c.nic.box.
box.			172800 IN NS a.nic.box.
[...]
;; Query time: 89 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Mon Nov 21 17:23:17 CET 2016
;; MSG SIZE  rcvd: 2938



    

Ces enregistrements ont pour but d'attirer l'attention des utilisateurs sur le risque de collision. Le TLD étant récent et pas encore peuplé, il ne devrait pas y avoir de requêtes DNS. S'il y en a quand même, c'est peut-être le résultat d'une collision avec un usage local. L'adresse IP 127.0.53.53 est une adresse locale à la machine. Si M. Michu tente de se connecter à http://quelquechose.box/ aujourd'hui, il sera redirigé vers la machine locale. Il verra une erreur (pas de serveur HTTP qui écoute) ou bien la page Web par défaut de sa machine (avec un message peu informatif comme « It works ») s'il y a un serveur HTTP. Si l'utilisateur regarde les enregistrements SRV, MX ou TXT, ou bien si un administrateur système regarde les requêtes DNS qui passent, ou bien les journaux du serveur de messagerie, peut-être comprendra-t-il qu'il doit agir. (Je trouve personnellement que la probabilité que cela arrive est assez faible.)

L'atelier lui-même, financé par Verisign (l'entreprise qui avait le plus crié « au loup » sur les name collisions), s'est donc tenu du 8 au 10 mars à Londres. Un site Web avait été mis en place pour cet atelier, et il contient les supports et les vidéos.

Je ne vais pas décrire tous les exposés de l'atelier, la liste complète figure dans l'annexe C du RFC, et les supports sont en ligne. Le RFC note qu'il y a eu plusieurs interventions sur la qualité des données du DITL (Day in the Life of the Internet) : il est trivial de les polluer (le DITL est annoncé publiquement, et à l'avance) par des requêtes artificielles. Aucune preuve n'a été trouvée d'une manipulation délibérée. De toute façon, les données montrent surtout qu'il y a beaucoup de n'importe quoi dans le trafic que reçoivent les serveurs racine (par exemple des requêtes avec le bit RD - Recursion Desired - alors que les serveurs de la racine ne sont pas récursifs). Cela peut être le résultat de bogues dans les résolveurs, de tests ou bien d'attaques délibérées.

La question de l'éducation des utilisateurs est revenue plusieurs fois. Faut-il s'inspirer du téléphone ou du système postal, qui ont tous les deux connu des changements qui nécessitaient une adaptation de l'utilisateur, qui s'est faite par le biais d'importantes campagnes de sensibilisation et d'éducation ?

Le comité de programme avait conclu que le sujet était loin d'être épuisé. Manque de données, manque de théories explicatives, manque d'intérêt pour la question, en tout cas, celle-ci restait largement ouverte après l'atelier (et je ne suis personnellement pas sûr que cela soit mieux aujourd'hui, plus de deux ans après l'atelier de Londres).


Téléchargez le RFC 8023


L'article seul

RFC 8003: Host Identity Protocol (HIP) Registration Extension

Date de publication du RFC : Octobre 2016
Auteur(s) du RFC : J. Laganier (Luminate Wireless), L. Eggert (NetApp)
Chemin des normes
Première rédaction de cet article le 26 novembre 2016


Le protocole HIP, décrit dans le RFC 7401 est très bien adapté au cas où l'adresse IP (le localisateur) change après l'établissement d'une association. Mais cela laisse ouvert le grand problème de la connexion initiale. Comment trouver une machine HIP ? Par le mécanisme de rendez-vous du RFC 8004 ? C'est certainement une bonne solution mais, alors, comment les machines HIP sont-elles connues du serveur de rendez-vous ? C'est là que notre RFC rentre en jeu pour normaliser un mécanisme d'enregistrement auprès d'un service. C'est un mécanisme générique, qui peut servir à d'autres choses que le rendez-vous, d'ailleurs. (Il était à l'origine spécifié dans le RFC 5203, que notre RFC remplace.)

Le mécanisme est très simple et le RFC court. On réutilise simplement les établissements d'associations de HIP, avec de nouveaux types de paramètres, notamment REG_INFO (pour l'hôte qui accepte d'être registrar, c'est-à-dire d'enregistrer) et REG_REQUEST (pour celui qui demande un enregistrement). Le mécanisme exact est détaillé dans la section 3 et les nouveaux paramètres dans la section 4.

HIP authentifiant les deux parties bien plus solidement que IP seul, le registrar (terme d'ailleurs mal choisi, on risque de confondre avec les bureaux d'enregistrement de noms de domaine) peut alors décider s'il accepte l'enregistrement ou pas (sections 3.3 et 6).

Le rendez-vous, normalisé dans le RFC 8004 est donc une simple application de notre RFC mais d'autres pourront apparaître à l'avenir (comme celle du RFC 5770).

Quels sont les changements depuis le premier RFC, le RFC 5203 ? La principale est qu'HIP, qui avait le statut « Expérimental » est désormais sur le chemin des Normes et que les références de notre RFC ont donc changé (nouveau protocole HIP en RFC 7401). Mais ce nouveau RFC ajoute aussi la possibilité d'authentifier le registrar par certificat (RFC 8002), ainsi qu'un nouveau type d'erreur, le numéro 2, « ressources insuffisantes chez le registrar ».

Question mise en œuvre, je n'ai pas vérifié mais, normalement, HIP for Linux et OpenHIP devraient s'adapter aux nouveaux RFC HIP.


Téléchargez le RFC 8003


L'article seul

RFC 8004: Host Identity Protocol (HIP) Rendezvous Extension

Date de publication du RFC : Octobre 2016
Auteur(s) du RFC : J. Laganier (Luminate Wireless,), L. Eggert (NetApp)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF hip
Première rédaction de cet article le 26 novembre 2016


HIP, par défaut, nécessite que l'initiateur d'une association connaisse le localisateur, l'adresse IP du répondeur. Si celui-ci bouge souvent, et qu'il n'est donc pas pratique de mettre cette adresse dans le DNS, une solution est d'utiliser le mécanisme de rendez-vous, décrit par ce RFC, où l'initiateur contacte un serveur de rendez-vous qui relaie vers le répondeur.

Le schéma est clairement expliqué dans la section 3 du RFC. En fonctionnement habituel de HIP, l'initiateur trouve l'identificateur et le localisateur du répondeur (typiquement, dans le DNS, cf. RFC 8005), puis le contacte directement. Si le localisateur n'est pas connu (ce qui est fréquent si le répondeur est un engin mobile, changeant souvent d'adresse IP), l'initiateur envoie le premier paquet (I1) au serveur de rendez-vous, qui le relaie au répondeur. Les autres paquets (R1, I2 et R2) seront transmis directement entre les deux machines HIP. Le mécanisme est détaillé dans la section 3.3 (il faut notamment procéder avec soin à la réécriture des adresses IP, en raison entre autre du RFC 2827).

Et comment l'initiateur trouve-t-il le serveur de rendez-vous ? En général dans le DNS, via les enregistrements de type HIP. Et comment le répondeur avait-il fait connaitre au serveur de rendez-vous son adresse IP ? Via le protocole d'enregistrement du RFC 8003, comme l'explique la section 4.

Comme toute indirection, le système de rendez-vous ouvre des problèmes de sécurité amusants. Si l'initiateur connaissait déjà l'identificateur du répondeur (donc sa clé publiqué), pas de problème, le passage par le serveur de rendez-vous ne diminue pas la sécurité. Si ce n'est pas le cas, alors, il n'y a rien à faire, l'initiateur n'a aucun moyen de vérifier l'identité du répondeur (section 5 du RFC).

Aucun changement depuis la première spécification, le RFC 5204, juste l'alignement avec la nouvelle version de HIP, celle du RFC 7401, désormais norme complète (et pas juste « expérimentale »).


Téléchargez le RFC 8004


L'article seul

RFC 8005: Host Identity Protocol (HIP) Domain Name System (DNS) Extensions

Date de publication du RFC : Octobre 2016
Auteur(s) du RFC : J. Laganier (Luminate Wireless)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF hip
Première rédaction de cet article le 26 novembre 2016


Le protocole HIP n'avait pas à l'origine de mécanisme pour trouver l'identificateur d'une machine distante. Cela avait été fait dans le RFC 5205, qui permettait de trouver l'identificateur dans le DNS. Ce nouveau RFC remplace le RFC 5205.

HIP fait partie de la famille des protocoles qui visent à séparer l'identificateur du localisateur. Les identificateurs HIP se nomment les HI (Host Identifier) et, autrefois, le seul moyen de trouver l'HI d'une autre machine était d'attendre qu'elle vous contacte, ou bien de le configurer manuellement. Avec ce RFC, on peut trouver l'HI, comme une adresse IP, dans le DNS.

Notre RFC crée donc un nouveau type d'enregistrement DNS, nommé logiquement HIP (numéro 55), qui stocke, en échange d'un nom de domaine, le HI, son condensat (résumé) cryptographique - le HIT (Host Identifier Tag) - et les éventuels serveurs de rendez-vous, serveurs qui, dans le protocole HIP, servent d'intermédiaires facultatifs lorsqu'on veut contacter une machine distante (cf. RFC 8004).

Notre RFC permet de trouver l'identificateur à partir du nom mais pas le localisateur ; les serveurs de rendez-vous sont une solution possible pour cela ; une autre est d'utiliser les traditionnels enregistrements A et AAAA du DNS, le localisateur HIP étant une adresse IP.

Les localisateurs peuvent changer fréquemment alors que le DNS n'est pas temps-réel et ne change pas instantanément. Si un hôte HIP veut pouvoir être contacté malgré des changements d'adresse IP rapides, il vaut peut-être mieux qu'il utilise le système de rendez-vous du RFC 8004.

Curieusement (pour moi), le HIT est donc stocké dans les données DNS, alors que celles-ci n'offrent aucune sécurité au point que le RFC exige en section 4.1 de recalculer le HIT qui vient d'être obtenu dans le DNS.

Le tout ressemble donc aux enregistrements IPSECKEY du RFC 4025, ce qui est normal, le HI étant une clé cryptographique publique.

Voici un exemple d'enregistrement HIP tel qu'il apparaitrait dans un fichier de zone (sections 5 et 6 de notre RFC). On y trouve l'algorithme cryptographique utilisé (2 = RSA), le HIT (en hexadécimal), le HI (encodé en Base64) et les éventuels serveurs de rendez-vous (ici, deux, indiqués à la fin) :

www.example.com.      IN  HIP ( 2 200100107B1A74DF365639CC39F1D578
                                AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p
                                9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQ
                                b1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D
                                rvs1.example.com.
                                rvs2.example.com. )

Par contre, je n'ai pas réussi à trouver encore ce genre d'enregistrement dans la nature.

L'ensemble du RFC est assez court, ce mécanisme d'annuaire qu'est le DNS étant simple et bien connu.

Quels sont les changements depuis le premier RFC, le RFC 5205 ? Évidement le passage sur le chemin des normes, faisant de HIP une norme complète. Mais aussi l'ajout de l'algorithme de cryptographie asymétrique ECDSA, et plusieurs clarifications du RFC original sur le format des enregistrements DNS, aussi bien leur format sur le réseau que dans le fichier de zone.


Téléchargez le RFC 8005


L'article seul

RFC 7971: Application-Layer Traffic Optimization (ALTO) Deployment Considerations

Date de publication du RFC : Octobre 2016
Auteur(s) du RFC : M. Stiemerling (Hochschule Darmstadt, S. Kiesel (University of Stuttgart), M. Scharf (Nokia), H. Seidel (BENOCS), S. Previdi (Cisco)
Pour information
Réalisé dans le cadre du groupe de travail IETF alto
Première rédaction de cet article le 22 novembre 2016


Il est fréquent aujourd'hui sur l'Internet qu'une application cherche à accéder à un contenu (mettons un film, ou bien la mise à jour d'un gros logiciel) qui est disponible à plusieurs endroits. Dans ce cas (qui est notamment fréquent pour le téléchargement en pair-à-pair), quelle source utiliser ? La « meilleure », bien sûr, mais comment la connaître ? Le but du protocole ALTO est de permettre de distribuer de l'information sur la topologie du réseau, afin que les applications puissent choisir la source la plus proche d'elles. ALTO est déjà normalisé (RFC 7285), ce nouveau RFC sert juste à décrire les scénarios d'usage et à donner des conseils pratiques de déploiement (déploiement qui semble très limité pour l'instant).

Outre le RFC décrivant le protocole (RFC 7285), il peut être utile de lire la description du problème qu'ALTO veut résoudre, le RFC 5693, et le cahier des charges, dans le RFC 6708.

La section 2 de notre RFC résume le fonctionnement d'ALTO. C'est un protocole client-serveur, le serveur ALTO connait l'information (la topologie du réseau, qui est connecté à qui, par quel genre de liens), le client est l'application qui veut accéder au contenu, il connait un ensemble potentiel de sources, et il veut savoir quelle est la « meilleure ». Par exemple, dans le cas de BitTorrent, le client a les adresses IP de l'essaim, il veut savoir à laquelle ou lesquelles demander les bouts de fichier (chunks) qui forment le contenu. Le client ALTO peut être un processus séparé, tournant en permanence, ou bien une bibliothèque liée à l'application. Il doit évidemment parler le protocole ALTO, donc connaitre HTTP et JSON.

Pour déployer ALTO, il y a donc quatre entités logiques à considérer :

  • L'origine de l'information (celle qui a compilé les informations de topologie, par exemple en commençant par lister les préfixes IP connus),
  • Le serveur ALTO, qui va distribuer cette information,
  • Le client ALTO, qui va la récupérer,
  • L'application (resource consumer, dans le RFC), qui va en faire quelque chose d'utile.

Ces entités sont typiquement gérées par des organisations différentes. Un exemple typique (mais ce n'est pas la seule possibilité) est que le FAI soit à l'origine de l'information (il connait son réseau), et la mette dans un serveur ALTO qu'il gère, ses abonnés ayant installé une application de partage de fichiers qui inclut un client ALTO. Dans ce cas, il y aurait deux organisations, le FAI gérant les deux premières entités et l'abonné les deux dernières. Mais d'autres répartitions peuvent exister.

Les organisations qui peuvent être impliquées sont en effet multiples : FAI et opérateurs réseau, bien sûr, utilisateurs, évidemment (agissant, soit seuls, soit en groupes se répartissant le travail), mais aussi des tiers, spécialisés dans la collecte et la distribution de cette information (par exemple des CDN). On pourrait même voir apparaitre des sociétés qui ne font que de l'ALTO.

Tout ceci a des conséquences sur le déploiement. Par exemple, un utilisateur peut faire confiance à un FAI mais pas à des tiers. Un FAI peut souhaiter distribuer de l'information à ses abonnés mais pas à tout l'Internet. ALTO définit un protocole, pas une politique : ce protocole permet différents modèles, y compris celui de serveurs ALTO spécialisés et payants. Autre conséquence de l'utilisation de telle ou telle répartition du travail, on pourrait avoir des serveurs ALTO partiels, qui ne contiennent de l'information que sur certains réseaux.

Dans tous les cas, le RFC rappelle qu'ALTO est juste une optimisation : une application doit fonctionner même si elle ne trouve aucun serveur ALTO, ou bien s'ils sont en panne.

Un petit rappel utile sur ALTO : il existe deux modes de fonctionnement différents, qui ont tous les deux des conséquences importantes, notamment sur la confidentialité. Dans le premier mode, le serveur ALTO fournit l'information qu'il a (sous forme de maps, des ensembles de données sur le réseaux, les liens, leur coût, etc) et le client cherche dedans ce qui l'intéresse. Ce mode préserve la vie privée du client (qui ne dit pas au serveur ce qui l'intéresse) mais pas celle du serveur (qui doit tout envoyer). Il n'est pas évident que beaucoup de FAI acceptent cela. Dans le second mode, le serveur permet des interrogations sur un point particulier (« qui est le plus proche de moi ? 192.0.2.87, 203.0.113.122 ou bien 198.51.100.20 ? »). Ce mode évite au serveur de tout divulguer mais oblige en revanche le client à révéler ses intentions (ici, les adresses IP des pairs potentiels, ce qui peut intéresser des organisations répressives comme la HADOPI). Notez que la fuite d'informations du serveur existe aussi dans le second mode : plusieurs clients ALTO peuvent coopérer pour poser beaucoup de questions et extraire ainsi une partie substantive de la base.

La partie 3 de notre RFC en vient aux conseils concrets pour les FAI. On considère que l'objectif du FAI est de minimiser ses coûts, donc a priori de garder le maximum de trafic en local (il y a des exceptions, que liste le RFC). Le serveur ALTO que gère le FAI va donc annoncer des coûts plus faibles pour les liens locaux.

Mais, d'abord, le FAI doit « remplir » le serveur ALTO avec de l'information. Cette étape d'avitaillement commence par la récolte d'informations sur le réseau. A priori, le FAI connait son propre réseau, et n'a donc pas de mal à récolter ces informations. Outre sa propre documentation interne, le FAI peut aussi utiliser de l'information issue d'autres sources, par exemple les protocoles de routage comme BGP (cf., entre autres, le RFC 7752) ou bien des mesures actives ou passives (cf. entre autres, le RFC 7491). Rappelez-vous qu'ALTO est uniquement un protocole permettant d'accéder à de l'information sur la topologie. Comment cette information a été récoltée et agrégée n'est pas de la responsabilité d'ALTO, de même que le protocole HTTP ne se soucie pas de comment est fabriquée la page HTML qu'il sert.

Le FAI doit ensuite appliquer ses critères (coût, performance, etc) à la topologie. Ces critères sont forcément imparfaits. Le client ALTO ne doit pas s'attendre à ce que l'information qui lui est donnée soit idéale dans tous les cas. Par exemple, le serveur ALTO peut indiquer un lien rapide et pas cher mais qui, au moment où le téléchargement commencera, sera saturé par un trafic intense (ALTO ne prétend pas être temps-réel). Et il y a bien d'autres choses qui ne seront pas connues de ceux qui ont compilé l'information, ou bien qui n'auront pas été incluses dans la base de données du serveur ALTO (« la carte n'est pas le territoire »). Les données distribuées par ALTO, les maps, sont supposées être relativement statiques. Mais, dans le monde réel, les choses changent et le client recevra donc peut-être une information légèrement dépassée.

Si vous trouvez le concept de map un peu abstrait, la section 3.5 du RFC donne plusieurs exemples. Par exemple, dans le cas le plus simple, celui d'un petit FAI ayant un seul opérateur de transit, les adresses dudit FAI seront dans le PID (Provider-defined IDentifier, cf. RFC 7285, section 5.1) 1, tout le reste de l'Internet étant le PID 2. Cela donnera une map (syntaxe décrite dans le RFC 7285, section 9.2) :

       {
       ...
        "network-map" : {
          "PID1" : {
            "ipv4" : [
              "192.0.2.0/24",
              "198.51.100.0/25"
            ],
            "ipv6" : [
              "2001:db8:100::/48"
            ]
          },
          "PID2" : {
            "ipv4" : [
              "0.0.0.0/0"
            ],
            "ipv6" : [
              "::/0"
            ]
          }
        }
      }

Un FAI plus gros, et à la topologie plus complexe, a plein de possibilités. Par exemple, ses propres réseaux peuvent être dans des PID différents, s'il veut pouvoir garder le trafic local à un de ses réseaux. Un exemple est celui où le même FAI a des abonnés fixes et mobiles, et où on souhaite limiter les transferts des abonnés fixes vers les mobiles, pour réduire l'utilisation des liens hertziens.

Reste ensuite à effectuer le déploiement des serveurs ALTO. Il existe plusieurs mises en œuvre logicielles d'ALTO et des compte-rendus d'expérience figurent dans les Internet-Drafts draft-seidel-alto-map-calculation et draft-lee-alto-chinatelecom-trial et dans le RFC 6875 (ainsi que, pour un protocole antérieur à ALTO, dans le RFC 5632). Cette expérience montre que certaines façons de collecter l'information peuvent être coûteuses : si un FAI a plusieurs liens avec l'Internet, et reçoit un flux BGP complet, et veut mettre chaque préfixe de la DFZ dans ses maps, il doit prévoir des machines assez costaud pour traiter cette information importante et assez changeante. Et le résultat serait une map qu'il serait difficile d'envoyer à tous les clients, vu sa taille. Il faut donc prévoir, dans ce cas extrême, de l'agrégation vigoureuse des préfixes IP.

La section 4 de notre RFC couvre ensuite l'utilisation d'ALTO, une fois qu'il est déployé. Normalement, tout le monde a intérêt à ce que ALTO soit utilisé : le FAI veut que les utilisateurs épargnent les liens réseaux les plus lents et les plus coûteux et les utilisateurs veulent les meilleures perfomances. En théorie, tout le monde trouvera son intérêt à utiliser ALTO.

Un exemple est celui de BitTorrent. Si les pairs BitTorrent incluent un client ALTO, chaque pair, quand il reçoit une liste d'adresses IP de l'essaim, peut alors interroger le serveur ALTO et trouver les « meilleurs » pairs. Ils peuvent même échanger cette information entre eux (PEX, Peer EXchange, dans le monde BitTorrent). Mais une autre possibilité est que ce ne soient pas les pairs qui interrogent le serveur ALTO mais le tracker (pour les essaims fonctionnant avec une machine qui sert de tracker, ce qui n'est pas toujours le cas). Ainsi, il n'est pas nécessaire de mettre un client BitTorrent dans chaque pair, c'est le tracker qui, grâce à l'information ALTO, choisit les meilleurs pairs pour chacun, et ne leur envoie que cela.

Le RFC se conclut pas une section 7 sur la sécurité. Parmi les problèmes à considérer, il y a le fait qu'un serveur ALTO malveillant, ou bien un serveur se faisant passer pour un serveur ALTO légitime, peut empoisonner le client avec de fausses données.


Téléchargez le RFC 7971


L'article seul

Fiche de lecture : Mastering Bitcoin

Auteur(s) du livre : Andreas Antonopoulos
Éditeur : O'Reilly
978-1-449-37404-4
Publié en 2015
Première rédaction de cet article le 20 novembre 2016


Vous voulez connaitre tous les détails techniques sur Bitcoin ? Voici un livre recommandé. À la fin, vous en saurez davantage que vous ne vouliez.

Le livre a été écrit par Andreas Antonopoulos, personnage connu dans le monde Bitcoin, et qui écrit de nombreux articles et donne plein de conférences (celle qu'il a donné à Paris le 11 octobre est en ligne, vous pouvez aussi voir les nombreux tweets que cela a entrainé et une excellente « storifycation de ces tweets). Son livre commence de manière très pédagogique, à travers des scénarios d'utilisation. Alice utilise Multibit pour acheter un café à Bob à Palo Alto, Bob fait refaire le site Web de son café à Gonesh, à Bangalore, et Jing mine du bitcoin à Shanghai. Au début, l'auteur fait peu de technique, se focalisant sur les applications.

Ensuite, cela devient plus technique, en commençant par l'installation d'un nœud Bitcoin (le livre n'est pas destiné à M. Michu). Andreas Antonopoulos explique le fonctionnement du client en ligne de commande qui permet de parler à son nœud Bitcoin. De la commande la plus triviale, permettant de savoir à quel bloc en est la chaîne locale :

 % bitcoin-cli getblockcount
439785
    

à des commandes plus complexes, ici pour voir l'achat du café d'Alice :

% bitcoin-cli gettransaction 0627052b6f28912f2703066a912ea577f2ce4da4caa5a5fbd8a57286c345c2f2
    

(Si vous obtenez le message d'erreur Invalid or non-wallet transaction id, c'est que vous n'avez pas bien lu le livre et les instructions qu'il donne pour accéder à toutes les transactions.)

À noter que les exemples ont été réellement faits sur la chaîne publique Bitcoin, et peuvent donc être vérifiés. L'adresse d'Alice est 1Cdid9KFAaatwczBwBttQcwXYCpvK8h7FK et on peut donc voir toutes ses transactions en ligne, de sa première obtention de 0,1 bitcoin auprès de son ami Joe (transaction 7957a35fe64f80d234d76d83a2a8f1a0d8149a41d81de548f0a65a8a999f6f18), à l'achat du café à Bob (transaction 0627052b6f28912f2703066a912ea577f2ce4da4caa5a5fbd8a57286c345c2f2). Le code QR de la demande de bitcoins de Bob, dans le livre, est également un vrai, et on peut le lire (bitcoin:1GdK9UzpHBzqzX2A9JFP3Di4weBwqgmoQA?amount=0.015&label=Bob%27s%20Cafe&message=Purchase%20at%20Bob%27s%20Cafe).

L'auteur pense aussi aux programmeurs et leur explique comment accéder aux données Bitcoin et les manipuler depuis un programme. Par exemple, en Python, avec la bibliothèque pycoin.

Je l'ai dit, ce livre, malgré ses premières pages très pédagogiques sur Bitcoin, est prévu pour les techniciens. Vous y trouverez même une explication de la cryptographie sur courbes elliptiques, permettant de décrire ensuite les différents formats de clés.

Les utilisateurs de l'autre chaîne de blocs Ethereum savent qu'une adresse Ethereum ne désigne pas forcément un compte mais peut référencer un programme qui sera exécuté lorsqu'on enverra quelque chose à cette adresse. Mais peu savent que cette possibilité existe dans Bitcoin depuis longtemps. Antonopoulos décrit donc en détail les différents types d'adresses Bitcoin, notamment les P2SH (Pay To Script Hash) où le paiement va déclencher l'exécution d'un programme qui pourra, par exemple, demander plusieurs signatures pour valider un paiement (la grande différence entre Ethereum et Bitcoin n'est pas la présence ou l'absence de programmes stockés dans la chaîne, elle est dans le fait que seul Ethereum a un langage de Turing ; au passage, le livre contient un court chapitre présentant rapidement quelques chaînes de blocs concurrentes). Il y a même un peu d'assembleur Bitcoin dans le livre (mais pas un cours complet sur ce langage).

Les gens du réseau aimeront également le chapitre sur le fonctionnement pair à pair de Bitcoin et sur la façon dont les nœuds Bitcoin échangent. Un petit coup de bitcoin-cli getpeerinfo et je vois que ma machine Bitcoin a 124 pairs, dont 11 se connectent en IPv6. 86 font tourner le logiciel de référence Bitcoin Core et 30 sont basés sur BitcoinJ (ce sont surtout des clients utilisant Multibit).

Je l'ai dit plus haut, ce livre n'est pas du tout nécessaire pour utiliser Bitcoin, ni même pour comprendre comment il fonctionne. En revanche, il est indispensable si vous voulez comprendre les points les plus délicats du fonctionnement de Bitcoin, comme les UTXO, la structure de la chaîne avec les arbres de Merkle, le fonctionnement de SPV... Difficile de trouver une question technique sur Bitcoin qui n'aurait pas de réponse dans ce livre.

Avertissement : j'ai acheté ce livre en payant en euros, pas en bitcoins. J'en profite pour rappeler que, si vous aimez ce blog, je veux bien des bitcoins.


L'article seul

Panne des résolveurs DNS d'Orange, observations et remarques

Première rédaction de cet article le 17 novembre 2016


Le 16 novembre, deux pannes successives ont affecté les résolveurs DNS d'Orange. Que s'est-il passé exactement, et quelles conséquences peut-on en tirer ?

Commençons par les observations. Au moins, il s'agira de faits. Les deux pannes sont survenues approximativement entre 0840 UTC (soit quasiment en même temps que la plénière de l'IETF dont le thème était... « Attacks Against the Architecture » !) et 1030 pour la première, et entre 1315 et 1410 (toujours UTC) pour la seconde. N'ayant pas de compte chez Orange, j'ai utilisé deux sources d'informations, les rézosocios, où d'innombrables messages ont signalé la panne, et les sondes RIPE Atlas. Pour ces dernières, j'ai demandé des sondes se trouvant dans l'AS 3215, celui d'Orange (notez qu'il abrite des services très différents, ne dépendant pas forcément des mêmes résolveurs DNS). À ma connaissance, Orange n'a rigoureusement rien communiqué, ni pendant la panne (malgré les innombrables cris lancés par ses clients sur les rézosocios), ni après, donc je ne peux me fier qu'à ces observations. Les messages des utilisateurs d'Orange étaient pour la plupart trop vagues (« rien ne marche »), ne citant même pas un nom de domaine qu'on puisse ensuite tester. Personne hélas pour procéder à une récolte sérieuse de données, par exemple avec dig. Ces messages des utilisateurs ne peuvent donc servir qu'à signaler et confirmer qu'il y avait un gros problème. Mais les sondes Atlas nous en disent davantage.

Que nous montrent-elles ? Je prends par exemple le domaine de l'Université Stanford. Si je veux vérifier qu'il est bien visible, je demande à cent sondes RIPE Atlas de résoudre ce nom en adresse IP :

% atlas-resolve --requested 100 online.stanford.edu
[] : 1 occurrences 
[171.67.216.22] : 33 occurrences 
[171.67.216.23] : 28 occurrences 
[171.67.216.21] : 37 occurrences 
Test #6935163 done at 2016-11-17T04:56:58Z

C'était le lendemain de la panne, et tout marche bien (une seule sonde n'a pas eu de réponse, et cela peut être de la faute de son réseau d'accès). Mais pendant la panne ? On voyait, en se limitant à l'AS 3215, des choses comme :

% atlas-resolve --requested 100 --as 3215 online.stanford.edu
[TIMEOUT(S)] : 13 occurrences 
[ERROR: SERVFAIL] : 65 occurrences 
[171.67.216.22] : 8 occurrences 
[171.67.216.23] : 7 occurrences 
[171.67.216.21] : 7 occurrences 
Test #6934676 done at 2016-11-16T08:53:51Z

Regardons de plus près. La majorité des sondes RIPE Atlas situées dans l'AS d'Orange n'a pu résoudre le nom, et a au contraire obtenu un code SERVFAIL (SERVer FAILure), indiquant que le résolveur (je reviens sur ce terme plus loin) utilisé n'a pu joindre aucun des serveurs faisant autorité pour le domaine stanford.edu. Pas mal de sondes n'ont simplement pas eu de réponses de leur résolveur à temps.

Mais cette unique observation ne nous permet pas de dire que le problème venait d'Orange. Il est parfaitement possible que ce soit Stanford qui ait des ennuis, panne ou dDoS. Il faut donc, comme toujours lorsqu'on fait des observations scientifiques, comparer avec des mesures faites dans d'autres circonstances. Ici, on va simplement demander aux sondes situées dans un pays voisin, l'Allemagne :

    
% atlas-resolve --requested 100 --country DE online.stanford.edu 
[] : 1 occurrences 
[171.67.216.22] : 33 occurrences 
[171.67.216.23] : 31 occurrences 
[171.67.216.21] : 35 occurrences 
Test #6934677 done at 2016-11-16T08:54:06Z

Au pays de Konrad Zuse, toutes les sondes ou presque ont une réponse. Cela laisse entendre que tout va bien à Stanford et que le problème ne vient pas de l'université californienne. (J'aurais aussi pu tester avec un autre AS français, celui de SFR ou de Free.)

Autre façon de voir que le problème était bien chez Orange et pas du côté des domaines testés, essayer avec d'autres domaines :

%  atlas-resolve --requested 100 --as 3215 kotaku.com
[ERROR: SERVFAIL] : 47 occurrences 
[151.101.1.34 151.101.129.34 151.101.193.34 151.101.65.34] : 50 occurrences 
Test #6934730 done at 2016-11-16T10:10:01Z

% atlas-resolve --requested 100 --as 3215 spotify.com
[194.132.197.147 194.132.198.165 194.132.198.228] : 76 occurrences 
[ERROR: SERVFAIL] : 19 occurrences 
[TIMEOUT(S)] : 4 occurrences 
Test #6934675 done at 2016-11-16T08:52:10Z
    

Tous ces domaines marchaient parfaitement depuis d'autres AS ou d'autres pays.

Donc, problème de résolution DNS chez Orange. Comme l'ont vite découvert bien des utilisateurs, changer de résolveur DNS suffisait à résoudre le problème (ce qu'on pouvait également tester avec ce programme atlas-resolve et l'option --nameserver).

Notons bien, qu'il s'agissait des résolveurs DNS, pas des serveurs faisant autorité, comme cela avait été le cas récemment lors de l'attaque contre Dyn. La distinction est cruciale car ces deux types de serveurs DNS n'ont pas grand'chose en commun. Si vous lisez un article qui parle de « serveur DNS » tout court, sans préciser s'il s'agit d'un résolveur ou bien d'un serveur faissant autorité, méfiez-vous, c'est souvent un signe d'ignorance, ou de négligence, de la part de l'auteur de l'article.

Maintenant, les remarques. D'abord, beaucoup de gens (par exemple dans cet article de Numerama, mais aussi dans d'innombrables tweets) ont suggéré de passer des résolveurs DNS d'Orange (ceux utilisés par défaut par les abonnés à ce FAI) à ceux de Google Public DNS ou bien à ceux de Cisco OpenDNS. La plupart des sociétés à but lucratif doivent payer des commerciaux et des chargés de relation publique pour faire leur publicité, mais Google n'en a pas besoin, ayant des millions de vendeurs bénévoles et enthousiastes parmi ses utilisateurs. Mais ceux qui écoutent ces conseils et passent à Google Public DNS lui donneront les données personelles qui permettent leur propre surveillance (cf. le RFC 7626 sur le caractère sensible des requêtes DNS). Je ne développe pas davantage ce point ici, Shaft l'a fait mieux que moi. J'observe que, si ce genre de pannes continue, les utilisateurs français dépendront presque tous, pour une activité critique, d'un résolveur états-unien d'une entreprise privée. Cela devrait logiquement agiter ceux qui nous parlent tout le temps de souveraineté numérique, mais, en général, ces gens ne sont pas intéressés par les problèmes concrets et opérationnels.

Mais alors quelle serait la bonne solution ? Le mieux évidemment est d'utiliser des résolveurs proches, donc a priori dans le cas idéal, ceux de son FAI. Ceux-ci ne devraient pas tomber en panne, le DNS étant absolument indispensable à tout usage de l'Internet. Mais lorsque des pannes aussi longues surviennent, il est normal d'envisager d'autres solutions, et la bonne est certainement d'avoir un résolveur sur son réseau local (pas forcément sur chaque machine), ce qui est facile avec des équipements comme le Turris Omnia.

Notez qu'une minorité des sondes RIPE Atlas sont déjà sur un réseau local qui utilise un tel résolveur. Cela explique en partie pourquoi, dans les tests ci-dessus, un certain nombre de sondes arrivaient à résoudre les noms de domaine, même au plus fort de la panne. (Cela n'explique qu'une partie du phénomène. Il semble que certains noms avaient un taux de réussites plus fort que d'autres, ce qui ne peut pas s'expliquer par le choix du résolveur.) Notez qu'on peut avoir l'adresse IP du résolveur utilisé par la sonde (avec l'option --displayresolvers) mais que cela ne renseigne pas tellement. D'abord, c'est souvent une adresse IP privée (RFC 1918), ensuite, le premier résolveur vu par la sonde fait fréquemment suivre à un résolveur plus gros, qu'on ne voit pas, et qui peut être ou ne pas être un résolveur « officiel » du FAI. Je vous montre quand même le résultat pour l'une des mesures faites ci-dessus (notez la bogue pour le cas du timeout, où le résolveur n'est pas connu) :

% atlas-resolve -r 100 --as 3215 --displayresolvers --measurement 6934670  kotaku.com    
[ERROR: SERVFAIL] : 27 occurrences (resolvers ['172.31.255.254', '192.168.1.1', '80.10.246.2', '192.168.2.1', '192.168.254.254', '192.168.3.1'])
[151.101.1.34 151.101.129.34 151.101.193.34 151.101.65.34] : 69 occurrences (resolvers ['2a01:cb08:898c:fc00::1', '172.16.3.1', '192.168.1.1', '10.10.11.4', '10.63.0.252', '10.112.0.1', '8.8.8.8', '192.168.119.1', '192.168.1.9', '192.168.0.1', '10.0.0.34', '80.10.246.136', '192.168.248.153', '192.168.4.10', '192.168.1.40', '192.168.221.254', '149.202.242.66', '192.168.255.254', '192.168.28.1', '192.168.2.1', '10.0.0.1', '192.168.0.31', '194.2.0.20', '192.168.10.10'])
[TIMEOUT(S)] : 4 occurrences (resolvers <__main__.Set instance at 0x7fedc8194f80>)
Test #6934670 done at 2016-11-16T08:44:41Z

Deuxième sujet de réflexions sur cette panne, que s'est-il passé ? En l'absence de toute communication de la part d'Orange, on ne peut guère que spéculer. Notons tout de suite qu'il ne s'agissait pas cette fois d'un détournement (comme lorsque Orange avait redirigé Google et Wikipédia vers le Ministère de l'Intérieur) mais d'une absence de réponse. Cette absence dépendait des domaines. Je n'ai pas eu immédiatement de signalement d'un problème pour un domaine hébergé en France, seulement pour des domaines états-uniens (c'est après, donc trop tard pour les mesures, que j'ai appris que des domaines hébergés en France étaient également touchés). Comme le code de retour SERVFAIL indique que le résolveur n'a pas réussi à parler aux serveurs faisant autorité, on peut donc supposer que les liens menant à ces réseaux outre-Atlantique étaient inutilisables. Suite à une erreur de configuration, par exemple dans des ACL ? À un problème de routage vers certaines destinations ? À une attaque par déni de service ? Je ne le sais pas. Mais je me demande bien quelle était la panne ou l'attaque qui pouvait bloquer les résolveurs, tout en laissant passer toutes les autres machines (puisque, une fois qu'on avait un résolveur normal, le trafic n'était pas affecté).


L'article seul

RFC 8020: NXDOMAIN: There Really Is Nothing Underneath

Date de publication du RFC : Novembre 2016
Auteur(s) du RFC : S. Bortzmeyer (AFNIC), S. Huque (Verisign Labs)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 9 novembre 2016


Tout le monde apprend à l'école que les noms de domaine sont organisés en un arbre. (Et j'invite tout le monde à lire la section 3.1 du RFC 1034, pour dire moins de bêtises sur les noms de domaine.) Il en découle logiquement que, si un nœud de l'arbre n'existe pas, les nœuds situés en dessous n'existent pas non plus. C'est évident ? Hélas, non. En pratique, bien des résolveurs DNS sont prudents et, lorsqu'ils reçoivent une réponse négative pour un nom, mettons foo.example, ils n'enregistrent pas pour autant le fait que les sous-domaines comme bar.foo.example n'existent pas non plus, et, si un client leur demande des informations sur ce sous-domaine, ils vont relayer la question aux serveurs faisant autorité, alors qu'ils auraient parfaitement pu répondre à partir de leur cache. Ce nouveau RFC remet les choses en place : les noms de domaine sont organisés en arbre, ce comportement traditionnel est donc bel et bien erroné, et un résolveur devrait, lorsqu'il reçoit une réponse négative, mémoriser le fait qu'il n'y a pas non plus de sous-domaines de ce nom. Cela améliorera les performances du DNS et, dans certains cas, sa résistance à des attaques par déni de service.

Voyons d'abord ce que fait un résolveur actuel. J'ai choisi Unbound. Il vient de démarrer, on lui demande foobar56711.se, qui n'existe pas :

% dig MX foobar56711.se.

...	 
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 56324

    

On a logiquement un NXDOMAIN (No Such Domain, ce nom n'existe pas ; cette erreur se nommait autrefois Name Error, et a le code 3). Où le résolveur a-t-il trouvé cette information ? Il a demandé aux serveurs faisant autorité, comme nous le montre tcpdump :

14:57:14.488196 IP (tos 0x0, ttl 57, id 52537, offset 0, flags [none], proto UDP (17), length 1063)
    130.239.5.114.53 > 10.10.86.133.44861: [udp sum ok] 64329 NXDomain*- q: MX? foobar56711.se. 0/6/1 ...     
    

Le serveur d'IIS (le registre de .se), 130.239.5.114 lui a bien dit NXDOMAIN. Maintenant, demandons au même résolveur xyz.foobar56711.se, sous-domaine du précédent :

% dig MX xyz.foobar56711.se.

...
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 64776

    

Et, si on regarde le trafic avec tcpdump, on voit que le résolveur a demandé encore au serveur faisant autorité, alors que c'était inutile !

15:00:32.929219 IP (tos 0x0, ttl 64, id 42641, offset 0, flags [none], proto UDP (17), length 75)
    10.10.86.133.40616 > 130.239.5.114.53: [bad udp cksum 0x8d98 -> 0xd7df!] 10643% [1au] MX? xyz.foobar56711.se. ar: . OPT UDPsize=4096 OK (47)
15:00:32.939437 IP (tos 0x0, ttl 57, id 14256, offset 0, flags [none], proto UDP (17), length 1067)
    130.239.5.114.53 > 10.10.86.133.40616: [udp sum ok] 10643 NXDomain*- q: MX? xyz.foobar56711.se. 0/6/1 ...
    

Pourquoi le résolveur est-il si prudent, et pose-t-il au serveur faisant autorité une question dont il aurait déjà dû connaitre la réponse ? Il y a plusieurs raisons mais la principale est que le RFC originel sur le DNS, le RFC 1034, est ambigu. Il ne décrivait pas de manière parfaitement claire ce qu'il faut faire lorsqu'un nom de domaine est un ENT, un Empty Non-Terminal, c'est-à-dire un nom de domaine qui n'a pas d'enregistrements mais qui a des sous-domaines. Certains ont pensé que cela autorisait à répondre NXDOMAIN lorsque le nom demandé est un ENT. Ce comportement a été clairement noté comme incorrect dans les RFC ultérieurs (section 7.16 du RFC 2136 et sections 2.2.2 et 2.2.3 du RFC 4592) mais tout le monde n'en avait pas forcément tiré les conséquences. Autre RFC qui contribuait au comportement erroné, le RFC 2308 (dans sa section 5) faisait l'erreur de dire qu'un résolveur ne pouvait renvoyer un NXDOMAIN que si la question portait sur exactement le même nom que celui qui avait été mis en cache. Notre nouveau RFC 8020 corrige cette erreur : un résolveur doit également renvoyer NXDOMAIN si la question est un sous-domaine d'un domaine inexistant.

La règle qui forme le cœur de ce nouveau RFC tient en une phrase (section 2) : « si un résolveur reçoit un NXDOMAIN, il peut et il devrait mémoriser le fait que ce nom et tous ceux en dessous n'existent pas ». Logiquement, les questions ultérieures portant sur un sous-domaine de ce nom devraient recevoir immédiatement un NXDOMAIN, sans déranger les serveurs faisant autorité. C'est d'ailleurs ce que fait Unbound, si on active l'option harden-below-nxdomain ainsi :

server:
    harden-below-nxdomain: yes     
   

On voit alors qu'Unbound, face aux deux requêtes successives pour foobar56711.se et xyz.foobar56711.se, n'écrit qu'une seule fois aux serveurs de .se. (Si cela ne marche pas pour vous, c'est peut-être que votre Unbound ne valide pas, vérifiez sa configuration DNSSEC, ou que le domaine est signé avec l'option opt-out.) Unbound suit donc le bon comportement mais, malheureusement, pas par défaut. (C'est déjà mieux que BIND, qui a toujours le mauvais comportement de demander systématiquement aux serveurs faisant autorité, ce qui annule partiellement l'intérêt d'avoir un cache.)

Voilà, vous savez maintenant l'essentiel sur le principe du NXDOMAIN cut. Voyons quelques détails, toujours en section 2 du RFC. D'abord, il faut noter que la règle n'est pas absolue : un résolveur, s'il y tient, peut continuer à renvoyer des réponses positives à une question sur un sous-domaine, même si le domaine parent n'existe pas, si le cache (la mémoire) du résolveur contenait des réponses pour ces sous-domaines. En terme d'implémentation, cela veut dire que le mode préféré est de supprimer tout le sous-arbre du cache lorsqu'on reçoit un NXDOMAIN, mais que ce n'est pas obligatoire.

D'autre part, rien n'est éternel dans le monde du DNS. Les informations reçues par le résolveur ne sont valables que pendant une période donnée, le TTL. Ainsi, une information positive (ce domaine existe) n'est vraie que jusqu'à expiration du TTL (après, il faut revalider auprès des serveurs faisant autorité). Même chose pour une information négative : la non-existence d'un domaine (et de tout le sous-arbre qui part de ce domaine) est établie pour un TTL donné (qui est celui du champ Minimum du SOA, cf. RFC 2308).

Dernier petit piège, s'il y a une chaîne d'alias menant au nom de domaine canonique, le NXDOMAIN s'applique au dernier nom de la chaîne (RFC 6604), et pas au nom explicitement demandé.

La section 4 de notre RFC détaille les bénéfices attendus du NXDOMAIN cut. Le principal est la diminution de la latence des réponses, et celle de la charge des serveurs faisant autorité. On aura moins de requêtes, donc un bénéfice pour tout l'écosystème. Cela sera encore plus efficace avec la QNAME minimisation du RFC 9156, puisque le résolveur pourra arrêter son traitement dès qu'il y aura un domaine absent.

Cela sera aussi utile dans le cas de certaines attaques par déni de service, notamment les attaques random QNAMEs avec un suffixe un peu long (comme dans le cas de l'attaque dafa888).

Mais tout n'est pas idéal dans cette vallée de larmes. Le NXDOMAIN cut peut aussi poser des problèmes, ce qu'examine la section 5. Le principal risque est celui que pose des serveurs faisant autorité bogués, comme ceux d'Akamai. Regardons le domaine de l'Université de Pennsylvanie, www.upenn.edu :

% dig  A www.upenn.edu   
www.upenn.edu.		300 IN CNAME www.upenn.edu-dscg.edgesuite.net.
   

C'est un alias pour un nom Edgesuite (une marque d'Akamai). Mais les serveurs de edgesuite.net sont bogués, ils répondent NXDOMAIN pour un ENT (Empty Non-Terminal, comme edu-dscg.edgesuite.net :


% dig @ns1-2.akam.net A edu-dscg.edgesuite.net     
...
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 659
...

   

La réponse correcte aurait dû être NODATA (c'est-à-dire le code NOERROR et une section Answer de taille nulle). Tant qu'Akamai n'aura pas réparé ses serveurs, des problèmes subsisteront.

Au fait, pourquoi ne pas se servir de l'enregistrement SOA, qui est renvoyé en cas de réponse négative, pour trouver un NXDOMAIN cut situé encore plus haut, et qui sera donc plus efficace pour limiter les requêtes ultérieures ? L'annexe A du RFC explique pourquoi c'est une fausse bonne idée. Prenons l'exemple d'un nom non existant, anything.which.does.not.exist.gouv.fr :


% dig AAAA anything.which.does.not.exist.gouv.fr 
...
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 35377
...
;; AUTHORITY SECTION:
fr.			5400 IN	SOA nsmaster.nic.fr. hostmaster.nic.fr. (
				2224131472 ; serial
...

Le SOA renvoyé indique fr. Il ne faut pas en déduire que les noms plus spécifiques n'existent pas (gouv.fr existe, mais ce n'est pas une zone séparée, voilà pourquoi le SOA indiquait son parent fr).

La section 6 du RFC contient quelques conseils pour les implémenteurs. Rappelez-vous que les exigences de ce RFC concernent le comportement extérieur du résolveur, pas la façon dont il est mis en œuvre. Cette réalisation concrète va donc dépendre de comment sont représentés les domaines dans la mémoire du résolveur. La représentation la plus évidente est d'utiliser un arbre puisque c'est le modèle des noms de domaine. Mais ce n'est pas obligatoire. Un autre choix pourrait être celui d'un dictionnaire, plus rapide (pour un nom de domaine très profond, il y aura moins de lectures dans la structure de données) mais qui rend certaines opérations plus difficiles (toutes celles définies par rapport au modèle d'arbre, et elles sont nombreuses dans le DNS). Et il existe des implémentations intermédiaires, par exemple avec un arbre augmenté d'un index. Bref, le programmeur a le choix. S'il a opté pour un arbre, la façon la plus simple de respecter les exigences du RFC et, en recevant un NXDOMAIN, de supprimer tout sous-arbre qui partirait du nom ainsi nié.

Un petit mot de sécurité, maintenant qu'on approche de la fin. Si un résolveur accepte un NXDOMAIN mensonger (attaque par empoisonnement), les conséquences risquent d'être sérieuses puisque c'est un sous-arbre entier qui serait « détruit ». C'est pour cela que le RFC autorise un résolveur prudent à ne pratiquer le NXDOMAIN cut que si le NXDOMAIN a été validé avec DNSSEC. C'est ce que fait Unbound, cité plus haut.

Notez que, si on a DNSSEC, une technique encore plus puissante consiste à synthétiser des réponses NXDOMAIN en utilisant les enregistrements NSEC. Elle est décrite dans un Internet-Draft actuellement en cours de discussion.

Quels sont les résolveurs qui gèrent aujourd'hui le NXDOMAIN cut ? Outre Unbound, déjà cité, il y a PowerDNS Recursor, mais qui est, curieusement, limité au cas particulier de la racine.

Un peu d'histoire pour finir : la prise de conscience du problème que pose le manque d'agressivité des caches des résolveurs est ancienne. Voici par exemple une partie d'un rapport de Paul Mockapetris à la réunion IETF n° 4 en 1986 : mockapetris-ietf-4-dns-root.jpg

Mais le projet concret qui a mené à ce RFC est bien plus récent. Il a été lancé (cf. les supports) à la réunion IETF de Yokohama, à peine plus d'un an avant la publication du RFC (on peut voir ici l'histoire des différents brouillons). On voit que l'IETF peut agir vite.


Téléchargez le RFC 8020


L'article seul

Fiche de lecture : Quand le digital défie l'État de droit

Auteur(s) du livre : Olivier Iteanu
Éditeur : Eyrolles
978-2-212-11859-9
Publié en 2016
Première rédaction de cet article le 2 novembre 2016


On ne peut plus se plaindre que l'irruption du numérique dans toutes les activités humaines se fasse sans réflexion politique ou juridique. Voici encore un nouvel ouvrage sur la question, écrit par un juriste qui connait bien ce domaine depuis des années. Il tourne autour d'une question « est-ce que cette irruption du numérique va se faire au détriment du droit ? ».

Olivier Iteanu se penche sur quatre grandes questions politico-juridiques : la liberté d'expression, la vie privée, le droit d'auteur et la gouvernance de l'Internet. Sa thèse principale est que, oui, le numérique menace l'État de droit (au passage, il y a une différence entre « État de droit » et « état de droit » et Iteanu met bien la majuscule). En gros, les GAFA tentent d'imposer leurs lois (les fameuses CGU que personne ne lit, et qui sont souvent illégales, par exemple en obligeant d'aller traiter les litiges en Californie). Et cela se fait au détriment des lois nationales des pays vassaux.

La thèse est étayée par de nombreux exemples, les argumentaires des GAFA (« mais vous pouvez toujours changer les paramètres de vie privée, si vous ne voulez pas que vos données soient diffusées ») bien réfutés. Je ne vais pas en discuter ici, je ne cherche pas à défendre Google :-) Mais le problème est qu'Iteanu semble considérer qu'il n'y a menace pour les citoyens que lorsqu'elle vient d'un GAFA états-unien. Ainsi, la section sur la liberté d'expression oppose « liberté d'expression » et « freedom of speech » (en anglais dans le texte, pour bien montrer que c'est un concept étranger). L'idée est que le « freedom of speech » est absolu (et permet donc des discours racistes, par exemple), alors que la liberté d'expression est bornée par la loi. D'abord, cette opposition États-Unis-premier-amendement-freedom-of-speech-totale vs. France-pays-de-raison-et-de-mesure est largement fausse. Le premier amendement ne crée pas une liberté d'expression totale. Il dit juste que l'État ne doit pas la limiter. Cela laisse les entreprises privées ou des groupes de citoyens libres de limiter la liberté tant qu'ils veulent (cf. les censures de Facebook, par exemple). Mais, surtout, tout le chapitre sur la liberté d'expression fait comme si le seul problème lié à la liberté d'expression était l'abus que certains en font, pour de la propagande nazie, par exemple. Les menaces contre la liberté d'expression ne sont pas mentionnées. Et l'état d'urgence en France n'est jamais cité.

La tonalité « souverainiste » du livre est d'ailleurs assez agaçante. Les seuls reproches faits aux institutions françaises ou européennes sont de trop céder aux pressions états-uniennes. À lire ce livre, on a un peu l'impression que les États en Europe et notamment en France ne font jamais rien de dangereux ou de négatif, et que la seule question politique est de résister aux empiètements des GAFA et du gouvernement de Washington. L'auteur fait remarquer à juste titre que le passage du règne de la loi à celui de CGU dictées par une entreprise capilatiste n'est pas un progrès, mais cette dénonciation serait plus convaincante si elle était accompagnée d'une critique de la loi (qui est présentée comme l'expression indiscutable de la volonté du peuple).

Sur la vie privée (opposée à la « privacy » anglo-saxonne), Iteanu pointe à juste titre le danger de la surveillance massive que fait le gouvernement états-unien, notamment via la NSA, et le fait que le défunt Safe Harbor soit « un chiffon de papier ». Mais il ne mentionne qu'en passant, et sans critiques, les contributions françaises à la surveillance, comme la loi Renseignement.

Sur le droit d'auteur, Iteanu reprend la théorie comme quoi il y aurait une différence de philosophie entre « droit d'auteur » et « copyright » anglo-saxon, et que cette différence aurait des conséquences pratiques (ce qui n'est pas vraiment le cas). Par contre, il est cette fois bien plus critique pour le système français, pointant l'inefficacité et l'injustice du système répressif que symbolise en France la HADOPI.

Enfin, la partie sur la gouvernance de l'Internet critique logiquement l'ICANN (le livre a été écrit avant le léger changement des relations entre l'ICANN et le gouvernement états-unien le 1er octobre 2016, mais cela a peu d'importance). L'ICANN est une cible facile (et justifiée) mais il est dommage que l'ONU soit citée comme alternative crédible, sans l'once d'une critique. Iteanu cite entre autres des gens dont la crédibilité est très faible, comme Bellanger qui, dans un article fumeux, accusait Google de détournements imaginaires.

(Les techniciens pinailleurs comme moi seront surpris du tableau présentant les serveurs racine, et plus précisément de sa dernière colonne, « suffixe du nom de domaine », qui place la NASA dans un curieux .usg, ne met pas l'armée états-unienne sous .mil, et voit le RIPE-NCC en .int. De toute façon, aujourd'hui, tous les serveurs racine sont nommés sous .net.)

En résumé, l'analyse des GAFA, de leur attitude, des menaces qu'ils représentent pour la vie privée ou pour la souveraineté nationale, est très bonne et résume bien le problème. Mais l'« oubli » complet des menaces venant d'autres acteurs, comme l'État français ou comme les entreprises françaises, diminue sérieusement l'intérêt du livre. Olivier Iteanu connait bien son sujet (et évite donc de parler des pires énormités souverainistes comme le cloud souverain ou l'OS souverain) mais, hélas, il se laisse trop emporter par un point de vue national.

Tiens, ça me donne envie de parler en anglais. Full disclosure : j'ai reçu un exemplaire gratuit de ce livre.


L'article seul

RFC 7999: BLACKHOLE Community

Date de publication du RFC : Octobre 2016
Auteur(s) du RFC : T. King, C. Dietzel (DE-CIX Management), J. Snijders (NTT), G. Doering (SpaceNet AG), G. Hankins (Nokia)
Pour information
Réalisé dans le cadre du groupe de travail IETF grow
Première rédaction de cet article le 20 octobre 2016


Lorsqu'on est soumis à une sérieuse attaque par déni de service volumétrique, il faut parfois sacrifier la machine qui en est la cible, afin de préserver le reste des ressources réseau. On demande alors à son opérateur de jeter le trafic à destination de cette machine, avant qu'il n'emprunte la liaison qu'on veut préserver. Cela peut se faire manuellement mais c'est évidemment plus rapide et moins risqué si on le fait automatiquement, via une annonce BGP vers le préfixe visé. Pour cela, on marque l'annonce BGP avec une communauté (RFC 1997) qui veut dire « poubelle donc tout ce trafic ». Ce nouveau RFC normalise une communauté standard, « bien connue », pour cela, BLACKHOLE (0xFFFF029A). Ainsi, il n'y aura plus besoin d'utiliser une communauté différente pour chaque opérateur.

Cette méthode consistant à envoyer le trafic destiné à la victime vers un « trou noir » (blackholing) est décrite dans les RFC 3882 et RFC 5635. Comme elle agit au niveau IP, elle ne nécessite pas d'équipements spéciaux, et elle est très rapide, ne prenant que peu de ressources chez les routeurs. Par contre, elle est peu subtile : tout le trafic à destination d'un préfixe donné (préfixe en général réduit à une seule adresse IP, celle de la machine attaquée) est jeté, qu'il fasse partie de l'attaque ou pas. Quel est l'intérêt de couper tout le trafic ? Cela réalise l'objectif de l'attaquant, non ? C'est en effet une mesure désespérée mais rationnelle : son but est de préserver les ressources réseau pour que les autres machines fonctionnent. Si vous êtes connecté à l'Internet par une liaison à 10 Gb/s, et qu'une attaque de 20 Gb/s frappe votre opérateur, votre ligne va être complètement inutilisable. Aucune action de votre côté n'y changerait rien, dès que les paquets sont arrivés chez vous, c'est trop tard. Ce RFC traite le cas où on demande à l'opérateur de jeter le trafic avant qu'il ne soit envoyé sur la ligne entre l'opérateur et vous.

Le problème (section 1 du RFC) est qu'il existait plusieurs méthodes pour déclencher cet envoi dans un trou noir, ce qui compliquait la tâche des équipes réseau, une annonce BGP marquée avec une certaine communauté, une annonce BGP avec un certain next hop, et des méthodes non-BGP (dont le coup de téléphone au NOC). D'où la solution de notre RFC, définir une communauté standard. Plus besoin de se poser de question (à part celle de savoir si votre opérateur accepte cette commande, voir les sections 3.3 et 4). Au passage, les communautés BGP sont décrites dans le RFC 1997.

Une communauté BLACKHOLE est donc définie (section 2) et mise dans le registre IANA des communautés bien connues. Sa valeur est 0xFFFF029A. Le 666 à la fin vient de la Bible et était déjà couramment employé par les opérateurs. Notez donc que ce RFC n'invente pas une nouvelle technique (demander à son pair de jeter certains paquets est une technique très ancienne), il lui donne juste une communauté standard.

Voilà, c'est tout, juste une réservation d'un nom et d'une valeur. Si vous êtes intéressés par les détails pratiques, la section 3 est consacrée aux problèmes opérationnels. D'abord, un point essentiel : accepter des annonces BGP étiquetées BLACKHOLE est un choix local. Aucun opérateur n'est obligé de respecter cette demande et, dans ce cas, ladite communauté est ignorée. Lorsqu'on se connecte à un nouveau pair BGP, il peut donc être prudent de lire leur documentation ou de leur poser la question. N'utilisez BLACKHOLE qu'entre des adultes consentants. (Notez que cet avertissement du RFC est un peu contradictoire avec l'avantage proclamé de la normalisation de BLACKHOLE : en pratique, on est toujours obligé de savoir ce que fait son pair, on ne peut pas compter sur une méthode standard qui marcherait partout.) Une liste des opérateurs et points d'échange qui acceptent BLACKHOLE est disponible en ligne.

Si tout le monde accepte BLACKHOLE, on s'en sert comment ? Lorsqu'une attaque DoS est en cours, on annonce un préfixe qui couvre l'adresse IP visée, et on y ajoute cette communauté. On peut aussi utiliser BLACKHOLE pour les annonces du RFC 5635 (mais pas avec celles du RFC 5575).

Attention à ne pas propager ces annonces ! En effet, étant en général très spécifiques (souvent une seule adresse IP), elles seraient préférées, si elles étaient insérées dans une table de routage. Leur effet est prévu pour être strictement local et, donc, les annonces doivent être marquées avec la communauté NO_EXPORT (ou NO_ADVERTISE).

En parlant de spécificité, quelle doit être la longueur des préfixes annoncés avec un BLACKHOLE attaché ? Souvent, l'attaque ne vise qu'une seule adresse et, donc, les annonces BLACKHOLE seront souvent des /32 (en IPv4) et /128 (en IPv6), afin de ne sacrifier que le strict minimum de son réseau. Si vous avez une politique BGP de n'accepter que des préfixes plus généraux, c'est un point à modifier. Aujourd'hui (RFC 7454, section 6.1.3), les préfixes plus spécifiques que /24 (IPv4) et /48 (IPv6) sont rarement acceptés. Il faut donc faire des exceptions pour les trous noirs.

Lorsqu'un opérateur reçoit une de ces annonces « envoie-moi tout ça dans un trou noir », que doit-il vérifier ? Comme le résultat de cette annonce est de jeter tout le trafic, une attaque avec une annonce mensongère, ou bien une erreur d'un opérateur maladroit, pourrait avoir de sérieuses conséquences. Notre RFC recommande donc un certain nombre de tests de vraisemblance : vérifier que le pair est autorisé à annoncer un préfixe couvrant celui qu'il annonce avec BLACKHOLE, et vérifier que BLACKHOLE avec ce pair a été spécifiquement permis (le RFC recommande plus loin que ce ne soit pas permis par défaut). Même chose s'il y a des serveurs de route (RFC 7947) sur le trajet.

Par contre, il faut, pour le cas spécifique des annonces BLACKHOLE, débrayer les techniques de validation comme celle du RFC 6811. Par exemple, si un ROA (Route Origin Authorisation, RFC 6482) autorise une longueur maximale de préfixe de /48, l'annonce BLACKHOLE de longueur /128 doit quand même être acceptée.

À des fins de traçabilité, pour faciliter l'analyse a posteriori d'une attaque, et du traitement qu'elle a reçu, le RFC recommande de journaliser toutes les annonces BLACKHOLE. (Cela permettra, par exemple, de repérer les pairs qui abusent du mécanisme, cf. section 6.)

Si vous travaillez chez un éditeur de logiciels pour routeurs, n'oubliez pas les conseils de la section 4, destinés aux programmeurs. D'abord, l'acceptation des annonces « trou noir » ne devrait pas être faite par défaut. Le RFC demande qu'une action explicite de l'administrateur réseau soit nécessaire. D'autre part, pour ne pas avoir à taper la valeur numérique de cette communauté, le RFC suggère de permettre une valeur texte à indiquer, par exemple blackhole.

Quelques petits points sur la sécurité pour finir (section 6). D'abord, bien se rappeler que BGP n'a par défaut aucun mécanisme pour empêcher ou détecter les modifications des annonces. Si un attaquant actif retire ou ajoute la communauté BLACKHOLE, ça ne se voit pas. Même le futur BGPSec ne l'empêchera pas, puisqu'il ne protège pas les communautés. Il y a donc des possibilités d'attaques par déni de service de ce côté.

C'est entre autre pour cela que le RFC demande qu'on vérifie qu'un pair qui annonce un préfixe avec BLACKHOLE est autorisé à le faire (RFC 7454, section 6.2.1.1.2).


Téléchargez le RFC 7999


L'article seul

Le routeur Turris Omnia

Première rédaction de cet article le 19 octobre 2016


Je viens d'installer chez moi un routeur Turris Omnia. Ça fait quoi et ça sert à quoi ?

Voici ce routeur avec ses copains et copines (sonde RIPE Atlas et Raspberry Pi de supervision) : turris-on.jpg (Version non réduite) Rassurez-vous, on peut contrôler par un bouton la luminosité des diodes (très intense par défaut).

Le Turris Omnia est avant tout un routeur pour la maison ou la petite entreprise. En tant que routeur, il... route, c'est-à-dire qu'il fait passer les paquets d'un réseau à l'autre, en l'occurrence entre le réseau de la maison et celui du FAI et, via ce dernier, à tout l'Internet. C'est donc l'équivalent de la box qui, en France (mais pas ailleurs) est souvent fournie par le FAI.

La différence principale est que l'Omnia ne comprend que du logiciel libre et est ouvert, au sens où on est super-utilisateur sur cette machine et où on peut la configurer comme on veut, contrairement aux boxes fermées dont on ne sait pas exactement ce qu'elles font (elles peuvent par exemple surveiller le trafic, même local). L'Omnia n'est pas conçu par une boîte commerciale mais par le registre du .cz, une organisation sans but lucratif (qui développe des tas de choses intéressantes).

D'autre part, des tas de services qui devraient être de base en 2016 (IPv6, validation DNSSEC) sont disponibles en série sur l'Omnia.

Si vous n'êtes pas technicien, je vous préviens que l'Omnia est installable et configurable sans trop de difficultés mais que toute adaptation un peu sérieuse nécessite, pour l'instant, de bonnes compétences d'administrateur système et réseau.

Suivons maintenant l'ordre chronologique de la mise en route. Commençons par le matériel. Voici l'Omnia vue de devant, posée sur le T-shirt (optionnel...). Le port USB peut servir de console série (je n'ai pas encore essayé) : turris-outside-front.jpg (Version non réduite).

Et l'arrière de la boîte. Les antennes Wi-Fi ne sont pas encore montées (les connecteurs dorés en haut). Le port SFP est rare sur ce genre de routeurs à la maison, mais je ne l'ai pas encore utilisé (il peut permettre des connexions directes à une fibre optique, par exemple) : turris-outside-back.jpg (Version non réduite).

Et voici l'Omnia ouverte, pour les amateurs d'électronique (la documentation du matériel est en ligne) : turris-inside.jpg (Version non réduite). Curieusement, une vis avait été oubliée à l'intérieur... J'ai découvert par la suite que c'était une des vis censées tenir les cartes Wifi. Le Turris Omnia a 1 ou 2 Go de RAM (j'ai le modèle à 1 Go), un processeur ARM à 1,6 Ghz, une Flash de 8 Go, et quelques trucs que les électroniciens adoreront comme des ports GPIO.

Attention à vérifier les connecteurs des antennes radio. Dans mon cas, ils étaient mal vissés, ce qui faisait que les antennes tombaient et, ce faisant, tournaient la petite carte située derrière les connecteurs, ce qui arrachait le fil menant à la carte WiFi. Bien serrer ces connecteurs avant de commencer.

Branchons-la, maintenant. Je suis abonné chez Free et, par défaut, c'est leur boitier qui fait l'interface physique avec la ligne ADSL (de toute façon, l'Omnia n'a pas de prise adaptée, à moins de passer par le SFP ?). J'ai donc décidé de garder la Freebox, mais elle s'occupe uniquement de la télévision, du téléphone fixe, et du branchement à l'ADSL. Tout le routage, le réseau local et le Wi-Fi sont faits par l'Omnia. Je laisse donc le Freebox Player (la boîte qui sert à la télé) branchée au Freebox Server (la Freebox proprement dit), comme avant. Et je passe la Freebox en mode « bridge ». Avec cette configuration, la télévision classique continue à fonctionner (regarder la télévision, gérer ses enregistrements via http://mafreebox.freebox.fr/, etc). Le téléphone marche aussi. Pour le reste, je branche la prise WAN de la Turris Omnia en Ethernet, sur le commutateur du Freebox Server. Les autres machines sont branchées sur le commutateur de l'Omnia (ou utilisent son Wi-Fi). Il y a cinq ports Ethernet utilisables.

Une fois l'Omnia et au moins un PC branché, on configure le routeur via le Web, en se connectant à http://192.168.1.1/ (rassurez-vous, tout cela est bien expliqué dans le joli manuel papier de quatre pages livré avec l'Omnia, ou bien en ligne. Il y a deux interfaces Web de configuration du Turris Omnia, Foris, orientée débutant, et spécifique à l'Omnia, et LuCI, bien plus riche, dont je parlerai plus longuement après. Voici ce que voit le célèbre M. Michu, lorsqu'il utilise Foris : turris-foris.png Free ne fournit apparemment pas de mécanisme pour la configuration automatique d'IPv6, il a donc fallu la faire à la main, statiquement.

Contrairement au Turris précédent, cette fois, on n'est plus obligé de parler la langue de Karel Čapek avec l'Omnia. Presque tout est traduit. (Mais pas encore les divers HOWTO en ligne.) C'est un progrès appréciable pour le non-polyglotte qui, en 2014, avec l'ancien Turris, recevait des notifications du genre « Upozorneni od Vaseho routeru Turris ##### Oznameni o aktualizacich ##### • Nainstalovaná verze 82 balíku updater... ». La documentation de Foris est très détaillée, et il est recommandé de la lire (par exemple pour configurer le Wi-Fi, lorsque Foris demande à M. Michu s'il veut du 2,4 GHz ou du 5 GHz... Au passage, l'Omnia peut faire les deux, en configurant deux interfaces avec des fréquences différentes, ce qui ne semble possible qu'avec LuCI ou le fichier texte de configuration.)

Si on découvre des bogues à signaler, il faut écrire à info@turris.cz qui répond bien. Il y a aussi un canal IRC #turris à Freenode (peu d'activité). Questions forums collectifs, il y avait un système de forums (avec les menus uniquement en tchèque) qui a été abandonné au profit de Discourse, que je recommande d'utiliser (on a des réponses). Il est apparemment nécessaire, pour se loguer, d'avoir mojeID (ce que j'utilise) ou bien un compte sur un GAFA.

Ensuite, tout fonctionne, le routeur route, on peut regarder des vidéos de chats, envoyer du courrier, parler avec les copains en XMPP, télécharger de la culture, etc.

Notez que le routeur est sécurisé par défaut. Le pare-feu interne, dans sa configuration d'origine, bloque les connexions entrantes. (IPv4 et IPv6, bien sûr, une fonction qui manque terriblement à la Freebox, cf. RFC 6092.) De même, le routeur a SSH et un résolveur DNS mais n'accepte pas les connexions SSH ou DNS de l'extérieur. (Parfois, c'est même trop sécurisé.)

Une autre particularité du Turris Omnia est que le routeur se met à jour tout seul, récupérant automatiquement les nouvelles versions des logiciels, afin de corriger notamment les failles de sécurité (c'est évidemment configurable, via l'onglet Updater de Foris). C'est en effet une défaillance courante chez ces petits engins installés à la maison : le code n'est pas mis à jour et de vieilles failles durent longtemps. Tous les matins, on peut voir sur Foris ce qui a été changé : turris-foris-update.png

On peut aussi le recevoir via le système de notification par courrier. Le Turris peut envoyer des messages via les MTA de NIC.CZ ou bien via le vôtre si vous la configurez ainsi (dans Maintenance).

Le Turris permet également d'envoyer ses données de trafic dans le nuage. Ce n'est évidemment pas activé par défaut mais, si on veut aider la science, cela se fait par l'onglet Data collection de Foris (« we'd like to inform you that you agreed with our EULA regarding data collection of your router »). Une fois cet envoi activé, et un compte sur le portail créé via le Turris, on pourra se connecter sur le portail (mojeID était nécessaire mais ce n'est plus le cas) et voir des jolis graphes de son trafic : turris-stats.png

Naturellement, l'administrateur système consciencieux, même s'il se nomme Michu, va faire des sauvegardes. L'interface Foris a une option Configuration backup dans son onglet Maintenance.

Passons maintenant à l'interface Web avancée, LuCI. Elle n'est pas spécifique à l'Omnia et est au contraire bien connue des utilisateurs d'OpenWrt, système sur lequel est bâti l'Omnia. Ce n'est pas génial d'avoir deux interfaces Web pour la configuration, je trouve. Mais LuCI est indispensable pour les fonctions avancées, comme la configuration du pare-feu. Voici l'écran principal de LuCI : turris-luci-1.png

LuCI peut servir à regarder l'état de certaines fonctions, ici le pare-feu : turris-luci-2.png

Mais aussi à configurer des fonctions comme, ici, le commutateur interne avec ses VLAN (je n'ai pas encore testé mais cela semble nécessaire si on veut connecter le Freebox Player au réseau local) : turris-luci-3.png

On peut aussi installer des programmes supplémentaires depuis LuCI. Le premier que j'ai mis était Majordomo (rien à voir avec le gestionnaire de listes de diffusion du même nom). Il permet d'intéressantes statistiques par machine (là aussi, quelque chose qui me manque sur la Freebox) : turris-majordomo.png

Le vrai geek va sans doute vouloir se connecter à son beau routeur libre en SSH (chose qu'on ne peut certainement pas faire avec la Freebox...). Une fois le serveur activé (Advanced administration dans Foris mais attention avec SSH, une bogue sérieuse est décrite plus loin) :

% ssh root@turris 
Password:

BusyBox v1.23.2 (2016-09-05 13:26:40 CEST) built-in shell (ash)

  _______  _    _  _____   _____   _____   _____ 
 |__   __|| |  | ||  __ \ |  __ \ |_   _| / ____|
    | |   | |  | || |__) || |__) |  | |  | (___  
    | |   | |  | ||  _  / |  _  /   | |   \___ \ 
    | |   | |__| || | \ \ | | \ \  _| |_  ____) |
    |_|    \____/ |_|  \_\|_|  \_\|_____||_____/ 
                                                 


root@turris:~# sensors
armada_thermal-virtual-0
Adapter: Virtual device
temp1:        +86.1°C  
    

Notez que je ne connais pas de moyen de connaitre le condensat de la clé publique SSH créée, depuis l'interface Web. On ne peut donc pas vérifier, la première fois, qu'on se connecte bien à son Turris Omnia.

Le Turris Omnia utilise OpenWrt, un Unix (avec noyau Linux). La plupart des commandes seront donc familières aux unixiens :

    

root@turris:~# uptime
 11:32:39 up 1 day,  3:35,  load average: 0.02, 0.05, 0.01

root@turris:~# df -h
Filesystem                Size      Used Available Use% Mounted on
/dev/mmcblk0p1            7.3G    180.5M      7.1G   2% /
tmpfs                   503.7M      6.9M    496.9M   1% /tmp
tmpfs                   512.0K      4.0K    508.0K   1% /dev

root@turris:~# dig fr.wikipedia.org

; <<>> DiG 9.9.8-P4 <<>> fr.wikipedia.org
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 38235
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;fr.wikipedia.org.		IN	A

;; ANSWER SECTION:
fr.wikipedia.org.	3	IN	A	91.198.174.192

;; Query time: 7 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Wed Oct 19 11:36:54 UTC 2016
;; MSG SIZE  rcvd: 61

root@turris:~# uname -a
Linux turris 4.4.13-05df79f63527051ea0071350f86faf76-7 #1 SMP Mon Sep 5 13:01:10 CEST 2016 armv7l GNU/Linux

Pour mémoire, l'ancien Turris, avant l'Omnia, affichait :

root@turris:~# uname -a
Linux turris 3.10.18-b09ae823eeafb345725b393bc5efbba7 #1 SMP Tue May 6 16:24:28 CEST 2014 ppc GNU/Linux

Et n'avait que 250 Mo de stockage.

Le résolveur par défaut du Turris Omnia, l'excellent Knot Resolver (produit par la même organisation que Turris), valide avec DNSSEC (comme tout le monde devrait faire, en 2016). Dommage, il reste encore des sérieuses bogues (comme une mauvaise indication du résultat ou comme l'impossibilité de couper la validation).

Un des avantages du shell est qu'on peut faire tout ce qu'on veut. Ainsi, le système de sauvegarde par l'interface Foris dont je parlais plus haut ne sauvegarde que /etc/config. Si on veut tout garder, on peut le faire avec un script et cron.

Pour faire quoi que ce soit sur l'Omnia, il vaut mieux connaitre OpenWrt (son Wiki, ses forums...) Par exemple, si vous préférez joe à vi (et, non, je n'ai pas trouvé d'emacs sur OpenWrt, système conçu pour des engins contraints en ressources matérielles) :

root@turris:~# opkg list | grep -i editor
joe - 4.2-1 - Joe is world-famous Wordstar like text editor, that also features Emacs and Pico emulation
nano - 2.6.0-1 - Nano (Nano's ANOther editor, or Not ANOther editor) is an enhanced clone of the Pico text editor.
vim - 7.4-3 - Vim is an almost compatible version of the UNIX editor Vi. (Tiny build)
zile - 2.3.24-4 - Zile is a small Emacs clone. Zile is a customizable, self-documenting real-time display editor. Zile was written to be as similar as possible to Emacs; every Emacs user should feel at home with Zile.
...

root@turris:~# opkg install joe
Installing joe (4.2-1) to root...
Downloading https://api.turris.cz/openwrt-repo/omnia/packages//packages/joe_4.2-1_mvebu.ipk.
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  238k  100  238k    0     0   589k      0 --:--:-- --:--:-- --:--:--  602k
Configuring joe.
    

La configuration IPv6 ne s'est pas faite toute seule (ce n'est pas entièrement la faute du Turris mais un peu quand même). Par défaut, le Turris distribue sur le réseau local des ULA (RFC 4193) comme fde8:9fa9:1aba:0:X:W:Y:Z. Pour réaliser la configuration en étant connecté à Free, j'ai suivi un bon HOWTO de OpenWrt mais il y manque un point important, la route par défaut statique (à ce sujet, cela vaut aussi la peine de consulter la documentation OpenWrt sur le réseau). Donc, ce que j'ai du faire :

  • Relever l'adresse locale au lien utilisée par l'Omnia sur la patte qui le connecte à la Freebox (ifconfig eth1),
  • Sur la Freebox (http://mafreebox.freebox.fr/, « Paramètres de la Freebox » puis « Configuration IPv6 »), mettre cette adresse en Next hop pour le préfixe que nous a alloué Free,
  • Au passage, notez sur la Freebox la valeur de ce préfixe alloué,
  • Configurer le réseau de l'Omnia (/etc/config/network) comme indiqué dans le HOWTO ci-dessus,
  • Ajouter une route statique sur l'Omnia (le HOWTO OpenWrt n'en parle pas).

Cela donc un /etc/config/network qui ressemble à (si 2001:db8:cafe:1234::1:fe/64 est le préfixe IPv6 alloué par Free, celui qu'on trouve dans l'interface Web de la Freebox) :

config interface 'lan'
	option ifname 'eth0 eth2'
	option force_link '1'
	option type 'bridge'
	option proto 'static'
	option netmask '255.255.255.0'
	option ipaddr '192.168.1.1'
	option ip6addr '2001:db8:cafe:1234::1:fe/64'
	option ip6prefix '2001:db8:cafe:1234::/64'
	option ip6gw '2001:db8:cafe:1234::1'
	option ip6assign '64'
	option mtu '1452'

config interface 'wan'
	option ifname 'eth1'
	option proto 'dhcp'
        option mtu '1452'

config interface 'wan6'
	option ifname '@wan'
	option _orig_bridge 'false'
	option proto 'static'
	option ip6addr '2001:db8:cafe:1234::2/126'
	option ip6gw '2001:db8:cafe:1234::1'
	option ip6prefix '2001:db8:cafe:1234::/64'

# Route par défaut statique
config route6
	option interface 'wan6'
	option target '::/0'
	option gateway 'fe80::f6ca:e5ff:fe4d:1f41'

Si vous êtes attentifs, vous aurez remarqué qu'on force une MTU à 1 452 octets. L'IPv6 de Free en ADSL n'étant pas natif (mais un tunnel 6rd, cf. RFC 5969), ce réglage était nécessaire pour éviter les symptômes habituels d'un problème de PMTUD (ping qui marche mais pas curl, etc).

Si votre FAI ne fournit pas IPv6, le Turris Omnia permet d'établir un tunnel, en théorie, mais je n'ai jamais testé.

Autre jouet amusant, le Turris a un pot de miel configurable, pour SSH et telnet. Les sessions capturées sont également transmises aux responsables du projet et visibles via le portail des utilisateurs (mon premier « pirate » venait de Turquie et a tapé uname -a).

Passons maintenant aux problèmes, car le logiciel a des bogues embêtantes. J'ai eu beaucoup d'ennuis avec le serveur NTP. Rien ne marchait. J'ai du finalement désactiver le serveur par défaut (/etc/config/system, option enabled '0') et ntpclient, puis installer ntpd qui, lui, fonctionne. (Normalement, sur OpenWrt, cela aurait du marcher tout seul, la doc le dit). Attention, supprimer avec opkg le paquetage ntpclient ne suffit pas, la mise à jour automatique de l'Omnia le réinstalle. Maintenant, la synchronisation temporelle marche :

root@turris:~# ntpq
ntpq> peers
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
+mx4.nic.fr      138.96.64.10     2 u  585 1024  377    8.661   -1.611   1.186
 webcgi1-g20.fre .INIT.          16 u    - 1024    0    0.000    0.000   0.000
 webcgi2-g20.fre .INIT.          16 u    - 1024    0    0.000    0.000   0.000
+pob01.aplu.fr   40.179.132.91    2 u  555 1024  377   10.465   -4.789   4.553
-host3.nuagelibr 138.96.64.10     2 u  193 1024  377   10.405    3.660   2.096
 vel.itat.io     131.188.3.223    2 u   98 1024    1   25.894    0.007   0.230
*cluster004.lino 82.95.215.61     2 u  557 1024  377    7.166   -0.876   0.973

Et les machines du réseau local peuvent se synchroniser sur le Turris. (Au passage, la commande ntpq est dans le paquetage ntp-utils.)

Second problème sérieux, avec le serveur SSH. Pour un certain nombre d'utilisateurs de l'Omnia, la création des clés SSH de la machine se passe mal et des fichiers de taille zéro sont créés (et cela ne se produit pas uniquement, contrairement à ce que racontent certains, lors d'une coupure de courant). Cela empêche évidemment le serveur SSH de démarrer. On ne peut donc pas se connecter au shell pour arranger les choses. Il faut alors utiliser le port USB comme port série (je n'ai pas essayé) ou bien réparer le problème entièrement depuis LuCI (System puis Custom commands) en exécutant de quoi rétablir le système. Et l'interface de LuCI est pénible pour cela (par exemple, ssh-keygen -N "" ne marchera pas car LuCI supprime la chaîne vide...). J'ai donc du définir des commandes rm -f /etc/ssh/ssh_host_ecdsa_key /etc/ssh/ssh_host_ecdsa_key.pub /etc/ssh/ssh_host_ecdsa_key /etc/ssh/ssh_host_ecdsa_key.pub /etc/ssh/ssh_host_rsa_key /etc/ssh/ssh_host_rsa_key.pub /etc/ssh/ssh_host_dsa_key /etc/ssh/ssh_host_dsa_key.pub /etc/ssh/ssh_host_ed25519_key /etc/ssh/ssh_host_ed25519_key.pub (eh non, pas droit aux jokers) puis ssh-keygen -A puis /etc/init.d/sshd start.

Autre méthode pour s'amuser, jouer avec les VLAN. En faisant une erreur dans la configuration du commutateur de l'Omnia, j'avais déclenché une tempête de trafic interne qui rendait le routeur totalement inutilisable. Même pas moyen de se connecter en SSH pour réparer. L'erreur étant dans la configuration, redémarrer ne servait à rien (l'Omnia n'a apparemment pas de mémorisation temporaire des configurations réseau potentiellement dangereuses, comme ça existe sur JunOS). Le port série aurait peut-être été une solution mais il y avait plus simple : remettre l'Omnia à sa configuration d'usine, se reconnecter, et restaurer la configuration sauvegardée.

Voilà, prochaine étape, installer un serveur SNMP...

Quelques autres lectures sur le Turris Omnia :

PS : si vous voulez acheter un Turris Omnia (j'ai eu le mien via le crowdfunding), voyez cette annonce.


L'article seul

Google détourné par Orange vers la place Beauvau

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


Aujourd'hui, bien des clients d'Orange ont eu la mauvaise surprise de ne pas pouvoir visiter Google. La plupart n'avaient pas de messages d'erreur précis, juste une longue attente et un message d'erreur vague du genre « timeout ». Certains avaient la désagréable surprise de voir apparaitre une page menaçante, les accusant d'avoir voulu se connecter à un site Web terroriste. À l'origine de ce problème, une erreur de configuration dans les résolveurs DNS d'Orange, en raison de la fonction de censure administrative du Web.

D'abord, voyons l'étendue du problème. Il n'affectait que les clients d'Orange, et seulement ceux qui utilisaient les résolveurs DNS de l'opérateur (voir plus loin pour une définition des termes techniques). Les sites inaccessibles incluaient http://www.google.fr/, mais aussi http://fr.wikipedia.org/, http://www.ovh.com/ et quelques autres. Beaucoup d'utilisateurs ont imputé le problème à Google à tort (mot-croisillon #GoogleDown sur Twitter, ce qui était complètement erroné).

Il est rapidement apparu que le problème venait du DNS. Ce système permet d'associer à un nom de domaine (comme www.afnic.fr ou youtube.com) des données techniques, comme l'adresse IP de la machine serveuse. Cette adresse IP est indispensable au bon fonctionnement de l'Internet. Résoudre (traduire) un nom de domaine en adresse IP est le travail de deux sortes de serveurs DNS : les serveurs faisant autorité, qui connaissent le contenu d'une partie du DNS (par exemple, les serveurs faisant autorité gérés par l'AFNIC connaissent le contenu de .fr, les serveurs faisant autorité pour cfeditions.com connaissent le contenu de cfeditions.com, etc), et les résolveurs. Ces derniers ne connaissent rien mais, demandant aux serveurs faisant autorité, et mémorisant leur réponse (ce que les informaticiens appellent, bizarrement, « cacher »), ils obtiennent l'information qu'ils distribuent aux utilisateurs. Les résolveurs sont typiquement gérés par les FAI (comme Orange) mais il existe aussi des serveurs publics comme ceux de FDN. L'utilisateur de l'Internet n'a en général pas à s'en soucier, son FAI lui indique automatiquement ses résolveurs et tout roule.

Normalement, donc, un résolveur n'a pas de données propres et se contente de relayer entre l'utilisateur et le serveur faisant autorité. Mais, comme quasiment toute communication Internet commence par une requête DNS, il est tentant, lorsqu'on souhaite contrôler l'usage de l'Internet, de demander aux résolveurs de mentir, c'est-à-dire de donner une information qui n'est pas celle venue du serveur faisant autorité. C'est ce qui est prévu en France en application du décret n° 2015-125 du 5 février 2015. Le Ministère de l'Intérieur envoie aux principaux FAI une liste des domaines à bloquer (un article de Numérama détaille ce processus) et ceux-ci déploient la configuration nécessaire dans leurs résolveurs.

Mais, ce lundi matin, lorsqu'on interrogeait les résolveurs d'Orange au sujet de l'adresse IP de www.google.fr, au lieu de répondre avec l'adresse contenue dans les serveurs faisant autorité pour google.fr (serveurs gérés par Google), par exemple 216.58.211.99, ils répondaient 90.85.16.52, une adresse appartenant à un sous-traitant du Ministère de l'Intérieur. Lorsqu'un navigateur Web se connecte à cette adresse, il obtient normalement une page l'avertissant que le nom de domaine fait partie de ceux qui sont bloqués, et un motif est indiqué (promotion du terrorisme, par exemple, comme dans l'image ci-dessus).

Mais ce serveur était bien trop faible pour encaisser l'énorme trafic de Google et de Wikipédia, et a vite cessé de fonctionner correctement. C'est ce qui explique l'absence de réponse fréquemment rencontrée, faisant croire aux utilisateurs que Google était en panne. (Une autre raison est que la plupart des accès à Google se font désormais en HTTPS et que le serveur du Ministère ne gère pas HTTPS, ne répondant pas, même pas par un refus de connexion.)

Comment une telle bavure a pu se produire ? L'erreur était-elle dans la liste envoyée par le Ministère de l'Intérieur ou bien uniquement chez Orange ? On n'a évidemment pas d'information à ce sujet (les pannes Internet ne font jamais l'objet d'analyses indépendantes et publiques, ce qui explique que la sécurité ne progresse guère). Tout est possible, y compris des erreurs humaines qui sembleraient invraisemblables (mais on voit vraiment de tout dans le monde réel). Une des hypothèses les plus intéressantes (elle explique notamment pourquoi il y a eu plusieurs noms touchés) est celle d'un fichier de test installé par erreur à la place du « bon ».

Au fait, comment sait-on que les clients d'Orange (et uniquement eux) recevaient cette fausse information ? En effet, dans l'Internet d'aujourd'hui, complexe et international, une observation faite en un point n'est pas suffisante. Les clients d'Orange peuvent s'exclamer en chœur « Google est planté » et ceux de Free répondre « non, tout va bien ici ». Et les deux groupes ont raison... de leur point de vue. J'ai utilisé, outre les mesures faites par des experts chez différents FAI (merci, merci, merci), le réseau des sondes RIPE Atlas. Ces petits boitiers très utiles permettent de mesurer un certain nombre d'indicateurs techniques depuis de nombreux points du réseau. (Des détails pour les techniciens figurent à la fin de cet article.)

La panne elle-même, c'est-à-dire l'envoi de fausses informations par les résolveurs DNS d'Orange, a duré environ une heure. Mais son effet avait été prolongé par la mémorisation (les fameux « caches ») des informations dans certains composants du réseau (par exemple la « box » chez l'utilisateur). Cela fait que, plusieurs heures après, Google ou Wikipédia étaient toujours inaccessibles pour certains utilisateurs.

Les leçons à en tirer ? Le DNS est un composant critique de l'Internet et sa résilience, sa capacité à résister aux pannes et à repartir ensuite, est donc cruciale. D'où l'importance de l'Observatoire de la résilience Internet. Toute interférence avec le fonctionnement du DNS, que ce soit pour des raisons politiques ou autres, le met potentiellement en péril. C'est ce qu'avait analysé le rapport du Conseil Scientifique de l'AFNIC « Conséquences du filtrage Internet par le DNS », qui mettait bien en évidence le risque de tels filtrages ou blocages. Une bavure analogue à celle de Google était déjà arrivée au Danemark mais il semble que personne ne tire de leçons de l'expérience.

Que peuvent faire les utilisateurs face à de tels risques ? Le problème de fond est bien évidemment politique (la censure administrative, effectuée au mépris des contraintes opérationnelles) et doit donc être traité politiquement. Mais existe-t-il des solutions techniques ? Pour l'instant, la meilleure est d'avoir son propre résolveur DNS. Notez bien que je ne parle pas forcément d'un résolveur par machine à la maison. Cela peut être fait dans un équipement partagé, comme ce que permet le routeur Turris Omnia. Beaucoup de gens proposaient d'utiliser un résolveur DNS public. Ce n'est pas forcément une bonne solution. Google Public DNS a tous les inconvénients des services Google (bien expliqués dans le récent livre de Tristan Nitot). Cisco OpenDNS y ajoute le fait qu'il s'agit d'un résolveur menteur, comme ceux des principaux FAI français. Ceux d'OpenNIC marchent rarement et, de toute façon, sont une racine alternative, avec les inconvénients que cela présente. Et les résolveurs de FDN ? Ils sont honnêtes mais ils partagent un inconvénient commun avec presque tous les résolveurs DNS publics : ils n'offrent aucune authentification et rien ne garantit donc qu'on parle bien au résolveur qu'on veut. (C'est ainsi que Google Public DNS a déjà été détourné.)

Quelques lectures sur cet incident :

Le reste de cet article est uniquement pour les techniciens, attention. Le script utilisé pour interroger les sondes Atlas est décrit ici. La commande exacte était atlas-resolve --as 3215 --requested 100 www.google.fr, l'AS 3215 étant celui d'Orange.

La panne semble avoir duré d'environ 07:40 UTC à 08:35. Un utilisateur d'Orange qui testait avec dig voyait :

% dig A +short @192.168.10.1 www.google.fr
90.85.16.52

% dig A +short @8.8.8.8 www.google.fr
172.217.20.35
  

Les sondes Atlas, elles, voyaient :

% atlas-resolve --as 3215 -r 100 www.google.fr
[74.125.24.94] : 1 occurrences
[216.58.208.195] : 2 occurrences
[74.125.206.94] : 2 occurrences
[216.58.210.35] : 2 occurrences
[216.58.210.227] : 3 occurrences
[216.58.211.67] : 3 occurrences
[172.217.16.67] : 2 occurrences
[216.58.213.35] : 1 occurrences
[216.58.211.99] : 2 occurrences
[172.217.18.227] : 2 occurrences
[216.58.204.3] : 1 occurrences
[90.85.16.52] : 75 occurrences
[216.58.208.227] : 2 occurrences
Test #6886264 done at 2016-10-17T08:06:14Z
  

Remarquez que certaines sondes, minoritaires, voient la vraie valeur, sans doute parce que le réseau où elles sont situées n'utilise pas les résolveurs DNS d'Orange. Mais la grande majorité voit le 90.85.16.52 mensonger. Un autre exemple avec les sondes Atlas, mais en leur demandant d'utiliser un autre résolveur (Google Public DNS) :

 % atlas-resolve --as 3215 -r 100 -e 8.8.4.4 www.google.fr
Nameserver 8.8.4.4
[172.217.18.227] : 3 occurrences
[216.58.219.67] : 1 occurrences
[172.217.23.67] : 1 occurrences
[216.58.210.3] : 1 occurrences
[216.58.211.67] : 8 occurrences
[172.217.16.67] : 3 occurrences
[216.58.210.163] : 1 occurrences
[172.217.16.163] : 2 occurrences
[172.217.19.131] : 8 occurrences
[216.58.201.35] : 4 occurrences
[74.125.206.94] : 4 occurrences
[216.58.213.99] : 1 occurrences
[172.217.23.99] : 1 occurrences
[172.217.20.35] : 5 occurrences
[216.58.208.227] : 10 occurrences
[216.58.210.131] : 1 occurrences
[216.58.204.67] : 2 occurrences
[216.58.211.99] : 11 occurrences
[216.58.210.227] : 8 occurrences
[216.58.212.99] : 2 occurrences
[172.217.23.3] : 1 occurrences
[216.58.204.3] : 1 occurrences
[216.58.208.163] : 1 occurrences
[216.58.210.195] : 6 occurrences
[216.58.192.99] : 1 occurrences
[216.58.208.195] : 10 occurrences
Test #6886273 done at 2016-10-17T08:13:06Z
  

Cette fois, personne ne voit le mensonge (notez que les serveurs DNS de Google servent des réponses très différentes, mais qui sont toutes dans un réseau Google). Notez aussi que d'autres services Google comme Gmail ou comme le spyware Analytics n'avaient aucun problème.

Wikipédia faisait partie des victimes, comme Google :

% atlas-resolve --as 3215 -r 100 fr.wikipedia.org
[91.198.174.192] : 21 occurrences
[90.85.16.52] : 73 occurrences
[208.80.154.224] : 1 occurrences
Test #6886283 done at 2016-10-17T08:22:22Z
  

Merci à tou·te·s c·eux·elles qui m'ont envoyé des informations et des résultats de mesure. Ça, c'est l'Internet, la coopération, l'échange d'informations et la décentralisation.


L'article seul

RFC 7960: Interoperability Issues between Domain-based Message Authentication, Reporting, and Conformance (DMARC) and Indirect Email Flows

Date de publication du RFC : Septembre 2016
Auteur(s) du RFC : F. Martin (LinkedIn), E. Lear (Cisco Systems), T. Draegen (dmarcian), E. Zwicky (Yahoo), K. Andersen (LinkedIn)
Pour information
Réalisé dans le cadre du groupe de travail IETF dmarc
Première rédaction de cet article le 11 octobre 2016


Le mécanisme DMARC permet d'indiquer dans le DNS la politique d'un domaine concernant l'authentification du courrier. Si je reçois un message prétendant venir de ma-banque.example, et qu'il n'est pas authentifié (ni SPF, ni DKIM, ni autre chose), comment savoir si c'est parce que ma banque est nulle en sécurité du courrier, ou bien parce que le message est un faux ? DMARC (normalisé dans le RFC 7489) permet de répondre à cette question en publiant un enregistrement qui indique si le courrier est censé être authentifié ou pas. Comme toutes les techniques de sécurité, ce mécanisme est imparfait et il pose notamment des problèmes avec les messages indirects. Par exemple, si vous avez une adresse à votre ancienne université, alice@univ.example et que le courrier qui lui est adressé est automatiquement transmis à votre adresse professionnelle, alice@evilcorp.example, comment DMARC va-t-il réagir avec cette indirection ? C'est ce qu'explore ce RFC.

Voici la politique DMARC de Gmail. Elle est tolérante (p=none, accepter les messages non authentifiés) :

    
% dig TXT _dmarc.gmail.com
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 59294
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
...
;; ANSWER SECTION:
_dmarc.gmail.com.	600 IN TXT "v=DMARC1; p=none; rua=mailto:mailauth-reports@google.com"
...

_dmarc.paypal.com.	300 IN TXT "v=DMARC1; p=reject; rua=mailto:d@rua.agari.com; ruf=mailto:dk@bounce.paypal.com,mailto:d@ruf.agari.com"

La question de départ de l'administrateur système est « si je mets une politique DMARC restrictive (genre p=reject), vais-je perdre des courriers légitimes, à cause d'indirections comme les listes de diffusion ? » (section 1 du RFC). Il est d'autant plus difficile de répondre à cette question que l'architecture du courrier électronique est complexe et mal spécifiée (RFC 5598). Bien des logiciels ne suivent pas les règles, d'autant plus que beaucoup de ces règles n'ont pas été explicites dès le début. (Un bon exemple : avec un .forward, le serveur de courrier doit-il garder l'expéditeur indiqué dans l'enveloppe du message ? Essayez de trouver un RFC qui spécifie cela !)

La section 2 de notre RFC décrit les causes des problèmes DMARC. Si un message est légitime (le destinataire veut le recevoir), et qu'il est en outre techniquement correct, un problème, au sens de ce RFC, est quand la politique de DMARC (qui peut être de rejet) est appliquée à ce message, parce qu'il a été transmis indirectement. C'est injuste. Évidemment, si la politique DMARC est p=none (ne rien faire), ce n'est pas un vrai problème. Mais un p=reject peut être très ennuyeux.

Première cause de problèmes, des différences entre les identificateurs utilisés. DMARC n'authentifie pas directement, il dépend de SPF (RFC 7208) et DKIM (RFC 6376) pour cela. Ce qui intéresse l'utilisateur, évidemment, c'est le nom dans le champ From: (RFC 5322) du message. Pour lui, c'est ça l'expéditeur. Mais DKIM, et surtout SPF, n'ont pas la même conception : ils peuvent utiliser d'autres identificateurs. DMARC considère que l'accord (alignment, cf. RFC 7489, section 3.1) entre les identificateurs authentifiés par SPF et DKIM, et le champ From: du message peut être strict ou laxiste. « Strict » indique une correspondance parfaite, laxiste se limite à vérifier que le nom de domaine est le même.

Le principal identificateur utilisé par SPF est celui donné par la commande MAIL FROM dans la session SMTP (RFC 5321). C'est la principale cause de désaccord : si SPF authentifie cet identificateur et qu'il est différent de l'adresse utilisée dans le champ From: de l'en-tête du message, que faire ?

Deuxième cause de problème, le relayage d'un message. Si Bob bob@isp.example écrit à alice@univ.example, et qu'elle (ou son administrateur système) a demandé un relayage automatique vers alice@evilcorp.example, les serveurs de courrier de evilcorp.example verront un message prétendant être de isp.example, mais transmis par les serveurs de univ.example... SPF sera content ou pas, selon la façon exacte dont a été fait le relayage (en préservant le MAIL FROM ou pas). DMARC ne sera jamais content car, si le MAIL FROM a été changé (reflétant le relais), SPF authentifiera mais il n'y aura plus d'accord entre les identificateurs.

Évidemment, si le message est modifié en cours de route, c'est encore pire. SPF ne protège pas l'intégrité du message, mais DKIM le fait. Mais qui diantre se permet de modifier les messages ? Hélas, pas mal de gestionnaires de listes de diffusion le font. DKIM a une option (déconseillée... voir la section 8.2 du RFC 6376) pour ne signer que le début du message, évitant ainsi que la signature soit invalidée par l'ajout, par exemple, d'un paragraphe final. Cela ne couvre que le cas des messages simples, sans MIME, où la modification est un simple ajout à la fin. Autre possibilité de DKIM pour éviter d'invalider les signatures en cas de modification du message, le mode relaxed de canonicalisation du contenu, qui permet de supporter des modifications triviales comme la transformation de N espaces consécutifs en un seul.

Reprenant le vocabulaire du RFC 5598 (relisez-le d'abord !), la section 3 de notre RFC liste les différents composants de la messagerie qui peuvent jouer un rôle dans les transmissions indirectes, et les problèmes qu'elles posent. D'abord, le MSA (Message Submission Agent.) C'est la première ligne de vérification : il fait respecter les règles d'une organisation (ADMD, ADministrative Management Domain). S'il accepte un message où le champ From: du RFC 5322 n'est pas dans un domaine contrôlé par l'ADMD, il y a des chances que DMARC râle par la suite. Le RFC cite plusieurs cas d'usage où cela se produit : la fonction « envoyer cet article à un ami » de certains sites Web, par exemple, puisque le message va partir avec le domaine du lecteur de l'article, pas avec celui du site Web. On peut trouver de nombreux autres exemples, comme un service de gestion d'agenda qui envoie des courriers de rappel, en utilisant comme expéditeur l'adresse de l'utilisateur, ce qui est plutôt une bonne chose (pour des messages du genre « l'heure de la réunion a changé ») mais peut gêner DMARC. (Mon exemple préféré est le cas où on a une adresse de courrier mais pas de moyen de soumettre du courrier via cette organisation, ce qui est fréquent avec les adresses de fonction. Par exemple, on est membre d'une organisation qui fournit des adresses à ses membres et/ou responsables, ce qui permet de recevoir du courrier, mais on n'a pas de MSA pour en envoyer, on doit donc utiliser celui d'une autre organisation.)

Et les MTA, eux, quel est leur rôle dans les problèmes DKIM ? S'il change l'encodage (par exemple en passant du « 8 bits » à l'abominable Quoted-Printable), il va invalider les signatures DKIM (la canonicalisation de DKIM ne prévoit pas des transformations aussi radicales, même si elles ne modifient pas le message final). Idem si le MTA corrige les en-têtes du message pour les rendre conformes (une tâche qui relève plutôt du MSA, le MTA devant lui, transmettre fidèlement les messages qu'il a choisi d'accepter) : cela sort également du champ de la canonicalisation DKIM et cela invalide donc les éventuelles signatures. Enfin, le changement ou la suppression de certaines parties MIME (par exemple l'élision d'un document ZIP attaché, pour des raisons de protection contre les logiciels malveillants transmis par courrier) va évidemment également rendre les signatures invalides.

Et le MDA ? Peut-il casser des choses, également ? Oui, s'il passe les messages par Sieve (RFC 5228), qui a la possibilité d'ajouter ou de retirer des en-têtes, voire de modifier le corps (extension Sieve du RFC 5703). Si les tests DMARC sont faits après le passage de Sieve, ou bien si le message est ensuite réinjecté dans le système de courrier, des problèmes peuvent se produire.

Reste le cas des intermédiaires (mediators). Ce sont les entités qui prennent un message, puis le ré-expédient (parfois après modification). Un exemple est l'alias. Via une entrée dans /etc/aliases ou bien via un .forward, ou bien via le redirect de Sieve, ou encore via encore une autre méthode, un message initialement destiné à une adresse est finalement transmis à une autre. C'est par exemple courant pour les adresses « ancien élève », que fournissent certaines universités, et qui permettent de garder à vie une adresse dans le domaine de l'établissement où on a fait ses études. Un certain nombre d'associations professionnelles fournissent un service équivalent. En général, ces intermédiaires ne cassent pas DKIM (ils ne modifient pas le message) mais, selon la façon dont ils redirigent, peuvent invalider l'autorisation SPF.

Un autre exemple d'intermédiaire classique est le gestionnaire de listes de diffusion. En plus de rediriger un message (ce qui fait que le message écrit par alice@univ.example n'est pas émis par les serveurs de courrier de l'université), ces logiciels changent souvent le message, par exemple en ajoutant une inutile étiquette [Ma jolie liste] aux sujets des messages, en ajoutant un texte à la fin (instructions de désabonnement, pourtant déjà possibles avec l'en-tête List-Unsubscribe:), en retirant des pièces jointes, ou bien (surtout dans les théocraties comme les États-Unis) en remplaçant des gros mots par des termes plus acceptables.

Toutes ces modifications vont probablement invalider les signatures DKIM (cf. RFC 6377) et faire que les messages envoyés par certains participants à la liste (ceux qui ont une politique DMARC p=reject) ne seront pas reçus par les destinataires qui testent cette politique. (Si un avis de non-remise est transmis, le logiciel de gestion de la liste peut en déduire que l'adresse n'existe pas, et désabonner d'autorité le destinataire.)

Et les filtres ? Certaines organisations insèrent dans le réseau des dispositifs qui vont analyser le courrier, par exemple à la recherche de logiciel malveillant. Souvent, ils vont modifier les messages, afin de supprimer ces contenus indésirables. Ces modifications vont évidemment invalider les signatures. Idem si on change ou supprime des URL contenus dans le message et considérés « dangereux ». Même chose avec un système anti-spam qui ajouterait un [SPAM] dans le sujet.

En revanche, le courrier reçu d'un serveur secondaire (MX de secours), qui a pris le relais pendant une panne du primaire, puis expédié le courrier quand le primaire remarche, ne pose pas de problèmes. Bien sûr, les tests SPF échoueront mais, normalement, on ne fait pas ces tests sur le courrier qui vient de son propre serveur secondaire.

Bon, voici le tour d'horizon complet de tout ce qui peut marcher mal. Mais que faire ? La section 4 du RFC s'attaque aux solutions. Elles sont nombreuses et très différentes. Mais attention : DMARC est là pour rejeter des messages considérés comme invalides. On peut arranger les choses pour que certains de ces messages « passent » mais cela va contre le but de DMARC. Si les messages sont de grande valeur (transactions financières, par exemple), il vaut mieux ne pas chercher de solutions, et simplement se contenter de messages transmis directement, ne subissant pas de traitements qui vont invalider SPF ou DKIM.

C'est d'autant plus vrai que l'écosystème du courrier électronique est très complexe. On trouve un zillion de logiciels différents, plus ou moins bien écrits. Par exemple, des gens utilisent encore Qmail, qui n'a plus eu une seule mise à jour depuis 1998. Certaines des mesures ou contre-mesures utilisées pour la sécurité du courrier sont parfaitement légales, mais vont casser tel ou tel logiciel qui est utilisé à certains endroits.

Assez d'avertissements, les solutions. D'abord, du côté de l'expéditeur. Celui-ci (ou son premier MTA) peut faire des efforts pour améliorer l'accord entre les identificateurs. Un logiciel sur info.example qui envoie du courrier pour le compte de bob@univ.example peut ainsi décider d'utiliser un en-tête From: qui ne posera pas de problème, celui du vrai envoyeur, et de mettre l'adresse de Bob dans un Reply-To:. Comme la plupart des solutions présentées dans cette section 4, elle est imparfaite (le destinataire peut se demander qui est cet envoyeur qu'il ne connait pas). Le RFC fournit de nombreux autres exemples de désaccord entre identités, qui peuvent être réparés en changeant un peu le processus d'envoi du message. Comme le disait ma grand-mère, « il y a toujours une solution, pour peu que chacun y mette du sien ».

Les envoyeurs peuvent aussi limiter le risque de modifications invalidantes, en ne signant pas trop d'en-têtes avec DKIM, ou en envoyant des messages parfaitement formés (pour éviter aux serveurs ultérieurs la tentation de les « réparer »).

Les receveurs peuvent aussi agir mais leurs possibilités sont plus limitées, note le RFC.

Entre les expéditeurs et les receveurs, il y a tous les intermédiaires qui prennent un message et le ré-expédient. Ce sont souvent eux qui causent le problème, et ils sont donc souvent en position de le réparer. Par exemple, ils peuvent changer le From: du message pour mettre le leur, ce qui permettrait à peu près n'importe quelle modification, et serait plus « franc » (puisque le message n'est plus tout à fait l'original, autant changer l'auteur...) Évidemment, dans ce cas, assez violent, il faut au minimum garder l'information sur l'émetteur originel, avec l'en-tête Original-From: (RFC 5703). Le problème est que le récepteur humain sera sans doute déconcerté par cet expéditeur (d'autant plus qu'Original-From: est peu ou pas affiché).

Comme les modifications invalident les signatures, les ré-expéditeurs pourraient les éviter, par exemple en ajoutant des en-têtes au lieu de modifier les existants, lorsqu'ils veulent ajouter un contenu (du genre « ceci est un spam »). Il serait peut-être préférable, dans certains cas, de rejeter les messages plutôt que de les modifier, ce qui cassera la vérification de signatures plus loin.

Et, en parlant des ré-expéditeurs, les listes de diffusion, pas vraiment prévues par DKIM, que faire pour elles ? Le RFC 6377 a déjà traité leur cas. Une technique courante est de modifier le champ From: pour mettre l'adresse de la liste, réduisant l'auteur original à un commentaire dans cet en-tête (avis personnel : je déteste ça). Comme cela rend difficile de répondre en privé au vrai auteur d'un message, l'ajout d'un Reply-To: peut aider. Une autre solution est d'emballer le message original dans une partie MIME message/rfc822. Cette partie resterait intact et le message emballant aurait comme expéditeur la liste. Mais peu de MUA savent afficher proprement ce genre de messages (spécialement dans le monde des mobiles).

Encore plus fasciste, le gestionnaire de liste pourrait interdire l'abonnement des gens utilisant une adresse où il y a une politique DMARC autre que p=none. (Le RFC oublie de parler du cas où une politique p=reject n'existait pas au moment de l'abonnement mais a été rajoutée après.)

Enfin, il existe aussi des solutions qui sont encore en cours de discussion à l'IETF, et dont le RFC décourage l'usage dans un environnement de production. Ce sont entre autres des extensions au modèle du RFC 8601 pour créer une chaîne d'authentification où chaque acteur important signerait le message en route. Ou, plus radical, des mécanismes stockant l'état initial d'un message avant transformation, pour pouvoir retrouver cet état original et vérifier la signature.

Bref, le problème n'est pas résolu...


Téléchargez le RFC 7960


L'article seul

RFC 7950: The YANG 1.1 Data Modeling Language

Date de publication du RFC : Août 2016
Auteur(s) du RFC : M. Bjorklund (Tail-f Systems)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF netmod
Première rédaction de cet article le 10 octobre 2016


Le protocole standard Netconf (normalisé dans le RFC 6241) permet de configurer un équipement réseau (par exemple un commutateur) à distance. Netconf fonctionne par des RPC dont les paramètres sont des actions à faire effectuer par l'équipement configuré, ou bien les nouvelles valeurs que peut prendre telle ou telle des variables de configuration de cet équipement. Mais comment savoir quelles actions sont possibles, quelles variables existent, et quelles valeurs elles peuvent prendre ? Jusqu'à présent, cela pouvait se spécifier uniquement dans une documentation en langue naturelle fournie avec l'équipement. Désormais, il est possible de spécifier ces informations dans un langage formel, YANG. La première version de YANG était normalisée dans RFC 6020, ce nouveau RFC normalise la nouvelle version, la 1.1, qui a peu de changements, mais certains cassent la compatibilité ascendante.

Ce RFC 7950 est très détaillé, plus de deux cents pages. Et je n'ai pas personnellement d'expérience pratique avec YANG. Donc, je ne donne ici qu'un très bref résumé. Un tel survol se trouve également dans la section 4 du RFC : YANG modélise les données (configuration et état) qui seront utilisées par Netconf. Ces données sont représentées sous forme arborescente. YANG est modulaire (section 5.1 du RFC), un module YANG pouvant se référer à d'autres modules. YANG définit un ensemble de types pour décrire les données (section 9 et RFC 6991). Il permet également d'indiquer les contraintes que doivent respecter les données. YANG, langage de haut niveau, ne décrit pas l'encodage utilisé sur le câble.

Notez que YANG peut être utilisé avec d'autres protocoles que Netconf, comme RESTCONF (décrit dans le RFC 8040).

YANG a donc bien des points communs avec le SMI des RFC 2578 et RFC 2579. Avant Netconf, beaucoup de gens pensaient que toute la gestion des équipements réseau se ferait en SNMP, en s'appuyant sur ce modèle SMI. Si, pour la lecture des variables, SNMP s'est largement imposé, force est de constater que, pour l'écriture de variables et pour les actions, SNMP reste très peu utilisé, au profit de toute une galaxie de mécanismes privés (Web, REST, SSH + CLI, etc), galaxie que Netconf vise à remplacer. Une MIB du SMI peut donc être traduite en YANG, l'inverse n'étant pas vrai (YANG étant plus riche).

La syntaxe de YANG utilise des groupes emboîtés, délimités par des accolades. Mais une syntaxe équivalente, en XML, existe, sous le nom de Yin. Tout module YANG peut être traduit en Yin sans perte et réciproquement (voir la section 13 pour plus de détails sur Yin).

Donc, un engin donné, routeur ou autre équipement qu'on veut gérer, est décrit par des modules YANG. Lorsqu'un serveur Netconf à bord dudit engin met en œuvre un module YANG, cela veut dire qu'il permet de modifier, via Netconf, les variables décrites dans le module (le serveur typique met en œuvre plusieurs modules). Voici le début d'un module possible :

     // Only an example, not a real module. 
     module acme-system {
         namespace "http://acme.example.com/system";
         prefix "acme";

         organization "ACME Inc.";
         contact "joe@acme.example";
         description
             "The module for entities implementing the ACME system.";

         revision 2010-08-05 {
             description "Initial revision.";
         }
...

On l'a dit, YANG est arborescent. Les feuilles de l'arbre (section 4.2.2.1 du RFC) contiennent une valeur particulière, par exemple, ici, le nom de l'engin géré :

       leaf host-name {
           type string;
           description "Hostname for this system";
       }

Ici, leaf est un mot-clé de YANG qui indique une feuille de l'arbre (plus de nœuds en dessous), host-name est le nom que l'auteur du module a donné à une variable, de type « chaîne de caractères ». Lorsqu'un serveur Netconf enverra cette information à un client (ou réciproquement), elle sera encodée en XML ainsi (Netconf utilise XML pour l'encodage des messages mais d'autres encodages sont possibles, cf. RFC 7951) :


       <host-name>my-router.example.com</host-name>

Donc, pour résumer, YANG modélise ce qu'on peut lire ou modifier, Netconf permet de le lire ou de le modifier effectivement.

Par contre, si un nœud de l'arbre YANG n'est pas une feuille, il est désigné par le mot-clé container. Par exemple, il y a ici deux containers emboîtés et une feuille :

     container system {
         container login {
             leaf message {
                 type string;
                 description
                     "Message given at start of login session";
             }
         }
     }

Lorsque Netconf utilise cette donnée, cela ressemblera, sur le câble, à ceci :


     <system>
       <login>
         <message>Good morning</message>
       </login>
     </system>

YANG dispose d'un certain nombre de types pour représenter les données (section 4.2.4 et RFC 6991), mais on peut aussi créer ses types (sections 4.2.5 et 7.3) par exemple ainsi :

     typedef percent {
         type uint8 {
             range "0 .. 100";
         }
         description "Percentage";
     }

     leaf completed {
         type percent;
     }

On a ajouté un intervalle de validité au type prédéfini uint8. Autre exemple, en indiquant une valeur par défaut, et en dérivant d'un type défini dans le module inet :

     typedef listen-ipv4-address {
         type inet:ipv4-address;
         default "0.0.0.0";
     }

YANG a bien d'autres possibilités, décrites en détail dans les sections suivantes. Par exemple, dans un monde idéal, tous les engins mettant en œuvre un module YANG donné géreraient la totalité des variables du module. Mais, comme ce n'est pas forcément le cas, YANG permet des déviations (sections 5.6.3 et 7.20.3). Prenons l'exemple du RFC, un routeur BGP qui suit un module YANG BGP. Le module ne donne pas de limite au nombre de pairs BGP mais un routeur bas de gamme pourrait avoir une limite, disons à 16 pairs. Un client Netconf qui tenterait de configurer un dix-septième pair recevrait donc une erreur. Le mot-clé YANG deviation permettrait audit client de savoir à l'avance en quoi ce routeur particulier dévie du modèle BGP général. Le client Netconf n'aurait donc pas à essayer pour voir, il pourrait savoir à l'avance que l'opération de configuration du dix-septième pair ne marchera pas.

La syntaxe formelle de YANG est décrite en section 6. Elle ressemble à celle de langages de programmation comme C ou à celle de SMIng du RFC 3780 (RFC qui n'a pas eu de succès). Cette syntaxe favorise la lisibilité par des humains, le cahier des charges étant de privilégier les lecteurs, pas les auteurs de modules, ni les programmeurs d'outils YANG. À noter que, comme dans toutes les normes modernes, YANG n'est pas limité à l'ASCII et peut utiliser tout Unicode.

Bien que YANG n'utilise pas XML, il réutilise un langage de ce monde, XPath (sections 6.4 et 7.5.3). XPath sert à indiquer les dépendances entre nœuds de l'arbre.

YANG permet en effet de définir des contraintes (section 8) que doivent respecter les variables, avec la directive must. Par exemple :

         must "ifType != 'ethernet' or " +
              "(ifType = 'ethernet' and ifMTU = 1500)" {
             error-message "An ethernet MTU must be 1500";
         }

Voici un exemple de requête Netconf complète, correspondant à une variable YANG. Soit un équipement muni d'un serveur SSH et d'un serveur Netconf pour sa configuration. Disons que le serveur Netconf met en œuvre la variable YANG port, définie ainsi :

     leaf port {
         type inet:port-number;
         default 22;
         description "The port which the SSH server listens to"
     }

La requête Netconf <edit-config> (RFC 6241, section 7.2) qui configure le serveur SSH pour écouter sur le port 2022 serait :


     <rpc message-id="101"
          xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"
          xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
       <edit-config>
         <target>
           <running/>
         </target>
         <config>
           <system xmlns="http://example.com/schema/config">
             <services>
               <ssh>
                 <port>2022</port>
               </ssh>
             </services>
           </system>
         </config>
       </edit-config>
     </rpc>

Le choix de YANG comme langage standard pour la description des capacités d'un serveur Netconf ne s'était pas fait sans mal. Plusieurs concurrents avaient été envisagés notamment Relax NG, un choix logique puisque Netconf utilise XML. Un langage de description de schémas comme Relax NG semblait donc un choix raisonnable. Parmi les discussions à ce sujet, citons par exemple le débat qui avait eu lieu sur la liste du secteur Applications de l'IETF. Les raisons du choix de YANG, telles que vues par les concepteurs de YANG, sont décrites sur le site officiel du projet mais je trouve cette comparaison très unilatérale.

Un bon tutoriel Netconf, couvrant également YANG, est disponible en http://www.aims-conference.org/issnsm-2008/06-netconf-yang.pdf.

Quelles sont les mises en œuvre de YANG ? Il en existe une liste sur le site officiel. Voyons par exemple l'outil pyang, qui sert à valider des schémas YANG (y compris de la nouvelle version 1.1 décrite dans ce RFC) et à les convertir dans d'autres formats. Il ne semble pas trop maintenu mais, bon, il marche. Il peut produire du XSD et du RelaxNG - enfin du DSDL mais c'est presque pareil. Voici un exemple de test d'un schéma invalide (leaf a été tapé laf) :


% pyang test.yang
test.yang:11: error: unexpected keyword "laf"

Et, si on corrige :

% pyang test.yang
% 

Maintenant, convertissons en Yin :


% cat test.yang
 module acme-foo {
         namespace "http://acme.example.com/foo";
         prefix "acfoo";

         list interface {
             key "name";
             leaf name {
                 type string;
             }

             leaf mtu {
                 type uint32;
                 description "The MTU of the interface.";
             }
         }
     }

% pyang -fyin test.yang
<?xml version="1.0" encoding="UTF-8"?>
<module name="acme-foo"
        xmlns="urn:ietf:params:xml:ns:yang:yin:1"
        xmlns:acfoo="http://acme.example.com/foo">
  <namespace uri="http://acme.example.com/foo"/>
  <prefix value="acfoo"/>
  <list name="interface">
    <key value="name"/>
    <leaf name="name">
      <type name="string"/>
    </leaf>
    <leaf name="mtu">
      <type name="uint32"/>
      <description>
        <text>The MTU of the interface.</text>
      </description>
    </leaf>
  </list>
</module>

Et voici une conversion du même code en DSL :


% pyang -fdsdl test.yang
<?xml version='1.0' encoding='UTF-8'?>
<grammar datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"
	 ns="http://acme.example.com/foo"
	 xmlns="http://relaxng.org/ns/structure/1.0"
	 xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0"
	 xmlns:acfoo="http://acme.example.com/foo"
	 xmlns:dc="http://purl.org/dc/terms"
	 xmlns:dsrl="http://purl.oclc.org/dsdl/dsrl"
	 xmlns:nm="urn:ietf:params:xml:ns:netmod:dsdl-attrib:1"
	 xmlns:sch="http://purl.oclc.org/dsdl/schematron">
  <dc:source>YANG module 'acme-foo' (automatic translation)</dc:source>
<start>
   <zeroOrMore>
      <element name="interface" nm:key="name">
	  <element name="name">
	     <data type="string"/>
	  </element>
	  <optional>
	     <element name="mtu"><a:documentation>The MTU of the interface.</a:documentation>
		<data type="unsignedInt"/>
	     </element>
	  </optional>
       </element>
   </zeroOrMore>
</start>
</grammar>

Outre pyang, il y a bien entendu même un mode Emacs, yang-mode.

Le site officiel du projet, http://www.yang-central.org/, contient beaucoup d'autre information sur YANG.

Notez que l'ancien YANG, 1.0, décrit dans le RFC 6020, n'est pas abandonné. L'ancien RFC reste d'actualité pour décrire la version 1.0, qui restera en usage un certain temps. Les principaux changements apportés par la version 1.1 de YANG sont décrits dans la section 1.1 du RFC. La liste est très longue, mais la plupart ne sont que des points de détail. Parmi les changements qui peuvent rendre illégaux des modèles YANG qui étaient légaux avant, il y a par exemple le changement d'interprétation des échappements dans les chaînes de caractères, ou bien le fait qu'une chaîne de caractères qui n'est pas encadrée par des apostrophes ou des guillemets n'a plus le droit de contenir des apostrophes ou guillemets (section 6.1.3). De même, les clés (identificateurs uniques) ne peuvent plus être conditionnelles (instructions when ou if-feature) ce qui est logique, mais rend également invalide certains anciens modèles YANG.


Téléchargez le RFC 7950


L'article seul

Fiche de lecture : surveillance://

Auteur(s) du livre : Tristan Nitot
Éditeur : C&F éditions
978-2-915825-65-7
Publié en 2016
Première rédaction de cet article le 9 octobre 2016


Si vous avez lu tous les articles d'Amaelle Guiton, de bluetouff et d'Andréa Fradin, si vous allez à tous les Quadr'Apéro de la Quadrature du Net (en lisant un livre de Schneier dans le métro) ou, bien sûr, si vous travaillez pour Facebook ou pour la DGSI, ce livre ne vous apprendra rien. Vous savez déjà que l'internaute ordinaire (pas le suspect de djihadisme ou de grand banditisme, non, le fameux M. Michu) est surveillé en permanence par les outils et services numériques qu'il utilise. Mais, contrairement au djihadiste ou au bandit, M. Michu ne le sait pas, ou bien il ne mesure pas exactement l'ampleur de la surveillance généralisée, ou alors il est complètement résigné, convaincu de ne rien pouvoir y faire. Le livre de Tristan Nitot vise à informer cet internaute innocent (dans tous les sens du terme) de la surveillance dont il fait l'objet, mais aussi à proposer des pistes pour améliorer les choses et faire reculer un peu la surveillance. (La préface d'Adrienne Charmet insiste sur l'importance de marcher sur ces deux jambes, l'exposition des problèmes, et celle des solutions.)

Ce livre est très court, ce qui reflète soit la paresse de l'auteur, soit son désir d'être utile à un maximum de gens qui pourraient être découragés en voyant un énorme pavé universitaire (qui, au passage, manque, sur ce sujet). L'auteur présente d'abord la variété des techniques de surveillance existantes. Contrairement à ce que prétendent les menteurs qui affirment qu'avec le chiffrement des smartphones, les policiers ne pourraient plus travailler, notre vie privée a énormément perdu avec l'arrivée de ce phono sapiens. Doté de capteurs perfectionnés, il enregistre tout et transmet tout à ses maîtres (qui ne sont pas son propriétaire...). Ensuite, les GAFA comme Google récoltent une quantité faramineuse de données, que leurs techniques perfectionnées permettent d'analyser. L'auteur donne plusieurs exemples concrets et précis (avec à chaque fois l'URL permettant d'aller se renseigner davantage, souci de sérieux rare). Toute cette partie est très pédagogique. Si vous êtes le geek instruit et politisé cité au début, c'est l'ouvrage à recommander à vos proches (et aux lointains aussi) moins informés, pour qu'ils comprennent ce qui arrive aujourd'hui à tout citoyen. Et ne leur racontez pas tout, laissez-leur le plaisir de découvrir l'erreur gravissime du cochon, citée à chaque conférence de l'auteur :-)

Tristan Nitot tord aussi le cou à quelques mythes comme le « je n'ai rien à cacher ». On a tous des choses (tout à fait légales) à cacher. Personnellement, je demande aux gens qui affirment n'avoir rien à cacher « votre dernier relevé bancaire, et la liste de vos dix derniers partenaires sexuels, avec les pratiques utilisées ».

Un point important de son livre est la question du modèle économique des acteurs de l'Internet. Si Google et Facebook nous surveillent autant, ce n'est pas parce qu'ils sont des filiales de la NSA, ni parce qu'ils sont vendus au diable ou aux reptiliens. C'est parce qu'ils sont gratuits, et qu'il faut bien se financer d'une manière ou d'une autre. Exploiter les données personnelles est une méthode rentable, et largement invisible pour l'utilisateur. Elle nécessite la récolte du plus grand nombre de données personnelles possible, et il n'est donc pas exagéré de noter que « le modèle d'affaires du Web, c'est la surveillance ».

Le désir de l'auteur (et de la préfacière) de ne pas uniquement décrire l'affreuse surveillance dont nous sommes l'objet, mais également de faire preuve d'un certain optimisme en indiquant des choix qui amélioreraient les choses, va parfois un peu loin. Si je peux comprendre l'analyse mesurée que Nitot fait d'Apple (société dont il ne cache pas les défauts mais qui, en matière de surveillance, semble en effet « moins pire » que les autres), j'ai plus de mal avec l'éloge qu'il fait de la société Sen.se dont le fondateur répète partout que la vie privée n'est pas son problème car « Facebook fait pire ». C'est ainsi que le produit Mother de cette société envoie tout dans « un ordinateur de quelqu'un d'autre » et que c'est présenté comme inévitable.

L'auteur continue en expliquant qu'un autre Internet est possible. Car dénoncer la surveillance, c'est très bien, mais cela peut mener à la sidération : convaincu d'être surveillé de partout, et de ne pas pouvoir l'empêcher, sauf à vivre dans une grotte sans électricité, le citoyen pourrait se décourager et renoncer à son droit à la vie privée. Il est donc nécessaire de proposer des pistes d'amélioration. Plusieurs sont avancées : le logiciel libre, bien sûr, condition nécessaire (mais pas du tout suffisante), le paiement des services (« si c'est gratuit, c'est que vous n'êtes pas le client, vous êtes la marchandise »), l'auto-hébergement (sans cacher, comme pour les autres solutions, les extrêmes difficultés que cela pose), le chiffrement (encore une condition nécessaire mais pas suffisante)... Nitot demande aussi que les partisans d'un autre Internet s'attaquent aussi au problème difficile de faire aussi bien, voire mieux, que les GAFA en matière de vécu utilisateur.

L'auteur détaille aussi, avec beaucoup de précision, quelques mesures d'hygiène numérique qui peuvent permettre de limiter un peu les dégâts de la surveillance. Par exemple, bloquer le spyware Google Analytics, ou bien avoir son propre nom de domaine permet de ne pas dépendre d'un seul fournisseur, et d'être donc libre de le quitter si ses pratiques ne sont pas acceptables.

Notons que ces manipulations sont parfois longues, ce qui reflète le désir des maîtres de la surveillance de nous empêcher de diminuer celle-ci. Il faut ainsi neuf étapes pour configurer Twitter de manière plus respectueuse de la vie privée.

Pour une genèse du livre, par son auteur, et pour une liste exhaustive des articles qui en parlent, voir sur le Standblog.

Déclaration de conflit d'intérêts : j'ai reçu un exemplaire gratuit de ce livre, mais il n'était pas accompagné d'une bouteille de vin, donc j'écris cet article à jeun et en toute objectivité.


L'article seul

RFC 7954: Locator/ID Separation Protocol (LISP) Endpoint Identifier (EID) Block

Date de publication du RFC : Septembre 2016
Auteur(s) du RFC : L. Iannone (Telecom ParisTech), D. Lewis (Cisco), D. Meyer (Brocade), V. Fuller
Intérêt historique uniquement
Réalisé dans le cadre du groupe de travail IETF lisp
Première rédaction de cet article le 23 septembre 2016


Le protocole expérimental LISP a besoin d'identificateurs pour les machines qui participent à l'expérimentation. Comme les identificateurs LISP sont pris dans le même espace de nommage que les adresses IP, il était préférable d'avoir un préfixe IP spécifique. C'est désormais chose faite, avec ce RFC, qui demande et obtient le préfixe 2001:5::/32. Si vous voyez quelque chose qui ressemble à une adresse IP et qui emploie ce préfixe, c'est qu'il s'agit d'un identificateur LISP.

En effet, LISP (RFC 6830) repose sur le principe de la séparation de l'identificateur et du localisateur. Les identificateurs sont stables et servent à... identifier une machine, les localisateurs sont liés aux connexions qu'on a au réseau et servent au routage. Les deux ont la forme physique d'une adresse IP, et on ne peut donc pas les distinguer par leur syntaxe. Les identificateurs sont formellement nommés EID (Endpoint IDentifier) et c'est pour eux que 2001:5::/32 a été réservé (section 1 du RFC).

La section 3 explique les raisons de cette réservation :

  • Identifier facilement le fait qu'une destination est accessible via LISP, et qu'on peut donc chercher son localisateur dans les tables de correspondance (RFC 6833). Actuellement, on ne peut pas savoir à l'avance, il faut demander au système de correspondance, peut-être pour rien.
  • Ainsi, si un routeur gère à la fois des destinations LISP et non-LISP (par exemple pour faire de l'ingénierie de trafic), cela lui permettra de ne pas pénaliser le trafic non-LISP, qui pourra être transmis immédiatement.
  • Si on souhaite traiter différemment le trafic LISP et le trafic non-LISP, cela dispensera d'utiliser du DPI pour le reconnaitre.
  • L'avantage précédent s'applique aussi au cas où on veut filtrer/bloquer l'un des deux trafics.
  • Cela facilitera la numérotation des réseaux qui sont mixtes : le ou les préfixes alloués pour l'IP traditionnel ne seront pas affectés, le réseau qui voudra faire du LISP prendra ses identificateurs dans 2001:5::/32 au lieu de devoir découper une partie de son espace d'adressage.
  • Conséquence : moins de fragmentation de l'espace d'adressage, et moins de routes dans la DFZ.

D'où cette réservation d'un préfixe dédié, en suivant les règles du RFC 3692.

Les réseaux qui utiliseront ce préfixe ne doivent évidemment pas annoncer de routes dans la DFZ (section 4 du RFC), ce préfixe ne servant qu'à des identificateurs et pas aux localisateurs. Pour la communication entre un réseau LISP numéroté avec le nouveau préfixe, et un réseau IP traditionnel, il faut utiliser les techniques d'interconnexion des RFC 6832 et RFC 7215. Le préfixe complet pourra être annoncé (comme un tout, ou comme des sous-préfixes très généraux, pour ne pas surcharger la table de routage) par des routeurs d'interconnexion (section 8 du RFC). Pour les routeurs non-LISP, ce sera un préfixe comme un autre, et il n'y a aucune raison de lui appliquer un traitement particulier.

Notre RFC exige également que ce nouveau préfixe 2001:5::/32 ne soit utilisé que par configuration explicite et ne soit donc pas mis en dur dans le logiciel des routeurs, d'abord parce que LISP pourra en utiliser d'autres dans le futur, ensuite parce que des réseaux feront quand même du LISP avec leurs propres adresses.

Pourquoi un préfixe de 32 bits ? Pourquoi pas plus spécifique ou moins spécifique (cela a été une grosse discussion dans le groupe de travail) ? La section 5 donne les raisons de ce choix :

  • Cela fait assez de préfixes pour le réseau de test LISP actuel (qui a environ 250 sous-préfixes /48), et pour ce qu'on peut envisager dans les prochaines années.
  • C'est cohérent avec des expériences comme celle du RFC 3056.

Le préfixe 2001:5::/32 est alloué pour trois ans, ce qui est suffisant pour l'expérimentation (sections 6 et 7). À la fin de celle-ci, le préfixe sera rendu ou bien transformé en allocation permanente (qu'il faudra justifier et documenter, cf. RFC 2860, section 4.3). L'allocation, faite en octobre 2015, est notée dans le registre IANA.

L'allocation des préfixes à l'intérieur de 2001:5::/32 est décrite dans le RFC 7955.


Téléchargez le RFC 7954


L'article seul

RFC 7955: Management Guidelines for the Locator/ID Separation Protocol (LISP) Endpoint Identifier (EID) Block

Date de publication du RFC : Septembre 2016
Auteur(s) du RFC : L. Iannone (Telecom ParisTech), R. Jorgensen (Bredbandsfylket Troms), D. Conrad (Virtualized, LLC), G. Huston (APNIC)
Intérêt historique uniquement
Réalisé dans le cadre du groupe de travail IETF lisp
Première rédaction de cet article le 23 septembre 2016


Le RFC 7954 réservait un préfixe IP, 2001:5::/32, pour les identificateurs du protocole expérimental LISP. Ce RFC 7955 décrit les mécanismes d'allocation à l'intérieur de ce préfixe. Ils sont simples et légers : un peu de documentation et on a son sous-préfixe.

Le RIPE-NCC assure la gestion de ce préfixe. La politique d'enregistrement est simple (sections 4 et 9 de notre RFC) :

  • Ce préfixe est expérimental et les allocations sont donc temporaires. N'espérez pas garder éternellement votre joli préfixe sous 2001:5::/32. Si l'expérience se termine et que le 2001:5::/32 cesse d'être utilisé, tous ses sous-préfixes disparaitront aussi.
  • Les allocations doivent être renouvelées tous les ans, afin de s'assurer que le titulaire est toujours actif dans le banc de test LISP. (C'est bien un renouvellement, pas une nouvelle allocation, on conserve le même préfixe.)
  • Les préfixes abandonnés ne sont pas réutilisés, autant que possible, ou alors en attendant au moins une semaine.
  • Une organisation peut avoir plusieurs sous-préfixes.
  • Premier arrivé, premier servi.

Quelles sont les règles que suivra le registre de 2001:5::/32 (section 5) ?

  • Suivre les règles habituelles des registres d'adresses IP : collecter et archiver l'information envoyée par le titulaire, et la rendre accessible (par exemple via whois).
  • Gérer les noms de domaine dans ip6.arpa correspondants au préfixe géré.
  • Allouer un sous-préfixe à quiconque le demande, sous seule condition qu'il fournisse les informations demandées dans la section suivante.

La section 6, en effet, contient les informations demandées aux titulaires (ce sont à peu près les mêmes que pour obtenir un numéro d'organisation privé). On y trouve les grands classiques, nom de l'organisation qui demande, adresse, informations de contact, taille du préfixe demandé, raisons de la demande...

Comme indiqué plus haut, c'est le RIPE-NCC qui gérera le préfixe. Normalement, tout est déjà en place mais pas encore annoncé (cela sera mis en ligne après la publication du RFC).


Téléchargez le RFC 7955


L'article seul

Fiche de lecture : Notre galaxie numérique: tous mutants

Auteur(s) du livre : Cyril Hlakkache
Éditeur : Kawa
978-2-36778-097-9
Publié en 2016
Première rédaction de cet article le 21 septembre 2016


Je suis perplexe devant ce livre. D'un côté, j'apprécie (comme Jean-Michel Planche, qui fait la postface) qu'on prenne de la hauteur par rapport aux transformations induites par le numérique, et qu'on essaie d'en parler à un large public. De l'autre, je me méfie des livres qui tentent de traiter tout en 250 pages, sautant d'un sujet à l'autre, et abusant de termes grandiloquents (mutation, digital, agilité...).

Mais le résultat n'est pas mauvais : l'auteur connaît ses sujets et, s'il se livre à quelques approximations et raccourcis, je n'ai pas trouvé de grosse erreur ridicule pour faire rire les lecteurs de mon blog. Pour donner une idée du style du livre, l'auteur parle de NTP en disant « C'est [NTP] qui permet au réseau des réseaux de battre la mesure pour que le tout fonctionne dans un même espace-temps ».

Cyril Hlakkache couvre à peu près tout ce qui a un rapport avec le numérique : Internet, la sécurité, le logiciel libre, les mégadonnées, la sous-traitance (pardon, cloud, c'est plus joli), la vie privée, la réalité virtuelle (avec Second Life ressorti des poubelles de l'histoire), l'IA, Bitcoin et le transhumanisme... Régulièrement, il dérape en se lançant dans des discours quasi-commerciaux et a-critiques, puis il corrige en reprenant un point de vue humaniste, soucieux des droits et des libertés des humains.

Globalement, c'est donc un livre que vous pouvez suggérer aux gens qui ne sont pas eux-mêmes complètement immergés dans cet univers numérique, et qui cherchent à s'informer et comprendre.

Déclaration de conflit d'intérêt : j'ai reçu un exemplaire de ce livre gratuitement.

Pour le suivi, il existe un blog du livre.


L'article seul

RFC 7962: Alternative Network Deployments: Taxonomy, Characterization, Technologies, and Architectures

Date de publication du RFC : Août 2016
Auteur(s) du RFC : J. Saldana (University of Zaragoza), A. Arcia-Moret (University of Cambridge), B. Braem (iMinds), E. Pietrosemoli (The Abdus Salam ICTP), A. Sathiaseelan (University of Cambridge), M. Zennaro (The Abdus Salam ICTP)
Pour information
Réalisé dans le cadre du groupe de recherche IRTF gaia
Première rédaction de cet article le 17 septembre 2016


On pourrait croire que la seule façon d'accéder à l'Internet est via un FAI commercial, géré hiérarchiquement (avec directeur, plein de sous-directeurs, etc), dont les utilisateurs paient pour bénéficier de l'accès (mais sans avoir leur mot à dire sur le fonctionnement du FAI), et disposant de grands moyens financiers et techniques. C'est certainement la vision dominante et elle arrange bien les gens des médias et des gouvernements, qui se retrouvent dans une situation connue, avec un petit nombre d'acteurs « professionnels ». Heureusement, l'Internet n'est pas comme cela : c'est une confédération de réseaux très variés, certains effectivement gérés comme indiqué plus haut, mais d'autres fonctionnant sur des modèles très différents, ayant fait des choix techniques, de gouvernance et de financement très différents et très variés. Cet excellent RFC décrit et classe les réseaux « alternatifs ».

Il a été écrit dans le cadre du groupe de recherche GAIA (Global Access to the Internet for All) de l'IRTF. GAIA vise à documenter ces déploiements « alternatifs » et à faciliter le partage d'expérience. Outre le simple rappel de l'existence de ces réseaux « alternatifs », son mérite est de proposer une taxonomie de ces réseaux (forcément imparfaite, vu leur variété) et de donner une idée de la variété des technologies qu'ils utilisent.

Ces techniques sont en effet souvent différentes de celles utilisées dans les réseaux « officiels » (mainstream). Ces réseaux « alternatifs » visent en général des situations difficiles, comme la connexion de lieux lointains, où l'argent ne coule pas à flots. À part cela, ces réseaux n'ont rien en commun, ni leur organisation, ni leurs buts. Qu'est-ce qui motive leur création ? (Au passage, le RFC fait comme si ces réseaux « alternatifs » étaient une création récente ; certains sont au contraire aussi vieux que l'Internet.) Les raisons de ces projets sont elles aussi très diverses : absence pure et simple de FAI commercial, insatisfaction vis-à-vis des FAI officiels existants, désir d'essayer quelque chose d'autre...

Passons au difficile jeu des définitions. Le RFC (section 1.1) définit le réseau « officiel » (mainstream) ainsi :

  • De grande taille, par exemple à l'échelle d'un pays,
  • Gestion du réseau centralisée : tout part d'en haut,
  • Gros investissements dans l'infrastructure,
  • Les utilisateurs sont de purs consommateurs : ils n'ont absolument pas leur mot à dire, et, la plupart du temps, ils ne reçoivent aucune information, ils ne savent pas ce qui se passe dans le réseau qu'ils utilisent.

Et les réseaux « alternatifs », comment se définissent-ils (section 1.2) ? C'est plus difficile car il en existe de nombreuses variantes :

  • En général de petite taille, par exemple à l'échelle d'une région,
  • La gestion du réseau n'est pas forcément centralisée,
  • Les frais d'infrastructure peuvent être très répartis (les utilisateurs en paient parfois un bout, des infrastructures publiques peuvent être utilisées, etc),
  • Les utilisateurs ne sont pas forcément de purs consommateurs, ils peuvent être partie prenante à la gouvernance du réseau, et/ou à son fonctionnement technique.

Ce problème des définitions est évidemment très présent dans tout le RFC. Par exemple, comment parler des pays qui ne sont pas les membres de l'OCDE (et encore, l'OCDE compte deux ou trois membres « intermédiaires ») ? Le Tiers-Monde ? Le Sud ? Les pays pauvres ? Les sous-développés ? Les « en voie de développement » ? La section 2 du RFC propose des définitions :

  • Nord et Sud (« global north » et « global south ») sont utilisés pour parler, d'une part des pays riches (même si certains, comme l'Australie, sont au Sud) et des autres. Ce ne sont pas des termes parfaits mais aucun ne l'est.
  • Fracture numérique : la différence d'accès à l'Internet entre les favorisés et les autres. Elle n'est pas seulement entre pays, elle peut aussi être à l'intérieur d'un pays.
  • Zones « rurales » et « urbaines » : les définitions officielles vont varier selon les pays mais, en gros, il est plus difficile de convaincre les opérateurs à but lucratif de venir dans les zones à faible densité de population (zones « rurales »).
  • « Réseau libre » (Free Network) : c'est un terme délicat, car politiquement chargé, mais notre RFC reprend la définition de la Free Network Foundation. Dans un réseau libre, on peut utiliser le réseau librement (la liberté s'arrêtant évidemment là où commence la liberté des autres, donc pas le droit de faire des DoS par exemple), comprendre comment il marche (pas de secrets) et on peut soi-même fournir des services au-dessus de ce réseau.

Maintenant, les cas où on déploie ces réseaux « alternatifs » (section 3 du RFC). Il y aurait actuellement 60 % de gens sur Terre sans connectivité Internet. Et la répartition est très inégale (20 % sans connexion au « Nord », 69 % au « Sud »). Parmi les facteurs qui vont intervenir :

  • La disponibilité de connexions internationales (ce n'est pas tout de se connecter entre soi, il faut aussi se relier au reste du monde), et de matériel,
  • Les problèmes d'alimentation électrique,
  • Le contexte légal. Ici, le RFC reprend telle quelle l'idéologie répandue à l'ISOC comme quoi la régulation, c'est mal, et qu'il faut tout privatiser.

Dans les zones rurales, on a vu que c'était souvent pire. Johnson, D., Pejovic, V., Belding, E., et G. van Stam, dans leur article « Traffic Characterization and Internet Usage in Rural Africa » (In Proceedings of the 20th International Conference Companion on World Wide Web) rapportent des latences mesurées à plusieurs secondes. Les problèmes des zones rurales sont souvent cruciaux : faible revenu monétaire, manque d'infrastructures de base comme l'électricité et les routes, densité de population réduite, manque de compétences (les techniciens compétents quittent rapidement ces zones pour aller en ville), etc.

La section 4 de notre RFC s'attaque ensuite au difficile problème de la classification de ces réseaux « alternatifs ». Sur quels critères faire cette classification ? Les auteurs du RFC en trouvent cinq. D'abord, quelle organisation gère le réseau ? Un groupe plus ou moins formel d'utilisateurs ? Une collectivité publique ? Une société privée ? Un organisme de recherche ou d'enseignement ? (En France, on aurait ajouté « Une association loi 1901 ? »)

Second critère de classification, le but de la création de ce réseau : fournir un accès qui n'existerait pas du tout autrement ? Fournir une alternative bon marché ? Expérimenter et tester ? S'attaquer à d'autres problèmes de fracture numérique (comme la littératie numérique) ? Fournir un accès d'urgence suite à une catastrophe ? Ou bien un but plus politique, par exemple des mécanismes de gouvernance différents, une approche davantage « bien commun » ? Ou fournir un accès libre et neutre, contrairement à ce que font la quasi-totalité des FAI ? (Ce dernier point est présenté de manière très modérée dans le RFC qui, globalement, évite de parler des choses qui fâchent, comme la politique.)

Bien sûr, un réseau alternatif peut avoir plusieurs de ces mobiles. Et ceux-ci peuvent être plus ou moins explicites, et ils évoluent dans le temps. Le réseau Redhook avait commencé plutôt comme outil local, avant de devenir le seul réseau à fonctionner après Sandy.

Un autre critère, proche du premier, est celui du modèle de gouvernance : très ouvert, avec une participation active des utilisateurs, ou bien plus traditionnelle, avec une organisation centrale qui s'occupe de tout ? (On peut avoir un réseau qui est la propriété d'un groupe d'utilisateurs mais qui, en pratique, est géré par une petite organisation structurée.)

Autre critère, qui va plaire aux techniciens, quelles sont les techniques employées dans ce réseau ? Wi-Fi traditionnel ? Wi-Fi modifié pour les longues distances (WiLD) ? WiMAX ? Espaces blancs de la télévision (cf. RFC 7545) ? Satellite comme dans le projet RIFE ? Voire des fibres optiques terrestres ?

Enfin, dernier critère de classification, le contexte : zone rurale ou urbaine, Nord ou Sud.

Avec ces critères, on peut maintenant procéder à la classification (section 5 du RFC). Notre RFC distingue (un peu arbitrairement) six catégories, caractérisées par les réponses à ces cinq critères. Première catégorie, les réseaux d'un groupe local (community networks). Géré par un groupe de citoyens proches, ils ont typiquement un fonctionnement très ouvert et participatif. Leur croissance est en général non planifiée et non organisée : les premiers membres se connectent puis d'autres volontaires les rejoignent. Le mécanisme de décision est la plupart du temps très décentralisé. En général, ils utilisent le Wi-Fi et chaque membre contribue donc à la croissance du réseau « physique » sous-jacent. Plusieurs exemples de tels réseaux sont décrits dans l'article de Braem, B., Baig Vinas, R., Kaplan, A., Neumann, A., Vilata i Balaguer, I., Tatum, B., Matson, M., Blondia, C., Barz, C., Rogge, H., Freitag, F., Navarro, L., Bonicioli, J., Papathanasiou, S., et P. Escrich, « A case for research with and on community networks », et une analyse technique détaillée d'un réseau d'un groupe local figure dans Vega, D., Baig, R., Cerda-Alabern, L., Medina, E., Meseguer, R., et L. Navarro, « A technological overview of the guifi.net community network ».

Seconde catégorie, les WISP (Wireless Internet Service Providers). Cette fois, le réseau est géré par une société traditionnelle, mais il est « alternatif » par le public visé (typiquement des régions rurales mal desservies, où l'infrastructure est minimale, et où les FAI traditionnels ne vont pas). C'est par exemple le cas de la société Airjaldi en Inde, ou d'EveryLayer.

Troisième catégorie de réseaux alternatifs, l'infrastructure partagée (Shared Infrastructure model). L'infrastructure du réseau est partagée entre un opérateur traditionnel et les utilisateurs. C'est le cas lorsque les utilisateurs détiennent le matériel (par exemple femtocell) mais que la gestion est assurée par un FAI. Les utilisateurs sont payés, soit directement par le FAI qui leur loue l'infrastructure, soit indirectement par l'accès à l'Internet qu'ils obtiennent via ce FAI. Dans pas mal de régions rurales dans le monde, la 3G a été déployée ainsi, via les femtocells. Prévue à l'origine pour fournir une meilleure couverture dans les bâtiments, cette technologie peut aussi être utilisée pour fournir des accès aux téléphones mobiles sans que l'opérateur ait eu à supporter de gros investissements.

Un exemple d'infrastructure partagée est le projet TUCAN3G, en utilisant WiLD Ce projet est décrit par Simo-Reigadas, J., Morgado, E., Municio, E., Prieto-Egido, I., et A. Martinez-Fernandez dans « Assessing IEEE 802.11 and IEEE 802.16 as backhaul technologies for rural 3G femtocells in rural areas of developing countries » et par Simo-Reigadas, J., Municio, E., Morgado, E., Castro, E., Martinez-Fernandez, A., Solorzano, L., et I. Prieto- Egido dans « Sharing low-cost wireless infrastructures with telecommunications operators to bring 3G services to rural communities ».

Autre catégorie possible, les approches « foule de volontaires » (Crowdshared approaches) où des utilisateurs qui ne se connaissent pas forcément mettent la main au portefeuille pour participer à un projet commun, qui sera géré par une une société ou par eux-mêmes. Typiquement, les utilisateurs mettent à la disposition de tous une partie de leur capacité réseau, et l'entité qui gère le réseau est une simple coordination, elle ne possède rien. C'est ce que promeut le mouvement OpenWireless. Parmi les exemples, on peut citer des sociétés comme FON, les projets municipaux comme décrit dans l'article de Heer, T., Hummen, R., Viol, N., Wirtz, H., Gotz, S., et K. Wehrle, « Collaborative municipal Wi-Fi networks- challenges and opportunities », ou les réseaux Wi-Fi de Sathiaseelan, A., Crowcroft, J., Goulden, M., Greiffenhagen, C., Mortier, R., Fairhurst, G., et D. McAuley, « Public Access WiFi Service (PAWS) ».

Il y a aussi des réseaux montés par des coopératives en milieu rural, ce qui forme la cinquième catégorie identifiée. Ce genre de coopératives fournissant un service local est courant et ancien. Le RFC cite l'exemple des États-Unis où l'électricité en milieu rural est souvent fournie ainsi, et ce depuis les années 1930. Ces coopératives peuvent même passer leurs propres fibres optiques (« CO-MO'S D.I.Y. model for building broadband »). Des partenariats sont possibles avec ceux qui fournissent d'autres services que l'Internet, comme l'électricité dans l'exemple ci-dessus. Deux exemples sont donnés dans l'article de Mitchell « Broadband at the Speed of Light: How Three Communities Built Next-Generation Networks » ou dans le guide « Broadband Guide for Electric Utilities ».

Enfin, dernière catégorie de réseau alternatif, ceux créés à des fins de recherche. Par exemple, le réseau est créé par une université pour explorer une technique et/ou des usages (comme Bernardi, B., Buneman, P., et M. Marina, « Tegola tiered mesh network testbed in rural Scotland »).

Après cette catégorisation des réseaux alternatifs, penchons-nous sur les technologies utilisées (section 6 du RFC). Le cas de réseaux filaires est rare mais existe (comme à Lowenstedt ou dans certains endroits de Guifi.net). La plupart du temps, les réseaux alternatifs utilisent l'hertzien. Les normes techniques en œuvre sont en général celles du groupe IEEE 802.

La plus connue est évidemment Wi-Fi (802.11). Mais on trouve aussi du GSM (une norme ETSI) par exemple dans un village mexicain ou dans le projet Village Base Station. Il y a même du GSM en logiciel libre, dans les projets OpenBTS ou OpenBSC. Ces projets sont en train de migrer vers des technologies plus rapides (mais, ce que le RFC oublie de dire, bien moins libres, notamment car pourries de brevets) comme la 4G.

On a signalé plus haut que certains réseaux peuvent utiliser les espaces blancs laissés par la télévision, découvrant les fréquences utilisables via une base de données (RFC 7545) ou bien en regardant le trafic existant pour voir si l'espace est vraiment blanc.

Le Wi-Fi est limité en portée, et certains réseaux utilisent des techniques plus adaptées aux longues distances comme WiMAX (IEEE 802.16) ou bien 802.22, qui utilise justement ces espaces blancs.

Et dans les couches au-dessus de ces couches 1 et 2, quelles techniques utilisent les réseaux alternatifs ? La section 7 du RFC décrit rapidement les divers choix. D'abord, la couche 3. La plupart des réseaux n'utilisent qu'IPv4 et, ne pouvant pas obtenir suffisamment d'adresses IP des RIR sans gros efforts, se limitent aux adresses IP privées du RFC 1918. (Avant l'épuisement des adresses IPv4, obtenir des adresses des RIR était plus simple que beaucoup de gens ne le croyaient, mais il fallait quand même se taper une bureaucratie complexe et des règles difficiles.)

Pour la plupart des réseaux alternatifs, IPv6 était déjà normalisé depuis longtemps lorsqu'ils ont démarré leur projet. Mais peu l'utilisent (ninux.org est une exception), probablement essentiellement par ignorance. (Le questionnaire « Questionnaire based Examination of Community Networks » incluait des questions sur IPv6).

Pour le routage, les choix dépendent souvent de la structure du réseau alternatif. Certains sont de type mesh, avec peu ou pas d'autorité centrale, d'autres sont plus structurés. Il y a donc des protocoles de routage traditionnels comme OSPF (le RFC cite aussi BGP, ce qui me surprend pour un réseau alternatif).

Mais il y a aussi des protocoles prévus pour des réseaux moins structurés, comme ceux utilisés dans les MANET. On peut trouver de l'OLSR (RFC 3626), parfois dans des versions modifiées (ce qui est le cas de http://olsr.org/), ou parfois sa récente version 2 (RFC 7181). D'autres réseaux utilisent du BATMAN. Le RFC cite l'excellent Babel (RFC 8966) mais n'indique pas s'il est très employé sur le terrain (il semble moins connu, dans un milieu où l'information circule mal).

Et la couche au-dessus, la couche transport ? L'un des problèmes que doit traiter cette couche est celui de la congestion : il faut assurer le partage de la capacité réseau entre plusieurs acteurs. Dans les réseaux alternatifs, pas forcément gérés centralement, et aux frontières pas toujours nettement délimitées, le défi est encore plus important. Il peut donc être intéressant d'enourager des protocoles « raisonnables » (RFC 6297), qui cèdent le pas systématiquement aux autres protocoles, afin que les activités non-critiques ne rentrent pas en compétition avec le trafic « important ».

Enfin, les utilisateurs ne s'intéressent typiquement qu'à une seule chose, les services, et il est donc utile de se demander ce que ces réseaux alternatifs proposent. Il y a bien sûr tous les services de base, notamment le Web. Certains services très répandus (vidéo haute définition, par exemple), peuvent être très coûteux pour les ressources souvent limités du réseau alternatif. Leur utilisation peut donc être restreinte. Et il y a aussi des services spécifiques des réseaux alternatifs : des VPN comme IC-VPN, des portails d'intérêt local comme Tidepools, des télévisions ou radios locales, des systèmes de relais de VoIP pour permettre des appels bon marché, des réseaux de capteurs permettant de la citizen science, etc.

Voilà, c'est terminé, cet article était long mais le RFC est plus long encore, et il se termine par une impressionnante bibliographie dont je n'ai cité que quelques extraits : plein de choses passionnantes à lire.


Téléchargez le RFC 7962


L'article seul

RFC 7937: Content Distribution Network Interconnection (CDNI) Logging Interface

Date de publication du RFC : Août 2016
Auteur(s) du RFC : F. Le Faucheur, G. Bertrand, I. Oprescu, R. Peterkofsky (Google)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF cdni
Première rédaction de cet article le 16 septembre 2016


Ce RFC fait partie de la série qui normalise les interactions entre un CDN amont (celui choisi par le client) et un CDN aval (celui auquel, pour une raison ou pour une autre, une partie du trafic est délégué). Il traite la question de la journalisation : comment est-ce que le CDN aval remonte au CDN amont le journal d'activité ?

Cette idée d'interconnexion standard des CDN est expliquée dans le RFC 6707, le cadre général est dans le RFC 7336, dont la section 4.4 identifie le besoin d'un mécanisme de journalisation, et le cahier des charges est dans le RFC 7337, la journalisation étant couverte dans sa section 8.

Notre nouveau RFC décrit d'abord (section 2) le modèle de la journalisation. Certains des aspects de celle-ci (comme la possibilité pour le CDN amont de configurer ce que le CDN aval va journaliser ou pas) sont considérés comme hors-sujet. Dans le modèle, la seule activité normalisée est la remontée des journaux depuis le CDN aval. Cela permettra au CDN amont de faire de jolies statistiques, de payer son CDN aval selon son activité, etc.

Après, on descend dans le concret : la section 3 décrit le format des journaux. Il est très inspiré du format ELF. Un fichier journal est composé d'enregistrements, chacun composé de champs. Voici un exemple d'une requête HTTP (où <HTAB> désigne une tabulation horizontale) :


2013-05-17<HTAB>00:39:09.145<HTAB>15.32<HTAB>FR/PACA/NCE/06100<HTAB>GET<HTAB>http://cdni-ucdn.dcdn-1.example.com/video/movie118.mp4<HTAB>HTTP/1.1<HTAB>200<HTAB>15799210<HTAB>"Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.127 Safari/533.4"<HTAB>"host1.example.com"<HTAB>1

    

Mais attention en lisant cet exemple, le format effectif peut être modifié par des directives placées au début du fichier. (La liste des directives figure dans un registre IANA.)

Le fichier journal peut être transmis par divers protocoles (sections 4 et 5 du RFC) mais celui décrit dans ce RFC est fondé sur Atom (RFC 4287). Le CDN aval publie un flux Atom où le CDN amont trouvera les noms des fichiers à télécharger, a priori en HTTP (et même plutôt HTTPS puisque ces journaux sont confidentiels, cf. section 7.3).


Téléchargez le RFC 7937


L'article seul

RFC 7947: Internet Exchange BGP Route Server

Date de publication du RFC : Septembre 2016
Auteur(s) du RFC : E. Jasinska (BigWave IT), N. Hilliard (INEX), R. Raszuk (Bloomberg LP), N. Bakker (Akamai)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF idr
Première rédaction de cet article le 9 septembre 2016


Ce nouveau RFC spécifie le comportement des serveurs de routes des points d'échange Internet. Un serveur de route collecte avec BGP les routes envoyées par ses pairs et les redistribue. Cela nécessite quelques ajustements du protocole BGP, expliqués ici. Un autre RFC, le RFC 7948, décrit le côté opérationnel.

Un point d'échange Internet connecte un certain nombre d'acteurs (opérateurs, hébergeurs, FAI, etc) à un réseau commun, en général au niveau de la couche 2, et avec Ethernet. Chacun de ces acteurs gère son ou ses routeurs, connecté au·x commutateur·s commun·s. Pour savoir à quel pair envoyer des paquets IP, ces routeurs ont besoin de s'informer mutuellement des préfixes IP qu'ils gèrent. Cela se fait avec le protocole BGP (RFC 4271).

Si le point d'échange rassemble N acteurs, connecter tout le monde nécessiterait N*(N-1)/2 sessions BGP. À chaque fois qu'un participant arriverait, il faudrait qu'il négocie N-1 accords de peering. Et, en fonctionnement quotidien, il devrait superviser N-1 sessions BGP. L'idée de base du serveur de routes est d'introduire un intermédiaire (le serveur de routes, route server), qui reçoit les routes de chacun et les redistribue à tous. Ainsi, il n'y a qu'une seule session BGP à établir, avec le serveur de routes. Il est en général géré par l'opérateur du point d'échange. (Sur la plupart des points d'échange, l'usage de ce serveur de routes n'est pas obligatoire, et il y a donc également des sessions BGP directes entre les participants, pour des raisons variées.)

Le serveur de routes parle BGP avec ses pairs (les routeurs des participants au point d'échange) mais lui-même n'est pas un routeur : il ne transmet pas les paquets IP. Il travaille sur le plan de contrôle, pas sur celui des données.

Un serveur de routes est donc très proche d'un réflecteur (RFC 4456). La différence est que le réflecteur de routes travaille à l'intérieur d'un AS (protocole iBGP), alors que le serveur de routes travaille entre AS différents (protocole eBGP).

Un serveur de routes ressemble aussi à un collecteur de routes, comme ceux du RIS. La différence est que le collecteur ne redistribue pas d'information à ses pairs BGP, il collecte des données, pour analyse, affichage, etc.

La section 2 du RFC forme le cœur de ce document. Elle rassemble les modifications du protocole BGP qui sont nécessaires pour le bon fonctionnement du serveur de routes. D'abord, le serveur ne doit pas modifier sans bonne raison les annonces qu'il reçoit : son but est de distribuer de l'information, pas de la bricoler. Le RFC demande ainsi que les attributs BGP bien connus (comme AS_PATH) ne soient pas modifiés, sauf très bonne raison. Ainsi, l'attribut NEXT_HOP qui indique l'adresse IP du routeur à qui faire suivre les paquets, ne doit pas être changé (ce que demandait la section 5.1.3 du RFC 4271) : le serveur de routes n'est pas un routeur, c'est à l'annonceur original qu'il faut transmettre les paquets. Idem pour AS_PATH cité plus haut : le serveur de routes ne doit pas mettre son propre numéro d'AS dans le chemin. De même, MULTI_EXIT_DISC (qui sert à choisir entre plusieurs routeurs d'un même AS voisin) doit être propagé aux clients du serveur de routes (normalement, il n'est pas propagé aux autres AS). Et, enfin, les communautés BGP (RFC 1997) indiquées dans une annonce ne doivent pas être changées, sauf évidemment si elles sont destinées au serveur de routes lui-même. On trouve des exemples de communautés destinées au serveur de routes dans la documentation du serveur de routes d'AMS-IX ou bien dans celle de celui de Netnod, alors que celle de France-IX se trouve dans un objet RIPE. Il y a aussi des serveurs de routes (comme ceux du France-IX qui étiquettent les annonces apprises avec une communauté indiquant où la route a été apprise (dans quel POP.)

Par défaut, toutes les routes de tous les clients sont distribuées à tous les autres clients. C'est le but d'un serveur de routes. Mais on peut souhaiter parfois une certaine restriction à cette redistribution. Cela peut être mis en œuvre par le serveur de routes (puisque le routeur original de l'annonce parle au serveur de routes, pas au client final). Idéalement, le serveur de routes devrait donc maintenir une base de routes, et un processus de décision BGP, pour chacun de ses clients. Cela permet de coller au mode de fonctionnement normal de BGP. Et cela ne nécessite aucun changement chez les clients. Mais c'est plus coûteux en ressources pour le serveur de routes. (Pour BIRD, voir l'option secondary, qui réduit l’usage mémoire et CPU de manière importante, expliquée dans cet exposé.)

Les autres solutions à ce problème d'un filtrage par client nécessitent des extensions à BGP, comme le Diverse path du RFC 6774 ou comme la future option ADD-PATH.

L'annexe de ce RFC consacrée aux remerciements résume un peu d'histoire des serveurs de routes. La première description de ce système date de 1995, dans le RFC 1863 (depuis reclassé comme « d'intérêt historique seulement », cf. RFC 4223).

Plusieurs mises en œuvre de serveurs de route existent évidemment, conformes à ce RFC. C'est par exemple le cas chez Cisco, BIRD et Quagga (voir le rapport technique sur ces programmes).

Merci à Arnaud Fenioux pour sa relecture et ses ajouts et corrections.


Téléchargez le RFC 7947


L'article seul

RFC 7948: Internet Exchange BGP Route Server Operations

Date de publication du RFC : Septembre 2016
Auteur(s) du RFC : N. Hilliard (INEX), E. Jasinska (Netflix), R. Raszuk (Mirantis), N. Bakker (Akamai Technologies)
Pour information
Réalisé dans le cadre du groupe de travail IETF grow
Première rédaction de cet article le 9 septembre 2016


Les points d'échange Internet sont un des maillons essentiels du bon fonctionnement de l'Internet, permettant des connexions faciles et relativement bon marché entre opérateurs. Une fois physiquement connecté au point d'échange, l'opérateur Internet doit encore établir une connexion BGP (RFC 4271) avec ses pairs. Si ceux-ci sont nombreux, établir N connexions bilatérales représente un coût administratif important. Il est souvent préférable d'établir une seule connexion multilatérale, par l'intermédiaire d'un serveur de routes (route server). Celui-ci récolte les annonces BGP de tous ses pairs et les redistribue. Ainsi, il suffit à l'opérateur d'une seule connexion, avec le serveur de routes. Ce nouveau RFC documente les questions opérationnelles liées aux serveurs de routes.

Le principe et le fonctionnement d'un serveur de routes sont expliqués dans le RFC 7947, produit par un autre groupe de travail IETF. Ce RFC 7948 se consacre aux détails opérationnels. Un serveur de routes est l'équivalent, pour le BGP externe (eBGP) de ce qu'est un « réflecteur de routes » (route reflector, RFC 4456) pour le BGP interne (iBGP). Le serveur de routes, lorsqu'il existe, est un composant crucial du point d'échange. Par exemple, s'il tombe en panne, les sessions BGP sont coupées, les annonces retirées et, même si les commutateurs et le réseau du point d'échange continuent à fonctionner, plus aucun trafic ne passe (à part si des sessions BGP bilatérales existent également). D'où l'importance d'une bonne gestion de ce composant.

Les sections 2 et 3 de notre RFC rappelent la différence entre sessions BGP bilatérales et multilatérales à un point d'échange. Si on ne fait que des sessions bilatérales (pas de serveur de routes), avec seulement quatre routeurs BGP sur le point d'échange, il faudra six sessions BGP pour une connectivité complète. Avec dix routeurs, il en faudrait quarante-cinq ! Établir, superviser et maintenir toutes ces sessions représente du travail. Les sessions multilatérales, via un serveur de routes, sont une bien meilleure solution. Avec dix routeurs au point d'échange, il n'y a plus besoin que de dix sessions BGP, chacun des dix routeurs ne faisant que BGP qu'avec le serveur de routes.

Le serveur de routes doit juste veiller à ne pas toucher à l'attribut BGP NEXT_HOP (RFC 4271, section 5.1.3), qui ne doit pas indiquer le serveur de routes, mais le routeur qui a annoncé la route (le serveur de routes n'est pas un routeur, et ne fait pas de transmission du trafic IP). Pour le point d'échange typique, il n'y a pas besoin de faire de la résolution récursive (utiliser un protocole de routage pour trouver comment joindre le routeur suivant) du NEXT_HOP : tous les routeurs sont sur le même réseau L2 et sont donc joignables directement. Par exemple, si je regarde le looking glass du France-IX et que lui demande les routes vers 194.0.9.0/24, il me montre :

194.0.9.0/24       via 37.49.236.20 on eth1 [RS1_PAR 2016-08-11 from 37.49.236.250] * (100) [AS2484i]
                   via 37.49.236.21 on eth1 [RS1_PAR 2016-08-11 from 37.49.236.250] (100) [AS2486i]
...

(L'AFNIC est connectée sur deux points de présence de ce point d'échange, d'où les deux routeurs.) Les NEXT_HOP sont les adresses des routeurs dans le point d'échange, 37.49.236.0/23.

La section 4, le gros morceau de notre RFC, décrit ensuite divers points que le serveur de routes doit garder en tête, pour faire un bon travail.

D'abord, le cas où on n'envoie pas exactement les mêmes informations à tous les clients. Sauf si le client BGP coopère, cela implique que le serveur garde une base des routes par groupe de clients, un groupe étant composé de tous les clients pour qui on applique la même politique de filtrage. Attention, cela consomme pas mal de mémoire (autant de base que de groupes) et de processeur (il faut faire tourner les algorithmes de sélection BGP pour tous les groupes) mais heureusement, en pratique, on utilise rarement ces politiques différentes. Traiter tous les clients de la même façon permet de garder une consommation de ressources raisonnable.

Qu'en est-il du risque de fuite de préfixes ? Si un routeur connecté au serveur de routes fuit et envoie, par exemple, la totalité de la DFZ au serveur de routes, celui-ci va-t-il transmettre tous ces préfixes à ses infortunés clients ? Cela serait très ennuyeux car tout le trafic partirait alors vers le routeur fautif, qui ne serait peut-être pas capable de le gérer. Il est donc très recommandé que le serveur de routes prenne des précautions contre les fuites. Au minimum, imposer un nombre maximal de préfixes à chaque client, et, idéalement, filtrer les préfixes autorisés pour chaque client. C'est moins grossier que la simple limite quantitative, mais c'est aussi plus dur à maintenir (on ne peut pas espérer que tous les clients tiennent à jour leurs préfixes dans les IRR...). Il est certainement préférable que les administrateurs des clients et du serveur de routes regardent le journal de leur routeur pour repérer les différences entre ce qui est théoriquement annoncé et ce qu'il l'est réellement.

Question fiabilité, notre RFC recommande que le serveur de routes soit redondant : s'il n'est composé que d'une seule machine, et qu'elle plante, le point d'échange ne servira plus. Il faut donc au moins deux machines, et prendre soin qu'elles soient configurées de manière à annoncer les mêmes routes. (C'est trivial si les machines sont identiques, il suffit qu'elles aient la même configuration, cela l'est moins si, pour augmenter la redondance, on choisit des machines ayant des logiciels différents.)

Autre précaution à prendre, côté client, ne pas vérifier que le chemin d'AS est cohérent. Par exemple, le serveur de routes ne va pas mettre son propre AS tout à gauche du chemin d'AS (RFC 7947, section 2.2.2) et le client ne doit donc pas vérifier que son pair, le serveur de routes, a un chemin d'AS incluant l'AS du pair BGP.

Comment contrôler l'exportation des routes vers certains clients ? La section 4.6 liste plusieurs méthodes :

  • Demander aux clients d'étiqueter les routes avec une communauté ordinaire (RFC 1997) ou bien une communauté étendue (RFC 4360). Attention, la taille limitée des valeurs des communautés ne permet pas d'y mettre deux numéros d'AS si ceux-ci sont sur quatre octets (RFC 4893). Comme exemple, regardez la politique des communautés BGP au France-IX.
  • Utiliser les politiques de distribution exprimées en RPSL (RFC 2622) dans les IRR.
  • Utiliser un IRR local au point d'échange, avec son interface spécifique pour y enregistrer des politiques. Cette posibilité est mentionnée par le RFC, mais quelqu'un connait un point d'échange qui fonctionne comme cela ? (Peut-être VIX et AMS-IX, à vérifier.)

On a vu que la grande majorité des points d'échange travaillaient au niveau 2. Normalement, toute machine connectée au réseau du point d'échange peut donc joindre n'importe quelle autre. Mais, en pratique, on a déjà vu des bogues dans un commutateur qui menaient à des communications non transitives. Par exemple, les routeurs A et B peuvent tous les deux joindre le serveur de routes mais ne peuvent pas se joindre mutuellement. Dans ce cas, A reçoit bien les routes de B (et réciproquement) mais, lorsqu'il essaie de transmettre des paquets à B, ceux-ci finissent dans un trou noir. Ce problème est spécifique aux serveurs de route : lorsqu'on a une connexion bilatérale, les paquets de contrôle (ceux envoyés en BGP) suivent en général le même chemin que ceux de données (les paquets IP transmis) et partagent donc le même sort, bon ou mauvais.

La solution à ce problème passe peut-être par des solutions comme BFD (RFC 5881), pour tester la connectivité entre les deux routeurs. Mais BFD nécessite une configuration bilatérale entre les deux routeurs et il n'existe actuellement aucun protocole pour faire cette configuration automatiquement. On retombe donc dans les problèmes de configuration manuelle d'un grand nombre de connexions bilatérales. Même si un protocole de configuration automatique existait, il resterait le problème d'informer le serveur de routes. En effet, un échec BFD indiquerait à A qu'il ne peut pas joindre B, et lui ferait marquer les routes vers B comme invalides mais le serveur de routes, n'étant pas au courant, continuerait à n'envoyer à A que la route invalide (un pair BGP ne transmet que la meilleure route vers une destination donnée).

Dernier piège, le détournement de NEXT_HOP. On a vu que le fonctionnement normal d'un serveur de routes est de ne pas se mettre comme « routeur suivant » mais au contraire de relayer aveuglément les NEXT_HOP indiqués en BGP par ses clients. Un client malveillant pourrait annoncer des routes au serveur de routes en indiquant comme « routeur suivant » le routeur d'un concurrent, pour lui faire acheminer son trafic, par exemple ou, pire, pour faire une attaque par déni de service en annonçant des préfixes très populaires avec le concurrent comme routeur suivant. Contrairement au problème précédent, celui-ci n'est pas spécifique aux serveurs de route, il existe aussi avec des sessions BGP bilatérales. Mais il peut faire davantage de dégâts lorsqu'on utilise un serveur de routes, tous les clients croyant l'annonce mensongère. Pour empêcher cela, il faudrait que les serveurs de route vérifient que l'attribut BGP NEXT_HOP corresponde à l'adresse IP du client. (Les clients ne peuvent pas faire ce test, ils doivent croire le serveur de routes, qui annonce des NEXT_HOP qui ne sont pas son adresse IP.)

Et pour finir, une sortie complète du looking glass du route server du France-IX concernant un serveur racine du DNS, M.root-servers.net (et, au passage, attention en anglais à ne pas confondre route server et root server) :

RS1 show route for 202.12.27.33/32 all - View the BGP map

202.12.27.0/24     via 37.49.237.106 on eth1 [RS1 2015-08-21 from 37.49.236.250] * (100) [AS7500i]
	Type: BGP unicast univ
	BGP.origin: IGP
	BGP.as_path: 7500
	BGP.next_hop: 37.49.237.106
	BGP.med: 500
	BGP.local_pref: 100
	BGP.atomic_aggr: 
	BGP.aggregator: 192.50.45.1 AS7500
	BGP.community: (51706,51706) (51706,64601) (51706,64650)

Les pages de présentation de quelques serveurs de route :

Merci à Arnaud Fenioux pour sa relecture et ses ajouts et corrections.


Téléchargez le RFC 7948


L'article seul

RFC 7958: DNSSEC Trust Anchor Publication for the Root Zone

Date de publication du RFC : Août 2016
Auteur(s) du RFC : J. Abley (Dyn), J. Schlyter (Kirei), G. Bailey (Microsoft)
Pour information
Première rédaction de cet article le 1 septembre 2016


Le mécanisme d'authentification des informations DNS nommé DNSSEC repose sur la même structure arborescente que le DNS : une zone publie un lien sécurisé vers les clés de ses sous-zones. Un résolveur DNS validant n'a donc besoin, dans la plupart des cas, que d'une seule clé publique, celle de la racine. Elle lui servira à vérifier les clés des TLD, qui serviront à valider les clés des domaines de deuxième niveau et ainsi de suite. Reste donc à configurer la clé de la racine dans le résolveur : c'est évidemment crucial, puisque toute la sécurité du système en dépend. Si un résolveur est configuré avec une clé fausse pour la racine, toute la validation DNSSEC est menacée. Comment est-ce que l'ICANN, qui gère la clé principale de la racine, publie cette clé cruciale ? Six ans après la signature de la racine du DNS, c'est enfin documenté, dans ce RFC.

Cela donne une idée de la vitesse des processus ICANN, organisation qui produit beaucoup de papier. Notez que ce nouveau RFC documente l'existant, déjà mis en œuvre, et ne prétend pas décrire la meilleure méthode. Notez aussi que ce format et cette méthode de distribution pourraient changer à l'avenir.

Si vous voulez réviser DNSSEC d'abord, outre les RFC de base sur ce système (RFC 4033, RFC 4034, RFC 4035...), notez surtout le RFC 6781, qui décrit les questions opérationnelles liées au bon fonctionnement de DNSSEC.

Les clés publiques configurées dans les résolveurs qui valident avec DNSSEC, sont appelées « points de départ de la confiance » trust anchors. Un point de départ de la confiance est une clé dont l'authenticité est admise, et non pas dérivée d'une autre clé, via une chaîne de signatures. Il en faut au moins un, celui de la racine, bien que certains résolveurs en ajoutent parfois deux ou trois pour des zones qu'ils veulent vérifier indépendamment. Lorsque le résolveur recevra une réponse de la racine, signée, il l'authentifiera avec la clé publique de la racine (le point de départ de la confiance). S'il veut vérifier une réponse d'un TLD, il l'authentifiera avec la clé publique du TLD, elle-même signée (et donc authentifiée) par la clé de la racine. Et ainsi de suite même pour les zones les plus profondes.

(Notez qu'il existe deux clés pour la plupart des zones, la KSK - Key Signing Key, et la ZSK - Zone Signing Key, mais on ne s'intéresse ici qu'aux KSK, c'est elles qui sont signées par la zone parente, et configurées comme points de départ de la confiance.)

La gestion de la clé de la racine par l'ICANN est décrite dans leur DNSSEC Practice Statement.

Le RFC rappelle aussi qu'il y a d'autres possibilités d'installation d'un point de départ de la confiance. Par exemple, si un tel point a été configuré une fois, ses remplacements éventuels peuvent être faits via le RFC 5011.

La section 2 du RFC décrit le format des clés publiées par l'IANA. Les trois formats, en fait :

Voici un exemple du fichier XML (à ne pas prendre comme s'il faisait autorité, évidemment) :


<TrustAnchor id="AD42165F-3B1A-4778-8F42-D34A1D41FD93" source="http://data.iana.org/root-anchors/root-anchors.xml">
 <Zone>.</Zone>
 <KeyDigest id="Kjqmt7v" validFrom="2010-07-15T00:00:00+00:00">
  <KeyTag>19036</KeyTag>
  <Algorithm>8</Algorithm>
  <DigestType>2</DigestType>
  <Digest>
  49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5
  </Digest>
 </KeyDigest>
</TrustAnchor>

    

L'élément <KeyTag> indique l'identifiant de la clé, actuellement 19036, comme on peut le voir avec dig :

      
% dig +multi +nodnssec DNSKEY .
...
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
...
;; ANSWER SECTION:
.			147724 IN DNSKEY 257 3 8 (
				AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQ
				bSEW0O8gcCjFFVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh
                                ...
				) ; KSK; alg = RSASHA256; key id = 19036
...

    

L'attribut id de l'élément <KeyDigest> sert à identifier un condensat particulier, et est utilisé pour nommer les autres fichiers. Par exemple, le certificat PKIX va se trouver dans le fichier Kjqmt7v.crt.

Pour produire un enregistrement DS à partir de ce fichier XML, il suffit de mettre <KeyTag>, <Algorithm>, <DigestType> et <Digest> bout à bout. Par exemple, avec le fichier XML ci-dessus, cela donnerait :

    
.  IN   DS   19036  8   2  49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5

(Des résolveurs comme Unbound acceptent ce format, pour le point de confiance de départ.)

Quant aux certificats, ils sont encodés en DER et signés par l'ICANN et leur champ SubjectPublicKeyInfo est la clé publique DNSSEC. Voici ce qu'en voit OpenSSL :

% openssl x509 -text -inform DER -in Kjqmt7v.crt 
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 7 (0x7)
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: O=ICANN, CN=ICANN DNSSEC CA/emailAddress=dnssec@icann.org
        Validity
            Not Before: Jun 11 18:43:20 2014 GMT
            Not After : Jun 10 18:43:20 2017 GMT
        Subject: O=ICANN, OU=IANA, CN=Root Zone KSK 2010-06-16T21:19:24+00:00/1.3.6.1.4.1.1000.53=. IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
	    ...
            X509v3 extensions:
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Authority Key Identifier: 
                keyid:8F:B2:42:69:C3:9D:E4:3C:FA:13:B9:FF:F2:C0:A4:EF:D8:0F:E8:22
            X509v3 Subject Key Identifier: 
                41:1A:92:FA:1B:56:76:1E:62:2B:71:CD:1A:FD:BB:43:99:5F:09:C9
    Signature Algorithm: sha256WithRSAEncryption
    ...
    

Comment récupérer le fichier XML de manière à être sûr de son authenticité ? C'est ce que spécifie la section 3 du RFC : on utilise HTTPS. L'URL est https://data.iana.org/root-anchors/root-anchors.xml.

Une autre solution (section 4) est de le récupérer en HTTP et de le vérifier avec une des signatures fournies : l'une est en CMS (RFC 5652) - son URL est https://data.iana.org/root-anchors/root-anchors.p7s, l'autre est en PGP (RFC 4880) - son URL est https://data.iana.org/root-anchors/root-anchors.asc. Cette signature PGP devrait être abandonnée à l'avenir.

Pour les amateurs d'histoire, l'annexe A rappelle que la clé actuelle, la 19036, a été générée au cours d'une cérémonie à Culpeper, le 16 juin 2010. Elle a été publiée dans le DNS pour la première fois le 15 juillet 2010.

Sinon, l'ISOC a écrit un bon article sur ce RFC, moins technique.


Téléchargez le RFC 7958


L'article seul

RFC 7979: Response to the IANA Stewardship Transition Coordination Group (ICG) Request for Proposals on the IANA Protocol Parameters Registries

Date de publication du RFC : Août 2016
Auteur(s) du RFC : E. Lear, R. Housley
Pour information
Réalisé dans le cadre du groupe de travail IETF ianaplan
Première rédaction de cet article le 30 août 2016


Un certain nombre de fonctions administrativo-politico-techniques dans l'Internet sont assurées par un service nommé l'IANA (Internet Assigned Numbers Authority). Cela va du spectaculaire (l'instruction des demandes d'ajout ou de suppression des TLD) jusqu'au routinier (la gestion des innombrables registres techniques que l'IANA maintient pour le compte de l'IETF). L'IANA est un service de l'ICANN et l'ICANN est sous tutelle du gouvernement états-unien pour effectuer ce travail, dit « fonction IANA ». Le gouvernement états-unien a annoncé en 2014 qu'il envisageait peut-être dans le futur de diminuer la dépendance de l'ICANN et a demandé, en attendant, aux parties intéressées, de soumettre des propositions. L'ICANN, toujours ravie qu'on propose des discussions et des réunions, a créé le ICG (IANA stewardship transition Coordination Group) qui a à son tour sollicité des commentaires. Ce nouveau RFC est la réponse de l'IETF à cet appel, ne concernant que la gestion des registres techniques. La gestion des noms de domaine et des adresses IP, bien plus politicienne et bien plus brûlante (surtout pour les noms de domaine) n'y figure pas. Voici donc « la position de l'IETF concernant l'avenir de la gestion des registres IANA, dans l'hypothèse où le gouvernement états-unien relâcherait son emprise ». Pour résumer cette position : la gestion des registres des paramètres des protocoles fonctionne actuellement bien et, quelles que soient les manœuvres autour de l'évolution du rôle du gouvernement US, il ne faut pas la changer. Ce RFC a été terminé en janvier 2015 mais n'est publié que maintenant, après l'approbation du plan de transition par l'ICANN en mars 2016 à sa réunion de Marrakech, et après l'accord du gouvernement états-unien en août.

L'agence du gouvernement états-unien chargée de superviser l'ICANN se nomme NTIA, dépendant du ministère du commerce (notez la vision de l'Internet que cela implique). Notez que cette supervision n'est pas le seul levier direct de ce gouvernement sur la gestion de ressources critiques de l'Internet. Il y a aussi la gestion de la racine du DNS, effectuée via Verisign. En mars 2014, génée par les révélations de Snowden, la NTIA a annoncé un projet d'évolution du statut de l'ICANN, passant du gouvernement états-unien à quelque chose de nouveau, encore à discuter. La NTIA a posé ses conditions (par exemple que le quelque chose de nouveau ne devait pas être multi-gouvernemental), et annoncé que, s'il n'y avait pas de plan satisfaisant (satisfaisant pour la NTIA) proposé, le projet serait abandonné ou redéfini.

C'est là qu'a été créé l'ICG (IANA Stewardship Coordination Group) dont la charte figure en annexe B de ce RFC. C'est cet ICG qui a émis l'appel aux commentaires (qui figure en annexe C du RFC). Cet appel demande entre autre de préciser si les réponses concernent la partie « noms de domaine », la partie « adresses IP » ou bien la partie « paramètres des protocoles » du travail de l'IANA (ce RFC concerne la troisième partie). Les réponses sont disponibles en ligne.

La section 2 de ce RFC est la réponse formelle de l'IETF, suivant le plan de l'appel à commentaires de l'ICG. D'abord, l'IETF répond à la question « l'IANA sert à quoi, pour vous ? » Bien des protocoles conçus ou gérés par l'IETF ont besoin de registres pour des paramètres du protocole. Par exemple, le protocole HTTP (RFC 7231) a des codes de retour des opérations (comme le célèbre 404) qui sont stockés à l'IANA. Ajouter un tel code (par exemple 451 pour « contenu censuré ») ne nécessite donc pas de modifier la norme HTTP. Ou bien, pour prendre un exemple nettement moins connu, le protocole PCP (RFC 6887) dispose d'un certain nombre d'options, qui ne sont pas fixées une fois pour toutes dans la norme mais sont notées dans un registre IANA, ce qui permet d'en ajouter facilement de nouvelles.

Pour que l'Internet fonctionne, il faut que ces paramètres des protocoles soient utilisés de la même manière par tous. Par exemple, cela signifie que les développeurs de logiciels Internet doivent utiliser les mêmes registres, en l'occurrence, ceux de l'IANA. Ainsi, un serveur HTTP peut renvoyer le code 403 en sachant bien que cela sera interprété par tous les clients comme signifiant « Accès interdit », car le code 403 figure dans le registre IANA avec cette définition. Ce rôle de l'IANA pour l'IETF est documenté dans le RFC 5226.

L'IANA gère également le TLD .arpa, qui est considéré comme un des registres de paramètres (RFC 3172).

Ce travail de l'IANA pour le compte de l'IETF est effectué en application du RFC 2860 (voir aussi ses déclinaisons concrètes), qui est le « contrat » entre les deux activités.

La question suivante est « qui êtes-vous ? » L'IETF se présente donc, SDO internationale, ouverte et dont la mission est décrite dans le RFC 3935. L'IETF fait les normes techniques de l'Internet « de la couche 3 jusqu'au bas de la couche 7 ». C'est elle qui est responsable d'IP de BGP, du DNS, de HTTP, etc. (Oui, tous les lecteurs de ce blog savent cela mais la réponse de l'IETF est conçue pour être lue par un public plus large.) Le côté ouvert de l'IETF est précisé dans le RFC 6852, le processus de création des normes dans le RFC 2026.

Une question difficile dans l'appel à commentaires était « quels recouvrements y a-t-il entre votre activité et celles d'autres organisations ou groupes ? » D'abord, la réponse met en avant le fait que les participants à l'IETF sont souvent membres d'autres organisations. (On parle de « participants » car l'IETF n'a pas de mécanisme d'adhésion formel.)

Ensuite, l'IETF a évidemment des activités qui s'approchent de très près de celles d'autres groupes, avec parfois des discussions sur la frontière. Ainsi, le RFC 6761, qui fait l'objet de beaucoup de débats en ce moment, prévoit un mécanisme d'enregistrement de noms de domaine par l'IETF, alors que certains voudraient que cela soit un monopole de l'ICANN. C'est aussi le cas des adresses IP (mais cela suscite bien moins d'intérêt car c'est plus important mais moins spectaculaire). Ainsi, si l'IANA gère l'espace d'adressage IP, l'IETF alloue également des portions de cet espace (RFC 7020, RFC 7249, et un exemple concret, les ULA du RFC 4193). Il y a aussi bien sûr des recouvrements envers ce que fait l'IETF, et le travail des opérationnels qui décident (ou pas) de déployer les protocoles normalisés. Par exemple, la gestion des serveurs racine du DNS est à la fois un secteur de l'IETF (RFC 7720) et des opérateurs de ces serveurs.

Les activités de l'IETF concernant IP et le routage l'amènent par contre du côté des RIR (par exemple lorsque l'IETF a ses propres allocations d'adresse, comme dans le RFC 6890). Un changement de norme technique peut impacter les opérationnels (nouvelles choses à gérer) et les RIR. Ainsi, l'extension de la taille des numéros d'AS de deux à quatre octets (RFC 6793) imposait évidemment aux RIR de changer leur logiciel et leur politique, pour allouer ces nouveaux numéros.

Pour tous ces points, le RFC insiste sur l'importance de la coordination entre ces acteurs, et sur les nombreux contacts que l'IETF maintient avec toutes ces communautés.

L'appel à commentaires de l'ICG demande ensuite comment les politiques sont décidées et comment les conflits sont gérés. Pour l'IETF, les principes figurent dans les RFC 6220 et RFC 5226. En gros, quelqu'un qui veut changer la politique de l'IETF, par exemple modifier le RFC 5226 (c'est justement en cours de discussion) va écrire un premier document, un Internet Draft, essayer de susciter de l'intérêt, en général le faire adopter par un des groupes de travail (à moins qu'un groupe soit créé spécialement), la proposition doit réunir un consensus (RFC 7282) et c'est souvent l'IESG qui prend la décision finale. Le tout est scandé par des last calls où les organisateurs demandent aux participants un dernier avis avant que le document n'avance. (Pour le fonctionnement des groupes de travail, on peut lire le RFC 2418, mais il n'est plus complètement à jour.)

Et les conflits ? Ils sont normalement réglés dans les groupes de travail mais, si c'est grave, la section 6.5 du RFC 2026 décrit un mécanisme d'appels successifs.

Un concept souvent cité en ce moment dans les discussions autour de l'ICANN et celui de redevabilité (accountability). L'organisation est-elle redevable à quelqu'un, ou bien est-ce un clan mafieux fermé qui décide de tout en interne et ne rend de comptes à personne (comme le CIO ou la FIFA) ? L'appel à commentaires demande donc de la documentation sur les mécanismes de redevabilité du répondeur. Pour l'IETF, c'est l'IAB qui joue ce rôle, en confirmant (ou pas) les nominations et en traitant les appels mentionnés un peu plus haut. C'est aussi l'IAB qui gère les canaux de communication (liaisons) avec les autres organisations. Et c'est l'IAB qui décide quel opérateur gère les registres de paramètres de protocole, actuellement l'ICANN via sa fonction IANA. L'IAB est officiellement décrite dans le RFC 2850. Elle est elle-même redevable devant les participants à l'IETF, par son mécanisme de désignation (RFC 3777).

Quel est le degré de formalisation de votre relation avec l'IANA, demande ensuite l'appel à commentaires ? Un MoU existe (RFC 2860). Son suivi quotidien est assuré par l'IAD (IETF Administrative Director), lui-même sous contrôle de l'IAOC (IETF Administrative Oversight Committee, cf. RFC 4071). Une de leurs tâches est de suivre les rapports de l'IANA sur ses résultats.

En théorie, si un conflit grave surgissait entre l'IETF et l'IANA, l'IETF pourrait mettre fin au travail en commun et choisir un nouvel opérateur pour ses registres (et ce RFC serait alors sans objet). Mais cela ne s'est jamais produit et une telle perspective semble peu probable.

L'appel à commentaires demande aussi à ceux qui répondent d'indiquer de quelle juridiction ils dépendent et quelles sont les lois qui leur sont applicables. L'IETF répond que son activité est mondiale (ce qui est vrai) et que les textes entre l'IANA et l'IETF ne spécifient pas de juridiction (ce qui est exact mais incomplet : l'IETF étant une activité de l'ISOC, l'IETF dépend de la juridiction états-unienne, comme le montrent, par exemple, les injonctions reçues).

Commencent ensuite les questions sensibles, par exemple les demandes de suggestions concernant les mécanismes futurs qui remplaceraient la NTIA. La réponse du RFC est qu'aucun changement n'est demandé par l'IETF : le système actuel avec l'IETF, l'ICANN, l'IAB, etc, a bien fonctionné, sans implication du NTIA, et n'a donc aucun besoin d'être remplacé ou « amélioré ». Les RFC 2860 et RFC 6220 fournissent un cadre satisfaisant et le résultat l'est également.

Cette partie de la réponse contient quand même quelques souhaits, pas forcément de changement mais de points importants à garder en tête :

  • Les registres des paramètres de protocole sont dans le domaine public (ils sont un « bien commun ») et doivent le rester, quels que soient les changements futurs.
  • S'il y a un changement, il faudra que l'ICANN et le nouvel opérateur travaillent ensemble à rendre la transition la plus invisible possible.

Et le RFC réaffirme les principes que l'IAB avait posé en mars 2014 :

  • La « communauté technique Internet » se débrouille très bien à l'heure actuelle et n'a pas besoin d'intervention extérieure.
  • L'enregistrement des paramètres techniques des protocoles doit reposer sur l'ouverture, la transparence et la redevabilité.
  • Tout changement devrait respecter les textes et les accords existants (jolie façon de dire qu'aucun changement n'est souhaité).
  • Les registres des paramètres techniques des protocoles et les autres registres (comme les RIR pour les adresses IP) sont essentiels, et fonctionnent aujourd'hui correctement.
  • L'IETF va continuer dans son rôle.
  • La gestion des registres des paramètres techniques est un service public.

J'avais signalé plus haut que la NTIA avait posé un certain nombre d'exigences pour accepter un éventuel plan de transition. La suite de l'appel à commentaires rappelle ces exigences et demande dans quelle mesure les propositions faites sont conformes à ces oukases. D'abord, la NTIA demande de « continuer avec le modèle multi-partiesprenantes » (ne me demandez pas de définir ce modèle...) L'IETF répond qu'en tant qu'organisation ouverte à tous, elle suit déjà ce modèle (même réponse à la demande de la NTIA que le futur éventuel système « conserve l'ouverture de l'Internet »). Ensuite, la NTIA exige de préserver « la sécurité et la stabilité du DNS » (une des phrases les plus citées dans les milieux de la gouvernance Internet...) L'IETF ne proposant pas de changement, la stabilité est certainement préservée. Puis le gouvernement états-unien veut que les propositions « satisfassent les utilisateurs et répondent à leurs besoins ». Le RFC estime que l'utilisation massive dans le monde des protocoles TCP/IP et donc des registres de l'IANA montre clairement que les utilisateurs sont contents. Dernier ordre de la NTIA : que la solution future ne soit pas multi-gouvernementale (rappelons que le mécanisme actuel de supervision de l'ICANN est mono-gouvernemental). L'IETF réplique que l'IAB n'est pas une organisation gouvernementale et que l'ordre est donc suivi.

L'appel à commentaires de l'ICG demande également par quel processus la réponse a été élaborée, une bonne façon de vérifier que le répondant a appliqué ses beaux principes, y compris lors de la conception de sa réponse. L'IETF explique que la réponse a été développée par le groupe de travail IANAPLAN, qui, comme tous les groupes de travail de l'IETF, était ouvert à tous et faisait tout son travail publiquement (cf. les archives de la liste de diffusion du groupe). Pour le montrer, comme le demande l'appel à commentaire, l'IETF cite de nombreux documents publiquement accessibles :

Le RFC estime que tout ce processus montre un net consensus de l'IETF en faveur de cette réponse. Quelques points sont restés contentieux jusqu'au bout (comme la demande que le nom de domaine iana.org soit transféré à l'IETF Trust).

Quelques lectures supplémentaires sur cette opération de transition :


Téléchargez le RFC 7979


L'article seul

RFC 7940: Representing Label Generation Rulesets Using XML

Date de publication du RFC : Août 2016
Auteur(s) du RFC : K. Davies (ICANN), A. Freytag (ASMUS)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF lager
Première rédaction de cet article le 29 août 2016


Lorsqu'on a des identificateurs en Unicode (par exemple pour les noms de domaine internationalisés), on souhaite souvent limiter le nombre de caractères autorisés, et avoir des possibilités de variante (par exemple, dire que deux chaînes de caractères Unicode sont en fait équivalentes sémantiquement). Il faut donc rédiger ces règles, et un langage formel est certainement utile pour cela. C'est ce que propose ce nouveau RFC, qui normalise un langage XML pour décrire les règles d'enregistrement de ces identificateurs Unicode.

Le terme utilisé par le RFC est LGR, pour Label Generation Ruleset. Label est le composant de base d'un nom de domaine, et Ruleset fait référence à l'ensemble des règles décrites en XML et qui permettront de savoir si un composant est valide, et quelles transformations éventuellement effectuer avant de l'enregistrer. C'est un concept qui vient de l'ICANN, qui a toujours présenté les IDN comme une chose dangereuse (bien à tort), nécessitant des variant tables ou autres algorithmes compliqués. Donc, si vous ne travaillez pas avec l'ICANN, il n'est pas nécessaire de connaitre ce RFC.

Le langage présenté dans ce RFC est assez complexe, mais le problème est complexe. Ceci dit, dans les cas « simples » (alphabet latin), les règles LGR seront également simples. Si on veut juste dire que é, è et ë sont autorisés dans les noms, et avec e comme variante, c'est trivial à faire, à peine plus compliqué que les tables du RFC 4290.

Notez que l'algorithme décrit par un LGR ne suffit pas comme règle d'enregistrements des noms de domaine : il existe d'autres règles (comme la priorité aux entreprises titulaires de propriété intellectuelle) qui ne sont pas exprimables par ces algorithmes.

Avant ce RFC, les règles concernant les IDN étaient publiées en langue naturelle, ou parfois dans le langage formel des RFC 3743 et/ou RFC 4290. Le langage décrit ici a vocation à les remplacer. Il est structuré, donc lisible par un programme, et permet de dériver automatiquement les programmes de vérification d'un nom (par exemple ceux qui sont lancés par un serveur EPP recevant un ordre <domain:create>, RFC 5731, section 3.2.1).

Le format est relativement simple si on a une politique simple mais permet le cas échéant de mettre en œuvre des politiques très complexes (qui sont utiles pour certaines écritures asiatiques, par exemple). Il est conçu pour les IDN mais peut être utilisé si on a à enregistrer des identificateurs Unicode dans un autre contexte.

Le cahier des charges du format des LGR figure en section 2 du RFC :

  • Doit pouvoir être programmé de manière raisonnablement directe (je n'ai pas essayé...)
  • Doit pouvoir être validé (l'ICANN, qui exige l'envoi d'une politique IDN pour les TLD qu'elle régule, peut ainsi tester automatiquement la validité de celles-ci). Notez aussi qu'un LGR sera développé pour la racine du DNS.
  • Doit pouvoir exprimer la notion de variantes (équivalence entre deux caractères, ou chaînes de caractère, par exemple entre les sinogrammes traditionnels et les simplifiés).
  • Doit pouvoir exprimer la notion de contexte (un caractère n'est valable que dans un certain contexte par exemple le sigma final grec, U+03F1 (ϱ) qui ne peut apparaître qu'en fin de mot).
  • Etc

Un point important de ce RFC est qu'il décrit un format, pas une politique : le RFC ne dit pas si le caractère Unicode U+00E8 (è) doit être considéré comme une variante du U+0065 (e) : il fournit juste le moyen d'exprimer cette équivalence, si on le décide.

La section 4 du RFC spécifie le format exact. (Le schéma formel - en Relax NG - est dans l'annexe D.) Un ensemble de règles LGR est mise dans un élément XML <lgr>. Il contient quelques métadonnées, dont la date et la langue ou l'écriture pour lesquels ce LGR est prévu. Comme l'ICANN, dans ses politiques IDN, mélange très souvent langue et écriture (par exemple en parlant de « domaines multilingues », ce qui est absurde), il faut préciser que la plupart des politiques portent sur des écritures (un nom de domaine n'a pas de langue : coca-cola.com est-il de l'anglais ?) La valeur de l'élément XML <language> est une étiquette du RFC 5646, avec la langue marquée comme « non définie » (und pour undeterminate). Un exemple pour une politique consacrée à l'alphabet cyrillique : <language>und-Cyrl</language>.

Les règles elle-mêmes sont en section 5. La plus simple est celle qui autorise un caractère donné, ici le tiret (cp = Code Point Unicode, ici U+002D) :

      
<char cp="002D"/>

    

On peut aussi autoriser un intervalle, ici tous les chiffres arabes :

      
<range first-cp="0030" last-cp="0039"/>

    

Comme on le voit, les caractères sont identifiés par leur point de code Unicode, écrit sans le « U+ » initial. Bien que XML permettre de représenter nativement tous les caractères Unicode, cette possibilité n'est pas exploitée par ce RFC (cf. Unicode Standard Annex #42).

Voici maintenant un exemple de règle qui précise que le point médian U+00B7 n'est autorisé qu'entre deux l (c'est le cas en catalan mais notez qu'en français, il est aussi utilisé dans une perspective féministe). Cela se fait en indiquant une séquence :

      
<char cp="006C 00B7 006C" comment="Catalan middle dot"/>

    

Et voici une règle contextuelle plus complexe. On veut n'autoriser le gluon de largeur nulle U+200D qu'après un virāma. Si une règle follows-virama (non montrée ici) a été définie, on peut écrire :

      
  <char cp="200D" when="follows-virama" />

    

Et les variantes ? Voici d'abord comment exprimer que le é est une simple variante du e (non pas que je recommande cette politique : c'est juste un exemple) :

      
 <char cp="00E8">
           <var cp="0065"/>
 </char>

    

Et une variante où un caractère (œ) est mis en correspondance avec deux caractères (oe) :

      
 <char cp="00F6">
           <var cp="006F 0065"/>
 </char>

    

Ces règles portaient sur des caractères qui formaient une partie d'un composant d'un nom. Mais il y a aussi des règles qui portent sur la totalité du composant (section 6 du RFC). Pour cela, d'abord un petit mot sur la notion de classe. On définit une classe de caractères à partir de propriétés Unicode. Ici, on a la classe des virāma, définie à partir de la propriété Unicode CCC (Canonical Combining Class) :

      
<class name="virama" property="ccc:9" />

    

On peut ensuite combiner les classes par intersection, union, etc.

Les règles permettent aussi d'utiliser des opérateurs booléens. Voici par exemple la règle traditionnelle des noms de machines (et pas des noms de domaine, contrairement aux bêtises qu'on lit souvent), autorisant lettres ASCII, chiffres et tiret. Elle utilise <choice>, qui fait un OU logique entre les termes :

      
       <rule name="ldh">
          <choice count="1+">
              <class by-ref="letter"/>
              <class by-ref="digit"/>
              <char cp="002D" comment="literal HYPHEN"/>
          </choice>
       </rule>

    

Des exemples plus réalistes et plus détaillés figurent dans l'annexe A.

Le document XML complet a le type MIME application/lgr+xml.

Quelques petits mots sur la sécurité (section 12 du RFC). Le RFC part du préjugé (qui est faux) comme quoi les noms en Unicode poseraient des problèmes de sécurité. La section 12 note ensuite (si on accepte cette prémisse) que les règles de ce RFC ne résolvent pas complètement le problème (qui est largement imaginaire). Il reste possible de faire des noms « trompeurs » même avec les règles les plus strictes. Outre question de sécurité à garder en tête : les règles de ce RFC peuvent permettre de concevoir des politiques LGR très complexes, qui peuvent épuiser les ressources de la machine qui tenterait de les évaluer.

Si vous voulez pratiquer avec vos propres LGR, l'ICANN a fait développer un outil qui est accessible en ligne (lisez la documentation pour connaitre le mot de passe) ou bien en source sur GitHub : lgr-core et lgr-django pour l'interface Web en Django.


Téléchargez le RFC 7940


L'article seul

RFC 7914: The scrypt Password-Based Key Derivation Function

Date de publication du RFC : Août 2016
Auteur(s) du RFC : C. Percival (Tarsnap), S. Josefsson (SJD AB)
Pour information
Première rédaction de cet article le 29 août 2016


À quoi ça sert, une fonction de dérivation de clé ? Comme leur nom l'indique, elles permettent d'obtenir des clés cryptographiques (ou autre matériel cryptographique) à partir des données qu'on leur fournit. Une utilisation courante est de fabriquer une clé pour un algorithme de chiffrement, à partir d'une phrase de passe. Cela permet d'obtenir une clé (longueur fixe, format donné) pour les opérations cryptographiques tout en laissant l'utilisateur manipuler uniquement des textes mémorisables. Par exemple, pour chiffrer un disque dur, l'utilisateur va indiquer une phrase de passe, mais le disque sera chiffré à partir de la clé obtenue en appliquant la fonction de dérivation de clé (KDF, pour Key Derivation Function) à cette phrase. Une autre utilisation est pour transformer un mot de passe qu'on doit stocker dans un fichier en une information inutilisable pour un attaquant qui mettrait la main dessus. Pour se connecter, on tape le mot de passe, on refait tourner la KDF et on vérifie qu'on obtient bien le résultat stocké.

Problème de cette méthode, l'ennemi peut tenter de faire lui-même la dérivation : il essaie des tas de mots de passe et regarde s'il obtient le résultat stocké. C'est pour cela qu'une des qualités d'une bonne fonction de dérivation est, paradoxalement, d'être lente : les gens qui connaissent le mot de passe ne seront pas gênés (ils ne font qu'un seul essai) alors que l'attaquant par force brute qui essaie des milliards de mots sera ralenti. Idéalement, on voudrait une fonction qui ne puisse pas facilement être mise en œuvre dans des ASIC, pour qu'un attaquant riche ne puisse pas investir dans une « machine à deviner les mots de passe ». C'est l'un des avantages de scrypt. (Les fanas de chaîne de blocs noteront que des chaînes comme Litecoin utilisent scrypt justement pour cette raison : rendre le minage plus accessible à tous en contrariant les ASIC.)

Pourquoi encore ajouter des fonctions de dérivation de clés (section 1 du RFC) ? Il y en a eu plein dans l'histoire, de la vénérable crypt à PBKDF2 (RFC 2898) puis aux récents bcrypt et Argon2. On en imagine souvent de nouvelles, par exemple celle-ci qui n'utilise pas du tout de chiffrement, juste de la condensation. Pour résister aux attaques par force brute (que la loi de Moore rend plus efficace chaque année), certaines ont un nombre d'itérations variables. On applique plusieurs fois l'opération de dérivation, si les machines deviennent plus rapides, on augmente ce nombre d'itérations. Cela ne marche bien que si l'attaquant utilise les mêmes logiciels que les utilisateurs normaux. Mais si la fonction de dérivation est facilement programmable dans des circuits matériels spécialisés, l'attaquant pas trop pauvre pourra s'acheter une ferme de cassage de mots de passe, remplie de circuits conçus spécifiquement, et travaillant en parallèle (les circuits deviennent plus rapides mais aussi plus petits : on peut en entasser davantage). Il ne joue alors plus dans la même catégorie que les utilisateurs légitimes.

C'est là que scrypt intervient : l'algorithme a été délibérement conçu pour être difficile à mettre dans un ASIC. scrypt a été publié en 2009 (voir l'article original qui fut présenté à USENIX). Ce RFC a commencé en 2013 et a eu une longue gestation. Il ne décrit pas scrypt, renvoyant au papier original, mais se contente de préciser les points qui sont nécessaires pour des mises en œuvre interopérables.

La section 2 du RFC décrit les paramètres de la fonction. Le plus évident est la phrase de passe, souvent choisie par un humain. Il y a aussi un sel, en général choisi aléatoirement (RFC 4086), et divers paramètres techniques, permettant notamment d'ajuster l'algorithme aux caractéristiques des machines dont on dispose. Une taille de bloc de 8 et un facteur de parallélisation de 1 conviennent bien à l'heure actuelle, mais vont sans doute augmenter dans le futur.

scrypt dépend de la fonction de condensation Salsa20 Core, plus exactement de sa version simplifiée Salsa20/8 Core (section 3 du RFC). Une mise en œuvre en C est incluse dans le RFC. (Voir la description originelle et la spécification de Salsa20.)

scrypt est un « chef d'orchestre », qui dépend de plusieurs autres algorithmes comme BlockMix (section 4), ROMix (section 5), le PBKDF2 du RFC 2898 et le HMAC-SHA-256 du RFC 6234. L'algorithme de scrypt, qui fait fonctionner ensemble tout cela, figure en section 6.

Si vous êtes programmeur et que vous mettez en œuvre scrypt, les sections 8 à 13 du RFC contiennent des vecteurs de test pour les différents algorithmes utilisés. Par exemple, avec la phrase de passe pleaseletmein, le sel SodiumChloride (exemple contestable, ce sel n'a pas été généré aléatoirement), le facteur CPU/mémoire à 16384, la taille de bloc 8 et le facteur de parallélisation 1, la clé dérivée par scrypt sera 70 23 bd cb 3a fd 73 48 46 1c 06 cd 81 fd 38 eb fd a8 fb ba 90 4f 8e 3e a9 b5 43 f6 54 5d a1 f2 d5 43 29 55 61 3f 0f cf 62 d4 97 05 24 2a 9a f9 e6 1e 85 dc 0d 65 1e 40 df cf 01 7b 45 57 58 87. Si vous trouvez une autre valeur, vérifiez votre programme.

Lisez aussi la section 14, consacrée aux questions de sécurité. Par exemple, scrypt peut consommer beaucoup de mémoire (c'est fait exprès, cela fait partie des techniques qui rendent difficile sa mise en œuvre en ASIC) et il y a donc un risque de déni de service si on accepte d'exécuter scrypt avec des paramètres quelconques, fournis depuis l'extérieur.

scrypt est, entre autres, présents dans OpenSSL depuis le 1.1.0, officiellement publiée juste après le RFC.


Téléchargez le RFC 7914


L'article seul

À quoi peut bien servir la chaîne de blocs ?

Première rédaction de cet article le 28 août 2016


Tous les jours, plusieurs articles apparaissent dans les médias pour expliquer que la chaîne de blocs (blockchain dans la langue de Satoshi Nakamoto) va résoudre encore un nouveau problème. Pour le non-spécialiste, il n'est pas évident de faire la part du réel et du fantasme dans toutes ces applications de la chaîne de blocs. C'est en pensant à ce non-spécialiste que j'ai écrit cet article : peu ou pas de technique, juste une exploration des choses où la chaîne de blocs est vraiment utile, par rapport à celles où elle n'a pas d'intérêt.

D'abord, je vais me permettre un court paragraphe rappelant ce qu'est la chaîne de blocs : il s'agit d'une base de données ordonnée (les blocs contiennent des transactions, opérations d'écriture dans la chaîne, qui sont dans un ordre précis), répartie sur un réseau (typiquement Internet), et qui n'a pas de gérant unique. Chaque machine, chaque nœud, porte toute la chaîne et détruire celle-ci nécessiterait donc de détruire des dizaines de milliers de machines, gérées par des gens différents. La chaîne de blocs est publique : tout le monde peut créer un nœud du jour au lendemain, qui va automatiquement télécharger et vérifier la chaîne, avec toutes les données qu'elle contient. Tout le monde peut y écrire (souvent moyennant finances) et ces écritures sont signées, et sont gardées éternellement dans la chaîne, qui est donc un livre des opérations, contenant tout l'historique. L'intégrité de la chaîne est garantie par la cryptographie. Toute modification est détectable par tous. Notez bien que j'ai dit toute modification. La chaîne ne distingue pas entre modification « légitime » ou « illégitime ». Une fois qu'une transaction est dans la chaîne, elle y est pour toujours, même si on croit avoir de bonnes raisons de l'annuler. (Oui, les techniciens vont noter que c'est plus compliqué que cela ; mais c'est toujours plus compliqué que cela, j'essaie d'en rester aux grandes lignes.)

Il n'y a donc pas besoin de faire confiance au Président de la Chaîne de Blocs (il n'existe d'ailleurs pas). La chaîne permet donc à des acteurs ne se connaissant pas, et ne se faisant a priori pas confiance, de travailler sur une base de données commune, consensuelle. C'est tout mais c'est énorme. La chaîne est « vérifiable par tous et contrôlée par personne ».

Les applications de la chaîne de blocs sont donc a priori nombreuses : toutes les fois où des acteurs différents faisaient appel à une autorité centrale, on pourrait mettre à la place une chaîne de blocs. L'exemple évident est la monnaie. Depuis le Moyen Âge, elle est typiquement garantie par un État (autorité centrale). Avec la chaîne de blocs, on peut concevoir une monnaie sans autorité centrale, et c'est bien le cas de Bitcoin, la technologie qui a lancé et popularisé cette idée de chaîne de blocs. Outre le plaisir de se débarrasser d'une autorité centrale qui ne mérite pas forcément la confiance qu'on lui porte, cela présente des avantages comme de faciliter les micropaiements.

Donc, est-ce que tout ce qui a besoin de vérification publique, sans autorité centrale, est « chaînedeblocsisable » ? Prenons quelques exemples.

Après la monnaie, un autre cas de service qui est souvent géré de manière centralisé est celui de la gestion de noms (création, suppression, etc) dans un espace de nommage. Par exemple, les noms d'utilisateur de Twitter sont gérés de manière centralisée par Twitter, ce qui permet d'assurer l'unicité de ces noms (il n'y a qu'une AdrienneCharmet sur Twitter). Mais cette centralisation donne aussi un contrôle excessif à Twitter : cette entreprise a pu ainsi à de nombreuses reprises fermer des comptes sur la base d'un simple signalement, souvent mensonger. La chaîne de blocs fournit une alternative : l'enregistrement des noms « premier arrivé, premier servi » peut se faire sur une chaîne de blocs, comme le fait le système Twister. Ainsi, plus personne ne peut supprimer des comptes, la censure devient bien plus difficile.

Un exemple très proche de celui-ci est celui des registres de noms de domaine. Ceux-ci enregistrent des noms de domaine, indispensables pour l'utilisation de l'Internet. Mais ils ont aussi le pouvoir de les supprimer (comme dans l'affaire Sci-Hub). On peut donc envisager de remplacer ces registres par une chaîne de blocs, où les transactions sont la création d'un nom de domaine. Le premier exemple avait été le système Namecoin, un autre exemple a été présenté par moi à la Journée du Conseil Scientifique de l'AFNIC de 2016. Attention, j'ai dit que le remplacement des registres de noms de domaine était possible techniquement, pas forcément qu'il était souhaitable, ni qu'il serait adopté (des tas de très bonnes idées n'ont connu aucun succès). En effet, la chaîne de blocs a aussi ses limites (voir plus loin).

Autre exemple d'application sans doute bien adaptée à la chaîne de blocs, le cadastre. Là aussi, on veut une information publique, et modifiable, et publiquement vérifiable. Au lieu de faire confiance à des autorités centrales, on pourrait tout mettre sur une chaîne de blocs. (Un exemple est souvent cité dans les médias mais sans jamais citer de source originelle donc je ne suis pas sûr qu'il soit réel.)

Dernier exemple d'une application qui est bien adaptée à la chaîne de blocs, l'enregistrement d'œuvres à des fins de prouver l'antériorité. Imaginons un artiste qui produise une vidéo, ne peut pas ou ne veut pas la publier tout de suite, mais souhaite pouvoir prouver plus tard qu'on était bien l'auteur. Même chose pour un chercheur scientifique qui est en train de rédiger un article, il ne sait pas encore quand il pourra le publier (il faut terminer certains détails, et puis le processus de publication scientifique peut être très long) mais, en cas de fuite, il veut pouvoir faire valoir son antériorité. Il existe des solutions centralisées traditionnelles, nécessitant une confiance aveugle dans un organisme comme l'INPI avec les enveloppes Soleau ou comme Ma Preuve. À la place, on pourrait utiliser la chaîne. Mais mettre directement leur œuvre dans la chaîne de blocs aurait deux inconvénients : cela pourrait leur coûter cher (voir plus loin les coûts de stockage dans la chaîne) et cela révèlerait leur œuvre (puisque la chaîne est publique, et lisible par tous). Une solution possible est le condensat. C'est une opération mathématique simple qui réduit (condense) un document de taille quelconque en un nombre relativement court. La condensation n'est pas inversible (à partir du condensat, on ne peut pas retrouver le contenu original). Les fonctions mathématiques utilisées ont pour propriété qu'on ne peut pas fabriquer un document ayant un condensat donné (sauf chance extraordinaire). Ainsi, si le condensat est stocké dans la chaîne de blocs, seul l'auteur original pourra, le jour venu, produire un document qui correspondra, prouvant ainsi qu'il était bien celui qui avait enregistré le condensat. J'ai développé cette idée dans mon exposé à Pas Sage en Seine 2016 mais ce n'est pas une idée originale. Elle est également mise en œuvre dans le système Blockai. Il a même été proposé d'utiliser une technique analogue pour faciliter le travail des historiens.

Dans le monde de la haute technologie, un bon moyen de trier entre les techniques sérieuses et celles qui relèvent du pipeau, c'est de regarder non pas ce qu'une technique sait faire mais ce qu'elle ne sait pas faire. Si la description d'une technique ne liste pas ses limites, n'indique pas ce qu'elle ne peut pas faire, c'est probablement que cette technique est du pipeau. Voyons donc les cas où la chaîne de blocs n'est pas adaptée. D'abord, un mot sur les coûts. Comme tous les nœuds (toutes les machines du réseau) doivent exécuter les transactions (pour pouvoir les vérifier), il n'est pas exagéré de dire que « la chaîne de blocs est le plus lent et le plus cher calculateur du monde ». Pour éviter les abus, toutes les transactions doivent être payées, et le coût dépend, par exemple, de la taille des données stockées. Pas question, donc, de stocker des vidéos dans la chaîne. (Tout au plus peut-on stocker de courtes données, comme les condensats cités plus haut.) Pour la même raison, les applications qui nécessitent de longs calculs ne sont pas adaptées à la chaîne de blocs.

Celle-ci a d'autres limites : comme la chaîne est publique, il ne faut surtout pas stocker de données confidentielles. On peut parfois stocker uniquement un condensat, comme dans l'exemple plus haut, mais il faut rappeler que les métadonnées (qui stocke des données et quand, par exemple) restent visibles et qu'elles peuvent déjà beaucoup révéler. Contrairement à une légende souvent reprise par des médias sensationnalistes, la chaîne n'est pas adaptée aux transactions vraiment confidentielles. Vouloir, comme je l'ai lu dans certains articles, stocker données de santé ou fichiers scolaires est donc absurde.

La chaîne de blocs est une construction virtuelle, ne vivant que sur un réseau d'ordinateurs. Elle ne permet donc pas de contrôler des objets physiques. Ainsi, on a vu parfois des articles promettant de remplacer Airbnb par la chaîne de blocs. On peut à la rigueur gérer une serrure connectée via une application qui lit la chaîne. Mais ce n'est pas l'application qui va regarder l'état de l'appartement après le passage du locataire et faire un rapport qui influencera la réputation du locataire (une information essentielle sur Airbnb, que connaissent tous les gens qui l'ont réellement utilisé).

Cette présentation était forcément assez générale. Le monde des chaînes de blocs est en pleine effervescence et les projets sont innombrables. Parmi les propositions nouvelles, on entend souvent parler de « chaînes de blocs privées ». Souvent, ce n'est pas décrit de manière assez précise pour qu'on puisse se faire une opinion sur ces « chaînes privées ». Disons qu'une chaîne vraiment privée n'a aucun intérêt : ce serait une base de données plus lente et plus chère que les bases existantes. À la rigueur, il peut y avoir un intérêt pour des chaînes « semi-privées », par exemple au sein d'un consortium dont les membres ne se font pas confiance.

Et pour finir, un petit rappel sur des inconvénients des chaînes. Je ne veux pas dire que cette technologie est sans intérêt, bien au contraire (je ne prendrais pas la peine d'écrire sur quelque chose absolument sans intérêt). Mais elle a des limites. On a dit que toutes les transactions étaient signées, ce qui est crucial pour la sécurité de la chaîne. Mais cette sécurité repose sur la bonne gestion des clefs cryptographiques utilisées. Il faut à la fois empêcher des tiers de lire les clefs privées (pas facile sur une machine Windows infestée de logiciels malveillants) et s'assurer que ces clefs privées sont bien sauvegardées, pour faire face, par exemple, à une panne du disque dur. Cela complique sérieusement l'utilisation de la chaîne de blocs pour M. Michu ! Il existe bien sûr des solutions techniques (signatures multiples) et organisationelles (des « notaires » à qui on sous-traiterait ce travail) à ce problème mais elles sont encore rares.

D'autre part, le caractère immuable des transactions dans la chaîne a des avantages (la censure est difficile) et des inconvénients (pas de droit à l'oubli, les transactions sont visibles éternellement...)

Merci à Michel Guillou pour ses articles et pour l'idée de celui-ci.


L'article seul

RFC 7929: DNS-Based Authentication of Named Entities (DANE) Bindings for OpenPGP

Date de publication du RFC : Août 2016
Auteur(s) du RFC : P. Wouters (Red Hat)
Expérimental
Réalisé dans le cadre du groupe de travail IETF dane
Première rédaction de cet article le 25 août 2016
Dernière mise à jour le 12 décembre 2017


Un problème classique du système de cryptographie OpenPGP, normalisé dans le RFC 4880 est de vérifier les clés publiques des correspondants. Les trouver, c'est relativement facile : le correspondant pense à vous les envoyer ou bien on se sert tout simplement d'un serveur de clés. Mais ceux-ci ne garantissent rien sur la clé. N'importe qui peut créer une clé marquée flotus@whitehouse.gov et la mettre sur les serveurs de clé, même si cette clé n'a rien à voir avec la Maison-Blanche. Avant la solution de ce nouveau RFC, il n'existait pas de mécanisme sécurisé pour récupérer une clé publique PGP. Que propose ce RFC ? De mettre les clés dans le DNS (nouveau type d'enregistrement OPENPGPKEY), dans le domaine de la partie droite de l'adresse de courrier, sécurisée par DNSSEC. En gros, il s'agit de faire pour le courrier et PGP ce que fait déjà DANE (RFC 6698) pour le Web/TLS.

Les serveurs de clés utilisent le protocole HKP (jamais décrit dans un RFC). Ils fournissent un service très utile en permettant de chercher une clé, par son identificateur, ou par l'adresse de courrier associé. Voici un exemple par identificateur :

    
% gpg --recv-key  0xF3396311465F8E5D
gpg: requesting key 465F8E5D from hkps server hkps.pool.sks-keyservers.net
gpg: key 465F8E5D: public key "Amaelle G <amaelle.guiton@techn0polis.net>" imported
...
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)
      
    

et un par adresse (notez que les adresses sont probablement toutes fausses) :


% gpg --search-key elysee.fr      
gpg: searching for "elysee.fr" from hkps server hkps.pool.sks-keyservers.net
(1)	hollande (flamby) <hollande@elysee.fr>
	  2048 bit RSA key CF22758A, created: 2014-01-06
(2)	jacques chirac (ancienne adresse) <jacques-chirac@elysee.fr>
	  2048 bit RSA key 2A97F759, created: 2007-11-15, expires: 2007-11-16 (expired)
(3)	kaziwan <kaziwan@elysee.gouv.fr>
	  1024 bit DSA key AA7FD67C, created: 2005-11-28
(4)	Gerard Calestroupat <gerard.calestroupat@elysee.fr>
	  1024 bit DSA key 82F02C73, created: 2003-08-05, expires: 2003-08-08 (expired)
(5)	Toto Berlingo <T.Berlingo@Elysee.fr>
	  1024 bit DSA key E9E920B7, created: 1999-06-10
    

Ces serveurs n'offrent aucune garantie : n'importe qui peut y publier une clé, avec n'importe quelle adresse et certaines clés sont clairement mensongères. L'usage normal est de récupérer la clé et ses signatures, puis de vérifier les signatures. Si elles sont faites par des gens qu'on a validés (directement, ou bien transitivement, jusqu'à une certaine profondeur), on estime la clé correcte (c'est ce qu'on nomme le web of trust). Autrement, la clé ne vaut rien. En outre, le seul système de révocation est de signer une révocation avec sa clé privée : si on l'a perdue, on ne pourra jamais retirer la clé des serveurs de clé. Pour ces deux raisons (fausses clés, et clés devenues inutilisables), il est donc difficile d'utiliser automatiquement, depuis un MUA ou un MTA, ces serveurs.

La solution proposée dans ce RFC est, comme souvent aujourd'hui, d'utiliser le DNS, qui a montré sa fiabilité et son ubiquité. Tout le monde peut faire des requêtes DNS, même coincé derrière un pare-feu, et tout le monde peut les valider, grâce à DNSSEC (RFC 4035).

On va donc publier dans sa zone DNS des enregistrements de type OPENPGPKEY, indexés par la partie gauche de l'adresse de courrier (c'est un peu plus compliqué, car elle peut contenir des caractères qui sont spéciaux pour le DNS ; voir plus loin). Le correspondant qui veut envoyer du courrier à quelqu'un cherchera cet enregistrement dans le DNS, et, s'il en trouve un, le validera avec DNSSEC et récupérera ainsi une clé PGP relativement sûre. La révocation d'une clé se fait simplement en retirant l'enregistrement du DNS.

La solution de ce RFC rend envisageable de récupérer et de vérifier automatiquement une clé avant l'envoi d'un message. Mais le RFC note bien qu'elle ne remplace pas complètement le web of trust, qui reste nécessaire si on veut une vérification sérieuse.

Ce RFC a le statut « Expérimental ». Il s'agit de tester l'idée et de voir si elle marche bien, et n'a pas trop d'inconvénients (par exemple de taille des zones DNS pour les domaines gérant beaucoup de comptes de courrier, surtout vu la taille des enregistrements OPENPGPKEY). Si le nombre de messages chiffrés avec OpenPGP augmente significativement suite à ce RFC, ce sera bon signe.

Notez qu'une expérience ressemblant à celle-ci avait déjà été faite avec le type d'enregistrement DNS CERT du RFC 4398. Ce fut un échec (peu de déploiement, peut-être en raison de la complexité du type CERT).

La section 2 de notre RFC décrit le format du nouveau type d'enregistrement DNS. Chaque enregistrement contient une et une seule clé. Si un utilisateur a plusieurs clés, il doit créer plusieurs enregistrements. Le type est 61 (et enregistré à l'IANA depuis août 2014). La partie droite de l'enregistrement (les données) contient la clé et au moins un ID et une auto-signature. Les clés PGP complètes, avec des tas de signatures, peuvent être grosses, trop pour le DNS ; le RFC recommande de ne publier que des clés minimales (pas trop de signatures, par exemple, et évidemment pas les photos qu'on peut inclure dans un attribut de la clé, cf. RFC 4880, section 5.12.1). Avec GnuPG, regardez l'exportation de ma clé avec toutes ses méta-données, et en exportation minimale (l'annexe A du RFC décrit les commandes GnuPG à utiliser) :

%  gpg --export CCC66677 > key.pgp 
% ls -lh key.pgp 
-rw-r--r-- 1 bortzmeyer bortzmeyer 86K Aug 25 17:17 key.pgp

%  gpg --export --export-options export-minimal,no-export-attributes CCC66677 > key.pgp
% ls -lh key.pgp                                                                       
-rw-r--r-- 1 bortzmeyer bortzmeyer 5.8K Aug 25 17:18 key.pgp   
    

Le format utilisé est celui du RFC 4880, section 11.1. C'est donc du binaire qui circule sur le réseau (rappelez-vous bien que, dans le DNS, le format de présentation, celui des fichiers de zone, et de la sortie de dig, n'a rien à voir avec le format binaire utilisé sur le réseau.) Les formats « texte » d'OpenPGP (« ASCII armor ») ne sont pas utilisés sur le réseau. (Donc, avec GnuPG, pas d'option --armor.)

Le format de présentation (celui des fichiers de zone et de la sortie de dig) encode la clé en Base64.

Et la partie gauche de l'enregistrement DNS ? Quel est le nom de domaine utilisé ? La section 3 du RFC fixe les règles :

  • Le domaine de l'adresse de courrier (partie droite de l'adresse de courrier) est celui où on met les enregistrements DNS OPENPGPKEY. La clé pour l'adresse stephane+chose@trucmachin.example sera donc dans la zone trucmachin.example.
  • Le nom de domaine sera la concaténation d'un condensat de la partie gauche de l'adresse de courrier (stephane+chose, dans l'exemple ci-dessus), et du composant _openpgpkey, avec le domaine de l'adresse de courrier (trucmachin.example dans l'exemple ci-dessus). Le condensat est tronqué à 28 octets. (Le nom de domaine n'est pas utilisé dans le condensat, pour faciliter la vie des opérateurs qui proposent la même adresse dans différents domaines.)
  • En fait, la règle est plus compliquée en raison des équivalences entre certains caractères (voir les exemples plus loin). Une correspondance est donc faite pour certains caractères. (Ce fut l'un des points les plus discutés dans le groupe de travail à l'IETF.)
  • Par exemple, les guillemets (oui, "jipoune le meilleur"@example.com est une adresse de courrier légale) sont retirés.
  • La condensation de la partie gauche de l'adresse de courrier est faite en SHA-256 (RFC 5754). Cela permet une protection limitée (cf. section 7.4) de la vie privée : même si un méchant met la main sur tout le fichier de zone, il ne trouvera pas facilement toutes les adresses (qui sont des données personnelles). Mais le but principal de cette condensation est de résoudre le problème de certains caractères qui sont permis dans la partie locale d'une adresse de courrier, mais qui posent des problèmes dans le DNS.

Ainsi, si l'adresse de l'utilisateur est hugh@example.com, la requête OPENPGPKEY devra chercher c93f1e400f26708f98cb19d936620da35eec8f72e57f9eec01c1afd6._openpgpkey.example.com. Voici comment calculer cela avec les outils du shell Unix (28 octets = 56 caractères dans la représentation en hexadécimal) :

    
% echo -n hugh | sha256sum | cut -c -56
c93f1e400f26708f98cb19d936620da35eec8f72e57f9eec01c1afd6

Une des difficultés pour trouver le bon nom de domaine est que les applications doivent traiter la partie gauche des adresses de courrier comme opaque (pas le droit d'analyser sa structure) et qu'elles ne connaissent pas les règles de canonicalisation qu'appliquera le domaine de destination, comme d'ignorer la casse de la partie locale (ce qui est souvent fait, mais pas toujours). Par exemple, Gmail ignore les points dans les adresses (donc foobar@gmail.com et foo.bar@gmail.com arrivent dans la même boîte aux lettres). L'émetteur qui ne connait pas cette règle va chercher la clé dans un domaine qui ne sera pas le bon. Idem avec les sous-adresses utilisées par certains domaines (en général avec le séparateur plus, comme stephane+blog, stephane+ietf, etc). Le RFC rappelle que l'émetteur ne peut pas se permettre de deviner ces règles locales, et qu'elles peuvent changer à tout moment. C'est au destinataire de se débrouiller, en publiant la clé à plusieurs noms, et en faisant attention aux variantes qu'il publie.

L'internationalisation des adresses de courrier complique évidemment encore un peu les choses (voir par exemple la section 10.1 du RFC 6530).

La section 6 du RFC se penche sur un problème pratique qu'on rencontre parfois avec le DNS : la difficulté à recevoir des réponses au-delà d'une certaine taille (il y a trois limites fréquemment rencontrées, la très ancienne limite de 512 octets du DNS, largement dépassée de nos jours, la limite de la MTU à 1 500 octets, au-delà de laquelle peut commencer la fragmentation, et la limite par défaut de la plupart des clients DNS à 4 096 octets). Les clés PGP peuvent être grosses, et le RFC recommende donc si possible de les récupérer sur TCP, pas UDP.

La section 7 de notre RFC analyse les questions de sécurité liées à cette technique. Elle rappelle que DNSSEC doit être utilisé : les enregistrements OPENPGPKEY récupérés ne doivent être utilisés que s'ils sont signés, et que la signature est valide. (Autrement, il serait trop facile à un attaquant de répondre avec une fausse clé.) Mais si DNSSEC est nécessaire, il n'est pas suffisant et la validation habituelle des clés PGP reste nécessaire si on veut un haut niveau de confidentialité. Ceci dit, comme souvent en sécurité, le mieux est l'ennemi du bien, et il vaut mieux une clé pas très vérifiée plutôt que d'envoyer le message en clair, comme le fait presque tout le monde aujourd'hui.

Et, évidemment, la sécurité DNSSEC doit être équivalente à la sécurité PGP puisqu'un attaquant qui aurait cassé la clé DNSSEC pourrait remplacer toutes les clés PGP du domaine. Il faut donc une cohérence dans les politiques de sécurité entre PGP et DNSSEC (section 7.6).

Autre problème de sécurité, cette fois lié à la vie privée : les requêtes DNS révèlent avec qui on veut communiquer de manière sécurisée par courrier (RFC 7626). Le fait que le nom de domaine utilisé soit un condensat de la partie locale de l'adresse de courrier limite un peu les risques, mais pas suffisamment (si on soupçonne qu'Alice écrit à bob@example.com mais qu'on n'en est pas sûr, il suffit de construire le nom où se trouve l'enregistrement OPENPGPKEY et de vérifier que ce nom est demandé, cf. section 7.4). C'est d'autant plus grave que les clients DNS actuels envoient en général le nom de domaine complet à tous les serveurs, même ceux qui n'en ont pas besoin. La minimisation de la requête (RFC 9156) limite ce problème. Le chiffrement des requêtes DNS (RFC 7858) peut faire le reste. Le cache du DNS limite un peu les risques et il est donc essentiel de ne pas faire une requête DNS externe à chaque fois qu'on envoie un message PGP à quelqu'un, cela ferait fuiter bien trop d'informations (section 7.5).

Pour limiter les risques qu'un attaquant récolte toutes les adresses de courrier du domaine, le RFC recommande de signer la zone en utilisant NSEC3 (RFC 5155).

À l'inverse de ce souci de protection de la vie privée, si une organisation veut lire le courrier de ses employés, la solution est qu'elle publie une clé d'organisation dans le DNS, pour pouvoir déchiffrer les messages entrants.

Un autre problème de sécurité est le risque d'utilisation dans des attaques par amplification. La taille importante des enregistrements OPENPGPKEY (surtout avec les clés RSA) aggrave ce risque. Le RFC suggère de n'envoyer ces enregistrements via UDP que si l'adresse IP source de la requête a été vérifiée, par exemple avec les petits gâteaux du RFC 7873.

Où en sont les mises en œuvre de ce RFC ? GnuPG contient le code pour gérer ces clés dans le DNS depuis la version 2.1.9. Même chose pour openpgp-milter.

L'outil hash-slinger permet quant à lui de générer et de vérifier des enregistrements OPENPGPKEY :

% openpgpkey --fetch --uid paul@nohats.ca  paul@nohats.ca
-----BEGIN PGP PUBLIC KEY BLOCK-----
Comment: paul@nohats.ca key obtained from DNS
Comment: key transfer was protected by DNSSEC
Version: GnuPG v1

mQENBFaJkKsBCADDSwQawRsKYqY/DuxWZjNNn39f14tDaswbpuF+PorNnt0MrepI
0yVY28NQ+5P09j75Os1jlqksK06aAVBtkJvr+T1ip85AxPUdTjD3U3zhM5/YATMi
...

On peut alors enregistrer la clé dans le trousseau PGP :


% openpgpkey --fetch --uid paul@nohats.ca  paul@nohats.ca | gpg --import
gpg: key BBAE5D31: public key "Paul Wouters (online key) <paul@nohats.ca>" imported
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)

   

Voici un exemple de récupération de ma clé :


% openpgpkey  --fetch --uid 'stephane@bortzmeyer.org' stephane@bortzmeyer.org |gpg  

pub  4096R/CCC66677 2014-02-08 Stéphane Bortzmeyer (Main key) <stephane@bortzmeyer.org>
uid                            Stéphane Bortzmeyer <stephane@sources.org>
uid                            Stéphane Bortzmeyer (Work address) <bortzmeyer@nic.fr>
uid                            TextSecure fingerprint (05 d6 3b dc b7 e4 d7 69 2f f6 24 d5 51 31 88 2f a5 59 ae 96 e0 fb a5 75 ab e6 6c 64 ca e9 bb 6a 77) <BdY73Lfk12kv9iTVUTGIL6VZrpbg+6V1q+ZsZMrpu2p3@base64>
sub  4096R/96A4A254 2014-02-09 [expires: 2018-01-10]
sub  4096R/57F02AA1 2014-02-09 [expires: 2017-01-10]

Mais comment ai-je fait pour que ça marche ? hash-slinger permet de créer la clé directement au bon format :

% openpgpkey --create stephane@bortzmeyer.org                                 
; keyid: 555F5B15CCC66677                                   
28182f0a278161989f90f090dabd6cab331663d8509ddbae617bb1e7._openpgpkey.bortzmeyer.org. IN OPENPGPKEY mQINBFL2VNABE...

Il n'y a plus qu'à la mettre dans le fichier de zone, et à re-signer. Mais, car il y a un mais, cela ne marche que si on a des logiciels récents, qui connaissent le type 61 (OPENPGPKEY). Si ce n'est pas le cas, le signeur refusera de signer, ou le serveur de recharger la zone. C'était mon cas, en raison d'une trop vieille version d'OpenDNSSEC. Trois solutions, commençons par la plus simple, demander à hash-slinger de générer un enregistrement DNS à la syntaxe générique (« types inconnus », du RFC 3597) :

% openpgpkey --create stephane@bortzmeyer.org --output generic
; keyid: 555F5B15CCC66677
28182f0a278161989f90f090dabd6cab331663d8509ddbae617bb1e7._openpgpkey.bortzmeyer.org. IN TYPE61 \# 5874 99020d0452f654d001100096b30513d96c42e697fd06674b1...

Et c'est cet enregistrement à la syntaxe générique qu'on met dans le fichier de zone. Sinon, si on aime bien faire l'encodage soi-même, utilisons xxd :

% openpgpkey --create stephane@bortzmeyer.org > key.zone
[Edit to keep the zone data]

% base64 -d key.zone > key.bin
[wc -c key.bin to know what number to put in the zone file]

% xxd -p key.bin > key.hex

Et on met le contenu de key.hex dans le fichier de zone. Sinon, l'annexe A du RFC fournit une variante de cette solution, utilisant hexdump.

Voici la récupération de cette clé dans le DNS, avec un dig récent, qui connait ce type OPENPGPKEY et sait formater le résultat :

% dig OPENPGPKEY   28182f0a278161989f90f090dabd6cab331663d8509ddbae617bb1e7._openpgpkey.bortzmeyer.org  
;; Truncated, retrying in TCP mode.
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 36368
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 9, ADDITIONAL: 13
...
;; ANSWER SECTION:
28182f0a278161989f90f090dabd6cab331663d8509ddbae617bb1e7._openpgpkey.bortzmeyer.org. 85841 IN OPENPGPKEY ( mQINBFL2VNABEACWswUT2WxC5pf9BmdLHzPeXzHZfvik
				ExJHaQ7LHPRVjAQtBiBN0vI3Uh0VgFzjA+0H2sqTduJY
				tqd8mrTh9clDnCbrMU8svc7MeWxkW21ogjqBYL8puA3d
                                ...         

Notez le « Truncated, retrying in TCP mode ». L'enregistrement est trop gros pour les paquets UDP qu'accepte dig par défaut (il fait huit kilo-octets, dig accepte quatre par défaut). Notez aussi le bit AD (Authentic Data) dans la réponse : celle-ci a bien été validée par DNSSEC.

Avec un dig ancien, qui ne connait pas ce nouveau type (et, cette fois, on demande directement en TCP, comme le recommande le RFC) :

% dig +tcp -t TYPE61 28182f0a278161989f90f090dabd6cab331663d8509ddbae617bb1e7._openpgpkey.bortzmeyer.org 
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 19989
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 9, ADDITIONAL: 29
...
;; ANSWER SECTION:
28182f0a278161989f90f090dabd6cab331663d8509ddbae617bb1e7._openpgpkey.bortzmeyer.org. 86206 IN TYPE61 \# 5874 ( 99020D0452F654D001100096B30513D96C42E697FD06
				674B1F33DE5F31D97EF8A4131247690ECB1CF4558C04
				2D06204DD2F237521D15805CE303ED07DACA9376E258
				B6A77C9AB4E1F5C9439C26EB314F2CBDCECC796C645B
                                ...

Sur ce sujet, vous pouvez aussi lire l'article de Johannes Weber, qui détaille une utilisation de l'outil de Shumon Huque.


Téléchargez le RFC 7929


L'article seul

RFC 7927: Information-Centric Networking (ICN) Research Challenges

Date de publication du RFC : Juillet 2016
Auteur(s) du RFC : D. Kutscher (NEC), S. Eum (NICT), K. Pentikousis (EICT), I. Psaras (UCL), D. Corujo (Universidade de Aveiro), D. Saucez (INRIA), T. Schmidt (HAW HAmburg), M. Waehlisch (FU Berlin)
Pour information
Réalisé dans le cadre du groupe de recherche IRTF icnrg
Première rédaction de cet article le 25 août 2016


Quels sont les défis qui attendent l'ICN (Information-Centric Networking), ce paradigme où le composant de base du réseau n'est pas la machine ou l'interface réseau mais l'unité d'information ? Le concept est à la mode depuis pas mal d'années mais ne progresse guère sur plusieurs points importants. Ce RFC de synthèse fait le point sur ce qui ne marche pas ou pas parfaitement dans l'ICN, et les axes de recherche souhaitables.

L'idée de base de l'ICN (également nommé CCN pour Content-Centric Networking) est de considérer que le réseau sert surtout à accéder à du contenu (un point de vue Minitel 2.0 très contestable) et qu'il faut donc architecturer le réseau autour de cet accès au contenu. Une unité d'information a un nom et le réseau permet avant tout d'accéder à cette unité d'information, en échange de ce nom (get(NOM)...) L'unité d'information est parfois nommée NDO pour Named Data Object. On voit que la localisation de l'information (que ce soit dans l'espace physique, ou dans celui défini par la topologie du réseau Internet) n'est pas prise en compte. Cette approche permettrait, en théorie, une meilleure efficacité (la mise en cache par les composants du réseau améliorerait les performances), un meilleur passage à l'échelle (la réplication de données populaires serait simple), et une meilleure résilience (le contenu serait à plusieurs endroits). Cette idée est décrite plus longuement dans le RFC 7476 (lecture recommandée, avant ce RFC 7927), et j'en ai déjà écrit une critique.

Pour la mettre en œuvre, on peut envisager une couche supplémentaire « accès au contenu » au-dessus de l'Internet actuel, ou bien une approche « table rase » où on remplace IP par un protocole orienté ICN. Notez qu'il existe déjà des mécanismes pour accéder à du contenu par son nom, en ne se souciant pas de la localisation, mécanismes qui fournissent la rapidité, le passage à l'échelle et la robustesse dont on parlait plus haut. Le plus évident est bien sûr BitTorrent mais on notera que les promoteurs de l'ICN n'en parlent quasiment jamais...

D'abord, une synthèse des problèmes avec l'approche actuelle, vus du point de vue des partisans de l'ICN (section 2 du RFC). Cette approche, qualifiée de host-centric, met au centre du réseau la machine. Identifiée par des noms de domaine et/ou des adresses IP, c'est l'unité de base du réseau. On peut bien sûr bâtir une couche ICN (ou para-ICN) au-dessus de cette approche (un CDN est un exemple partiel) mais, comme le réseau n'est pas au courant, cela entraine des limitations :

  • La circulation du trafic n'est pas optimale, puisque l'infrastructure du réseau (le routage, par exemple) ne peut pas optimiser pour le trafic des unités d'information,
  • Les capacités du réseau, par exemple en diffusion, ne sont pas ou peu utilisées,
  • Il n'est pas évident pour le réseau de savoir ce qu'il peut garder dans un cache local (le Web doit recourir à des CDN explicitement configurés),
  • La validation des données (la vérification de leur authenticité et de leur intégrité) n'est pas assurée par le réseau et doit utiliser d'autres mécanismes.

Pour ce dernier point, celui de la validation, je suis personnellement toujours stupéfait que le Web n'ait toujours pas un mécanisme standard pour authentifier une page qu'on a récupéré. À l'heure actuelle, il faut toujours se contenter de mécanismes ad hoc, comme une signature PGP détachée du fichier qu'on veut valider. (Non, HTTPS n'est pas une solution, d'abord parce qu'il ne fonctionne qu'en transfert, pas après, donc on ne peut pas valider quelque chose qui stationne dans un cache, et ensuite parce qu'il est incompatible avec des miroirs, sauf à distribuer une clé privée à plein d'autres acteurs.)

Avant d'aller plus loin, la section 3 du RFC nous apporte une petite révision des termes et concepts essentiels en ICN. Pour les termes, il faut se souvenir de :

  • NDO (Named Data Object) : une unité de données ayant un nom,
  • Demandeur (requestor) : l'entité qui demande un NDO, en indiquant son nom,
  • Éditeur (publisher) : l'éditeur qui publie un NDO, le met en ligne. L'éditeur n'est pas forcément le créateur du NDO.

Une fois armé de cette terminologie, on peut expliquer le concept central de l'ICN : un réseau dont l'objet de base est le NDO (pas le paquet, pas la machine), et dont le service de base est d'envoyer des NDO aux demandeurs.

Ceux qui ont assisté à mon exposé à Pas Sage En Seine 2016 ont pu voir un exemple d'ICN mis en œuvre sur la chaîne de blocs (exemple FindByHash).

Sur le papier, c'est très joli, mais voyons maintenant les défis que cela pose (section 4 du RFC, le gros morceau de ce texte). D'abord, le nommage et l'authentification (les deux sont en général liés dans l'ICN). Nommer un NDO est aussi crucial dans l'ICN que de donner une adresse IP à une machine dans l'Internet classique. Et comme l'objet nommé peut être récupéré à partir de divers endroits dans le réseau ICN, vérifier l'authenticité par le biais de l'origine marche encore moins que dans le Web actuel. Il y a des tas de solutions possibles, résumées dans des études comme « Naming in Content-Oriented Architectures » de Ghodsi, A., Koponen, T., Rajahalme, J., Sarolahti, P., et S. Shenker ou bien « A Survey of Information-Centric Networking » de Ahlgren, B., Dannewitz, C., Imbrenda, C., Kutscher, D., et B. Ohlman.

Il y a deux grandes façons d'organiser le nommage dans l'ICN : espace de nommage hiérarchique, ou bien espace de nommage plat. Par exemple, un nommage hiérarchique pourrait produire des noms comme pays/éditeur/date/NDO. Cette façon de nommer simplifie nettement le routage et le passage à l'échelle. La structure des noms permet de faire une structure identique pour la PKI qui servira à authentifier le contenu (ainsi, une AC pour un éditeur donné ne pourra pas signer des certificats d'un autre éditeur, contrairement à ce qu'on voit sur le Web aujourd'hui, où la structure arborescente des noms de domaine n'est pas utilisée pour limiter les dégâts que peut faire une AC.) Cette structure hiérarchique peut aussi permettre de faire des noms lisibles par des humains. (Par contre, le RFC oublie de noter que de tels noms suscitent d'innombrables disputes de gouvernance : tout le monde veut être à la racine, veut tel nom, etc.)

Autre solution, l'espace de nommage plat. Typiquement, le NDO est désigné par un condensat cryptographique de son contenu. Cela permet l'authentification de manière évidente : on récupère le contenu, on calcule le condensat, et on doit retrouver le nom. Et un tel système peut être complètement réparti, sans autorité jouant un rôle particulier. Par contre, l'absence de structure dans le nom nécessitera un système de résolution adapté (comme une DHT). Une telle solution est même déjà décrite dans un RFC, le RFC 6920.

Aucune des deux façons de gérer l'espace de nommage n'est parfaite (cf. le triangle de Zooko). Par exemple, les condensats cryptographique ne sont pas maniables par un humain, mais les noms hiérarchiques ne peuvent pas être alloués de manière complètement pair-à-pair.

Les sujets de recherche existants sur le nommage sont :

  • Le nommage d'objets qui n'existent pas encore (un flux vidéo filmé en temps réel, par exemple). On ne peut donc pas utiliser de condensat cryptographique. Mais peut-être un mécanisme à deux étapes, un structure de données non-cryptographique décrivant le contenu, qui serait elle-même condensée ?
  • La protection de la vie privée. Avec de l'ICN ordinaire, tout le monde voit à quel contenu vous accédez. Cela concerne même les équipements intermédiaires, puisque le but est justement que le réseau voit tout.
  • Nommer les nouvelles versions d'un objet. Un principe de base de l'ICN est que le nom désigne le contenu. On change une virgule à un texte, il faut un nouveau nom (c'est particulièrement évident pour les noms fondés sur un condensat cryptographique). Comment gérer la notion de « nouvelle version, légèrement modifiée » ? Une possibilité serait d'avoir des noms incluant un numéro de version, ce qui nécessiterait un mécanisme de résolution adapté (pour des opérations comme « je veux la dernière version »).
  • Restreindre l'accès dans certains cas. Le paradigme de l'ICN est que tout le monde a accès, ce qui permet aux éléments du réseau eux-même d'avoir accès à tout et, par exemple, de le mettre en cache. Si on veut des NDO à accès restreint, comment faire ? Les solutions de sécurité du monde réel, comme le chiffrement de bout en bout sont incompatibles avec le paradigme de l'ICN.

En parlant de restriction d'accès, la sécurité, dans son ensemble est un difficile problème pour l'ICN (section 4.2). C'est le cas de la plupart des solutions miracles qui sont proposées pour l'Internet : une idée simple qui semble bien marcher, puis, dès qu'on creuse les détails pratiques, les ennuis surgissent puis, dès qu'on arrive à la sécurité, l'idée simple s'effondre. Dans le cas de l'ICN, le RFC suggère plusieurs pistes de travail. D'abord, l'authentification des données, sans doute la partie la plus facile à réaliser (et celles, on l'a vu, où le Web actuel est défaillant). Comme on peut récupérer un NDO depuis n'importe où, pas forcément depuis le serveur d'origine, il est crucial de l'authentifier. Évidemment, si le nom de l'objet est un condensat de son contenu, comme c'est le cas avec le RFC 6920, la vérification de l'intégrité est facile : on récupère l'objet, on condense et on regarde si on tombe bien sur la même valeur. Pour des objets générés dynamiquement, cette solution ne fonctionne pas et il faut donc signer l'objet avec de la cryptographie asymétrique. D'ailleurs, cette cryptographie est nécessaire dans tous les cas : vérifier le nom-qui-est-un-condensat prouve l'intégrité de l'objet, pas que l'objet vient bien de l'auteur attendu. Ici, une signature cryptographique est donc également nécessaire. Comme toujours avec la cryptographie à clés publiques, cela laisse ouvert l'énorme problème de la distribution des clés... (cf. RFC 5280 pour une approche possible).

Pour l'utilisateur normal, vérifier que l'objet 148aec5042e7c05df755d9ce8adec80a1e9c10b1557194fd94e45146416a0de8 a bien un contenu qui correspond à ce condensat n'a qu'un intérêt limité. M. Michu voudrait une authentification plus forte, vérifier qu'il s'agit bien du guide de sécurité Java de l'ANSSI ou que c'est bien la série télé qu'il cherchait. Et, là, le problème est difficile. Les défenseurs du pair-à-pair prétendent par exemple souvent que BitTorrent est pair-à-pair, qu'il fonctionne sans centre mais, pour la très grande majorité des usages, c'est faux. M. Michu utilise un moteur de recherche centralisé, comme The Pirate Bay ou comme isoHunt. Il récupère alors un magnet (qui contient un condensat du fichier convoité), et, ensuite, on est vraiment en pair-à-pair : on télécharge, on vérifie le condensat et on s'installe dans son fauteuil pour regarder. Mais l'étape du moteur de recherche, avec ses pubs mensongères, était tout, sauf pair-à-pair.

En ICN, comment lier un NDO à une identité du monde extérieur, par exemple un acteur connu et de confiance ? C'est un problème essentiel mais non encore résolu.

Le contrôle d'accès, on l'a vu, est également un problème difficile. Comment faire si je veux vendre du contenu sans permettre aux destinataires de le redistribuer ? Il n'y a pas de solution évidente. Les approches intégrées sont celles où l'entité qui publie utilise des mesures pour limiter la redistribution (typiquement des menottes numériques), les approches séparées comptent sur une tierce-partie qui gère les accès (je vous laisse imaginer les conséquences en terme de liberté de choix de son logiciel par M. Michu...) On peut bien sûr chiffrer le contenu qu'on va distribuer (ah, Canal+...) mais il reste à distribuer les clés ensuite.

La cryptographie n'est pas éternelle, les algorithmes de cryptographie finissant par être affaiblis, puis cassés. Ce n'est pas un problème si on publie du contenu à courte durée de vie mais, si le contenu est encore utile et payant dans dix ans, l'efficacité de la cryptographie devient incertaine : comment garantir que l'algorithme utilisé sera toujours incassé ? L'idéal serait un mécanisme de re-signature et de re-chiffrement mais cela pose encore le problème de la gestion des clés privées.

Autre conséquence de la mise en cache et de la distribution à partir de plusieurs endroits, l'auteur d'un contenu n'aura plus de statistiques d'accès fiables. De la même façon, retirer un contenu publié sera encore plus difficile que sur le Web actuel (un contenu populaire est davantage répliqué et donc plus dur à supprimer).

Autre problème de sécurité avec l'ICN, le risque d'attaque par déni de service via le cache. Un des buts de l'ICN est de permettre, et même d'encourager, la mise en cache automatique du contenu par les éléments du réseau, comme les routeurs. Cela ouvre une possibilité d'attaque où le méchant téléchargerait plein de choses sans intérêt juste pour remplir les caches. Pire : comme l'ICN renonce explicitement au principe de bout en bout, ces éléments intermédiaires mantiennent un état et peuvent également être attaqués par ce biais. Par exemple, en annonçant plein de contenus divers, on pourrait remplir la table de routage.

Après la sécurité, le routage dans l'ICN pose également des défis intéressants. Le terme n'a pas tout à fait le même sens dans l'ICN que dans l'Internet actuel. L'ICN permet d'obtenir un contenu (le NDO, Named Data Object) en échange d'un nom. Cela nécessite trois étapes : la première est de résoudre le nom en un localisateur, plus concret. La deuxième est d'envoyer la demande de contenu à cet endroit. La troisième est d'obtenir la réponse (le NDO). Ces trois étapes peuvent être faites de différentes manières, catégorisées comme routage par nom (route-by-name), recherche par nom (lookup-by-name) et hybride.

Le routage par nom consiste à ne pas avoir la première étape, celle de résolution, ce qui simplifie le modèle : le réseau comprend directement les noms. Il faut donc une « table de routage » dont la taille permette de stocker tous les NDO. Comme on envisage entre 10^15 et 10^22 NDO, le défi technique est colossal. Sans compter qu'il faut aussi identifier la source de la requête, puisqu'il faudra bien lui envoyer le contenu demandé (c'est ce que fait l'algorithme des miettes de pain, cf. Rosensweig, E. et J. Kurose, « Breadcrumbs: Efficient, Best-Effort Content Location in Cache Networks »). Les sujets de recherche sur le routage par nom comportent donc, entre autres :

  • Les mécanismes d'agrégation permettant de réduire le nombre d'entrée dans la table de routage,
  • Si on utilise des noms hiérarchiques (par exemple /IETF/IRTF/ICN/Research challenges pour ce RFC) afin de permettre l'agrégation, comment permettre aux utilisateurs d'utiliser des noms plus simples ? (Se servir d'un moteur de recherche serait de la triche, puisqu'on voulait se dispenser de l'étape de résolution.)

La catégorie « recherche par nom » regroupe les mécanismes de routage qui, eux, ont une étape de résolution explicite. On résout le nom (qui est pratique pour un humain, et stable) en un localisateur (qui est pratique pour le réseau et qui pourrait être une simple adresse IP). C'est par exemple ainsi que fonctionne le système « MDHT: A hierarchical name resolution service for information-centric networks ». Les défis techniques à relever sont l'accès rapide au localisateur (en se rappelant que le contenu peut être à plusieurs endroits) et la mise à jour efficace (car le contenu peut changer de localisation, c'est même un des buts de l'ICN). Notez que les gens de l'ICN aiment bien réinventer la roue et que le DNS n'est même pas mentionné.

Enfin, il y a les solutions de la catégorie hybride. Par exemple, on fait du routage par le nom en local mais on résout le nom en un localisateur dès qu'on sort de ce domaine local.

Vous aimez les défis techniques et la liste n'est pas encore assez longue pour vous ? Il reste plusieurs problèmes à affronter. Par exemple, le contrôle de congestion. Il n'a pas à être de bout en bout puisque, dans l'ICN, la communication peut se faire via des éléments intermédiaires (voir par exemple « ConTug: A Receiver-Driven Transport Protocol for Content-Centric Networks »).

On a vu qu'un des intérêts principaux de l'ICN était de permettre la mise en cache automatique par des éléments du réseau, et l'accès au contenu à partir de ces caches. La bonne utilisation de ceux-ci soulève plusieurs questions :

  • Placer ces caches sur le chemin des données (on-path caching), ou bien à côté, avec une redirection, comme avec les CDN actuels (off-path caching) ? Le cache sur le chemin est plus conforme aux principes d'architecture de l'ICN, mais il suppose des équipements capables de suivre tout le trafic, donc très rapides. Et ces équipements seront-ils rentabilisés ? Bien des contenus sont peu accédés et le cache ne servira donc pas autant qu'on ne pouvait l'espérer.
  • Combien d'équipements capable de gérer un cache faut-il placer ?
  • Comment gérer l'obsolescence ? Un contenu populaire va se trouver stocké dans de nombreux caches distribués un peu partout. Lorsque le contenu est modifié, ces caches auront une information obsolète. Il y a plusieurs approches pour ce problème. On les classe en général en approches directes, où l'information est stockée dans le NDO lui-même (par exemple une date d'expiration, après laquelle il faudra virer le contenu du cache), et approches indirectes, où on re-valide la fraicheur du contenu auprès du serveur original (ce qui suppose que son identité soit marquée dans le NDO). Les approches indirectes permettent de gérer le cas où la date d'expiration n'est pas connue à l'avance. Notez qu'un système où le nom change avec le contenu (comme les ni: du RFC 6920) ne résout pas le problème : il faut maintenant un mécanisme pour informer les clients du nouveau nom.

Les administrateurs réseau sont habitués à des outils comme ping et traceroute pour tester et déboguer leur réseau. Comment feront-ils avec l'ICN ? C'est un autre défi. Étant donné que ping et traceroute ne sont apparus que de nombreuses années après IP, on peut prévoir que, pendant un certain temps, les administrateurs des réseaux ICN souffriront du manque d'outils adaptés.

Quelles applications utiliseront l'ICN, si tous ces défis sont relevés, et avec succès ? Le RFC se termine par une liste d'applications potentielles (cf. RFC 7476) :

  • Le Web semble un candidat évident, le paradigme « tout n'est qu'accès à du contenu » collant à peu près à une partie des usages du Web (en gros, les utilisations de la méthode HTTP GET). Les noms des NDO remmplaceront-ils les URI ? Il n'est pas évident que tous les usages du Web (POST, PUT, et autres méthodes utilisées par les applications REST) s'adaptent aussi bien à l'ICN.
  • La vidéo est typiquement un domaine où la pure consommation (on se contente d'accéder à du contenu) est très répandue. Elle semble donc un autre bon candidat pour l'ICN. Un autre document du groupe de recherche ICN de l'IRTF, le RFC 7933, étudie plus en détail cette application.
  • Et l'Internet des Objets ? L'article de Baccelli, E., Mehlis, C., Hahm, O., Schmidt, T., et M. Waehlisch, « Information Centric Networking in the IoT: Experiments with NDN in the Wild » étudie ses liens avec l'ICN. Par exemple, bien des applications IoT reposent sur un modèle PUSH, où l'objet envoie des données à son rythme, pas en réponse à une requête. Un tel modèle ne s'adapte pas bien à l'ICN.

Une conclusion personnelle ? Il y a plein d'idées intéressantes dans l'ICN, et c'est donc un sujet de recherche utile, malgré la prémisse de départ (« tout est accès au contenu ») qui est fausse.


Téléchargez le RFC 7927


L'article seul

RFC 7934: Host address availability recommendations

Date de publication du RFC : Juillet 2016
Auteur(s) du RFC : L. Colitti (Google), V. Cerf (Google), S. Cheshire (Apple), D. Schinazi (Apple)
Réalisé dans le cadre du groupe de travail IETF v6ops
Première rédaction de cet article le 24 juillet 2016


Combien d'adresses IPv6 faut-il permettre à une machine qui se connecte ? « Une » est évidemment le minimum mais est-ce suffisant ? Non, explique ce RFC qui recommande aux opérateurs et FAI de permettre aux machines de s'allouer autant d'adresses IPv6 qu'elles en ont besoin.

IPv6 est juste une nouvelle version d'IP. Ce n'est pas un nouveau protocole. Néanmoins, la taille bien plus importante de son espace d'adressage a des conséquences qui sont souvent oubliées par les administrateurs de réseaux. Ainsi, il est fréquent que la gestion des réseaux soit faite en limitant chaque machine à une seule adresse IPv6. En IPv4, il n'y a évidemment pas d'autre choix possible, en raison de la pénurie d'adresses publiques. Mais en IPv6, il n'y a aucune raison de se limiter, et beaucoup de raisons de permettre davantage d'adresses. Bref, bien qu'IPv6 ne soit pas complètement nouveau, cela ne veut pas dire que les bonnes pratiques IPv4 s'appliquent directement à IPv6.

Il est banal de faire remarquer que les adresses IPv6 sont, en pratique, illimitées. Un simple lien réseau (numéroté avec un préfixe de 64 bits) offre quatre milliards de fois plus d'adresses que tout l'Internet IPv4 ! Il n'est donc pas du tout obligatoire de rationner. IPv6 est conçu depuis le début (section 2 de notre RFC) avec l'idée que chaque machine (et même chaque interface réseau de chaque machine) aura plusieurs adresses IP (par exemple, une adresse locale au lien, une adresse publique stable, et au moins une adresse temporaire du RFC 8981). Et toutes les mises en œuvre d'IPv6 existantes gèrent cela correctement.

Mais quel est l'intérêt de permettre plusieurs adresses ? La section 3 de ce RFC répond à la question :

Et quels sont les problèmes si on ne fait pas ce que recommande ce RFC ? La section 4 les liste. Évidemment, si ajouter des adresses IP est complètement impossible, on est fichus. Et si la connexion au réseau permet d'ajouter des adresses IPv6 mais que cela nécessite une action explicite (par exemple via l'interface Web de l'hébergeur) ? Cela entraine :

  • Délai supplémentaire avant de déployer un nouveau service sur la machine,
  • Risque qu'un problème survienne au cours de l'opération (tiens, c'était juste le jour où l'interface Web a un problème),
  • Complexité car il faut gérer une action en plus (pour laquelle il n'y a pas de mécanisme normalisé.)

Pourquoi les opérateurs restreindraient-ils ainsi l'obtention d'adresses IPv6 supplémentaires ? Par pur sadisme ? Non, il peut y avoir des raisons objectives :

  • Limites du matériel (TCAM limité en taille),
  • Souhait de garder une cohérence avec le style IPv4 (une adresse IP par machine, qui peut servir d'identificateur simple),
  • Volonté de faire payer par tous les moyens possibles, y compris par adresse IPv6 supplémentaire.

Avec le temps, il faut espérer que les limites matérielles reculent et que la raison business (faire payer) soit rejetée par les utilisateurs (ils peuvent la contourner, par exemple en faisant du NAT, ce qui serait un comble pour IPv6).

À propos de NAT, est-ce que c'est une bonne stratégie pour résoudre le problème d'un opérateur qui ne laisserait pas assez d'adresses IPv6 à ses clients (section 5 du RFC) ? Les problèmes et limites du NAT sont bien connus (RFC 2993). Les applications sont plus complexes (car leurs programmeurs doivent déployer des trésors d'ingéniosité pour contourner le NAT), la gestion de la durée de vie des correspondances entre adresses dans le routeur NAT est pénible (quel intervalle entre les paquets d'entretien de la connexion ?), etc. C'est pour cela que le NAT sur IPv6 est très déconseillé (RFC 5902).

Ce n'est pas faute de mises en œuvre (le NAT66 est dans Linux depuis 2012...), un vendeur de virtualisation l'a aussi développé, précisement pour contourner ce manque d'adresses IPv6 allouées, mais il n'est pas souhaitable que cela continue. Le but d'IPv6 est d'avoir une vraie connectivité de bout en bout, qui ne soit limitée que par des choix délibérés (Alice ne veut plus parler à Bob), pas par des limites techniques inutiles.

Et si l'opérateur du réseau où se connecte la machine a été convaincu par ce RFC, et veut permettre à ses clients d'allouer les multiples adresses IPv6 dont ils ont besoin, quels sont les mécanismes techniques dont il dispose pour cela ? La section 6 les couvre :

  • Naturellement, le moyen le plus simple est d'utiliser SLAAC (RFC 4862) : les routeurs annoncent les préfixes IP publics et chaque machine forme des adresses à volonté en utilisant ces préfixes. Comme SLAAC impose de détecter les éventuelles collisions, avant d'utiliser une adresse (RFC 4862, section 5.4), le risque que deux machines se retrouvent avec la même adresse est nul. C'est évidemment encore mieux si chaque machine a son propre préfixe /64, elle n'a même plus à tester les collisions.
  • On peut utiliser DHCP (RFC 8415). Le protocole permet de continuer à réclamer des adresses.
  • Et il y a aussi la délégation de préfixes IPv6 via DHCP (RFC 8415). Cela permet d'envoyer un /64 à chaque client, dont il fera ce qu'il voudra.

Un tableau à la fin de la section 6 résume les forces et faiblesses de chaque solution.

Au fait, combien d'adresses exactement peut-on s'attendre à voir sur une seule machine ? La section 7 se lance dans la spéculation. Les adresses « vie privée » du RFC 8981 peuvent consommer jusqu'à huit adresses en même temps. Avec une demi-douzaine de services réseau, et une demi-douzaine de machines virtuelles (ou de containers) hébergés, avoir vingt adresses sur une seule machine peut donc être raisonnable. Mais, bien sûr, il est difficile de prévoir les usages futurs et, en pratique, ce sera peut-être bien plus.

Allez, c'est presque fini, la section 8 du RFC synthétise les recommendations officielles :

  • Il est recommandé que les hébergeurs et FAI qui déploient IPv6 permettent aux client d'avoir plusieurs adresses IP par machine.
  • Il est également recommandé qu'il n'y ait pas de limite stricte au nombre d'adresses utilisables.
  • Il est recommandé que cette allocation d'adresses supplémentaires puisse se faire sans requête explicite à l'hébergeur ou FAI.

Ces recommandations, si elles sont suivies, auront quelques conséquences pratiques (section 9). Par exemple, elles ne permettent pas de garder trace de quelles adresses sont utilisées par quelle machine. (Alors qu'avec une demande d'allocation explicite, par exemple par le biais d'une nouvelle interface virtuelle, comme c'est le cas actuellement chez Gandi, ce suivi est possible.) C'est ennuyeux si on veut remonter d'une adresse IP qui pose un problème (par exemple parce qu'il a téléchargé Les tortues Ninja) à son propriétaire. Une solution de remplacement est de superviser le réseau et de relever les réponses NDP, permettant ainsi de se constituer une base de la relation entre les adresses IP et les adresses MAC. Le logiciel NDPMon permet de faire cela. (On peut aussi interroger les commutateurs en SNMP, pour avoir un résultat analogue.) Les auteurs du RFC notent que tous leurs employeurs ont déjà un tel système en place, et ils citent plusieurs gros campus universitaires qui font de même, ce qui montre le caractère réaliste de la proposition.

Puisqu'on parle de sécurité, il faut noter que de ne pas permettre officiellement aux machines de s'attribuer des adresses IP supplémentaires ne signifiera pas qu'elles ne le feront pas. Si on n'a pas de sécurité dans la couche 2 (cf. RFC 7039), les machines peuvent toujours se configurer ce qu'elles veulent. En outre, si le mode d'allocation est DHCP, les efforts actuels pour améliorer la vie privée des utilisateurs de DHCP (RFC 7844) vont de toute façon diminuer l'intérêt de DHCP pour la sécurité.

Autre problème pratique pour les administrateurs réseau, les limites du matériel. Si un commutateur connecte mille machines, sa table de correspondance adresses IP <-> adresses MAC aura mille entrées. Si chaque machine s'alloue dix adresses, cette table devra stocker dix mille entrées. Le commutateur a-t-il cette capacité ? S'il ne l'a pas, on risque des pertes de connectivité. Certes, le matériel va évoluer. Mais il existe une autre solution, suggérée par notre RFC : utiliser un préfixe IP par machine. Ainsi, le commutateur n'aura à gérer qu'une seule entrée par machine, quel que soit son nombre d'adresses. Évidemment, cela consommera davantage d'adresses IPv6, et cela compliquera un peu la gestion des adresses. Cette proposition est donc légèrement plus sujette à controverse que la principale (permettre plusieurs adresses par machine) qui, elle, est largement reconnue comme justifiée.


Téléchargez le RFC 7934


L'article seul

RFC 7942: Improving Awareness of Running Code: The Implementation Status Section

Date de publication du RFC : Juillet 2016
Auteur(s) du RFC : Y. Sheffer (Intuit), A. Farrel (Juniper)
Première rédaction de cet article le 23 juillet 2016


L'IETF se vante souvent de ne pas croire au blabla des marketeux, mais uniquement au code qui tourne. Comme le dit fièrement sa devise, « We believe in rough consensus and running code ». Mais, en pratique, les normes produites et publiées en RFC ne contiennent pas toujours la mention d'une mise en œuvre effective de cette norme. Parfois, c'est parce qu'il n'y en a pas (contrairement à une légende tenace, ce n'est nullement une obligation pour la publication d'un RFC). Parfois, c'est parce qu'elle n'est pas mentionnée. Avant la publication d'un RFC, lorsque le document est encore un simple Internet-Draft, la mention de l'existence de programmes mettant en œuvre le protocole ou le format décrit est facultative. Ce RFC propose de formaliser et d'encourager cette mention. Son prédecesseur, le RFC 6982 avait lancé l'idée, comme une expérimentation. Elle a été un grand succès et ce nouveau RFC passe donc au stade supérieur : publier l'état des implémentations d'un draft est désormais une Bonne Pratique (BCP, « Best Common Practice »).

Cela ne concerne que les Internet-Drafts, pas les RFC. En effet, les RFC sont stables (jamais modifiés) alors que les URL pointant vers un programme ne le sont pas : un programme peut être abandonné, plus maintenu, on peut se retrouver avec des 404, etc. Donc, un RFC n'est pas le bon endroit pour stocker un catalogue de mises en œuvre d'un protocole. Ce RFC 7942 ne vise que les Internet-Drafts, afin d'aider à l'évaluation d'une proposition. La section décrivant les mises en œuvre est donc typiquement supprimée lors de la publication du RFC. Comparez par exemple le draft-ietf-dnsop-qname-minimisation (dont la section 8 décrit les mises en œuvre existantes) avec le RFC 7816 (qui n'a plus cette section).

Le concept de running code est décrit dans le Tao (cf. RFC 4677 et RFC 6722). Il synthétise l'approche pragmatique de l'IETF : une norme qui n'est pas mise en œuvre ne sert à rien. Malgré cela, bien des RFC n'ont jamais connu la moindre mise en œuvre. En effet, ce principe général du running code n'a jamais été traduit dans une exigence formalisée et globale pour les auteurs de RFC. Il existe par contre des règles locales. Ainsi, la Routing Area de l'IETF (les groupes de travail qui normalisent les protocoles de routage) a longtemps demandé (RFC 1264) au moins une mise en œuvre avant la publication d'un RFC sur le chemin des normes. Le RFC 4794 a supprimé cette règle, qui reste appliquée par certains groupes de la Routing Area comme IDR. À noter qu'avant le RFC 6982, il y avait déjà des compte-rendus de mise en œuvre (implementation reports) qui étaient des documents séparés, racontant des expériences concrètes de développement.

Notre RFC 7942 n'impose pas une règle (la section Implementation Status reste facultative), mais il encourage fortement à formaliser une section dans les Internet-Drafts, qui permettra de documenter les mises en œuvre connues. L'idée est que les Internet-Drafts ayant cette section seront examinés avec plus de bienveillance, sans toutefois qu'elle soit obligatoire.

La section 4 du RFC fait la liste de tous les avantages qu'il y a à indiquer ces mises en œuvre dans l'Internet-Draft : meilleure information pour la prise de décision (aussi bien sur la publication de l'Internet-Draft que sur le statut du futur RFC), encouragement aux tests d'interopérabilité, possibilité (lorsque le code est publié) de mieux comprendre le protocole (beaucoup de programmeurs préfèrent lire le source plutôt que le RFC mais attention, la référence doit rester le RFC, le code n'est pas une spécification), et enfin assurance que telle fonction du RFC peut effectivement être mise en œuvre. C'est en effet souvent le cas (par exemple lors de la discussion qui a mené au RFC 5155) que certaines personnes affirment que la technologie envisagée est tout simplement trop complexe pour être programmée. L'existence d'un programme qu'on peut tester permet de d'assurer que, si, la technologie est réaliste (bien d'autres SDO produisent sans hésiter des technologies impossible à programmer dans des conditions raisonnables).

Cette section, « Implementation status » est décrite en section 2 de ce RFC. Elle est située vers la fin (comme l'actuelle - et obligatoire, elle - « Security considerations ») et peut comporter les points suivants :

  • Une description du programme,
  • L'organisation qui a développé le programme,
  • Un URL pour le téléchargement du programme, et les conditions de la licence (comme tous les points situés ici, il est facultatif : toutes ces mises en œuvre d'une norme IETF ne seront pas forcément en logiciel libre, ni même publiquement accessibles),
  • Le niveau de maturité du programme (une preuve que ça marche, vite faite en un week-end pour tester l'Internet-Draft, n'est pas la même chose qu'une version 1.0 testée et polie),
  • Le taux de couverture de la spécification par le programme (des mises en œuvre expérimentales peuvent sauter les parties les plus difficiles de la spécification...).

Cette section peut aussi indiquer l'expérience tirée de cette mise en œuvre, ainsi que des informations sur l'interopérabilité, au cas où plusieurs mises en œuvre existent. Les présidents des groupes de travail sont explicitement chargés de vérifier que cette section ne dégénère pas en simple marketing pour le produit d'un vendeur. Notre RFC propose aussi un texte standard d'avertissement (« boilerplate ») à inclure au début de cette section « Implementation status ».

D'autres endroits que l'Internet-Draft lui-même auraient pu être utilisés pour informer sur les mises en œuvre existantes. Le RFC suggère (section 3) de passer au wiki de l'IETF lorsque la liste des programmes devient trop longue, lorsqu'il semble préférable que cette liste soit maintenue par les implémenteurs plutôt que par les auteurs de l'Internet-Draft, lorsque le groupe de travail maintient activement un wiki, ou enfin lorsque la liste en question semble utile, même après la publication en RFC (pour indiquer le niveau d'adoption par les programmeurs). Dans tous ces cas, il est bon d'indiquer l'URL du wiki en question dans l'Internet-Draft.

De très nombreux Internet-Drafts incluent désormais une telle section Implementation Status, « bien trop pour qu'on puisse les compter », note l'IESG dans son approbation de ce document. Quelques exemples d'Internet-Drafts qui incluent actuellement cette section : draft-ietf-dnsop-nxdomain-cut ou draft-ietf-dane-openpgpkey.

Le principal changement par rapport au RFC précédent, le RFC 6982 est un changement de statut. On passe de « expérimental » à « Bonne Pratique », reflétant le succès de cette expérience. Autrement, il n'y a que des changements de rédaction, rien de crucial.


Téléchargez le RFC 7942


L'article seul

RFC 7915: IP/ICMP Translation Algorithm

Date de publication du RFC : Juin 2016
Auteur(s) du RFC : C. Bao, X. Li (CERNET Center/Tsinghua University), F. Baker (Cisco Systems), T. Anderson (Redpill Linpro), F. Gont (Huawei Technologies)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF v6ops
Première rédaction de cet article le 22 juillet 2016


Parmi les nombreuses techniques de coexistence d'IPv4 et IPv6, l'ex-groupe de travail Behave développait un mécanisme de traduction permettant à une machine IPv6 de communiquer avec une machine v4 et réciproquement. Une des pièces de ce mécanisme (désormé transféré au groupe de travail v6ops) est l'algorithme de traduction, présenté dans ce RFC 7915. (Il remplace l'ancien RFC 6145, avec assez peu de changements.)

Ce nouveau mécanisme de traduction entre IPv4 et IPv6 s'inscrit dans le cadre décrit dans le RFC 6144. Il vise à remplacer « NAT-PT » (RFC 2765 et RFC 2766), officiellement retiré, après n'avoir eu aucun succès.

Plus spécifiquement, notre RFC 7915 est la version sans état du traducteur, c'est-à-dire que le traducteur peut traiter chaque paquet indépendamment des autres. Le traducteur n'a pas de table des flots en cours. S'il redémarre et perd toute mémoire, pas de problème, il peut immédiatement reprendre son travail. Cette technique permet notamment le passage à l'échelle : un traducteur d'adresses peut gérer un très grand nombre de clients sans épuiser sa mémoire. Et on peut mettre plusieurs traducteurs en parallèle, sans coordination entre eux : les paquets d'un même flot peuvent passer par des traducteurs différents. Mais cette technique a aussi quelques inconvénients comme le fait que les fragments ICMP ne seront pas traduits. Il existe donc également une version avec état du nouveau mécanisme, normalisée dans le RFC 6146. La section 1.3 discute plus en détail ces deux possibilités, avec ou sans état.

Donc, le NAT64 (son nom non officiel) vise à traduire des adresses IP entre deux réseaux, l'un v4 et l'autre v6. Comme notre RFC 7915 ne traite que le cas sans état, les adresses doivent être converties de manière purement algorithmique, sans référence à leur histoire (cf. RFC 6052, et la section 6 de ce RFC, pour ces algorithmes).

Dit comme ça, cela a l'air simple mais la traduction entre deux protocoles différents porte pas mal de pièges. Ainsi, les en-têtes de paquet n'ont pas la même taille en v4 (20 octets ou plus) et en v6 (40 octets, fixe), ce qui fait que des problèmes de MTU peuvent se poser (section 1.4). Le traducteur doit se comporter comme un routeur, donc fragmenter les paquets trop gros (en IPv4) ou retourner un message ICMP « Packet too big ».

La section 4 du RFC décrit en détail les opérations que doit faire le traducteur depuis IPv4 vers IPv6 (rappelez-vous que la traduction des adresses v4 en v6 est essentiellement dans le RFC 6052, section 2). Il y a des détails que ne connaissent pas les routeurs NAT44, qui se contentent de changer adresses et ports. En effet, ici, il faut traduire tout l'en-tête. Je ne vais pas résumer complètement cette section, juste pointer quelques pièges possibles. Ainsi, les en-têtes n'étant pas les mêmes en v4 et en v6, notre RFC doit spécifier quoi en faire. Certains cas sont évidents (comme le champ Longueur), d'autres moins. Ainsi, le champ TOS de IPv4 doit être copié verbatim dans le champ Traffic Class de IPv6. Mais le traducteur doit aussi offrir une option pour ignorer le TOS et mettre systématiquement zéro comme Traffic Class. Le champ TTL de IPv4 doit être copié dans Hop limit mais après avoir été décrémenté (rappelez-vous que le traducteur est un routeur).

La vraie difficulté n'est pas tellement dans la traduction d'IP que dans celle d'ICMP. En effet, le paquet ICMP contient le début du paquet IP qui a motivé son envoi, et ce début de paquet doit être traduit, également, sans quoi le destinataire du paquet ICMP n'y comprendra rien (par exemple, sans traduction ICMP, il recevrait en IPv6 un paquet ICMP dont le contenu est un paquet IPv4...). Notre RFC détaille donc les traductions à faire pour tous les modèles de paquets ICMP.

Le traducteur doit aussi veiller au champ Type d'ICMP, dont les valeurs sont différentes entre IPv4 et IPv6 (par exemple, Echo Reply est 0 en v4 et 129 en v6). Certains types n'ont pas d'équivalent (comme les types Timestamp ou Address Mask d'ICMPv4, absents d'ICMPv6) et le paquet ICMP doit donc être abandonné.

Enfin, le traducteur doit aussi prendre en charge les en-têtes de la couche 4 car la traduction des adresses peut ne pas être neutre pour la somme de contrôle (section 4.5) et il peut donc être nécessaire de recalculer cette dernière.

Et en sens inverse ? La section 5 décrit la traduction d'IPv6 vers IPv4. On retrouve TOS et Traffic Class, les problèmes de MTU et de fragmentation, et la traduction des messages ICMP.

La section 6 de notre RFC, une nouveauté depuis le RFC 6145, revient sur les algorithmes de correspondance entre les adresses IPv4 et IPv6. Les algorithmes obligatoires sont décrits dans le RFC 6052, mais un traducteur peut en ajouter d'autres.

Les problèmes de MTU et de fragmentation sont des cauchemars habituels sur l'Internet, notamment en raison d'équipements intermédiaires (typiquement des pare-feux) programmés avec les pieds par des anonymes, ou bien configurés n'importe comment, et qui bloquent les paquets ICMP, voire les modifient, en ignorant complètement le RFC 4890. Les traducteurs v4<->v6 auront donc ce problème, comme tant d'autres techniques utiles. La section 7 doit donc se pencher sur le traitement des paquets ICMP Packet too big qui signalent normalement que la MTU est plus réduite que ne le croit l'émetteur et qu'il faut fragmenter. Comme ces paquets sont parfois interceptés, voire modifiés, par des machines gérées par des incompétents, le traducteur doit donc parfois faire des efforts spécifiques. Si les paquets sont interceptés, la détection de la MTU du chemin n'est plus possible (RFC 2923) et il ne restera plus que la solution du RFC 4821 (faire faire le travail par les couches supérieures).

Rien n'étant parfait en ce bas monde, les traducteurs NAT64 vont aussi introduire de nouvelles questions de sécurité. La section 8 tente de prévoir lesquelles mais reste optimiste en considérant que la plupart des problèmes existent déjà dans IPv4 ou dans IPv6. Ainsi, comme avec le NAT traditionnel, l'authentification des paquets par IPsec (RFC 4302) ne marchera pas.

Pour les gens qui aiment bien les exposés concrets, avec des 0 et des 1, l'annexe A explique en grand détail le processus de traduction avec un réseau simple d'exemple, connectant le réseau traditionnel 198.51.100.0/24 et le réseau nouveau 2001:db8::/32, via un traducteur. Deux machines, H4 et H6, Alice et Bob du NAT64, vont tenter de communiquer. Le traducteur utilise le préfixe 2001:db8:100::/40 pour représenter les adresses IPv4 et 192.0.2.0/24 pour représenter les adresses IPv6. Ainsi, H6, qui a l'adresse 2001:db8:1c0:2:21:: est représenté en v4 par 192.0.2.33. H4 a l'adresse 198.51.100.2. behave-xlate-stateless Une fois le routage correctement configuré pour passer par le traducteur, suivez le RFC pour voir le trajet des paquets et les opérations qu'ils subissent, dans le cas où c'est H6 qui initie la connexion, et dans le cas inverse.

Au moins deux mises en œuvre existent déjà, faite par Ecdysis/Viagénie (avec état) et Tayga (sans état, mais nettement plus simple, d'après ses utilisateurs). Pour compenser l'absence de traduction avec état chez Tayga, on peut, sur Linux, le coupler avec SNAT/MASQUERADE (merci à Guillaume Leclanché pour sa suggestion).

Quels sont les changements entre ce mécanisme et celui du RFC 6145 ? Rien de dramatique. Ils sont résumés en section 2. Certains traitent les bogues détectées dans l'ancien RFC. D'autres changements tiennent compte du conseil actuel qui est de ne plus compter sur les « fragments atomiques » du RFC 6946 (ils ont même été franchement abandonnés avec le RFC 8021.)

Pour réfléchir à la grande question « avec état ou sans état », un article « pro-état » : « Stateless NAT64 is useless ».


Téléchargez le RFC 7915


L'article seul

RFC 7920: Problem Statement for the Interface to the Routing System

Date de publication du RFC : Juin 2016
Auteur(s) du RFC : A. Atlas (Juniper), T. Nadeau (Brocade), D. Ward (Cisco)
Pour information
Réalisé dans le cadre du groupe de travail IETF i2rs
Première rédaction de cet article le 21 juillet 2016


Autrefois, la configuration des routeurs était relativement statique. On indiquait la politique de routage (le coût de tel ou tel lien, par exemple), les préfixes IP, les pairs BGP, parfois des routes statiques, et le routeur parlait avec ses copains routeurs, construisant ses tables qu'il allait ensuite utiliser pour la transmission des paquets. La configuration n'était pas modifiée tous les jours et quand c'était nécessaire, on se connectait à tous les routeurs qu'il fallait changer et on modifiait la config. Dans les organisations plus modernes, on édite la config, on la commite dans un VCS et on la pushe vers les routeurs avec Ansible ou un truc équivalent. Aujourd'hui, même cela ne suffit pas, on voudrait être plus agile. On voudrait modifier la configuration des routeurs à peu près en temps réel, pour répondre à des considérations de business (créer un nouveau service pour un client, profiter de variations de prix chez les transitaires...) ou à des problèmes de sécurité (déployer des filtres subtils). Cette exigence nécessite une interface vers le routeur, utilisable par des programmes. C'est le projet I2RS, Interface To the Routing System. Ce premier RFC du groupe de travail décrit précisement le problème qu'on essaie de résoudre. (Notez que le buzzword SDN n'apparait pas une seule fois dans ce RFC...)

C'est que les réseaux modernes sont grands et complexes : il n'est plus possible de faire les choses à la main en se connectant sur chaque routeur isolément. Il faut donc automatiser, et il faut donc qu'un programme puisse se connecter aux routeurs et changer leurs configurations. Cela se fait bien sûr depuis longtemps (cf. Rancid et l'exposé de Joe Abley à NANOG et l'annexe A de notre RFC qui liste les solutions existantes), mais, en l'absence d'interface normalisée, c'était assez pénible à programmer et maintenir. Il s'agit donc de standardiser ce qui existe déjà, ce qui ne devrait pas être une tâche insurmontable.

La terminologie utilisée par I2RS est décrite dans un autre RFC, le RFC 7921. Pour le résumer (section 2 du RFC) : le routeur contient un agent I2RS, qui sait parler aux différents composants du routeur (sa base de données indiquant les différents liens connectés, son système de gestion de la configuration, sa base de routes - RIB, etc). Le logiciel qui pilote les changements est le client I2RS. Il y aura sans doute un seul client pour beaucoup d'agents, installé dans le système de gestion du réseau. Entre le client et l'agent, le protocole I2RS, qui sera normalisé dans les futurs RFC du groupe de travail I2RS. A priori, le client sera juste un intermédiaire pour des applications qui piloteront le routage (le but du découplage client/application étant d'éviter que chaque application doive parler I2RS : elles pourront interagir avec le client au-dessus d'un protocole plus classique comme REST).

Pour que le client puisse parler intelligemment à l'agent, il devra avoir en tête un modèle de données décrivant le routeur, ce qu'il sait faire, ce qu'on peut lui demander.

La section 3 de notre RFC présente la nécessité de ce modèle de données. Un tel modèle avait déjà été développé pour le projet ForCES (RFC 3746), en se focalisant sur la transmission, alors que I2RS est surtout intéressé par le routage (le plan de contrôle, accès à la RIB, etc).

Comme le note la section 4, un logiciel qui voudrait vraiment donner des instructions au routeur devrait apprendre la topologie du réseau, quels sont les liens physiques ou virtuels auxquels le routeur est connecté, leur état, etc. C'est évidemment le routeur qui connait le mieux cette information et il est donc nécessaire de lui demander.

L'application aura souvent besoin de connaitre en outre le trafic réellement échangé. IPFIX (RFC 5470) est certainement utilisable pour cela, si l'application peut le configurer dynamiquement.

Enfin, la section 5 rassemble les « points divers ». Elle rappelle qu'I2RS n'impose pas forcément le développement d'un nouveau protocole ; si un protocole, ou un ensemble de protocoles existant(s) suffit, c'est parfait (l'annexe A du RFC propose des pistes en ce sens). Mais la solution doit penser à :

  • Permettre des opérations asynchrones : pas question d'attendre la fin d'une opération avant de commencer la suivante.
  • Bonne granularité des opérations ; si on veut changer la configuration pour un préfixe IP, il ne faut pas verrouiller tout le routeur.
  • Possibilité que plusieurs clients parlent au routeur en même temps, avec le minimum de coordination entre eux.
  • Débit maximum élevé ; 10 000 opérations par seconde ne devraient pas être un problème.
  • Faible latence ; les opérations simples devraient pouvoir se faire en bien moins qu'une seconde (contrairement à, par exemple, un changement de configuration du routeur avec l'interface CLI des routeurs actuels, où le commit peut être très long).
  • Possibilité de filtrer l'information au départ du routeur, pour que l'application n'ait pas à tout récupérer avant le traitement.
  • Et, bien sûr, sécurité ; un système mettant en œuvre I2RS va pouvoir modifier la configuration du routeur, ce qui est potentiellement très dangereux. Il faut donc pouvoir authentifier et autoriser les accès.

Voici pour le cahier des charges. L'annexe A propose quelques pistes qui vont en ce sens. À l'heure actuelle, l'interface la plus générale des routeurs est la CLI. Elle permet d'apprendre l'état du routeur et de changer sa configuration. Voici un exemple sur un Juniper :

bortzmeyer@MX-1> show interfaces

...
      
Physical interface: ge-1/1/9, Enabled, Physical link is Up
  Interface index: 177, SNMP ifIndex: 531
  Description: To infinity and beyond
  Link-level type: Ethernet, MTU: 1514, MRU: 1522, Speed: 1000mbps, BPDU Error: None,
  MAC-REWRITE Error: None, Loopback: Disabled, Source filtering: Disabled, Flow control: Enabled,
  Auto-negotiation: Enabled, Remote fault: Online
  Pad to minimum frame size: Disabled
  Device flags   : Present Running
  Interface flags: SNMP-Traps Internal: 0x0
  Link flags     : None
  CoS queues     : 8 supported, 8 maximum usable queues
  Current address: 5c:5e:ab:0e:4b:f1, Hardware address: 5c:5e:ab:0e:4b:f1
  Last flapped   : 2016-02-12 11:31:56 CET (22w5d 23:10 ago)
  Input rate     : 672 bps (1 pps)
  Output rate    : 672 bps (1 pps)
  Active alarms  : None
  Active defects : None
  Interface transmit statistics: Disabled

  Physical interface: xe-0/0/2, Enabled, Physical link is Up
  Interface index: 156, SNMP ifIndex: 510
  Link-level type: Ethernet, MTU: 1514, MRU: 1522, LAN-PHY mode, Speed: 10Gbps, BPDU Error: None,
  MAC-REWRITE Error: None, Loopback: None, Source filtering: Disabled, Flow control: Enabled
  Pad to minimum frame size: Disabled
  Device flags   : Present Running
  Interface flags: SNMP-Traps Internal: 0x0
  Link flags     : None
  CoS queues     : 8 supported, 8 maximum usable queues
  Current address: 5c:5e:ab:0e:4b:72, Hardware address: 5c:5e:ab:0e:4b:72
  Last flapped   : 2016-07-07 14:28:31 CEST (1w6d 21:11 ago)
  Input rate     : 0 bps (0 pps)
  Output rate    : 0 bps (0 pps)
  Active alarms  : None
  Active defects : None
  PCS statistics                      Seconds
    Bit errors                             0
    Errored blocks                         1
  Interface transmit statistics: Disabled

...
    

Ce shell n'est pas normalisé : chaque marque de routeur a le sien. Comme l'information retournée n'est pas structurée, si on veut la traiter depuis un programme, il faut faire du scraping, ce qui est pénible et peu gratifiant (d'autant plus que le « format » peut changer sans prévenir lors de la sortie d'une nouvelle version du système d'exploitation du routeur).

Les routeurs ont aussi des interfaces reposant sur un protocole et des données structurées. La plus connue est SNMP. SNMP est très utilisé pour récupérer de l'information (état des interfaces, quantité de trafic qui passe) mais, bien qu'il permette en théorie la configuration des équipements réseau, en pratique, cette possibilité a été très peu utilisée. Les raisons de cette non-utilisation sont nombreuses (complexité, absence de sémantiques avancées comme le regroupement de plusieurs changements dans une « transaction » unique, sur laquelle on peut revenir globalement, etc). SNMP ne semble donc pas envisageable pour I2RS.

Enfin, cette annexe A cite Netconf comme étant sans doute la solution disponible la plus proche, même si elle n'est pas parfaite et aurait besoin d'être complétée (voir les travaux en cours dans le RFC 7921).


Téléchargez le RFC 7920


L'article seul

RFC 7925: Transport Layer Security (TLS) / Datagram Transport Layer Security (DTLS) Profiles for the Internet of Things

Date de publication du RFC : Juillet 2016
Auteur(s) du RFC : H. Tschofenig (ARM), T. Fossati (Nokia)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dice
Première rédaction de cet article le 20 juillet 2016


Dans le futur, nous répètent les consultants, il y aura partout dans nos maisons, bureaux et usines, des petits objets électroniques connectés à l'Internet. C'est le fameux Internet des Objets. Ces choses serviront à mesurer le monde et à le modifier et poseront donc des problèmes de sécurité. Par exemple, sans précautions particulières, un capteur dans une usine qui envoie en Wi-Fi les informations qu'il récolte permettrait à un écoutant indiscret, même situé en dehors de l'usine, de surveiller l'activité de celle-ci. Il va donc de soi qu'il faut utiliser de la cryptographie dans ces objets. Mais celle-ci est parfois coûteuse en ressources machine, et ce nouveau RFC propose donc des profils du protocole TLS, limitant les options possibles de façon à économiser les ressources des objets.

Ces objets sont en effet contraints au sens du RFC 7228. Un TLS complet serait trop pour eux. Bien sûr, on pourrait concevoir des protocoles cryptographiques spécialement conçus à leur intention mais il faudrait développer, valider et déboguer ces protocoles et l'expérience de la cryptographie sur l'Internet montre que c'est beaucoup plus difficile que ça n'en a l'air. D'où le choix d'utiliser TLS (RFC 5246), protocole connu et éprouvé.

Notons au passage que, contrairement à ce que dit le RFC, le principal danger que pose l'Internet des Objets ne vient pas forcément d'un tiers inconnu : presque toute la domotique actuelle fonctionne avec le cloud, toutes les données récoltées étant envoyées sur les serveurs du vendeur, qui peut en faire ce qu'il veut. Chiffrer le trafic entre l'objet et ces serveurs ne comble pas cette énorme faille de sécurité.

Les profils de TLS (et de DTLS, son équivalent pour UDP, cf. RFC 6347) spécifiés dans ce RFC peuvent s'appliquer aux communications utilisant CoAP (RFC 7252) comme à celles utilisant d'autres protocoles applicatifs. Ce sont des profils, des restrictions de TLS, et ils n'introduisent donc pas un nouveau protocole, ni même de nouvelles extensions à ces protocoles.

Par exemple (section 4.4), ce RFC impose que, si on authentifie avec un certificat, les certificats X.509 utilisent ECDSA uniquement. (Gérer tous les algorithmes possibles dans un objet contraint serait trop coûteux, par exemple en occupation de la flash.) Au revoir, RSA, donc.

Toujours sur les certificats, le profil abandonne OCSP (RFC 6960) et les CRL (qui ne marchent guère, en pratique) : la révocation des certificats devra se faire uniquement par le biais d'une mise à jour du logiciel de l'objet.

Toujours concernant la cryptographie, ce RFC impose (section 13) de n'utiliser que des suites de chiffrement intègres (AEAD) comme TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 (AES avec CCM, cf. RFC 7251).

Comme l'utilisation de TLS dans ces objets contraints est récente, il n'y a pas trop à se préoccuper de la base installée. On peut donc décider de ne jamais gérer des trucs trop anciens. C'est ainsi que la version minimale de TLS acceptée dans les profils de ce RFC est la 1.2 (section 18).

Il y a quelques points où ce RFC rend obligatoire des fonctions qui étaient optionnelles dans TLS, parce qu'elles sont cruciales pour des objets contraints. C'est le cas de la reprise de session TLS précédente, qui permet d'éviter de refaire des opérations cryptographiques coûteuses à chaque démarrage. Par contre, certaines fonctions sont déconseillées, comme la compression, coûteuse et sans doute inutile dans l'Internet des Objets où les protocoles sont déjà optimisés pour réduire la taille des données échangées. (En outre, il existe de bonnes raisons de sécurité de couper la compression TLS, RFC 7525, section 3.3.) Idem pour la renégotiation du RFC 5746, qui est exclue.

Un problème courant en cryptographie est celui de la génération de nombres aléatoires (TLS en utilise plusieurs). Il est encore plus aigu dans l'Internet des Objets car ces objets n'ont souvent pas beaucoup de sources d'entropie (section 12 du RFC). Pas de disque dur mobile, pas de clavier, pas de souris dont les mouvements sont partiellement aléatoires. Il y a donc un risque élevé que tous les objets identiques génèrent les mêmes nombres « aléatoires ». Bref, il faut que les développeurs fassent très attention aux conseils du RFC 4086.

Autre manque des objets contraints, celui d'une horloge fiable. Pour des opérations comme la validation de la non-expiration d'un certificat, cela peut être très gênant.

Les objets contraints sont... contraints de bien d'autre façon, comme en puissance du processeur. Cela peut rendre certaines opérations cryptographiques irréalistes en logiciel. La section 19 du RFC donne des conseils sur la mise en œuvre matérielle de ces opérations :

  • Les rendre accessibles au programmeur, pas uniquement au système de base, de manière à ce que la mise en œuvre de TLS puisse bénéficier, par exemple, de l'AES présent dans le matériel, au lieu de devoir le réécrire en moins efficace.
  • Mais être souple, car un même algorithme cryptographique peut être utilisé de plusieurs façons. Ainsi, certaines mises en œuvre matérielles d'AES-CCM sont conçues pour Bluetooth avec un numnique de taille fixe, qui n'est pas celle utilisée par TLS, ce qui interdit leur réutilisation.
  • Penser à l'agilité cryptographique (la possibilité de changer d'algorithme cryptographique, pour suivre les progrès de la cryptanalyse). Par exemple, il faut se demander comment permettre à ChaCha20 (RFC 8439 et RFC 7905) de remplacer AES dans le futur.

Toujours en cryptographie, la section 20 donne des recommendations sur la longueur des clés. Un point important, et spécifique aux objets, est que les engins déployés restent souvent sur le terrain très longtemps, par exemple dix ans. On ne remplace pas les capteurs, ou l'ordinateur embarqué dans une machine, comme on change d'iPhone ! La longueur des clés doit donc être prévue pour les attaques du futur, pas pour celles d'aujourd'hui.

Les objets dont on parle dans ce RFC sont souvent déployés dans des environnements où les contraintes de vie privée sont fortes. Cela peut être une usine qui ne veut pas que ses processus soient espionnés, ou bien une maison dont les habitants ne veulent pas être surveillés (section 22 du RFC). TLS ne protège pas contre tout et certaines fuites d'information persistent même quand il est utilisé. Elles peuvent venir du protocole TLS lui-même (la reprise de session utilise des informations qui permettent de suivre une machine à la trace) ou bien provenir de métadonnées diverses. Par exemple, s'il existe un capteur de présence qui envoie un message lorsque quelqu'un rentre dans l'appartement, chiffrer ce message ne fait pas gagner grand'chose : une fois qu'un observateur a identifié le capteur de présence, le seul envoi du message suffit à l'informer d'une arrivée. Une vraie protection de la vie privée peut donc nécessiter des méthodes additionnelles comme l'envoi de trafic bidon.

Le RFC se termine en rappelant qu'il est crucial de fournir un mécanisme de mise à jour simple des engins. Les objets de l'Internet des Objets sont souvent de type « je pose et puis j'oublie », sans aucun moyen de mettre à jour leur logiciel. Or, la sécurité peut nécessiter une telle mise à jour, soit pour corriger une bogue dans la bibliothèque TLS, soit pour révoquer des clés et en mettre d'autres. Un exemple d'un mécanisme de mise à jour adapté est LWM2M.

Si vous voulez rire un peu, l'annexe A du RFC précise comment faire tourner DTLS sur... SMS.


Téléchargez le RFC 7925


L'article seul

RFC 7890: Concepts and Terminology for Peer to Peer SIP

Date de publication du RFC : Juin 2016
Auteur(s) du RFC : D. Bryan (Cogent Force), P. Matthews (Alcatel-Lucent), E. Shim (Samsung Electronics), D. Willis (Softarmor Systems), S. Dawkins (Huawei)
Pour information
Réalisé dans le cadre du groupe de travail IETF p2psip
Première rédaction de cet article le 19 juillet 2016


Le mécanisme de signalisation d'appels SIP, largement utilisé pour la téléphonie sur IP, dépend de serveurs stables et connectés en permanence (proxies, registrars, etc), pour la mise en relation des participants. Une solution entièrement pair-à-pair est en cours de développement, P2PSIP (peer to peer SIP). Ce nouveau RFC décrit ses concepts et le vocabulaire qu'elle emploie.

C'est en effet le cœur du problème de toute solution pair-à-pair sur l'Internet : le rendez-vous. Comment deux machines pas toujours allumées, pas toujours connectées, coincées derrière des équipements qui leur interdisent les connexions entrantes, peuvent-elles rentrer en relation ? Si Alice appelle Bob via des téléphones SIP, comment faire sonner la machine de Bob, bloquée derrière son routeur NAT ? La solution classique de SIP (RFC 3261) est de d'abord faire correspondre une adresse SIP (appelée AoR pour Address of Record) avec un ou plusieurs URI, qui indiquent les machines à contacter. Ces machines sont des intermédiaires, reliés à l'Internet en permanence, et qui peuvent donc tout le temps recevoir le message INVITE d'établissement de connexion (cf. RFC 3263). L'idée de base du SIP pair-à-pair, P2PSIP, est de remplacer ces intermédiaires, ces relais, par un réseau P2P.

Le mécanisme exact, nommé RELOAD, est spécifié dans le RFC 6940 (notez que le protocole RELOAD peut servir à d'autres applications que SIP). Les machines des utilisateurs s'enregistrent dans une DHT, où les appelants vont trouver le moyen de les contacter. (Par défaut, la DHT utilisée est Chord.)

La section 2 de notre RFC donne une présentation générale de la solution complète. Un réseau pair-à-pair overlay sert à établir la correspondance entre adresses (AoR) et les URI indiquant les moyens de connexion. Ce même réseau sert également à acheminer les messages SIP, si les machines d'Alice et Bob n'arrivent pas à se parler directement (un problème fréquent dans l'Internet ossifié et fermé d'aujourd'hui). Ce réseau overlay de pairs stocke les correspondances, et les duplique sur plusieurs nœuds (comme dans tout réseau pair-à-pair, chaque machine peut faire défection à tout moment). Ce sont les services de base de l'overlay, ceux qui sont absolument indispensables au bon fonctionnement de P2PSIP. Mais certains pairs peuvent accepter de participer à d'autres services, comme un service de répondeur audio, pour les cas où Bob a éteint sa machine (cf. RFC 7374). De même, certains pairs peuvent assurer des services de proxy ou de registrar SIP traditionnel, pour permettre aux clients SIP anciens de se connecter via P2PSIP.

On n'est pas obligé d'être un pair dans ce réseau P2PSIP. Un softphone SIP peut être un simple client, utilisant les services de l'overlay sans y contribuer.

Notez qu'il existe d'autres moyens de faire du SIP sans l'appareil traditionnel des serveurs relais centraux. Ces moyens sont en général limités au réseau local (par exemple les RFC 6762 et RFC 6763).

Le cœur du RFC est sa section 4, qui regroupe les définitions. Je ne vais pas les reprendre ici. La plupart sont classiques dans le monde du pair-à-pair (overlay, peer...). À noter les termes de Node ID (l'identificateur unique d'un pair - RFC 6940, section 4.1) et de peer admission (le mécanisme par lequel on admet un nouveau pair : RELOAD permet un réseau fermé, où il faut montrer patte blanche à un serveur d'inscription avant de rentrer - RFC 6940, section 11.3.)


Téléchargez le RFC 7890


L'article seul

Un bel exemple de logiciels de sécurité dangereux

Première rédaction de cet article le 17 juillet 2016


On répète souvent aux utilisateurs que l'Internet est un lieu dangereux (ce n'est pas faux) et qu'il faut utiliser des logiciels qui les protègent magiquement : anti-virus, logiciels de contrôle parental, etc. Mais ce sont des logiciels, ils ont donc des bogues et ils ne sont pas mieux écrits que la moyenne des logiciels. Leurs bogues peuvent sérieusement affecter la sécurité de la machine. Morale : ajouter du logiciel de sécurité n'améliore pas forcément la sécurité.

Pour ceux qui ne seraient pas convaincus de ces évidences, je recommande très fortement la lecture de l'excellent article « Killed by Proxy: Analyzing Client-end TLS Interception Software ». Les auteurs, Mohammad Mannan et Xavier de Carné-Carnavalet, ont testé en labo un certain nombre de logiciels qui font de l'« interception TLS » et découvert que la plupart ouvraient des boulevards à des attaquants. Qu'est-ce qu'un logiciel d'interception TLS ? C'est un logiciel qui est un relais TLS, entre le logiciel de l'utilisateur (typiquement un navigateur Web) et le vrai serveur. L'intercepteur se fait passer pour le vrai serveur auprès du navigateur Web et pour le client auprès du vrai serveur. Pour ne pas lever d'alerte de sécurité dans le navigateur, il présente un certificat valable. Ce genre de logiciel est donc un détournement délibéré du modèle de sécurité de TLS : il casse la sécurité exprès. Il n'est donc pas étonnant qu'ils ouvrent des failles graves.

Pour comprendre ces failles, un petit mot sur le fonctionnement des ces logiciels : ils tournent sur la machine de l'utilisateur (contrairement aux relais TLS que les grandes entreprises et les administrations installent souvent près de l'accès Internet, pour surveiller les malwares et espionner les employés), ils détournent le trafic TLS (typiquement HTTPS) et ils présentent un certificat valable pour le nom de domaine demandé. Ce certificat a pu être généré en usine ou bien à l'installation du logiciel. Ce certificat est parfois protégé par une phrase de passe. Pour que le certificat soit accepté, ils mettent leur propre AC dans le magasin du système, avec une période de validité allant jusqu'à 20 ans. (En général, ils n'expliquent pas clairement à l'utilisateur ce qu'ils font, ce qui augmente encore le danger.) Le logiciel d'interception reçoit les connexions locales, venant du navigateur Web, et se connecte lui-même aux vrais serveurs distants. Ces logiciels sont presque toujours privateurs, aucun accès au code source (bien que tous utilisent, sans honte, un logiciel libre, OpenSSL), aucun moyen de les vérifier.

La totalité des logiciels testés par les auteurs a au moins une faille TLS. Inutile donc de chercher le « bon antivirus » ou le « bon logiciel de contrôle parental ». Voici une liste non limitative de ces failles :

  • Acceptation de certificats externes (présentés par le vrai serveur) signés par l'AC du logiciel d'interception. Un pirate qui peut faire signer ces faux certificats peut donc faire accepter n'importe quoi aux machines ayant installé ces logiciels.
  • Comportements bizarres lors de l'expiration de la licence, comme d'accepter soudainement tous les certificats externes, sans les valider.
  • Non-suppression de leur AC du magasin lorsqu'on exécute le programme de désinstallation du logiciel. On ne peut donc jamais réellement faire marche arrière.
  • Clés privées sécurisant le certificat stockées sans protection, ou avec une protection identique pour toutes les installations du logiciel, permettant à un logiciel malveillant (sans privilèges Administrateur) d'y accéder et de faire donc ensuite accepter n'importe quel serveur TLS mensonger.
  • Modification des erreurs TLS lorsque le certificat externe (celui du vrai serveur) est invalide. Par exemple, un certificat dont le nom (le sujet) ne correspond pas devient un certificat signé par une AC inconnue, ce qui sera le message affiché par le navigateur.
  • Bien pire, la plupart des logiciels acceptent presque tous les certificats externes invalides, masquant toute erreur.
  • Sécurité cryptographique plus faible qu'un vrai navigateur (par exemple, acceptation de certificats qui utilisent MD5, vulnérabilité à Poodle, etc).
  • Acceptation d'AC qui auraient dû être retirées depuis longtemps, comme DigiNotar.

Pourquoi les sociétés qui écrivent ces logiciels feraient des efforts pour la sécurité ? Leurs utilisateurs ne sont pas des connaisseurs, des tas de gens auto-proclamés experts en sécurité servent de vendeurs pour ces logiciels en répétant aux utilisateurs « pensez à installer un anti-virus » et la non-disponibilité du code source rend difficile toute analyse de ces logiciels.


L'article seul

RFC 7908: Problem Definition and Classification of BGP Route Leaks

Date de publication du RFC : Juin 2016
Auteur(s) du RFC : K. Sriram, D. Montgomery (US NIST), D. McPherson, E. Osterweil (Verisign), B. Dickson
Pour information
Réalisé dans le cadre du groupe de travail IETF grow
Première rédaction de cet article le 8 juillet 2016


Il est bien connu que le protocole de routage BGP connait fréquemment des « fuites de route » (route leaks). Les forums où les opérateurs discutent sont plein de discussions et d'alertes sur la dernière fuite en cours, il existe un compte Twitter dédié pour les alertes automatiques de fuites, le rapport sur la résilience de l'Internet en France en parle longuement. Bref, le sujet est bien connu. Curieusement, il n'y a pas de définition simple et consensuelle de ce qu'est une fuite. Il en existe en fait plusieurs sortes, et ce nouveau RFC tente de faire le point et de définir rigoureusement les différents types de fuite.

La fuite est en effet un sérieux problème : des routeurs vont recevoir des routes incorrectes et, s'ils les acceptent, le routage normal peut être perturbé, menant à des pannes, ou à du tromboning (paquets IP routés par un chemin bien plus long que l'optimum).

La liste des incidents de routage médiatiquement connus est longue : le détournement de YouTube par Pakistan Telecom, la fuite venue de Malaisie, et bien d'autres décrites dans l'abondante bibliographie de notre RFC (cf. section 1 du RFC). L'IETF travaille depuis longtemps à des solutions techniques à ce problème (notamment via son groupe de travail SIDR) mais, pour résoudre un problème, il vaut mieux bien le comprendre. C'est le travail de ce nouveau RFC, qui tente une taxonomie des fuites.

Donc, d'abord, une (tentative de) définition (section 2 du RFC). Une fuite est la propagation de l'annonce d'une route au-delà de la portée prévue. Ce n'est donc pas la seule annonce qui est le problème, c'est sa propagation. Si le Pakistan veut annoncer les routes de YouTube dans le pays, à des fins de censure, ce n'est pas une fuite de route, mais un détournement délibéré (comme celui de Google Public DNS en Turquie). La fuite a commencé quand Pakistan Telecom a bêtement laissé se propager cette annonce au monde entier.

La définition s'appuie donc sur une politique de routage qui définit « ce qui est prévu ». La politique de routage est décidée par chaque acteur (l'Internet n'a pas de Chef, chacun est maître de sa politique) et mise en œuvre dans la configuration des routeurs, sous forme de règles disant ce qui est accepté et ce qui est refusé. Si les opérateurs ne commettaient jamais d'erreurs, on pourrait dire que ces règles suffiraient à décrire la politique de routage. Mais ils en commettent (par exemple, le transitaire de Pakistan Telecom aurait dû n'accepter de son client qu'un ensemble fini de routes, celles correspondant aux préfixes alloués à Pakistan Telecom et à ses clients). Une fuite de route est donc l'équivalent pour les opérateurs réseau de ce qu'est une bogue pour les programmeurs : « ce n'est pas ce que je voulais, mais c'est ce que j'ai dit ».

La définition de la politique de routage dépend des relations entre acteurs (on n'accepte pas la même chose d'un client, d'un transitaire, d'un pair...) Le RFC cite (section 2) plusieurs études expliquant ces relations compliquées.

Au fait, on a supposé que les « fuites de routes » étaient mauvaises et qu'il fallait les combattre. Mais pourquoi ? Parce qu'elles peuvent mener à des pannes (la route annoncée à tort ne fonctionne pas) ou à des chemins sous-optimaux (un long détour). Cela concerne les fuites accidentelles, de loin les plus nombreuses (il y a davantage de maladroits que de malveillants). Mais il y a aussi des fuites délibérées, provoquées pour faire une attaque par déni de service, ou bien pour forcer le trafic à passer en un point où il pourra être plus facilement surveillé.

C'est pour cela que les gens qui ne chiffrent pas leurs communications avec des arguments du genre « non, mais ça ne sort pas du pays, de toute façon », ont gravement tort. La vulnérabilité du routage fait que leur trafic peut soudainement partir bien plus loin.

Voyons maintenant la classification des fuites (section 3). Le RFC les classe en différents types, identifiés par un numéro. Le type 1 est « virage en épingle à cheveux avec un préfixe complet ». C'est ce qui se produit quand un AS de bordure apprend un préfixe d'un de ses transitaires et le ré-annonce à un autre transitaire (d'où l'épingle à cheveux). Le second transitaire, s'il ne filtre pas les préfixes que peut annoncer son client, risque fort d'accepter la route (préférence donnée aux routes des clients sur celles des fournisseurs) et le trafic sera donc envoyé à l'AS de bordure (qui pourra ou pas le gérer). Ce fut le cas de l'incident Dodo, ainsi que de la fuite en Malaisie citée plus haut.

Le type 2, lui, est « fuite latérale ». Un acteur reçoit une route d'un pair et la transmet à un autre pair. (Voir la conférence de Jared Mauch à NANOG, où il observe qu'il n'est pas facile de détecter automatiquement ces fuites, car les relations entre acteurs peuvent être compliquées.)

L'incident de type 3, lui, se produit lorsque un AS apprend d'un transitaire des routes qu'il annonce à son pair (normalement, on n'annonce à un pair que ses routes à soi). L'exposé de Mauch en cite également des exemples.

Le type 4 est l'inverse : un pair laisse fuir les préfixes d'un pair vers un transitaire. Ce fut le cas de l'incident Moratel contre Google, ou d'un problème frappant Amazon.

Le type 5 se nomme « ré-origination ». L'AS maladroit annonce les routes comme si elles venaient de lui, et c'est son numéro d'AS qui apparait comme origine (le début du chemin d'AS). Ce fut le cas lors de grande fuite chinoise de 2010, ou pendant le curieux détournement islando-biélorusse (un des rares cas où le shunt semblait volontaire).

Le type 6 est la « fuite de préfixes plus spécifiques ». Un AS typique annonce dans son IGP des préfixes bien plus spécifiques que ce qu'il annonce publiquement, afin de contrôler plus finement le routage interne. Une erreur (redistribution de l'IGP dans l'EGP...) et paf, les préfixes spécifiques fuient. Étant plus spécifiques que le préfixe « normal », ils seront préférés lors de la transmission des paquets. Le cas le plus spectaculaire fut celui de l'AS 701.

Le RFC ne discute pas des solutions possibles, ce n'est pas son but. Les curieux pourront regarder du côté des systèmes d'alerte ou de RPKI/ROA.


Téléchargez le RFC 7908


L'article seul

RFC 7905: ChaCha20-Poly1305 Cipher Suites for Transport Layer Security (TLS)

Date de publication du RFC : Juin 2016
Auteur(s) du RFC : A. Langley (Google), W. Chang (Google), N. Mavrogiannopoulos (Red Hat), J. Strombergson (Secworks Sweden), S. Josefsson (SJD)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF tls
Première rédaction de cet article le 8 juillet 2016


Ce court RFC ajoute les algorithmes de cryptographie ChaCha20 et Poly1305 à la liste de ceux utilisables dans le protocole TLS.

ChaCha20 (dérivé de l'ancien Salsa20) est un algorithme de chiffrement symétrique et Poly1305 un authentificateur. Tous les deux ont été conçus par Dan Bernstein et sont décrits dans le RFC 8439. (Ce nouveau RFC ne fait que de les adapter à leur usage dans le cas spécifique de TLS.) ChaCha a été utilisé dans BLAKE, la version de ce RFC, ChaCha20 doit son nom au fait qu'il exécute 20 tours (rounds). Quant à Poly1305, c'est un authentificateur de Wegman-Carter. Que fait un authentificateur ? Il prend une clé, un message et fabrique une étiquette. Un attaquant n'a qu'une probabilité infime de produire une étiquette valide.

Les deux algorithmes ont été conçus en pensant surtout à une mise en œuvre en logiciel (AES restant sans doute plus rapide quand on peut utiliser du matériel spécialisé. On trouve des mesures de performance dans cet article de Google ou cet article de Cloudflare.)

Les algorithmes potentiellement concurrents ont des faiblesses : risques de sécurité pour AES-CBC ou RC4 (cf. RFC 7465), problèmes de performance pour les autres algorithmes AEAD comme AES-GCM. Comme RC4, ChaCha20 est un algorithme à flot continu, mais il n'a pas ses failles de sécurité.

Pour le cas de TLS (section 2 du RFC), ChaCha20 et Poly1305 sont utilisés ensemble, pour former un algorithme AEAD (RFC 5116). Son identifiant TLS est AEAD_CHACHA20_POLY1305 et il peut s'utiliser avec les différents algorithmes d'authentification utilisés dans TLS. Par exemple, on peut avoir une session TLS dont la cipher suite est TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 ce qui veut dire :

Ces identifiants ont été ajoutés dans le registre IANA pour TLS.

Quel est le niveau de sécurité du nouvel algorithme ? Son prédécesseur Salsa20 a bénéficié d'analyses de sécurité sérieuses (Salsa20 security et The eSTREAM Portfolio). ChaCha20 traite les failles connues de Salsa. Et il était utilisé dans un des finalistes du concours SHA-3, ce qui lui a valu d'autres examens de près.

Si, en plus de ChaCha20 et Poly1305, on utilise Curve25519 pour la cryptographie asymétrique, on aura une cryptographie tout-Bernstein, ce qui peut aussi amener à se poser des questions.

Et les mises en œuvre ? ChaCha20 est dans OpenSSL depuis la version 1.1.0 (pas encore officiellement publiée, et qui semble encore peu répandue) et dans GnuTLS depuis la 3.4.0. Il existe une liste apparemment à jour des mises en œuvre.


Téléchargez le RFC 7905


L'article seul

Un Internet favorable ou défavorable aux Droits Humains ?

Première rédaction de cet article le 7 juillet 2016


Le 21 juin, dans les locaux de Radio France, j'ai eu le plaisir de parler aux employés de la direction du numérique sur le thème « Libertés dans le numérique, un Internet favorable ou défavorable aux droits de l'homme ? » Cette conférence était largement inspirée des travaux du groupe de recherche HRPC (Human Rights [and] Protocol Considerations).

La présentation était :

Lawrence Lessig est fameux pour sa phrase « code is law » qui rappelait l'importance des infrastructures dans les possibilités offertes aux citoyens. Si on a le droit de se déplacer librement mais qu'il n'y a pas de transports en commun et que les voitures sont hors de prix, que vaut ce droit ?

De même, dans le monde numérique, les techniques effectivement disponibles encouragent les droits de l'homme ou au contraire les limitent. Par exemple, certains composants de l'Internet rendent trop facile la censure.

On explorera ces caractéristiques de l'Internet, et on discutera de comment elles pourraient être modifiées.

Voici les supports de l'exposé :

Et la vidéo est maintenant disponible.

Merci à Maziar Dowlatabadi et Nadia Nwafo pour l'idée, et l'organisation.


L'article seul

RFC 7872: Observations on the Dropping of Packets with IPv6 Extension Headers in the Real World

Date de publication du RFC : Juin 2016
Auteur(s) du RFC : F. Gont (SI6 Networks / UTN-FRH), J. Linkova (Google), T. Chown (University of Southampton), W. Liu (Huawei)
Pour information
Réalisé dans le cadre du groupe de travail IETF v6ops
Première rédaction de cet article le 5 juillet 2016


Normalement, l'Internet est un monde idéal où la machine d'Alice peut envoyer à celle de Bob les paquets qu'elle veut, Bob les recevra intacts (s'il le veut). Dans la réalité, pas mal de machines intermédiaires ne respectent pas ce principe de bout en bout. Il est fréquent que les paquets « inhabituels » soient jetés en route. Cela peut être le résultat d'une politique délibérée (pare-feu appliquant le principe « dans le doute, on jette ») ou bien, souvent, de l'incompétence des programmeurs qui n'ont pas lu les RFC et ne connaissent pas telle ou telle option. Par exemple, IPv6 permet d'ajouter au paquet, entre l'en-tête proprement dit et la charge utile du paquet, un ou plusieurs en-têtes d'extension. C'est rare en pratique. Est-ce que les programmeurs des middleboxes ont fait attention à cette possibilité ? Les paquets ayant ces en-têtes d'extension ont-ils de bonne chances d'arriver au but ? Ce nouveau RFC est un compte-rendu de mesures effectuées dans l'Internet pour essayer de quantifier l'ampleur exacte du problème.

Un point important du travail effectué par les auteurs du RFC est qu'ils ne sont pas contentés de chercher si les paquets étaient jetés mais également ils étaient jetés. La différence est politiquement cruciale. Si le paquet IPv6 portant un en-tête d'extension est jeté par la machine de Bob, car Bob n'aime pas ces en-têtes et il a configuré son Netfilter pour les envoyer vers DROP, pas de problème : Bob est libre d'accepter ou de refuser ce qu'il veut. Si, par contre, le paquet a été jeté par le FAI d'Alice ou de Bob, ou, encore pire, par un opérateur de transit entre les deux FAI, c'est grave, c'est une violation de la neutralité du réseau, violation qui empêche deux adultes consentants de s'envoyer les paquets qu'ils veulent. Le mécanisme de mesure cherche donc à trouver dans quel AS le paquet a disparu.

Les mesures ont été faites en août 2014 et juin 2015. Le RFC détaille suffisamment la façon dont elles ont été faites (annexe A) pour qu'une autre équipe puisse recommencer les mesures à une date ultérieure, pour voir si la situation s'améliore.

Les en-têtes d'extension IPv6 sont décrits dans le RFC 2460, section 4. Ils sont de deux plusieurs sortes, entre autre :

  • L'en-tête de fragmentation, qui doit pouvoir passer si on veut que les paquets IP fragmentés arrivents (les principaux émetteurs de paquets IPv6 fragmentés sont sans doute les serveurs DNS, notamment avec DNSSEC, car UDP ne négocie pas la MSS).
  • L'en-tête « Options pour la destination » (Destination Options) qui, comme son nom l'indique, ne doit pas être examiné par les routeurs sur le chemin. Il contient des informations pour la machine terminale de destination.
  • L'en-tête « Options pour chaque intermédiaire » (Hop-by-Hop Options) qui, comme son nom l'indique, doit être examiné par les routeurs sur le trajet, il contient des informations pour eux.

Outre la fragmentation, un exemple d'utilisation de ces en-têtes est le protocole CONEX (RFC 7837). Si vous voulez ajouter des options pour la destination dans un paquet IPv6, vous pouvez regarder mon tutoriel.

Quelles sont les chances de survie des paquets portant ces en-têtes d'extension dans le sauvage Internet ? Des études comme « Discovering Path MTU black holes on the Internet using RIPE Atlas », « Fragmentation and Extension header Support in the IPv6 Internet » ou bien « IPv6 Extension Headers in the Real World v2.0 » s'étaient déjà penchées sur la question. Les mesures de ce RFC détaillent et complètent ces résultats préliminaires, notamment sur la différenciation entre perte de paquet près de la destination, et perte du paquet en transit. La conclusion est, qu'hélas, les paquets IPv6 portant des en-têtes d'extension font effectivement l'objet d'une discrimination négative (« entêtophobie » ?).

Donc, qu'est-ce que ça donne dans l'Internet réel (section 2) ? Deux listes de serveurs IPv6 ont été utilisées, celle du World IPv6 Launch Day et le premier million d'Alexa. De ces listes de domaines ont été extraits les adresses IP des sites Web (dig AAAA LE-DOMAINE et, oui, je sais que c'est un sérieux raccourci de supposer que tout domaine a un serveur Web à l'apex), des relais de messagerie (dig MX LE-DOMAINE puis obtenir l'adresse IPv6 des serveurs), et des serveurs de noms (dig NS LE-DOMAINE). Les adresses absurdes (::1...) ont été retirées. Ensuite, pour chaque adresse ainsi obtenue, trois types de paquets ont été envoyés :

  • Un avec en-tête d'extension Destination Options,
  • Un avec en-tête d'extension Hop-by-hop Options,
  • Un fragmenté en deux fragments d'à peu près 512 octets.

Les paquets étaient tous du TCP à destination d'un port correspondant au service (25 pour les serveurs de messagerie, par exemple).

Un point très important et original de cette expérience était la recherche d'information sur se produisait l'éventuelle perte de paquets (dans quel AS). L'hypothèse de base est qu'une élimination du paquet dans l'AS de destination peut être acceptable, parce qu'elle résulte d'une décision consciente du destinataire. En tout cas, il sera plus facile de changer la politique de l'AS de destination. En revanche, une élimination dans un AS intermédiaire est inacceptable : elle indique filtrage ou erreur de configuration dans un réseau qui devrait être neutre. Notez que l'hypothèse n'est pas parfaite : si un particulier héberge un serveur chez lui et que son FAI filtre les paquets IPv6 avec en-tête d'extension, c'est quand même inacceptable, et c'est difficile pour le particulier de le faire corriger.

Comment identifier l'AS qui jette le paquet ? L'idée est de faire l'équivalent d'un traceroute (en fait, deux, un avec l'en-tête de destination et un sans, pour comparer : cf. annexe B.1) et de voir quel est le dernier routeur qui a répondu. C'est loin d'être idéal. Des routeurs ne répondent pas, pour d'autres, il est difficile d'évaluer à quel AS ils appartiennent (dans un lien de peering entre deux acteurs A et B, les adresses IP utilisées ont pu être fournies par A ou bien par B ; cf. annexe B.2). Et l'absence d'un routeur dans le résultat de traceroute ne prouve pas que le routeur n'a pas transmis le paquet juste avant. La mesure indique donc deux cas, l'optimiste, où on suppose, en l'absence de preuve opposée, que les paquets manquant ont été jetés par l'AS de destination et le pessimiste où on fait la supposition inverse.

Les résultats complets des mesures figurent dans le RFC. Je résume ici une partie. Pour les serveurs Web de la liste du World IPv6 Launch Day :

  • 12 % des serveurs n'ont pas reçu le paquet envoyé avec un en-tête Destination Options. Entre 18 % (optimiste) et 21 % (pessimiste) de ces pertes se sont produites avant l'AS de destination.
  • 41 % des serveurs n'ont pas reçu le paquet envoyé avec un en-tête Hop-by-hop Options. Entre 31 % (optimiste) et 40 % (pessimiste) de ces pertes se sont produites avant l'AS de destination.
  • 31 % des serveurs n'ont pas reçu le paquet fragmenté. Entre 5 % (optimiste) et 7 % (pessimiste) de ces pertes se sont produites avant l'AS de destination.

Les résultats ne sont guère différents pour les autres services (comme SMTP), indiquant que le problème, quand il est présent, est bien dans la couche 3. Idem avec le jeu de données Alexa : peu de différences.

On voit que les paquets utilisant l'en-tête d'extension « Options pour chaque intermédiaire » sont ceux qui s'en tirent le plus mal (c'est un peu logique, cet en-tête étant censé être examiné par tous les routeurs intermédiaires). Les fragments passent assez mal également. Enfin, on note qu'un pourcentage significatif des paquets sont jetés par un AS de transit, qui viole ainsi massivement le principe de bout en bout. Triste état de l'Internet actuel, pourri de middleboxes qui se permettent tout.

Si vous voulez refaire l'expérience vous-même, pour contrôler les résultats, ou bien pour mesurer l'évolution dans quelque temps, l'annexe A vous donne les éléments nécessaires. Vous aurez besoin du toolkit de SI6. Les données d'Alexa sont disponibles en ligne. L'outil script6 dans le toolkit SI6 permet d'obtenir les adresses IP nécessaires. Par exemple :

% cat top-1m.txt | script6 get-mx | script6 get-aaaa
    

Et on obtient ainsi les adresses IP des relais de messagerie. Pour supprimer les adresses incorrectes (par exemple ::1), on utilise l'outil addr6 du toolkit :

%  cat top-1m-mail-aaaa.txt | addr6 -i -q -B multicast -B unspec -k global     
    

Il n'y a plus maintenant qu'à envoyer les paquets portant les en-têtes d'extension, ou fragmentés. Ici, les serveurs de messagerie avec l'en-tête Destination Options (« do8 ») :

% cat top-1m-mail-aaaa-unique.txt | script6 trace6 do8 tcp 25      
    

L'annexe B de notre RFC contient quelques avertissements méthodologiques.

Un traceroute ordinaire ne suffit pas à faire les mesures décrites plus haut pour identifier le routeur responsable d'une perte de paquet (le traceroute ordinaire ne permet pas d'ajouter l'en-tête d'extension aux paquets utilisés). Il faut utiliser un outil spécial comme le path6 du toolkit SI6. Encore plus simple, dans le même paquetage, l'outil blackhole6. Voyons d'abord path6 pour comprendre les détails :

% sudo path6  -d yeti.ipv6.ernet.in 
Tracing path to yeti.ipv6.ernet.in (2001:e30:1c1e:1::333)...

  1 (2001:4b98:dc0:41::250)   1.1 ms   0.5 ms   0.4 ms
  2 (2001:4b98:1f::c3d3:249)   1.2 ms   3.5 ms   3.4 ms
  3 (2001:7f8:54::173)   1.1 ms   0.8 ms   0.6 ms
  4 (2001:1a00:1:cafe::e)  141.3 ms  140.7 ms  140.6 ms
  5 (2001:1a00:1:cafe::145)  118.8 ms  118.8 ms  119.5 ms
  6 (2001:1a00:1:cafe::141)  140.7 ms  137.2 ms  137.3 ms
  7 (2001:1a00:1:cafe::10b)  144.0 ms  144.3 ms  144.1 ms
  8 (2001:1a00:1:cafe::212)  140.5 ms  140.5 ms  140.5 ms
  9 (2001:1a00:1:cafe::207)  137.0 ms  137.0 ms  136.9 ms
 10 (2001:1a00:acca:101f::2)  136.5 ms  136.4 ms  136.5 ms
 11 (2001:4528:ffff:ff04::1)  152.2 ms  152.1 ms  152.2 ms
 12 (2001:4528:fff:c48::1)  163.6 ms  163.7 ms  163.6 ms
 13 (2001:e30:1c1e::1)  162.6 ms  162.3 ms  162.2 ms
 14 (2001:e30:1c1e:1::333)  174.5 ms  175.1 ms  175.2 ms
    

OK, on arrive à joindre la machine en Inde. Maintenant, ajoutons l'en-tête Hop-by-Hop Options :

% sudo path6 --hbh-opt-hdr 8 -d yeti.ipv6.ernet.in
Tracing path to yeti.ipv6.ernet.in (2001:e30:1c1e:1::333)...

  1 (2001:4b98:dc0:41::250)  20.9 ms  20.0 ms  19.0 ms
  2 (2001:4b98:1f::c3d3:249)  20.8 ms  20.2 ms  18.5 ms
  3 (2001:4b98:1f::c3c4:3)  20.7 ms  20.4 ms  18.5 ms
  4 (2001:1a00:1:cafe::e)  154.3 ms  14.4 ms  152.1 ms
  5 (2001:1a00:1:cafe::e)  151.0 ms  129.6 ms  148.9 ms
  6 (2001:1a00:1:cafe::141)  151.2 ms  126.2 ms  148.8 ms
  7 (2001:1a00:1:cafe::141)  156.5 ms  156.8 ms  158.6 ms
  8 (2001:1a00:1:cafe::212)  153.6 ms  191.2 ms  151.4 ms
  9 (2001:1a00:1:cafe::212)  155.3 ms  151.1 ms  157.7 ms
 10 (2001:1a00:1:cafe::207)  *  155.619995 ms *
 11 ()   *  *  *
 12 ()   *  *  *
 13 ()   *  *  *
 ...
    

Aïe, ça n'arrive plus. Le routeur situé après 2001:1a00:1:cafe::207 a jeté le paquet. En comparant les deux path6, on peut voir que le coupable est 2001:1a00:acca:101f::2 (Flag, désormais une marque de Reliance). L'outil blackhole6 fait tout ce travail automatiquement (EH = Extension Header, HBH 8 = Hop-by-Hop, size 8) :

% sudo blackhole6 yeti.ipv6.ernet.in hbh8         
SI6 Networks IPv6 Toolkit v2.0 (Guille)
blackhole6: A tool to find IPv6 blackholes
Tracing yeti.ipv6.ernet.in (2001:e30:1c1e:1::333)...

Dst. IPv6 address: 2001:e30:1c1e:1::333 (AS2697 - ERX-ERNET-AS Education and Research Network, IN)
Last node (no EHs): 2001:e30:1c1e:1::333 (AS2697 - ERX-ERNET-AS Education and Research Network, IN) (14 hop(s))
Last node (HBH 8): 2001:1a00:1:cafe::207 (AS15412 - FLAG-AS Flag Telecom Global Internet AS, GB) (10 hop(s))
Dropping node: 2001:1a00:acca:101f::2 (AS15412 - FLAG-AS Flag Telecom Global Internet AS, GB || AS Unknown - Unknown)
    

Sur ce sujet et ces tests, on peut aussi regarder l'exposé de Mehdi Kouhen au symposium Polytechnique/Cisco, ou bien celui d'Eric Vyncke à Protosec à Buenos Aires.


Téléchargez le RFC 7872


L'article seul

Exposé technique « Développer un contrat/programme sur Ethereum »

Première rédaction de cet article le 4 juillet 2016
Dernière mise à jour le 6 juillet 2016


Le 2 juillet, au festival Pas Sage en Seine / Hacker Space Festival, j'ai eu le plaisir de faire un exposé sur la chaîne de blocs Ethereum, plus précisement sur l'écriture de programmes (on dit parfois contrats) Ethereum. Cet exposé s'adresse donc surtout aux programmeurs.

Voici les supports de l'exposé :

Il y aussi la vidéo en ligne.

Les deux contrats présentés à Pas Sage En Seine, Soleau et FindByHash, ont été installés sur la chaîne de blocs. Sur la chaîne de tests « Morden », Soleau est installé en 0x165180498e843c5119d7d57b866da1392b8e8185 et FindByHash en 0x78db9a1dfe1b46c4361ac91cda111f5366ddc0e5.

Sur la « vraie » chaîne, Soleau est en 0x39aa4006ee5941c0c0e41b924fdafcb2c4c918e8 et FindByHash en 0x9b6e416ea0d89a09b4ae036a774b1d31825252f8. Si vous voulez interagir avec ces contrats, voici l'ABI de Soleau :

[{"constant":true,"inputs":[{"name":"hash","type":"string"}],"name":"get","outputs":[{"name":"success","type":"bool"},{"name":"theBlock","type":"uint256"},{"name":"theTime","type":"uint256"},{"name":"holder","type":"address"}],"type":"function"},{"constant":false,"inputs":[{"name":"hash","type":"string"}],"name":"record","outputs":[{"name":"success","type":"bool"},{"name":"already","type":"bool"},{"name":"theBlock","type":"uint256"}],"type":"function"}]  

Et celle de FindByHash :

[{"constant":true,"inputs":[{"name":"key","type":"string"},{"name":"index","type":"uint256"}],"name":"get","outputs":[{"name":"","type":"bool"},{"name":"","type":"string"}],"type":"function"},{"constant":true,"inputs":[{"name":"key","type":"string"}],"name":"num_of","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"key","type":"string"},{"name":"value","type":"string"}],"name":"set","outputs":[{"name":"","type":"bool"}],"type":"function"},{"inputs":[],"type":"constructor"}]

Ça s'utilise comment ? Prenons l'exemple de Soleau sur la chaîne de test. Si on utilise le logiciel geth, avec sa console JavaScript, on déclare le contrat et on indique l'adresse :

soleauC = eth.contract([{"constant":true,"inputs":[{"name":"hash","type":"string"}],"name":"get","outputs":[{"name":"success","type":"bool"},{"name":"theBlock","type":"uint256"},{"name":"theTime","type":"uint256"},{"name":"holder","type":"address"}],"type":"function"},{"constant":false,"inputs":[{"name":"hash","type":"string"}],"name":"record","outputs":[{"name":"success","type":"bool"},{"name":"already","type":"bool"},{"name":"theBlock","type":"uint256"}],"type":"function"}])

soleau = soleauC.at("0x165180498e843c5119d7d57b866da1392b8e8185")  

Une fois que c'est fait, on peut appeler l'ABI du contrat. Ici, on demande si un condensat est bien stocké dans la chaîne :

> soleau.get("98461ec184a39f0b8d89401a2756ffc84c2473a772655b425d794db6e7b68a8a")
[true, 1211232, 1467041583, "0xaf8e19438e05c68cbdafe33ff15a439ce6742972"]
> soleau.get("666")
[false, 0, 0, "0x0000000000000000000000000000000000000000"]

Sur la chaîne principale, le même contrat a une valeur 5e1e7a61931acb3f0e2bb80fc1d88e242d8556e6 stockée :

> soleau.get("5e1e7a61931acb3f0e2bb80fc1d88e242d8556e6")
[true, 1830809, 1467745954, "0xc90cd1fa9940a4d4a07a37c53bb4f423fd286945"]

On peut aussi ajouter des valeurs (ici, sur la chaîne de test). Comme cela change l'état de la chaîne, il faut faire une transaction, et payer, à la fois l'essence (ici, 400000 unités mais moins de 100000 seront effectivement utilisées) et le prix prévu dans le contrat :

> soleau.record.sendTransaction("d479b91d7a2cdd21f605c5632344228dd5f75d66", {from: eth.accounts[0], gas: 400000, value: web3.toWei(0.001)})
"0xfb6bc725e303c79c2c5426c3a0d4fce90b635521826e5bd3e94ddfa3d80c48da"

Le résultat est l'identificateur de la transaction, que vous pouvez regarder en ligne (avec le bouton Convert to ASCII, vous verrez le condensat enregistré, dans les données de la transaction). Sur la chaîne principale, un exemple de transaction de ce contrat est disponible ici. Pour le contrat FindByHash, si vous voulez regarder des valeurs enregistrées, il y a cf4163b8f4c13b915e246ea7d2792156 sur la chaîne de tests et 3d10dcb5e503d3b8abc2fa5a72adb0a503930e0b6b8a893f17dda63b9b717dba sur la chaîne principale :

> findhash.num_of("cf4163b8f4c13b915e246ea7d2792156")
2
> findhash.get("cf4163b8f4c13b915e246ea7d2792156", 0)
[true, "https://localhost/"]
> findhash.get("cf4163b8f4c13b915e246ea7d2792156", 1)
[true, "https://www.bortzmeyer.org/toto"]

Pour enregistrer des URL dans ce contrat, le plus simple est ce petit script shell, qui s'utilise ainsi :

% findbyhash-register-url.sh http://www.bortzmeyer.org/pas-sage-en-seine-ethereum.html
...
"0x82a808828a115547b242f335783bf75a0c96d2d746ab9dff160898a8f28a5411"
3d10dcb5e503d3b8abc2fa5a72adb0a503930e0b6b8a893f17dda63b9b717dba registered for http://www.bortzmeyer.org/pas-sage-en-seine-ethereum.html

(Et vous pouvez voir la transaction en ligne.)

Si le sujet vous intéresse, j'en parlais plus longuement à la Journée du Conseil Scientifique de l'AFNIC le 11 juillet (avec d'autres exemples de code, rassurez-vous).

Il y avait plein d'autres trucs géniaux à PSESHSF, n'hésitez pas à regarder le programme. Mes préférés (c'est complètement subjectif), faire son pain soi-même (et avec du levain), les explications (avec démo de diffuseur d'odeurs et bonbons qui sentent bon) sur le marketing sensoriel, le projet pour un camp de hackers en été en France, la conférence sur l'éducation au numérique (qui ne sortira sans doute pas en vidéo, l'auteur étant mineur), même si sa seconde partie, sur l'éducation au business a suscité (à juste titre), des réactions houleuses, la reprise de contrôle de l'alimentation, le système d'exploitation Qubes (j'avais parlé de ce système sur ce blog mais sans le tester), la bière libre (j'ai goûté ; un peu forte), l'appel aux citoyens à participer à la science, la synthèse du récent virage de la Quadrature du Net, le bilan de la loi Renseignement, etc.


L'article seul

RFC 7848: Mark and Signed Mark Objects Mapping

Date de publication du RFC : Juin 2016
Auteur(s) du RFC : G. Lozano (ICANN)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF eppext
Première rédaction de cet article le 28 juin 2016


Les registres de noms de domaine ont parfois des règles d'enregistrement spéciales, pendant une période limitée, lorsqu'on ouvre un nouveau TLD, ou si on change radicalement ses règles d'enregistrement. Ces règles spéciales pour les périodes de « lever de soleil » (sunrise, lorsque le nouveau TLD est créé) servent en général à favoriser les détenteurs de marques ou autres titres de propriété intellectuelle. L'idée est que, pendant le lever de soleil, seuls ces détenteurs aient le privilège d'enregistrer un nom, les autres attendront. Pour que le registre puisse facilement vérifier la possession d'une marque déposée, il faut un format standard pour les décrire, et c'est ce que contient ce RFC. Il a été écrit par un employé de l'ICANN car il vise surtout un service de l'ICANN, la TMCH (Trade Mark Clearing House).

La TMCH est un registre de marques créé par l'ICANN (voir sa description officielle). Il a suscité d'innombrables débats (par exemple, de quel droit l'ICANN crée un registre mondial faisant autorité, excluant les marques qui n'ont pas voulu passer par ce processus ?) mais ce RFC ne concerne que la partie technique, le format de description de ces marques. Il s'applique a priori aux TLD ICANN comme .pizza ou .maif mais les autres sont libres de s'en servir également. Comme les objets décrits dans ce RFC peuvent être signés, il faut avoir une PKI. Dans le cas des TLD ICANN, elle est décrite dans le document officiel cité plus haut. Les objets eux-mêmes sont décrits en XML, pour pouvoir être utilisés dans le protocole EPP (RFC 5730).

Les objets sont dans les espaces de noms urn:ietf:params:xml:ns:mark-1.0 (abrégé en mark: dans ce RFC) et urn:ietf:params:xml:ns:signedMark-1.0 (abrégé en smd: dans ce RFC).

Les objets XML décrivant les marques incluent des informations sur les personnes ou entités qui gèrent les marques. Il y a ainsi des <mark:holder> et des <mark:contact>, qui comprennent des éléments classiques : nom, adresse postale (qui comprend elle-même ville, pays...), adresse de courrier électronique, etc.

Les marques sont décrites par un élément <mark:mark>. Celui-ci contient le nom de la marque, des références au registre initial (par exemple, en France, l'INPI), le contact et le titulaire (décrits au paragraphe précédent) et d'autres informations utiles aux juristes (comme les biens et services couverts par cette marque, puisque les marques, contrairement aux noms de domaine, sont normalement spécifiques).

Les objets décrivant une marque peuvent être signés, grâce à XML Signature. Voici un exemple (très simplifié, voir la section 2.3 du RFC pour le XML complet) d'une marque avec sa signature :


<?xml version="1.0" encoding="UTF-8"?>
 <smd:signedMark xmlns:smd="urn:ietf:params:xml:ns:signedMark-1.0" id="smd1">
   <smd:issuerInfo issuerID="65535">
     <smd:org>ICANN TMCH TESTING TMV</smd:org>
     <smd:email>notavailable@example.com</smd:email>
     ...
   </smd:issuerInfo>
   <mark:mark xmlns:mark="urn:ietf:params:xml:ns:mark-1.0">
     <mark:trademark>
       <mark:id>00052013734689731373468973-65535</mark:id>
       <mark:markName>Test &amp; Validate</mark:markName>
       <mark:holder entitlement="owner">
         <mark:org>Ag corporation</mark:org>
	 ...
	 <mark:jurisdiction>US</mark:jurisdiction>
         <mark:class>15</mark:class>
       <mark:label>testandvalidate</mark:label>
       ...
       <mark:regNum>1234</mark:regNum>
       <mark:regDate>2012-12-31T23:00:00.000Z</mark:regDate>
     </mark:trademark>
   </mark:mark>
  <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
  ...
  <SignatureMethod
     Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
     ...
     <SignatureValue>
 jMu4PfyQGiJBF0GWSEPFCJjmywCEqR2h4LD+ge6XQ+JnmKFFCuCZS/3SLKAx0L1w
 ...
 </Signature>
 </smd:signedMark>

    

L'élement XML peut aussi être intégralement encodé en Base64 (RFC 4648), et ça sera alors un <smd:encodedSignedMark>.

La syntaxe exacte est spécifiée dans la section 3 du RFC, avec le langage W3C Schema.

Quelles sont les mises en œuvre de ce format ? Le kit de développement logiciel de Verisign l'intègre (il est disponible en ligne), et c'est aussi le cas de Net::DRI (dans Net::DRI::Protocol::EPP::Extensions::ICANN::MarkSignedMark, ouf). Côté serveur, le serveur EPP de Verisign pour des TLD comme .com. D'autres serveurs EPP peuvent utiliser ce format comme REngin, ou celui d'Uniregistry.


Téléchargez le RFC 7848


L'article seul

RFC 7854: BGP Monitoring Protocol (BMP)

Date de publication du RFC : Juin 2016
Auteur(s) du RFC : J. Scudder (Juniper Networks), R. Fernando (Cisco), S. Stuart (Google)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF grow
Première rédaction de cet article le 28 juin 2016


Ce nouveau protocole BMP (BGP Monitoring Protocol) va faciliter le travail des administrateurs réseaux qui font du BGP. Il permet d'obtenir sous une forme structurée les tables BGP. Avant, la solution la plus répandue était d'utiliser l'interface en ligne de commande du routeur (show ip bgp routes sur un Cisco), et d'analyser le résultat depuis son programme, une méthode qui est très fragile, le format de sortie ayant été conçu pour des humains et pas pour des programmes.

Les tables convoitées sont bien sûr la RIB mais aussi des informations comme les mises à jour de routes reçues. BMP donne accès à une table BGP nommée Adj-RIB-In, « Adjacent [peers] Routing Information Base - Incoming », définie dans le RFC 4271, section 1.1. Elle stocke les informations brutes (avant les décisions par le routeur) transmises par les pairs BGP.

BMP fonctionne (section 3) en établissant une connexion TCP avec le routeur convoité. Celui-ci envoie ensuite l'information qu'il veut. Il n'y a pas de négociation ou de discussion au début. Dès que la connexion est établie, le routeur transmet. Il envoie d'abord des messages Peer Up pour chacun de ses pairs, puis des messages Route Monitoring pour toute sa base de routes (la section 5 les décrit plus en détails). Une fois que c'est fait, le routeur transmet des messages indiquant les changements : Route Monitoring en cas d'annonce ou de retrait d'une route, Peer Up ou Peer Down s'il y a des changements chez les pairs. Autres messages possibles : Stats Report pour envoyer des statistiques globales (voir les sections 4.8 et 7), Initiation et Termination pour les débuts et fins de sessions, Route Mirroring pour envoyer verbatim les annonces BGP reçues (c'est une vision de plus bas niveau que Route Monitoring et cela permet, par exemple, d'analyser des annonces BGP syntaxiquement incorrectes, cf. section 6).

Le client BMP ne transmet jamais de message au serveur (au routeur), à tel point que le routeur peut parfaitement fermer la moitié de la connexion TCP, ou mettre sa fenêtre d'envoi à zéro (ou encore, jeter tous les messages qui seraient envoyés). Toute la configuration est dans le routeur.

Le format des messages est décrit en section 4. C'est du classique. On trouve dans le message un numéro de version (actuellement 1), la longueur du message, le type du message (la liste des types est indiquée plus haut) représentée par un entier (0 pour Route Monitoring, 1 pour Stats Report (ou Statistics Report), etc), puis les données. À noter que le type arrive après la longueur, alors que c'est en général le contraire (encodage TLV).

Pour la plupart des messages BMP, il y aura un second en-tête, rassemblant les informations sur le pair (son adresse IP, son AS, etc).

Les différents paramètres numériques sont désormais stockés dans un registre IANA.

Quelques petits mots sur la sécurité pour finir. Pour économiser ses ressources, le routeur peut évidemment (section 3.2) restreindre l'ensemble des adresses IP autorisées à se connecter en BMP à lui, tout comme il peut limiter le nombre de sessions BMP (par exemple, une au maximum par adresse IP, cinq au total). Il peut aussi y avoir des questions de confidentialité (section 11). Bien sûr, la liste des routes dans la DFZ est publique, mais ce n'est pas forcément le cas des peerings privés ou de VPN utilisant BGP comme ceux du RFC 4364. Donc, attention à bien restreindre l'accès.

BMP est en cours d'élaboration depuis pas mal de temps déjà. Résultat, des mises en œuvre ont eu le temps d'apparaitre. Wireshark sait analyser le BMP. Et il existe deux récepteurs (clients) libres, BMPreceiver et OpenBMP. Côté serveur (routeur), Cisco et Juniper savent envoyer du BMP.


Téléchargez le RFC 7854


L'article seul

RFC 7901: CHAIN Query Requests in DNS

Date de publication du RFC : Juin 2016
Auteur(s) du RFC : P. Wouters (Red Hat)
Expérimental
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 24 juin 2016


Lorsqu'un client DNS parle à un résolveur, il pose une question et obtient une réponse. Avant DNSSEC, ce mode de fonctionnement simple était souvent satisfaisant. Mais, avec DNSSEC, il est beaucoup plus fréquent de devoir faire plusieurs requêtes pour obtenir toute l'information nécessaire pour valider les réponses. (Il faut les clés de toutes les zones situées entre la racine et la zone visée.) Cela coûtait cher en latence. Cette extension EDNS expérimentale permet au client DNS de demander au résolveur de chercher et de renvoyer toutes les réponses d'un coup.

Cette extension est particulièrement utile pour le cas de machines terminales hébergeant leur propre résolveur validant (ce qui est la meilleure configuration, question confiance et sécurité). Ce n'est donc pas un hasard si l'auteur du RFC travaille chez Red Hat, système qui est livré par défaut avec une telle configuration. Mais, lorsqu'un tel résolveur validant veut vérifier les informations obtenues sur foo.bar.example, il devra (en supposant qu'il y a une zone par composant du nom de domaine) obtenir la délégation sécurisée de example (dig @la-racine DS example), la clé de example (dig @ns-example DNSKEY example), la délégation sécurisée de bar.example, etc (la clé de la racine, elle, est en dur dans le résolveur, il faut bien partir de quelque part). À faire séquentiellement, cela serait beaucoup de requêtes, donc du temps passé à attendre les réponses. Sur des liens à latence élevée (ce qui arrive souvent aux machines terminales), cela peut être pénible, même si le cache DNS aidera, pour les requêtes suivantes.

L'idée de cette extension (sections 1 et 3 du RFC) est donc que le résolveur validant local ait un forwarder (attention, le RFC utilise un vocabulaire erroné, en donnant à forwarder un sens différent de celui qu'il a dans les RFC 2308 et RFC 8499 ; j'utilise, moi, la terminologie standard). Le résolveur validant local va demander à ce forwarder, grâce à la nouvelle extension EDNS CHAIN, d'envoyer tout d'un coup (tous les DS et DNSKEY nécessaires). Bien sûr, le forwarder, lui, devra faire toutes les requêtes mais, a priori, il a un plus gros cache et sera mieux connecté.

Cette nouvelle extension est donc conçue pour des résolveurs, et est ignorée par les serveurs faisant autorité. Notez que le résolveur validant local peut être un démon autonome (Unbound tournant sur mon portable Unix) ou bien une partie d'une application qui embarquerait ses propres fonctions de résolution de noms.

Le format de l'extension est décrit en section 4 du RFC. C'est une option EDNS (RFC 6891), encodée, comme les autres options EDNS, en TLV. Le type (le code) est 13. La valeur est composée d'un seul champ, l'ancêtre le plus proche (Closest Trust Point) dont on connaisse les informations nécessaires à la validation. Le résolveur validant local a en effet certaines informations (dans sa configuration ou dans son cache) qu'il n'est pas nécessaire de lui envoyer. Dans l'exemple plus haut, si le résolveur validant local connait déjà la clé DNSSEC de example, il mettra dans le champ Closest Trust Point ce nom de domaine, indiquant au forwarder qu'il peut se contenter des informations situées plus bas, dans l'arbre du DNS. Ce nom est encodé dans le format habituel du DNS (qui n'est pas le format texte avec les points).

La section 5 du RFC décrit comment utiliser cette extension au DNS. Si on veut tester les capacités du résolveur qu'on interroge, on peut utiliser une option CHAIN vide (longueur nulle). Si le serveur à qui on a envoyé cette option répond avec la même option nulle, c'est bon. Attention, les serveurs récursifs qui mettent en œuvre CHAIN n'accepteront des requêtes « réelles » (longueur non nulle) qu'au-dessus d'un transport où l'adresse IP source est vérifiée. Le but est d'éviter les attaques par réflexion avec amplification (voir aussi la section 7.2). Pour vérifier l'adresse IP source (ce qui ne se fait normalement pas en UDP), il y a plusieurs solutions, notamment TCP (RFC 7766) et les gâteaux (RFC 7873).

Une fois qu'on a un tel transport, et que le client DNS a testé que le serveur qu'il interroge gère bien CHAIN, on peut y aller. Le client met l'ancêtre le plus proche (dont il a les clés) du nom demandé dans le champ Closest Trust Point. Dans le cas le plus courant (résolveur validant configuré avec une seule clé, celle de la racine), le résolveur « froid », qui vient de démarrer et dont le cache est vide, il commencera par mettre la racine en Closest Trust Point puis, au fur et à mesure qu'il se « réchauffera » (que son cache se peuplera), il pourra mettre des noms plus proches du nom demandé (et donc plus éloignés de la racine). Par exemple, si le résolveur validant local est configuré avec la clé de la racine, et qu'il a appris par les réponses précédentes la clé de example, mais pas celle de bar.example, et qu'il veut des informations sur le nom foo.bar.example, son option CHAIN vaudra {type = 13, longueur = 9, valeur = 0x07 0x65 0x78 0x61 0x6d 0x70 0x6c 0x65 0x00} (la longueur est celle de la partie « valeur » uniquement, le nom example est encodé selon la norme DNS). S'il connaissait également la clé de bar.example, son option CHAIN vaudrait {type = 13, longueur = 13, valeur = 0x03 0x62 0x61 0x72 0x07 0x65 0x78 0x61 0x6d 0x70 0x6c 0x65 0x00}. D'autres exemples figurent en section 9 du RFC.

Faut-il envoyer l'option CHAIN à chaque requête ? On peut mais il est recommandé de se souvenir de quels serveurs la gèrent et de n'envoyer qu'à ceux-ci (autrement, non seulement on fait du travail inutile mais on renseigne des serveurs extérieurs sur l'état de son cache). Comme il existe des middleboxes boguées sur certains trajets, la stratégie de repli du RFC 6891, section 6.2.2 peut être utile.

Et le serveur interrogé, que fait-il ? S'il accepte de répondre à une requête contenant l'extension CHAIN, il doit :

  • Ajouter à la réponse, dans la section Autorité, les enregistrements DNSSEC nécessaires (DS, DNSKEY et NSEC),
  • Mettre une CHAIN dans la réponse, avec la valeur Closest Trust Point mise au nom le plus bas (le plus éloigné de la racine) pour lequel ces informations sont nécessaires. (C'est surtout utile lorsque le serveur n'envoie pas une chaîne complète, par exemple pour économiser le réseau.)

Évidemment, si la question avait une erreur de syntaxe (taille de la partie Valeur inférieure à la Longueur, par exemple), le serveur répond FORMERR (FORmat ERRor).

La section 7 sur la sécurité étudie quelques programmes que peut poser cette extension au DNS. D'abord, mettre en œuvre cette option fatigue davantage le serveur interrogé, en terme de travail et de capacité du réseau. Un serveur est donc toujours libre d'ignorer les options CHAIN et de s'en tenir au service minimum.

Ensuite, comme vu plus haut, les réponses suivant une question qui utilise CHAIN vont être évidemment plus grosses que les réponses DNS habituelles. Il y a donc un risque d'attaques par réflexion avec amplification, si un attaquant usurpe l'adresse IP de sa victime. C'est pour cela que notre RFC impose de ne répondre avec une chaîne complète que si l'adresse IP du client a été vérifiée (par exemple parce qu'il utilise TCP, ou bien les cookies du RFC 7873).

CHAIN a aussi quelques effets sur la vie privée. Le résolveur validant local va indiquer à son forwarder (et à tout espion qui surveille le trafic) comment il est configuré et ce qu'il y a dans son cache.

Il ne semble pas qu'il existe de mise en œuvre de cette option CHAIN pour l'instant, même si c'est en projet pour Go.

Si vous vous intéressez à la conception des protocoles réseaux, notez que cette extension a fait l'objet d'une discussion pour savoir s'il ne valait pas mieux, pour réduire la latence, envoyer toutes les requêtes possibles en parallèle (cette idée a finalement été rejetée).


Téléchargez le RFC 7901


L'article seul

Version 9 d'Unicode

Première rédaction de cet article le 22 juin 2016


Le 21 juin, la nouvelle version d'Unicode est sortie, la 9.0. Une description officielle des principaux changements est disponible mais voici ceux qui m'ont intéressé particulièrement. (Il n'y a pas de changement radical.)

Pour explorer plus facilement la grande base Unicode, j'utilise un programme qui la convertit en SQL et permet ensuite de faire des analyses variées. Faisons quelques requêtes SQL :

ucd=> SELECT count(*) AS Total FROM Characters;
 total  
--------
 128237

Combien caractères sont arrivés avec la version 9 ?


ucd=> SELECT version,count(version) FROM Characters GROUP BY version ORDER BY version;
...
 8.0     |  7716
 9.0     |  7500

7 500 nouveaux pile. Lesquels ?

ucd=> SELECT To_U(codepoint) AS Codepoint, name FROM Characters WHERE version='9.0';
 codepoint |                                    name                                    
-----------+----------------------------------------------------------------------------
...
 U+8BA     | ARABIC LETTER YEH WITH TWO DOTS BELOW AND SMALL NOON ABOVE
...
 U+8E2     | ARABIC DISPUTED END OF AYAH
...
 U+23FB    | POWER SYMBOL
 U+23FC    | POWER ON-OFF SYMBOL
 U+23FD    | POWER ON SYMBOL
 U+23FE    | POWER SLEEP SYMBOL
...
 U+104D8   | OSAGE SMALL LETTER A
 U+104D9   | OSAGE SMALL LETTER AI
 U+104DA   | OSAGE SMALL LETTER AIN
...
 U+17000   | TANGUT IDEOGRAPH-17000
 U+17001   | TANGUT IDEOGRAPH-17001
 U+17002   | TANGUT IDEOGRAPH-17002
...
 U+1F921   | CLOWN FACE
 U+1F922   | NAUSEATED FACE
 U+1F923   | ROLLING ON THE FLOOR LAUGHING
...
 U+1F933   | SELFIE
...
 U+1F953   | BACON
 U+1F954   | POTATO
 U+1F955   | CARROT

On trouve également des écritures entièrement nouvelles comme l'osage ou le tangoute, qui fait 91 % des nouveaux caractères de cette version. Et il y a bien sûr l'habituel lot d'emojis pour faire rire les réseaux sociaux (signe des temps, il y a maintenant un emoji pour selfie). Je ne sais pas pourquoi on ajoute des caractères arabes pré-composés comme le « ARABIC LETTER YEH WITH TWO DOTS BELOW AND SMALL NOON ABOVE » au lieu de permettre sa composition à partir de caractères existants. On note aussi un caractère dont le nom indique qu'il est contesté... (Il existe déjà U+6DD, « ARABIC END OF AYAH » mais on me souffle que le nouveau serait nécessaire au Pakistan.) On note qu'après un long lobbying, les symboles d'allumage et d'extinction de votre machine sont désormais dans Unicode.

Si vous avez les bonnes polices de caractères, voici les caractères pris en exemple plus haut : ࢺ ࣢ ⏻ ⏼ ⏽ ⏾ 𐓘 𐓙 𐓚 𗀀 𗀁 𗀂 🤡 🤢 🤣 🤳 🥓 🥔 🥕

Il n'y a pas que l'ajout de nouveaux caractères, mais aussi quelques légers changements techniques. Par exemple, les règles de passage à la ligne (UAX #14) prennent désormais en compte les gens qui ont un signe $ dans leur nom (comme Travi$ Scott) et les règles IDN (UTS #46) ont corrigé une bogue.


L'article seul

RFC 7855: Source Packet Routing in Networking (SPRING) Problem Statement and Requirements

Date de publication du RFC : Mai 2016
Auteur(s) du RFC : S. Previdi, C. Filsfils (Cisco Systems), B. Decraene, S. Litkowski (Orange), M. Horneffer (Deutsche Telekom), R. Shakir (Jive Communications)
Pour information
Réalisé dans le cadre du groupe de travail IETF spring
Première rédaction de cet article le 22 juin 2016


Traditionnellement, la transmission d'un paquet IP au routeur suivant était faite uniquement sur la base de l'adresse de destination, sans tenir compte du reste du paquet. Et la décision est prise par chaque routeur, sur le trajet, en complète indépendance. Or, l'émetteur d'un paquet voudrait souvent décider de la route suivie ou, au minimum, l'influencer. C'est pour cela qu'il existe des mécanismes de routage par la source (source routing). Leurs défauts et leurs limites ont mené à la recherche d'une meilleure solution, dite SPRING (Source Packet Routing In NetworkinG). Ce RFC est la description du problème.

Notez que le terme « source » a, pour SPRING, un sens plus large que lorsqu'on parle habituellement de source routing. Dans ce dernier cas, la source était uniquement l'émetteur original. Pour SPRING, la source est l'endroit où on définit la politique de routage ultérieur, elle peut se situer au milieu du trajet.

Avant SPRING, il y avait plusieurs solutions permettant à la source de décider du routage mais aucune n'a été largement déployée (à part MPLS). C'est dû en partie à leur manque de souplesse, en partie à des problèmes de sécurité.

La future solution SPRING doit être un meilleur système (section 1 du RFC), et déployable de manière incréméntale (il ne serait évidemment pas réaliste de devoir changer tout l'Internet). En outre, l'état doit être maintenu dans le paquet lui-même, pas dans les routeurs intermédiaires. L'expérience de l'Internet a en effet largement montré que pour faire marcher un grand réseau complexe, il ne faut pas maintenir d'état dans les nœuds intermédiaires.

SPRING devra être assez général marcher avec plusieurs mécanismes de transmission des paquets (dataplanes, cf. section 2). Les principaux visés sont MPLS et IPv6 avec un nouvel en-tête de routage (cf. RFC 2460, section 4.4).

La section 3 présente plusieurs scénarios d'usage, pour montrer pourquoi un système tel que SPRING est utile. Il y a par exemple la création de tunnels pour faire des VPN (RFC 4364).

Il y a aussi le reroutage rapide de paquets (FRR, Fast ReRoute), et bien sûr l'ingéniérie de trafic. Pour ce dernier scénario, notre RFC demande que la future solution SPRING permette des options strictes (le paquet suit exactement le chemin spécifié) ou laxistes (le paquet suit à peu près le chemin spécifié), puisse fonctionner en centralisé (SDN) ou en décentralisé, etc.

Une des raisons du peu de déploiement des solutions de routage par la source est évidemment la sécurité (section 4 du RFC). SPRING met le chemin désiré dans le paquet (pour éviter de garder un état dans le réseau). Or, si on suit aveuglément les desiderata de chaque paquet, on ouvre la voie à des tas d'attaques. Par exemple, un paquet spécifie un détour considérable par un autre pays, et cela occupe pour rien les liaisons internationales. Un paquet spécifie un trajet qui boucle et les routeurs qui lui obéiraient feraient une attaque par déni de service contre eux-mêmes.

Le RFC impose donc que SPRING fournisse un mécanisme de « domaines de confiance » avec des frontières bien claires. Si un paquet vient d'un domaine de confiance, on lui obéit. S'il vient de n'importe où sur l'Internet, on ignore ses demandes (ou bien on vire ces options de routage par la source lorsque le paquet change de domaine).

La réalisation concrète de SPRING sur un système de transmission donné (comme MPLS ou IPv6) doit également documenter les risques spécifiques à ce dataplane. Par exemple, MPLS est en général utilisé uniquement à l'intérieur d'un domaine contrôlé et connu (le réseau d'un opérateur) alors qu'IPv6 est de bout en bout donc pose davantage de risques (mais il dispose de possibilités supplémentaires, comme la signature cryptographique des en-têtes).

Il faut maintenant attendre les RFC décrivant les solutions, ils sont en cours de développement dans le groupe SPRING.


Téléchargez le RFC 7855


L'article seul

RFC 7874: WebRTC Audio Codec and Processing Requirements

Date de publication du RFC : Mai 2016
Auteur(s) du RFC : JM. Valin (Mozilla), C. Bran (Plantronics)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF rtcweb
Première rédaction de cet article le 21 juin 2016


Ce très court RFC expose les exigences en matière de codec audio pour WebRTC. Opus et G.711 sont ainsi obligatoires.

WebRTC permet de communiquer (texte, audio et vidéo) entre deux machines, typiquement via les navigateurs Web (ainsi, Firefox et Chrome sont tous les deux capables de faire du WebRTC.) On sait qu'il existe un grand nombre de moyens de représenter les sons sous forme d'un flux de données numériques et, pour que la communication puisse se faire, il faut que les participants aient au moins un de ces moyens en commun. C'est le but de ce RFC. D'autres codecs peuvent évidemment être gérés par le logiciel mais ceux-ci sont obligatoires (section 3 du RFC) :

  • Opus (RFC 6716), avec le format du RFC 7587.
  • G.711, avec le format de la section 4.5.14 du RFC 3551.
  • La gestion du bruit de fond du RFC 3389. (Sauf pour Opus, qui a sa propre gestion.)
  • Le format audio/telephone-event du RFC 4733 (DTMF), qui permet d'envoyer les indispensables signaux « si vous voulez de la musique d'attente pendant une heure, tapez 1, si vous voulez parler à un incompétent sous-payé qui ne comprendra pas votre problème, tapez 2 ».

Les autres codecs facultatifs sont décrits dans le RFC 7875, ce qui a permis à chacun de faire citer son codec favori.

Notre RFC spécifie également le niveau sonore (section 4). Contrairement aux recommandations UIT G.169 et G.115, il n'est pas constant car il dépend de la bande passante.

Il y a aussi une mention de la suppression d'écho (section 5 du RFC), mais sans solution unique imposée.


Téléchargez le RFC 7874


L'article seul

The DAO, Ethereum, et l'attaque de juin 2016

Première rédaction de cet article le 20 juin 2016


Vendredi 17 juin 2016, une attaque spectaculaire contre l'organisation The DAO a eu lieu, menant à la soustraction d'environ un tiers de ses fonds. Quelles leçons à en tirer ?

Si vous connaissez au moins un peu The DAO et Ethereum, vous pouvez lire tout de suite mes réflexions sur cette crise. Si vous ne connaissez pas, vous pouvez lire en anglais la bonne explication de Robert Graham ou bien en français les articles de Wikipédia sur Ethereum et les contrats.

Comme d'habitude lorsqu'un gros problème de cybersécurité est publié, on trouve du grand n'importe quoi dans les médias ou sur les rézosocios. Il est donc important de commencer par être précis sur les faits :

  • La bogue n'était pas dans la chaîne de blocs Ethereum, ni même dans un autre élément d'infrastructure comme le compilateur Solidity. Elle était uniquement dans un contrat (un programme stocké dans la chaîne Ethereum), le contrat The DAO. Dire qu'Ethereum est menacé, ou que le concept de chaîne de blocs est menacé, revient à affirmer que PHP, voire le Web entier, est menacé parce qu'on a trouvé une bogue dans WordPress.
  • Le voleur n'a pas réussi à récupérer les fonds soustraits à The DAO et il n'est pas sûr qu'il y arrive jamais. On est loin du casse du siècle. La transparence de la chaîne de blocs, qui crée bien des vulnérabilités, fournit également les moyens d'empêcher le voleur de jouir du fruit de son forfait.
  • L'attaque n'a rien à voir avec les problèmes de Mt. Gox, souvent cités par des journalistes paresseux (« crypto-monnaie? Citons MtGox ! »). Il ne s'agit pas du piratage (ou de la malhonnêteté) d'un site centralisé particulier, mais d'une faille d'un contrat, un concept spécifique à Ethereum et qui n'a donc pas de vrai équivalent jusqu'à présent.

Mais cela ne veut pas dire que cette bogue est juste un détail sans importance et qu'on peut passer. Il s'agit d'une crise grave, dont il faudra tirer les leçons. D'abord, sur l'aspect technique (mais je parle des questions financières, légales et de gouvernance par la suite). L'origine du problème est une bogue dans le code de The DAO (pour les cœurs bien accrochés, voici les explications techniques complètes). C'est une banalité de noter qu'on ne sait pas écrire du logiciel sans bogues. Tout logiciel a des bogues et, avant de confier des fonds à un contrat, il faut garder ce point en tête. Un des rares cas dans cette affaire où les pessimistes systématiques (« ce n'est pas moi qui a inventé ce truc, donc ça va rater ») avaient raison est quand ils pointaient le fait qu'il y aura forcément des bogues dans les contrats et, qu'en l'absence de mécanisme de recours, on aura du mal à en gérer les conséquences.

Cela ne veut pas dire qu'il faut baisser les bras et renoncer à programmer. Mais il faut changer, et d'état d'esprit, et sans doute de techniques utilisées. Emin Gün Sirer fait remarquer à juste titre que l'écriture d'un contrat devrait ressembler à celle du code d'un avion ou d'une centrale nucléaire, pas à celle d'un site Web avec images et CMS. Or, aujourd'hui, pas mal de programmeurs de contrat sont plutôt dans la mentalité « si le code semble faire vaguemement ce qu'on veut, c'est bon », qui a mené à pas mal de désastres de sécurité sur le Web. Du point de vue des techniques utilisées, le même Sirer a raison de dire qu'il faut se poser la question des langages de programmation. Un langage impératif comme Solidity est-il vraiment la meilleure solution pour faire des contrats sûrs, et ne faudrait-il pas plutôt utiliser des langages plus adaptés, par exemple plus fonctionnels, inspirés d'Haskell ? Ces langages ont un fossé plus réduit entre la spécification et l'exécution. Plus radicale, la vérification formelle des contrats devrait-elle être la norme ? A priori oui, mais soyons prudents : les mécanismes de vérification formelle des programmes sont lourds et compliqués et ont leurs propres bogues.

En parlant de spécification, Vitalik Buterin a fait un très bon article pour expliquer qu'une bogue, c'est par définition une déviation par rapport à la spécification, et que réduire le nombre de bogues implique d'être clair dans la spécification, ce qui est déjà un défi considérable. Dans un message non authentifié, un individu se présentant comme l'attaquant prétend ainsi que, le code du contrat étant sa loi, par définition, toute opération faite avec le contrat The DAO est légale, y compris son vol. Il est bien sûr de mauvaise foi, mais on peut noter qu'il n'est pas possible de lui opposer une spécification précise de ce que le contrat était censé faire.

Autre leçon technique, un rappel que la complexité est l'ennemie de la sécurité. Le code de The DAO comprenait de nombreuses fonctions (comme celle permettant de retirer ses fonds, à l'origine de la bogue), ce qui augmentait la probabilité d'avoir une bogue. J'ai toujours expliqué que le terme de smart contract était dangereux car il encourageait les programmeurs à faire du code compliqué, alors qu'un bon contrat est au contraire trivial à lire et à analyser. Un programmeur de contrat ne devrait pas être admiré pour ses hacks astucieux mais au contraire pour sa capacité à faire du code ennuyeux et évident. (Je pensais à la validation d'un contrat par ses utilisateurs, mais ce raisonnement s'applique également à la sécurité.)

A posteriori, il est clair qu'on est passé trop rapidement du petit contrat « Hello, World », à un gros truc complexe, avec plein de fric, comme The DAO. C'est un peu comme si, immédiatement après la traversée de la Manche par Blériot, on avait lancé sur l'Atlantique un avion de 500 passagers payants...

Il y a aussi des leçons à tirer de l'excessive focalisation sur l'argent, commune à une bonne partie de la communauté Ethereum, et aux médias. Les médias ont surtout présenté cette crise sous son angle financier (The DAO a perdu 50 millions, l'ether a baissé de 50 %, etc) alors que la chaîne de blocs Ethereum, contrairement à celle de Bitcoin, ne sert pas qu'à des transactions financières. Des tas de contrats ne consomment des ethers que pour acheter l'essence (le mécanisme par lequel on paie pour l'exécution des contrats). Se focaliser sur les contrats à caractère financier, comme The DAO, empêche de voir toutes les potentialités de la chaîne de blocs (plusieurs articles ont ainsi présenté, de manière erronée, Ethereum comme étant juste « une crypto-monnaie concurrente de Bitcoin »). Et, évidemment, stocker autant d'argent allait attirer les voleurs. Bref, tant que les articles sur Ethereum continueront à mettre en avant le cours de l'ether en comparant avec la monnaie étatique traditionnelle, on n'arrivera pas à comprendre toutes les potentialités (disruptives, forcément disruptives) de la chaîne de blocs.

Il y a également bien des leçons à tirer de la crise de The DAO en terme de gouvernance de la chaîne de blocs. Normalement, les contrats « intelligents » étaient censés se gouverner tout seuls. Le code est la loi, il est exécuté fidèlement par la la machinerie Ethereum, et il n'y a donc pas de place pour l'interprétation ou l'action humaine. Face à la crise et au vol d'ethers, que fallait-il faire ? En schématisant, il y avait deux positions : les principiels voulaient qu'on laisse les choses se produire. The DAO avait une bogue, ils perdent leur argent. Selon eux, toute autre solution aurait mis en cause ce qui était justement l'un des principaux arguments en faveur des contrats, leur côté automatique, insensibles aux passions et aux manipulations humaines. Les réalistes, de l'autre côté, considéraient qu'on ne pouvait pas rester sans rien faire et voir le voleur emporter l'argent. Ils prônent un fork, c'est-à-dire une scission délibérée de la chaîne : une nouvelle version des logiciels est produite, appliquant des règles différentes (par exemple empêchant les transferts depuis le compte du voleur). Certains nœuds du réseau adoptent le fork, d'autres pas. Si les premiers sont plus nombreux, leur chaîne est considérée comme la bonne, les autres n'ont plus qu'à se soumettre, ou à partir et faire leur chaîne de leur côté (ce qui serait évidemment une grosse tuile pour Ethereum). Vu superficiellement, cela serait une décision centrale dans un système, la chaîne de blocs, conçu justement pour éviter cela. Mais si une telle décision peut en effet être prise par un petit groupe de gens (en gros, les développeurs des logiciels qui font marcher la chaîne ; notez que, contrairement à Bitcoin, il n'existe pas qu'un seul logiciel), sa mise en œuvre, elle, dépend de tous les gens qui gèrent des nœuds (enfin, surtout des mineurs), et qu'il faut convaincre. C'est pour cela que les articles de Buterin, par exemple, insistent sur le fait que les développeurs comme lui n'imposent pas, ils proposent. Une attitude tout à fait opposée était celle de de Stephan Tual qui, dans ce tweet et celui-ci accusait tout opposant (ceux qui refusent le fork, les principiels), d'être forcément en cheville avec le voleur, et appelait même à les dénoncer ! Ce délire robespierro-stalinien a certainement fait bien plus de mal à Ethereum que la bogue elle-même.

Un des éléments du débat était aussi le statut particulier de The DAO. Pourquoi forker juste pour eux, disent les principiels ? Fera-t-on pareil à chaque fois qu'un contrat a une bogue ? Le seul argument des réalistes est la taille : The DAO est « too big to fail ». Après que tant de gens, aussi bien à l'intérieur de la communauté Ethereum qu'à l'extérieur, aient entretenu une certaine confusion entre Ethereum et The DAO, il est difficile de laisser tomber le canard boiteux. Même si cela a mené à des injustices flagrantes, comme l'appel lancé par Slock.it à faire une attaque par déni de service contre toute la chaîne Ethereum, pour ralentir l'attaquant (cette boîte a fait une bogue, et la fait payer à tout le monde).

Cette crise pose donc évidemment la question de ce mode de gouvernance « le code [des contrats] est la seule règle ». Thibault Verbiest a ainsi estimé que ce n'était pas souhaitable et qu'il fallait une régulation étatique des chaînes de blocs.

Les habituels ricaneurs ont évidemment proclamé qu'ils avaient bien raison, et que la chaîne de blocs était fichue, et que cela les faisait bien rigoler (manger le popcorn en regardant le film est évidemment plus facile que de travailler). Mais on est loin d'une telle conclusion. Si The DAO ne survivra probablement pas à cette crise, l'idée de contrat, les autres contrats et Ethereum lui-même sont bien vivants et continueront, une fois la crise actuelle digérée. Les contrats sont une innovation et, comme toute innovation, les débuts sont un peu cahotiques. Lors des débuts de l'aviation, le projet le plus sérieux, celui qui avait de très loin le plus gros budget et la plus grande attention des médias était celui de Langley. Le 8 décembre 1903, son projet se termine après un nouveau crash, qui mène beaucoup de gens à affirmer que l'aviation est morte. Une semaine après, le premier avion des frères Wright décolle avec succès... Matthew Spoke estime même que cette attaque est une bonne chose, elle va forcer à être plus sérieux.

PS : j'ai oublié d'en parler initialement, mais voici la déclaration de conflit d'intérêt. Je ne possède pas (et n'ai jamais possédé) de tokens (de parts) de The DAO.


L'article seul

RFC 7871: Client Subnet in DNS Queries

Date de publication du RFC : Mai 2016
Auteur(s) du RFC : C. Contavalli, W. van der Gaast (Google), D. Lawrence (Akamai Technologies), W. Kumari (Google)
Pour information
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 20 juin 2016
Dernière mise à jour le 13 juin 2022


Ce nouveau RFC décrit une option EDNS qui permet à un client DNS d'indiquer au serveur l'adresse IP d'origine de la requête DNS. Pourquoi diable ferait-on cela, au prix de la vie privée ? Cette option est surtout utile dans le cas de l'utilisation d'un gros résolveur DNS public (comme Google Public DNS) et d'un CDN.

Pour comprendre pourquoi, il faut se rappeler que le DNS ne fonctionne pas de bout en bout. La machine de M. Michu émet des requêtes DNS à un résolveur (en général fourni par le FAI ou par le réseau local, mais certaines personnes, victimes du marketing, préfèrent les résolveurs publics comme OpenDNS, plus lointains et plus lents). Ce résolveur, à son tour, interroge les serveurs faisant autorité. Si M. Michu voulait se connecter à un site Web pour voir des vidéos de chats, il est possible qu'un nouvel acteur soit présent, le CDN (comme Akamai) qui héberge les dites vidéos. Les serveurs DNS faisant autorité pour le CDN renvoient souvent une adresse IP différente selon l'adresse IP du résolveur qui les interroge. Si l'adresse IP du client est au Sénégal, l'adresse IP du serveur de vidéos qui sera renvoyée sera celle du centre de données le plus « proche » du Sénégal. En temps normal, cela fonctionne plus ou moins. Bien sûr, le serveur DNS faisant autorité pour le CDN ne voit pas le « vrai » client, M. Michu, il voit le résolveur DNS utilisé mais les deux sont proches : si M. Michu est en Colombie, son résolveur DNS le sera aussi. Voici un exemple, vu avec les sondes RIPE Atlas, où on demande, au Sénégal (SN) puis en Colombie (CO) l'adresse IP de www.elysee.fr, hébergé sur un CDN états-unien :

% blaeu-resolve --country SN www.elysee.fr
[207.123.59.254 209.84.7.126 8.27.7.254] : 1 occurrences 
[209.84.7.126 8.253.3.254 8.27.7.254] : 1 occurrences 
[4.26.233.254 4.26.236.126 8.254.119.126] : 1 occurrences 
[207.123.59.254 209.84.7.126 8.253.3.254] : 1 occurrences 
[207.123.59.254 8.26.223.254 8.27.7.254] : 1 occurrences 
Test #4106632 done at 2016-06-15T22:52:44Z

% blaeu-resolve --country CO www.elysee.fr
[192.221.116.253] : 3 occurrences 
[205.128.71.253 4.27.25.125 8.27.155.126] : 1 occurrences 
[206.33.52.253 209.84.20.126 8.253.16.126] : 1 occurrences 
Test #4106633 done at 2016-06-15T22:52:46Z
  

On voit qu'on a obtenu des adresses IP très différentes et, espérons-le, adaptées à chaque pays.

Autre exemple, avec un service de PowerDNS, qui renvoyait (il semble ne plus marcher) une géolocalisation du client. Ici, j'utilise dig depuis deux machines différentes, une en France et l'autre aux États-Unis :

%  dig +short -t txt www.geo.powerdns.com 
"bonjour france 2a01:db8:8bd9:85cb:21e:8cff:fe76:29b6/26"

% dig +short -t txt www.geo.powerdns.com 
"hello USA 204.62.14.153/22"

On voit que le résolveur que j'utilise (qui, à chaque fois, était sur le réseau local de la machine cliente), a bien été géolocalisé. Si j'utilise un résolveur public :

%  dig @8.8.8.8 +short -t txt www.geo.powerdns.com  
"bonjour france XX.YY.152.0/11"

Ici, cela a marché car Google Public DNS a des serveurs en France. Si cela n'avait pas été le cas, j'aurais été géolocalisé... quelque part ailleurs.

Tout change (section 1 du RFC) si on utilise un résolveur DNS public comme Verisign Public DNS ou bien Yandex DNS. Dans ce cas, l'adresse IP du résolveur, vue par le serveur faisant autorité pour le CDN, n'a plus grand'chose à voir avec celle du vrai client, elle peut être très lointaine. Les serveurs DNS faisant autorité risquent donc de renvoyer une adresse IP de serveur Web qui ne soit pas optimale. Certes, tout marchera quand même mais ça sera plus lent alors qu'officiellement, le but des CDN est d'accélerer l'arrivée de la vidéo du chat (non, de François Hollande).

On voit que ce RFC résout donc un problème que n'a pas tout le monde. Seuls ceux qui se servent d'un résolveur public lointain, et qui visitent des sites Web hébergés sur un CDN (en général les gros sites commerciaux) auront le problème. C'est une des raisons qui expliquent que ce RFC a pas mal trainé (voyez cet article, qui date de plusieurs années) à l'IETF : son intérêt n'est pas évident, et il y avait beaucoup de contestation. Mais l'IETF a finalement choisi de documenter cette option (qui est effectivement déployée), sans forcément la recommander.

Donc, comment est-ce que cela résout le problème décrit plus haut ? L'idée est de standardiser une option EDNS que les résolveurs publics ajouteront dans leur requête aux serveurs faisant autorité, et qui indiquera la « vraie » adresse IP d'origine (section 5 du RFC). Imaginons que M. Michu ait pour adresse IP 192.0.2.56 et qu'il utilise Google Public DNS. Ce dernier va transmettre la requête au CDN et ajoutera l'option Client Subnet (ce n'est donc pas M. Michu qui le fera). Le serveur DNS du CDN verra une requête arriver de, mettons, 74.125.17.1. L'option EDNS Client Subnet contiendra le préfixe de l'adresse IP de M. Michu, 192.0.2.0/25. Il saura alors qu'il doit adapter ses réponses, non pas au préfixe 74.125.17.0/24 (son client direct) mais au préfixe 192.0.2.0/25 (le vrai client). C'est donc une option entre résolveur et serveur faisant autorité, pas entre machine terminale et résolveur.

Le format de l'option est décrite dans la section 6 du RFC. Comme toutes les options EDNS (RFC 6891), elle est encodée en TLV : le type est 8, la valeur est composée de :

  • La famille d'adresses utilisée (IPv4 ou IPv6, l'exemple ci-dessus utilisait IPv4),
  • La longueur du préfixe indiqué dans la requête DNS (25 bits dans l'exemple ci-dessus),
  • La longueur significative du préfixe dans la réponse DNS (elle est mise à zéro dans les requêtes),
  • Le préfixe lui-même (192.0.2.0 dans l'exemple plus haut).

La section 7 du RFC décrit les détails du protocole. Le résolveur va mettre dans son cache les réponses du serveur faisant autorité. Normalement, l'information dans le cache est indexée par le nom de domaine (et le type de données demandé, mais je simplifie). Avec ECS (EDNS Client Subnet), l'information est indexée par le couple {nom de domaine, préfixe IP}. En effet, deux requêtes pour le même nom peuvent avoir donné des résultats différents selon le préfixe IP (c'est bien le but !).

Le résolveur qui met cette option doit choisir la longueur du préfixe envoyé. Il tient compte de deux choses :

  • La capacité de son cache : si le préfixe est trop spécifique, le cache devra stocker davantage de données (imaginons en IPv6 une réponse différente par adresse IP : le cache pourrait avoir à stocker 2^128 réponses par nom de domaine !)
  • La protection de la vie privée des utilisateurs. ECS la menace déjà, n'aggravons pas les choses. En utilisant un préfixe assez général, on limite l'indiscrétion.

Mais l'affaire est un peu plus compliquée : le client d'origine (la machine de M. Michu, le stub resolver) a pu mettre une option ECS elle-même (ce n'est pas courant aujourd'hui mais ça pourrait arriver). Dans ce cas, le résolveur doit en tenir compte et mettre comme longueur la plus courte entre celle demandée par le client (a priori pour protéger sa vie privée) et celle que le résolveur aurait choisi tout seul.

Si la requête reçue par le résolveur avait l'option ECS et une longueur de zéro, cela indique le souhait du client qu'on ne transmette pas son adresse IP du tout. Le résolveur doit évidemment respecter cette demande.

Et le serveur faisant autorité, que doit-il mettre dans sa réponse ? (S'il envoie des réponses différentes selon la source, et s'il gère l'option ECS, EDNS Client Subnet ; autrement, c'est simple, il ne fait rien de particulier.) Il met une option ECS dans la réponses, avec :

  • La famille, la longueur du préfixe demandé, et le préfixe identiques à celui de la requête,
  • Une longueur effective (scope prefix length) qui indique pour quel préfixe la réponse est valable. Cette longueur effective peut être supérieure à la longueur demandée (le préfixe était trop général, pense le serveur), ou inférieure (le préfixe était inutilement spécifique, le serveur ne varie pas ses réponses à ce point).

(Notez que le RFC est bien plus détaillé que ce résumé, car il y a plein de cas rigolos. Je me suis limité à une présentation générale, je n'essaie pas de traduire tout le RFC.)

En recevant cette réponse, le résolveur va la mettre dans son cache, en tenant compte de la longueur du préfixe (et, bien sûr, le résolveur transmet la réponse à son client). Une réponse valable pour 2001:db8:43:bef::/64 ne pourra pas être utilisée pour le client 2001:db8:43:bed::1. Quelle longueur sera utilisée pour indexer le cache ? Celle demandée ou bien celle effective ? Les régles exactes sont un peu complexes (il faut tenir compte de la longueur effective, mais aussi des limites du cache, qui ne veut pas stocker une réponse pour des préfixes trop spécifiques), je vous renvoie à la section 7.3.1 du RFC.

Les questions ultérieures des clients du résolveur pourront recevoir une réponse tirée du cache, sans repasser par les serveurs faisant autorité. Mais ECS impose d'organiser le cache différemment. Avec le DNS classique, si on a dans le cache la réponse à une question pour cat.example.com (je simplifie en ne tenant pas compte du type des données DNS), et qu'on reçoit une question pour ce nom, on peut répondre avec les données du cache. Avec ECS, le cache doit en plus tenir compte du préfixe stocké avec la réponse, et de l'adresse IP du client.

Et avec DNSSEC, ça se passe comment (section 9 du RFC) ? Les CDN ne signent pas leur zone en général. Mais s'ils s'y mettent (il le faudrait), il y aura quelques précautions à prendre.

Et avec le NAT ? Il n'y a normalement pas de problèmes, sauf évidemment si le résolveur est NATé et ne le sait pas : il mettrait, dans ce cas, une adresse privée dans l'option ECS, ce qui serait idiot.

Reste à regarder les problèmes de sécurité et notamment de vie privée. ECS diminue forcément votre vie privée. Il ajoute en effet une information qui n'était pas là sans lui (et le RFC 8165 dit bien que c'est mal). C'est pour limiter les dégâts que le RFC recommande aux résolveurs qui ajoutent une option Client Subnet de la limiter aux 24 premiers bits en IPv4 et aux 56 premiers en IPv6. Un résolveur qui connait bien la topologie de son réseau peut faire encore mieux : s'il sait que tous ses clients sont proches, et couverts par le même /20, il peut ainsi ne transmettre que les vingt premiers bits, sans diminuer l'intérêt du service.

Notez que, avec les clients DNS d'aujourd'hui, votre résolveur mettra votre adresse IP dans ses requêtes sortantes. On peut en sortir (opt-out en mettant une option ECS avec une longueur nulle) mais cela nécessite une action explicite (que ne permettent pas forcément les clients DNS actuels, notamment les stub resolvers, ceux qui sont intégrés dans le système d'exploitation). Le RFC recommande donc que cette option ECS soit désactivée par défaut, en raison de ces risques.

L'option ECS peut être vue par les serveurs faisant autorité, mais également par les tiers qui espionnent le trafic. Pour empêcher cela, il faudra déployer des solutions de chiffrement du trafic DNS, comme celles sur lesquelles travaille le groupe DPRIVE.

Un bon article sur les problèmes de vie privée liés à ECS est le « Understanding the Privacy Implications of ECS » de Panagiotis Kintis, Yacin Nadji, David Dagon, Michael Farrell et Manos Antonakakis. Un autre bon article sur cette question est celui de Frank Denis.

Voyons maintenant cette option ECS en action. Elle est par exemple utilisée par Google dont le résolveur public ajoute cette option avant de l'envoyer aux serveurs faisant autorité. Mais on trouve une liste d'utilisateurs plus détaillée sur le site de promotion de la technologie.

Parmi les logiciels libres qui la mettent en œuvre, on note la bibliothèque getdns. Ou bien le programme dig livré avec BIND. Voici un exemple avec la nouvelle option +subnet de dig (prise sur un BIND 9.11, l'option était déjà en 9.10) :

% dig +subnet=8.189.152.0/25 @ns-1568.awsdns-04.co.uk  A www.amazon.com 
...
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; CLIENT-SUBNET: 8.189.152.0/25/0
...
;; ANSWER SECTION:
www.amazon.com.         60 IN A 54.239.25.192
...

Et ce que voit le serveur faisant autorité ? On peut le savoir en faisant tourner tcpdump sur un serveur faisant autorité qu'on contrôle, mais il y a plus simple, utiliser un domaine dont les serveurs faisant autorité renverront l'information ECS qu'ils ont reçu. J'en connais trois, qui répondent aux requêtes DNS de type TXT :

  • _country.pool.ntp.org,
  • whoami​.​fastly​.​net et whoami​6.​fastly​.​net,
  • et mon ecs.dyn.bortzmeyer.fr (qui utilise le logiciel Drink).

Voici un exemple :


% dig ecs.dyn.bortzmeyer.fr TXT
...
;; ANSWER SECTION:
ecs.dyn.bortzmeyer.fr.	0 IN TXT "78.196.62.0/24"

;; Query time: 15 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: lun. juin 13 14:08:23 CEST 2022

    

Un service analogue, edns-client-sub.net renvoie sous forme d'un objet JSON les options ECS reçues, ainsi que la géolocalisation. Ici, mon résolveur n'envoie pas ECS :

% dig +short -t txt edns-client-sub.net
"{'ecs':'False','ts':'1447875683.94','recursive':{'cc':'FR','srcip':'XX.YY.152.187','sport':'37512'}}"

Mais Google, lui, le fait (et heureusement, sinon j'aurais été géolocalisé en Belgique, où se trouve le serveur de Google utilisé) :

% dig @8.8.8.8 +short -t txt edns-client-sub.net 
"{'ecs_payload':{'family':'1','optcode':'0x08','cc':'FR','ip':'XX.YY.152.0','mask':'24','scope':'0'},
     'ecs':'True','ts':'1447875689.25','recursive':{'cc':'BE','srcip':'74.125.47.152','sport':'41735'}}"

Mais ce service ne semble plus fonctionner, en juin 2022.

Enfin, voici un exemple de code Python qui coupe ECS chez le résolveur, pour protéger la vie privée de l'utilisateur. Il utilise la bibliothèque dnspython :

opt = dns.edns.ECSOption(address='', srclen=0) # Disable ECS (RFC 7871, section 7.1.2)
options = [opt]
message = dns.message.make_query(qname, dns.rdatatype.from_text(qtype),
       use_edns=True, options=options)
    

Téléchargez le RFC 7871


L'article seul

RFC 7824: Privacy considerations for DHCPv6

Date de publication du RFC : Mai 2016
Auteur(s) du RFC : S. Krishnan (Ericsson), T. Mrugalski (ISC), S. Jiang (Huawei Technologies)
Pour information
Réalisé dans le cadre du groupe de travail IETF dhc
Première rédaction de cet article le 12 juin 2016


Le protocole DHCP sert à transmettre à une machine qui vient de se connecter au réseau, des informations utiles pour sa connexion. Il est surtout connu pour son utilisation avec IPv4 mais DHCP existe aussi pour IPv6 (il est normalisé dans le RFC 8415). Comme son équivalent IPv4, DHCP pour IPv6 pose un certain nombre de problèmes de vie privée, que ce RFC explore.

Il fait donc partie de la série de RFC développés après le RFC 6973 et, surtout, après les révélations de Snowden qui ont mené l'IETF à s'engager plus vigoureusement contre la surveillance massive. Ce RFC ne propose pas de solutions (elles sont décrites dans le RFC 7844), il décrit le problème.

Le problème fondamental est le même qu'en IPv4 (RFC 7819) : le client DHCP, lorsqu'il vient de se connecter à un réseau et émet des requêtes, publie des informations trop détaillées, dont certaines sont des véritables identificateurs stables (cf. section 2 de notre RFC), permettant au serveur DHCP, mais aussi à toute machine qui écoute le réseau, de suivre à la trace une machine donnée. Au contraire des solutions comme SLAAC, où le client est purement passif, DHCP impose au client d'annoncer son existence et de donner des informations. Bref, si vous avez déjà lu le RFC équivalent pour IPv4, le RFC 7819, vous n'apprendrez pas grand'chose de nouveau.

La section 3 du RFC donne une liste aussi complète que possible des options DHCPv6 qui peuvent servir à la surveillance. D'abord, l'adresse IP source. Bon, elle ne fait pas partie de DHCP à proprement parler et tout protocole va la publier, puisqu'elle apparait dans tous les paquets émis. (Dans le cas de DHCP, la requête du client est émise depuis une adresse locale au lien, link-local, celles qui commencent par fe80::.) Néanmoins, l'adresse IP source mérite une mention car certains mécanismes de génération d'une adresse IPv6 peuvent poser des problèmes de vie privée (cf. RFC 7721). Il faut donc utiliser des mécanismes comme ceux du RFC 8981 ou du RFC 7217.

L'exemple suivant est celui d'une option particulièrement dangereuse pour la vie privée, Client Identifier, qui envoie au serveur le DUID (DHCPv6 Unique Identifier, RFC 8415, section 11) du client. Comme son nom l'indique, il identifie chaque machine de manière unique et, par défaut, il est stable. La méthode la plus courante pour le générer est d'utiliser l'adresse MAC, elle-même un identificateur unique et stable. Même si on prend la précaution de changer l'adresse MAC, le DUID ne change pas. C'est donc un excellent moyen de suivre une machine, cassant complètement la sécurité de techniques comme celle du RFC 8981.

Également dangereuse, l'option Client FQDN (RFC 4704) qui envoie un FQDN.

Certaines options peuvent être moins clairement indiscrètes mais peuvent néanmoins révéler indirectement l'identité du client. C'est le cas de l'option Option Request qui dit au serveur quelles options on souhaiterait qu'il utilise. Cette liste de choix peut servir à distinguer entre plusieurs clients DHCP : toutes les fois où il y a un choix dans un protocole, il y a une possibilité de fingerprinting.

Certaines options n'envoient pas directement un identificateur unique mais envoient de l'information sur une classe à laquelle appartient la machine. Par exemple, les options Vendor Class et Vendor-specific Information (sections 21.16 et 21.17 du RFC 8415), ou encore l'option Client System Architecture (RFC 5970), indiquent le matériel et le logiciel du client.

On n'a vu ici que des options allant du client vers le serveur mais l'inverse existe aussi, et certaines options qu'un serveur peut envoyer sont révélatrices (par exemple Civic Location, RFC 4776). Mais les problèmes de vie privée du serveur sont moins graves que ceux du client et notre RFC passe donc rapidement (voir aussi la section 5.3).

En dehors des options DHCP, certains mécanismes utilisés dans le cadre de DHCP peuvent être bien indiscrets. C'est par exemple le cas de la demande d'adresses temporaires (RFC 8415, section 6.5), pourtant bien intentionnée. Le but était de pouvoir obtenir des adresses qui ne soient pas stables, pour minimiser justement les risques pour la vie privée. Le RFC détaille les nombreux problèmes et pièges que récèle ce mécanisme. Mais le principal problème est que la seule demande de ces adresses, visible par tout surveillant, est déjà très révélatrice ! Cela revient à sa promener avec une cagoule sur sa tête pour préserver sa vie privée.

Autre mécanisme qui peut être révélateur, la mise à jour du DNS que font certains serveurs DHCP. Si le nom utilisé est stable (cf. l'option Client FQDN mentionnée plus haut), tout surveillant ayant accès au DNS (c'est-à-dire tout le monde) pourra suivre les changements d'adresse IP de la machine, connaissant ainsi ses déplacements d'un réseau à l'autre.

Les stratégies d'allocation d'adresses du serveur DHCP peuvent également être dangereuses pour la vie privée. Le serveur DHCP dispose d'une certaine plage d'adresses. S'il alloue les adresses en commençant toujours par la plus basse adresse libre, les adresses attribuées vont être assez prévisibles, ce qui n'est en général pas bon pour la discrétion. (Et ce mécanisme, qui a certes l'avantage d'être simple et rapide, tend à concentrer les adresses allouées au début de la plage.) Autre possibilité, allouer des adresses fixes (le même client - identifié par une option comme Client Identifier - a toujours la même adresse IP). C'est évidemment très pratique pour l'administrateur du réseau local. Mais c'est la pire solution pour la vie privée, puisque cela oblige le client à divulguer son identité, et cela permet même aux serveurs extérieurs de le suivre à la trace lorsqu'il communique avec eux avec son adresse fixe. Pour la vie privée, la meilleure stratégie d'allocation est sans doute le tirage au sort parmi les adresses libres de la plage.

Maintenant qu'on a vu les vulnérabilités de DHCPv6, voyons ce qu'un attaquant peut en faire (section 5 du RFC). D'abord, il peut découvrir le type de machine chez le client (matériel et/ou logiciel), ce qui peut être utile, par exemple pour sélectionner une attaque spécifique à un système d'exploitation, ou bien, si le matériel/logiciel utilisé est rare, pour identifier un client particulier. Cette information sur le type de machine peut être trouvé dans l'adresse MAC (les premiers octets identifient le vendeur), dans les identificateurs dérivés de l'adresse MAC, ou dans les options comme Vendor Class.

L'espion peut également utiliser ces faiblesses de DHCPv6 pour identifier les réseaux visités précédemment (je n'en ai pas parlé plus haut, mais il existe une option qui indique la précédente adresse IP utilisée : elle est pratique pour obtenir une adresse stable, mais elle est indiscrète).

Plus généralement, le surveillant peut essayer de découvrir une identité stable, lui permettant de savoir combien de machines utilisent ce serveur DHCP, et lui permettant également de corréler deux machines sur deux réseaux, découvrant qu'il s'agit en fait de la même. Le DUID est particulièrement sensible ici.

Le surveillant peut ainsi suivre une machine, soit dans le temps (toutes ses activités en un réseau donné), soit dans l'espace (suivre à la trace un engin mobile).

Si le surveillant a les moyens d'une agence d'un État riche (par exemple si le surveillant est la NSA), il peut effectuer une surveillance massive très efficace (RFC 7258). Il est par exemple conceptuellement aisé de bâtir une liste de très nombreuses machines, en observant beaucoup de réseaux : les failles de sécurité de DHCPv6 citées dans ce RFC permettront de reconnaitre chaque machine individuelle. Ainsi, un organisme comme la NSA peut se faire une base de données permettant de répondre très vite à des questions du genre « où était 38:59:f9:7d:b6:47 la dernière fois qu'on l'a vu ? »

Enfin, la section 6 de notre RFC rappelle une triste réalité : en sécurité, il faut en général faire des compromis. Ici, le RFC note que toute authentification du client va à l'encontre du souhait de préserver la vie privée. Ce genre de choix (sécurité de son réseau, ou bien vie privée des utilisateurs) est bien embêtant pour l'administrateur système.


Téléchargez le RFC 7824


L'article seul

RFC 7873: Domain Name System (DNS) Cookies

Date de publication du RFC : Mai 2016
Auteur(s) du RFC : Donald Eastlake (Huawei), Mark Andrews (ISC)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 10 juin 2016


La grande majorité des requêtes DNS passent aujourd'hui sur UDP. Ce protocole ne fournit aucun mécanisme permettant de vérifier un tant soit peu l'adresse IP source de la requête. Contrairement à ce qui arrive avec TCP, il est trivial de mentir sur l'adresse IP source, sans être détecté. Cela permet des comportements négatifs, comme les attaques par réflexion. Ce nouveau RFC propose un mécanisme simple et léger pour s'assurer de l'adresse IP source du client : des petits gâteaux, les cookies.

Le principe est le même que pour les cookies de HTTP (décrits dans le RFC 6265) : le serveur DNS génère un nombre imprévisible qu'il transmet au client. Celui-ci renvoie ce nombre à chaque requête, prouvant qu'il recevait bien les réponses, et n'avait donc pas triché sur son adresse IP. (Notez une grosse différence avec les cookies du Web : ils changent quand l'adresse IP du client change et ils ne peuvent donc pas être utilisés pour suivre à la trace un client mobile.)

Bien sûr, une autre solution serait d'utiliser TCP (comme proposé dans le RFC 7766) ou bien DTLS (RFC en cours de discussion). Mais les petits gâteaux se veulent une solution moins radicale, de déploiement peut-être plus facile. Ils ne sont pas forcément utilisés seuls, ils peuvent être combinés avec d'autres mesures anti-usurpation, comme celles du RFC 5452.

Comme avec toute technique de sécurité, il faut regarder en détail les menaces auxquelles elle répond (section 2 du RFC). En usurpant l'adresse IP source, un méchant peut effectuer des attaques par déni de service, et il peut empoisonner un cache. Voyons ces deux cas.

D'abord, l'attaque par déni de service : en usurpant l'adresse IP source, on peut effectuer une attaque par réflexion. Dans ces attaques, le méchant envoie un paquet à un tiers, le réflecteur, en mentant sur son adresse IP source : le méchant met celle de la victime. Lorsque le réflecteur répondra, il enverra un message à la victime. Cette attaque est surtout intéressante lorsqu'elle est combinée avec l'amplification. Si la réponse est plus grosse que la question (ce qui est en général le cas avec le DNS), le méchant aura frappé la victime avec davantage d'octets que ce qu'il a lui-même envoyé.

Avec les cookies, cette attaque ne serait pas possible, la réponse à une requête ayant un cookie erroné étant plus petite que la question.

Notez que les cookies ne protègent pas contre un attaquant situé sur le chemin (on-path attacker) et qui peut lire le trafic réseau : voyant les paquets, il verra le cookie et pourra le transmettre. Les cookies n'empêchent donc pas toutes les attaques. D'autre part, si l'attaquant matraque directement le serveur DNS (sans réflexion), les cookies n'empêcheront pas l'attaque mais ils permettent de s'assurer que l'adresse IP source est exacte, ce qui autorisera de remonter à la source de l'attaque.

Le déni de service peut aussi viser le serveur DNS (au lieu de simplement l'utiliser comme réflecteur dans une attaque par réflexion). Chaque requête DNS va donner du travail au serveur et un nombre excessif peut dépasser ses capacités (comme dans l'attaque dafa888). Le problème est surtout aigu pour les serveurs récursifs, qui ont nettement plus à faire lorsqu'une requête arrive. Et ceux qui ont le plus de travail sont les serveurs récursifs qui valident avec DNSSEC : lors de la réception d'une réponse, il faut faire des calculs cryptographiques pour cette validation. Ces attaques par déni de service, au contraire de celles faites par réflexion, n'imposent pas de tricher sur l'adresse IP source mais, en le faisant, l'attaquant a l'avantage de rendre plus difficile son identification. Et cela peut lui permettre de faire traiter des requêtes qui seraient normalement refusées. Par exemple, si un résolveur n'accepte de requêtes que de son réseau (ce qui est la bonne pratique, cf. RFC 5358), et si on a oublié de filtrer en entrée les requêtes prétendant venir du réseau local, une attaque reste possible, en usurpant les adresses IP locales (une telle attaque est décrite dans l'exposé de Lars Nøring).

Après les attaques par déni de service, voyons les attaques visant à faire accepter de fausses réponses, ce qui peut mener à empoisonner le cache. Le principe est de répondre à la place du vrai serveur faisant autorité, en usurpant son adresse IP. Si le méchant est plus rapide, sa réponse peut, dans certains cas, être acceptée par un résolveur (qui la mettra peut-être dans son cache, ce qui sera encore pire). L'attaque Kaminsky est une version améliorée de cette vieille attaque. Les cookies sont une bonne protection contre ce genre d'attaques.

Après les attaques, voyons les défenses. Il n'y a pas que les cookies dans la vie. D'abord, il y a DNSSEC (RFC 4034 et RFC 4035). DNSSEC permet d'authentifier les réponses DNS, résolvant ainsi complètement les attaques par empoisonnement. Par contre, il ne résout pas les attaques par déni de service et, pire, les calculs cryptographiques qu'il impose et la taille des réponses plus élevées peuvent dans certains cas aggraver une partie de ces attaques. (Le RFC ne le note pas, mais DNSSEC a une autre limite, que les cookies résolvent : s'il empêche l'empoisonnement, il ne permet pas pour autant d'obtenir la réponse DNS correcte. DNSSEC protège bien du hameçonnage, beaucoup moins de la censure.)

Autre solution de sécurité, TSIG (RFC 8945). TSIG est meilleur que les cookies dans la mesure où il permet de vérifier cryptographiquement l'identité de la machine avec qui on parle DNS. Mais il est non trivial à déployer : reposant sur de la cryptographie symétrique, il impose un partage des clés préalable. Cela le limite à des usages entre parties qui se connaissent bien (typiquement pour sécuriser les transferts de zone). On note aussi que, comme DNSSEC, mais contrairement aux cookies, il nécessite des horloges synchronisées.

Pour résoudre ce problème de déployabilité, on peut envisager le mécanisme de distribution de clés TKEY (RFC 2930) ou bien passer à de la cryptographie asymétrique avec SIG(0) (RFC 2931). Mais aucune de ces deux techniques n'a connu de déploiement significatif.

Bref, les solutions de sécurité existantes ne résolvent pas réellement les problèmes que veulent traiter les cookies. Mais assez parlé de la « concurrence », venons-en aux cookies, comment marchent-ils (section 4 de notre RFC) ? Les cookies s'appuient sur EDNS (RFC 6891). Ils sont donc une option dans l'enregistrement EDNS. L'option cookie de EDNS porte le numéro 10. Comme toutes les options EDNS, elle est codée en TLV : le type 10, la longueur et la valeur, qui comprend un ou deux cookies. S'il n'y a que le cookie client, la longueur est fixe, de 8 octets. S'il y a en plus le cookie serveur, la longueur peut aller de 16 à 40 octets.

Le cookie client est normalement le résultat d'une fonction non-prévisible des adresses IP du client et du serveur, et d'un secret connu du client (par exemple, généré aléatoirement en suivant le RFC 4086, et changé de temps en temps). Cette fonction est, par exemple, une condensation mais le client prend ce qu'il veut : il est le seul à avoir besoin d'interpréter ses propres cookies, ils sont opaques pour tout autre acteur. L'adresse IP du client est incluse dans les paramètres de la fonction notamment pour des raisons de vie privée : empêcher le client d'être reconnu s'il change d'adresse IP (le but de nos cookies DNS n'est pas du tout le même que celui des fameux cookies du Web).

Le cookie serveur prend comme paramètres de sa propre fonction (qui n'est pas forcément la même) l'adresse IP de son client, un secret (mêmes propriétés que chez le client), et le cookie du client (et pourquoi le cookie client ne se sert pas du cookie serveur ? Voyez la section 6.) Voilà comment on fabrique les gâteaux.

Mais comment les utilise-t-on ? La section 5 l'explique. Le client qui gère les gâteaux fabrique un cookie client qu'il envoie dans ses requêtes DNS. S'il n'a jamais parlé au serveur, il envoie une option cookie de forme courte, ne comprenant qu'un seul cookie, le sien. S'il a déjà parlé au serveur et mémorisé le cookie de celui-ci, il fabrique une option EDNS cookie longue, incluant les deux cookies.

Si le serveur ne comprend rien aux cookies, il ne met pas l'option dans la réponse, et le client sait alors qu'il s'agit d'un vieux serveur, sans gestion des cookies. (Ou bien c'était une attaque par repli ; le cas ne semble pas traité dans le RFC, la solution est sans doute que le client mémorise les serveurs cookie-capable, pour détecter ces attaques.)

Si, par contre, le serveur gère les cookies, il y a cinq possibilités :

  • Si c'est le client qui est vieux, il n'envoie pas de cookie. Le serveur répond alors comme aujourd'hui. Les cookies ne posent donc pas de problème d'interopérabilité : vieux et récents logiciels peuvent cohabiter.
  • Si l'option EDNS cookie est présente, mais invalide (longueur inférieure à 8 octets, par exemple), le serveur répond FORMERR (FORmat ERRor).
  • Si la requête ne contient qu'un cookie client (client qui ne connaissait pas encore ce serveur), le serveur décide alors, selon sa politique à lui, de laisser tomber la requête (c'est violent, et cela implique de configurer le serveur avec les cookies des clients), d'envoyer un code d'erreur BADCOOKIE (valeur 23), incluant le cookie du serveur, ou enfin de répondre normalement, en ajoutant son cookie. En effet, dans ce cas, le client n'est pas « authentifié ». On n'a pas vérifié son adresse IP source. Il peut donc être justifié de ne pas donner la réponse tout de suite (le BADCOOKIE) ou bien, par exemple, de limiter le trafic de ce client (comme on le fait aujourd'hui, avant les cookies, puisqu'on n'est jamais sûr de l'adresse IP du client).
  • Il y a deux cookies dans la requête mais le cookie serveur est incorrect, par exemple parce que le secret utilisé par le serveur a changé. C'est parfaitement normal et cela n'indique, ni une erreur, ni une attaque, simplement qu'on ne peut pas authentifier le client. On répond donc comme dans le cas précédent (avec trois choix, dont seuls les deux derniers sont réalistes).
  • Il y a deux cookies dans la requête et le cookie serveur est correct. On a donc une certitude raisonnable que le client n'a pas usurpé son adresse IP (puisqu'il a reçu le bon cookie du serveur) et on va donc lui répondre. Les mesures de méfiance comme la limitation de trafic peuvent être débrayées pour cette requête.

Lorsqu'il reçoit une réponse, le client doit mémoriser le cookie du serveur. C'est particulièrement important la première fois, lorsque le client n'est pas encore authentifié. Si la réponse était BADCOOKIE, cela veut dire qu'on a affaire à un serveur grognon qui ne veut pas répondre sans qu'on lui donne un cookie correct : on retransmet alors la requête, cette fois en incluant le cookie transmis par le serveur.

Voilà, c'est tout. Avec ce système, on a une authentification légère et simple de l'adresse IP du client. Dans la vraie vie, il y aura peut-être quelques problèmes pratiques, que couvre la section 6 de notre RFC. Par exemple, si le client est derrière du NAT (RFC 3022), un méchant situé sur le même réseau local que lui pourrait faire une requête au serveur, obtenir le cookie du serveur et envoyer ensuite des requêtes en usurpant l'adresse IP locale du client légitime. Le serveur ne peut pas distinguer ces deux clients, le bon et le méchant. C'est pour cela que le cookie serveur inclut dans les paramètres de sa fonction le cookie du client. Ainsi, les deux machines, la gentille et la méchante auront des cookies serveur différents.

Un problème du même genre (plusieurs machines derrière une même adresse IP) pourrait survenir côté serveur, par exemple en raison de l'anycast. Mais on ne peut pas appliquer la même solution : si le cookie serveur dépend du cookie client et le cookie client du cookie serveur, on a une boucle sans fin. Le serveur doit donc se débrouiller : soit avoir le même secret (et donc les mêmes cookies) sur toutes les machines (c'est l'approche la plus simple, et c'est celle recommandée par le RFC), soit faire en sorte qu'un client donné arrive toujours sur la même machine.

D'autres considérations pratiques figurent en section 7, notamment sur le remplacement d'un secret (ce qui invalidera les cookies précédemment distribués).

Et quelques discussions sur la sécurité, pour finir (section 9 du RFC). L'« authentification » fournie par les cookies est faible : elle ne protège pas contre un attaquant situé sur le chemin de communication entre client et serveur, lorsqu'il peut lire le trafic. Dans ce cas, l'attaquant a en effet accès au cookie et peut facilement le rejouer. Par exemple, si on est connecté à un réseau Wi-Fi public sans sécurité (pas de WPA), n'importe quel client du même réseau peut voir passer les cookies. Néanmoins, les cookies réduisent quand même sérieusement l'ampleur du problème. Une attaque (l'usurpation d'adresse IP) que tout l'Internet pouvait faire est maintenant restreinte à un sous-ensemble de l'Internet. Si cela est encore trop, il faut passer à une sécurisation cryptographique comme celle que fournit le RFC 7858.

L'algorithme utilisé pour calculer les cookies est évidemment crucial. Il n'a pas besoin d'être normalisé, puisque seule la machine qui émet le cookie original a besoin de le comprendre. Mais il doit garantir des cookies très difficiles à prévoir par un attaquant. On peut par exemple utiliser SHA-256 (RFC 6234, mais il n'y a pas forcément besoin de cryptographie top canon, les cookies n'étant qu'une authentification faible, de toute façon). Depuis la parution de notre RFC, le RFC 9018 a décrit un algorithme recommandé si des serveurs veulent être compatibles, par exemple s'ils font partie du même service anycast.

Des exemples d'algorithmes figurent dans les annexes A et B (mais le RFC 9018 en a abandonné certains). Pour le client DNS, un algorithme simple serait d'appliquer la fonction simple et rapide FNV-64 à la concaténation des adresses IP du client et du serveur, et du secret. Un algorithme plus compliqué, mais plus sûr, serait de remplacer FNV par SHA-256, plus coûteux.

Pour le serveur, l'algorithme simple serait un FNV-64 de la concaténation de l'adresse IP du client, du cookie du client, et du secret. Pour l'algorithme compliqué, on peut tirer profit de la longueur plus grande du cookie serveur pour y mettre davantage d'informations : par exemple, huit octets calculés comme dans l'algorithme simple suivis de l'heure de génération du cookie (pour détecter plus facilement les vieux cookies, avant même toute opération cryptographique).

Et les mises en œuvre ? Les cookies sont gérés par BIND à partir de la version 9.11 (pas encore officiellement publiée). Ils sont activés par défaut. Et Wireshark sait les afficher. Ici, un client nouveau (il ne connait pas encore le cookie serveur) :


No.     Time           Source                Destination           Protocol Length Info
      1 0.000000       192.168.2.9           192.168.2.7           DNS      97     Standard query 0x0000 SOA foobar.example OPT
...
Domain Name System (query)
...
    Additional records
        <Root>: type OPT
...
        Data length: 12
            Option: COOKIE
                Option Code: COOKIE (10)
                Option Length: 8
                Option Data: fb40ce9a68a6f1f0
                Client Cookie: fb40ce9a68a6f1f0
                Server Cookie: <MISSING>


No.     Time           Source                Destination           Protocol Length Info
      2 0.003910       192.168.2.7           192.168.2.9           DNS      200    Standard query response 0x0000 SOA foobar.example SOA ns1.foobar.example NS ns1.nic.fr NS ns2.nic.fr OPT
...
      Additional records
        <Root>: type OPT
...
        Data length: 28
            Option: COOKIE
                Option Code: COOKIE (10)
                Option Length: 24
                Option Data: fb40ce9a68a6f1f0727e7501575acc5977ced0351ad20d56
                Client Cookie: fb40ce9a68a6f1f0
                Server Cookie: 727e7501575acc5977ced0351ad20d56

L'algorithme de condensation peut être choisi mais, apparemment, uniquement à la compilation (avec --with-cc-alg=ALGALG vaut aes|sha1|sha256).

Le dig livré avec cette version de BIND peut passer des cookies :

% dig +cookie @192.168.2.7 foobar.example
...
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
; COOKIE: 51648e4b14ad9db8eb0d28c7575acbdde8f541a0cb52e2c2 (good)
;; QUESTION SECTION:
;foobar.example.                IN A
...
     

Pour les programmeurs en Go, la bibliothèque Go DNS gère désormais les cookies. Un exemple de code Go pour les envoyer :

     
	m := new(dns.Msg)
	m.Question = make([]dns.Question, 1)
	c := new(dns.Client)
	m.Question[0] = dns.Question{zone, dns.TypeSOA, dns.ClassINET}
	o := new(dns.OPT)
	o.Hdr.Name = "."
	o.Hdr.Rrtype = dns.TypeOPT
	o.Hdr.Class = 4096
	e := new(dns.EDNS0_COOKIE)
	e.Code = dns.EDNS0COOKIE
	e.Cookie = "fb40ce9a68a6f1f0"
	o.Option = append(o.Option, e)
	m.Extra = make([]dns.RR, 1)
	m.Extra[0] = o

Téléchargez le RFC 7873


L'article seul

RFC 7799: Active and Passive Metrics and Methods (with Hybrid Types In-Between)

Date de publication du RFC : Mai 2016
Auteur(s) du RFC : A. Morton (AT&T Labs)
Pour information
Réalisé dans le cadre du groupe de travail IETF ippm
Première rédaction de cet article le 30 mai 2016


Dans le monde de la métrologie, il existe deux classes de mesures effectuées sur l'Internet : les mesures actives et les mesures passives. La signification de ces termes semble assez intuitive mais ce nouveau RFC fournit des définitions rigoureuses, qui n'étaient pas encore publiées. (Il y a aussi des mesures hybrides.)

Cela fait pourtant de très nombreuses années que ces deux termes sont largement utilisés. Par exemple, en 2000 s'est tenue une conférence « Passive and Active Measurement (PAM) ». Et les termes étaient certainement plus anciens.

En première approximation, on peut caractériser ces deux classes ainsi (section 1 du RFC) :

  • Une mesure active nécessite un envoi de paquets dédiés à cette mesure.
  • Une mesure passive ne dépend que des paquets qui seraient envoyés de toute façon, même si la mesure n'avait pas lieu.

Du point de vue des outils, on peut donc noter que les ultra-traditionnels ping et traceroute font des mesures actives et que tcpdump permet des mesures passives.

Mais, les choses étant plus compliquées dans la vraie vie des vrais réseaux, notre RFC va un peu plus loin que cela. Sa section 3 définit plus précisement les termes. Elle s'appuie sur des RFC précédents comme les RFC 2330 et RFC 6390 qui définissaient, par exemple, la notion de métrique (une grandeur qu'on mesure), ou comme le RFC 7011, qui définissait la notion de point d'observation. On s'appuie aussi sur des documents qui ne sont pas des RFC comme la norme UIT Y.1540 qui définit la notion de « population [de paquets] qui nous intéresse » (stream of interest) ou comme la norme UIT Y.1731.

Notez que les adjectifs « actif » et « passif » peuvent s'appliquer aux méthodes de mesure ou bien aux métriques.

Armé de ces définitions, on peut dire que les méthodes de mesure actives ont les caractéristiques suivantes :

  • La population de paquets qui nous intéresse est générée (synthétisée). Parfois un autre flux de paquets est généré, même si leur sort ne nous intéresse pas directement, par exemple pour générer de la charge.
  • Les paquets générés ont un contenu qui est spécifique à la mesure, qui n'a pas d'intérêt autrement. C'est par exemple le numéro de séquence dans les paquets ICMP (RFC 792) que génère ping, numéros qui permettent de faire correspondre une réponse à une question.
  • Source et destination des paquets sont connus a priori.
  • D'ailleurs, toutes les caractéristiques de la population sont connues à l'avance, ce qui facilite nettement l'observation. Parfois, certaines caractéristiques seront changées en route (comme le champ TTL dans l'en-tête IPv4).

Comme la mesure active introduit du trafic réseau qui n'existerait pas sans elle, elle perturbe le réseau qu'on veut mesurer. Un des défis importants des mesures actives est de minimiser cette perturbation ou, au minimum, de pouvoir quantifier cette perturbation pour l'indiquer comme marge d'erreur dans les résultats (section 4.1).

Une métrique active est simplement une métrique dont la définition inclut des méthodes actives. Par exemple, le type des paquets qu'on a injecté dans le réseau.

Les méthodes passives, par contre, ont ces propriétés :

  • Elles sont fondées sur l'observation de paquets non modifiés et non perturbés. Une méthode passive ne laisse aucune trace sur le réseau.
  • Elles ne sont donc utiles que s'il existe déjà des paquets intéressants, puisqu'elles n'en créent pas et n'en modifient pas.

Il faut faire attention en observant les paquets : comme on ne choisit pas leurs caractéristiques, on risque de ne pas voir le vrai phénomène, car on n'observait que le phénomène supposé. (Il m'est arrivé d'utiliser tcpdump pour observer un trafic LDAP et de filtrer sur l'adresse du serveur LDAP. Je ne comprenais pas pourquoi aucun trafic n'était visible. En fait, je ne capturais que les paquets IPv4 alors que le trafic se faisait en IPv6.)

Une observation passive peut se faire en un seul point, ou en plusieurs. Un exemple d'observation passive est ce que fait un routeur IPFIX (RFC 7011).

Une métrique passive est une métrique fondée uniquement sur l'observation passive. Par exemple, le temps de trajet entre deux points peut être formalisée dans une métrique passive : on observe le paquet à un point et à l'autre, et on en déduit le temps de son voyage.

Évidemment, dans le monde réel, les classifications ne sont pas toujours très simples. Par exemple, il existe des méthodes hybrides. Les « hybrides de type I » partent d'un flux de paquets existant mais le modifient, ou bien modifient le traitement qu'il subit. Par exemple, si on observe un flux existant mais qu'on envoie en même temps des données dans le réseau pour le charger, on est en présence d'une méthode hybride de type I. Les métriques spatiales du RFC 5644 sont un cas de métriques hybrides.

Et les hybrides de type II ? Le terme indique les méthodes où il y a plusieurs populations intéressantes générées activement (et d'autres qu'on observe passivement).

La section 4 de notre RFC discute de certains problèmes de métrologie et compare l'effet des méthodes et métriques actives ou passives. Par exemple, si on veut mesurer la capacité d'un lien, une méthode active serait de tenter d'envoyer le plus de données possible, une méthode passive d'observer le trafic et de regarder le débit maximum atteint. La première méthode va remplir le tuyau, gênant les applications en cours. La seconde risque de sous-estimer la capacité (si les machines sont lentes, elles peuvent ne pas réussir à remplir le tuyau.)

Au passage, l'importance des mesures est telle que l'IETF envisage un mécanisme de mesure instrumentant les paquets eux-mêmes : c'est l'option IPv6 PDM (Performance and Diagnostic Measurements, actuellement à l'état de projet), qui consiste à ajouter un nouvel en-tête d'extension aux paquets IP pour y noter les informations nécessaires aux mesures. Les mesures ainsi faites seraient plutôt des hybrides de type I. (On ajoute des données à des paquets existants.)


Téléchargez le RFC 7799


L'article seul

Valider qu'un contrat Ethereum est bien ce qu'il prétend être

Première rédaction de cet article le 29 mai 2016


La chaîne de blocs Ethereum permet bien plus que de gérer de l'argent : elle autorise la création de programmes (appelés contrats) qui peuvent être invoqués par des utilisateurs, qui envoient leur argent au contrat, espérant que celui-ci va bien faire ce qui est promis. Mais comment le vérifier ?

Les contrats (le terme marketing est smart contracts) sont des programmes informatiques : dans le cas le plus courant, ils sont écrits par un programmeur dans un langage « de haut niveau » puis compilé dans le langage machine d'Ethereum.

Le contrat, comme son nom l'indique, est censé faire quelque chose. Imaginons par exemple un serveur de clés PGP dans la chaîne de blocs : il est censé recevoir des clés, les stocker, et les restituer à la demande. Les gens qui stockent des clés paient (en ethers) pour cela. Il est légitime de se demander « est-ce que ce programme va bien faire ce qui est prévu, ou bien va-t-il soudainement détruire toutes les clés, et j'aurais alors dépensé mes ethers pour rien ? » C'est d'autant plus critique qu'il existe des contrats qui brassent des sommes d'argent importantes. Les utilisateurs se fient typiquement à la documentation publique de ce contrat, alors qu'on ne peut pas être sûr qu'elle corresponde au contrat réel (soit par suite d'une erreur, soit par suite d'une volonté délibérée). Le code s'exécute dans la chaîne de blocs, sans intervention humaine (c'est le but des smart contracts). Comment valider ce code ? C'est à mon avis le gros problème de ces « contrats intelligents ».

Arrivé à ce stade, mes lecteurs partisans du logiciel libre ont déjà une réponse : on distribue le code source (rappelez-vous qu'un contrat n'est qu'un programme), des gens le liront et le vérifieront. Si suffisamment de gens compétents le lisent, le contrat est vérifié, on peut lui faire confiance. Mais c'est très insuffisant.

Déjà, analyser un code source complexe peut être difficile (on peut espérer que les auteurs de contrats, voulant inspirer confiance, essaieront d'écrire du code clair et lisible). Il est clair que la disponibilité du code source est un pré-requis : s'il n'est pas public, il ne faut jamais envoyer de l'argent à ce contrat. Seulement, ça ne suffit pas : ce qui est stocké et exécuté sur la blockchain, c'est du langage machine d'Ethereum (à peu près du même niveau d'abstraction que le langage des processeurs matériels). Ça, c'est vraiment dur à valider. Pour donner un exemple, voici un contrat très très simple écrit en Solidity, il stocke une valeur et permet de la récupérer :

contract SimpleStorage {
  uint storedData;

  function set(uint x) {
    storedData = x;
  }

  function get() constant returns (uint retVal) {
    return storedData;
  }
}

Il est trivial à analyser et à vérifier. Seulement, ce n'est pas ça qu'exécute la chaîne de blocs, mais un code machine. Voici sa version en assembleur, produite par l'option --asm du compilateur solc : storage.asm (je ne l'ai pas incluse dans cet article, elle est trop longue). Mais ce n'est pas non plus ce que stocke la chaîne de blocs, en fait, on a juste les opcodes, sans les jolis commentaires et tout :

% solc --opcodes storage.sol 

======= SimpleStorage =======
Opcodes: 
PUSH1 0x60 PUSH1 0x40 MSTORE PUSH1 0x97 DUP1 PUSH1 0x10 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN PUSH1 0x60 PUSH1 0x40 MSTORE PUSH1 0x0 CALLDATALOAD PUSH29 0x100000000000000000000000000000000000000000000000000000000 SWAP1 DIV DUP1 PUSH4 0x60FE47B1 EQ PUSH1 0x41 JUMPI DUP1 PUSH4 0x6D4CE63C EQ PUSH1 0x57 JUMPI PUSH1 0x3F JUMP JUMPDEST STOP JUMPDEST PUSH1 0x55 PUSH1 0x4 DUP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 POP POP PUSH1 0x78 JUMP JUMPDEST STOP JUMPDEST PUSH1 0x62 PUSH1 0x4 DUP1 POP POP PUSH1 0x86 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST DUP1 PUSH1 0x0 PUSH1 0x0 POP DUP2 SWAP1 SSTORE POP JUMPDEST POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x0 PUSH1 0x0 POP SLOAD SWAP1 POP PUSH1 0x94 JUMP JUMPDEST SWAP1 JUMP 
    

À noter que c'était sans l'optimisation. Celle-ci réduit sérieusement le nombre d'instructions :

% solc --opcodes storage.sol |wc -w 
137
% solc --opcodes --optimize storage.sol |wc -w
73

Si vous voulez observer ce contrat en ligne, il a été déployé sur la chaîne de blocs, à l'adresse 0x48b4cb193b587c6f2dab1a9123a7bd5e7d490ced (et ça m'a coûté 69 558 unités d'essence, payées 0,00139116 ethers). Le résultat est visible sur les explorateurs de la chaîne, comme etherscan.io, Etherchain ou ether.camp. Sur Etherscan.io, la fonction Switch To Opcodes View vous permet de passer des instructions en assembleur au code binaire. Sur Ether.camp, ce sont les liens code et asm. Au passage, si vous voulez interagir avec ce contrat (après l'avoir vérifié !), les instructions en console sont :

storage = eth.contract([{"constant":false,"inputs":[{"name":"x","type":"uint256"}],"name":"set","outputs":[],"type":"function"},{"constant":true,"inputs":[],"name":"get","outputs":[{"name":"retVal","type":"uint256"}],"type":"function"}]).at("0x48b4cb193b587c6f2dab1a9123a7bd5e7d490ced")

Et cela permet de stocker et de récupérer des valeurs depuis la console de geth (cela vous coûtera 26 563 unités d'essence, soit, aujourd'hui, 0,00053126 ether) :

> storage.set(42,{from:eth.accounts[0]})
"0x36084ff3d5bf0235326277b2d5ba30b1964f6d8b3720b9aef0578faeaeb2678b"
...
> storage.get()
42

Quittons ce détour technique et revenons à la question de fond, la vérification. Cette préoccupation est relativement fréquente dans le monde Ethereum. Il y a quelques mois, elle ne suscitait guère d'intérêt. Il y a plusieurs solutions pour vérifier un contrat avant de lui confier ses précieux ethers :

  • On compile le code source soi-même et on vérifie que le binaire correspond. S'il correspond, on peut être rassuré : sauf bogue/malhonnêteté du compilateur, le contrat fait bien ce que dit le code source. C'est ainsi que fonctionnent les services de vérification de code des explorateurs (comme Etherscan ou Etherchain), ce qui ajoute d'ailleurs une confiance supplémentaire : il faut faire confiance à ce service.
  • On vérifie directement le code machine, par rétro-ingénierie, comme le font les reverseurs qui analysent le logiciel malveillant (pour lequel ils n'ont évidemment pas les sources). C'est très sûr mais très complexe, puisqu'on travaille sur du matériau de très bas niveau. À ma connaissance, personne n'a encore développé cette compétence mais cela se fera sans doute, étant donné l'inquiétude sur la sécurité des contrats. Cela fera de beaux articles de blog :-)
  • On copie le code machine et on fait tourner le contrat dans une chaîne de blocs de test (comme Morden), en utilisant ce contrat comme une boîte noire : on n'essaie pas de comprendre le code, mais on voit s'il répond bien aux fonctions qu'on appelle. Cette méthode est plus simple mais limitée : si le contrat est complexe, on aura du mal à tester tous les cas. Et, même avec un contrat trivial comme celui donné en exemple plus haut, on ne peut pas ainsi découvrir si certaines valeurs (comme 42...) ne vont pas activer la porte dérobée.
  • Il y a aussi cette technique, spécifique à Solidity, que je n'ai pas encore creusée.

Dans le cas de la première méthode, la recompilation, si le binaire obtenu correspond à celui déployé, on est tranquille. Mais s'il ne correspond pas ? Est-ce que cela veut dire que quelqu'un essaie de nous tromper ? Non, car le code obtenu dépend du compilateur, et de sa version exacte. Si le binaire correspond, on est rassuré, s'il ne correspond pas, on n'est pas plus avancé. Et le problème devient plus compliqué avec le temps (certains contrats peuvent être éternels) : comment on retrouve le compilateur utilisé deux ans après ? Il faudrait que le code soit étiqueté avec la version du compilateur, ce qui n'est pas le cas, et qu'on dispose d'une copie de cet ancien compilateur.

Bref, il n'y a pas de solution parfaite aujourd'hui. Lorsque vous mettez de l'argent dans un contrat sérieux, vous avez forcément une incertitude. Vous pouvez la réduire en regardant les vérifications faites par d'autres. Pour The DAO, le code source est en ligne. Il existe une documentation sur cette vérification et des détails. Et le code a été vérifié par certains explorateurs, comme Etherscan.

Et, pour finir, une copie d'écran d'un cas où ça a marché, la vérification du contrat montré plus haut : etherchain-verify-storage.png


L'article seul

RFC 7844: Anonymity profile for DHCP clients

Date de publication du RFC : Mai 2016
Auteur(s) du RFC : C. Huitema (Microsoft), T. Mrugalski (ISC), S. Krishnan (Ericsson)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dhc
Première rédaction de cet article le 29 mai 2016


Vous vous connectez à un réseau IP, vous obtenez la configuration via un serveur DHCP, mais vous voulez rester relativement anonyme, et vous n'avez pas envie que le serveur, ou que des indiscrets qui écoutent, sachent qui vous êtes ? C'est là que ce RFC est utile en proposant un profil de requête DHCP qui envoie le moins d'informations possibles.

C'est que DHCP, par défaut, est trop bavard. Comme l'expliquent bien les RFC 7819 et RFC 7824, une requête DHCP comporte pas mal de champs et d'options qui peuvent contenir des identificateurs stables, qui permettront au serveur DHCP, ou à des espions qui écoutent le trafic, de reconnaitre une machine. Un exemple d'une telle surveillance est celle effectuée dans les aéroports canadiens mais ce n'est certainement pas la seule. Un des buts de cette surveillance peut être, pour quelqu'un qui peut écouter en plusieurs endroits, de suivre à la trace les utilisateurs en déplacement, en reconnaissant les requêtes spécifiques de leur ordinateur portable ou smartphone. Bien sûr, DHCP n'est pas le seul outil pour faire cela. L'identificateur stable le plus évident est l'adresse MAC, mais c'est aussi le plus connu : les utilisateurs soucieux de leur vie privée prennent souvent des mesures pour la changer de temps en temps. Mais peu de gens pensent aux risques pour la vie privée associés à DHCP. Ceux-ci sont désormais bien établis, et documentés dans les RFC 7819 et RFC 7824.

Mais pourquoi en faire un RFC, une norme ? Après tout, on pourrait se contenter d'attendre que les différents fournisseurs de clients DHCP minimisent les informations envoyées. Le problème est qu'ils risquent de le faire légèrement différemment (certains supprimant une option de la requête que d'autres garderont, par exemple). Cette différence permettra une différenciation des utilisateurs, justement ce qu'on veut éviter (cf. la section 2.4). Au contraire, si tout le monde met en œuvre ce profil standard, tous les clients seront pareils, ce qui protège nettement mieux leur anonymat.

La section 2 de notre RFC détaille certains problèmes concrets. J'ai dit plus haut que l'identificateur le plus évident pour suivre une machine à la trace était l'adresse MAC. En Wi-Fi, n'importe qui peut la voir, même si le réseau utilise le chiffrement, puisqu'elle est dans la partie en clair du paquet. En la corrélant avec d'autres informations qu'on retrouve ailleurs, on peut remonter à l'individu qui utilise la machine en question. Le danger est donc réel.

La contre-mesure évidente est de changer l'adresse MAC, en la remplaçant par une valeur aléatoire, par exemple avec macchanger. Cela a fait d'ailleurs l'objets de tests en grand à la réunion IETF de Honolulu, ainsi que dans d'autres réunions. Il n'y a pas de norme technique décrivant cette « aléatoirisation ». Parmi les choix possibles :

  • Un tirage au hasard à chaque connexion à un réseau,
  • Un tirage au hasard pour chaque nouveau réseau mais on garde toujours la même adresse MAC pour un réseau donné,
  • Des changements de temps en temps, si on reste connecté sur des longues périodes. (Cela ne marchera pas en Wi-Fi où le changement d'adresse MAC nécessitera déconnexion/reconnexion donc peut-être changement d'adresse IP donc coupure des connexions TCP en cours.) Cette astuce n'est même pas forcément efficace : un observateur peut facilement noter le départ d'une machine et l'arrivée immédiate d'une autre, corrélant ces deux événements.

En tout cas, un changement de l'adresse MAC est nécessaire, sinon, le profil DHCP « anonyme » de ce RFC aura une utilité limitée. Mais, inversement, attention à ne pas se contenter de changer un seul identificateur. Si on change d'adresse MAC en gardant tout le reste, la tâche d'un surveillant est trop facile, et il déduira sans problème la nouvelle adresse MAC. Il faut changer l'adresse MAC, l'adresse IP et les identificateurs DHCP en même temps.

Notre RFC mentionne qu'il existe des techniques de plus bas niveau (couche 1) qui peuvent défaire tout le travail de protection de la vie privée. Par exemple, certains récepteurs radio permettent d'identifier des particularités d'un émetteur physique et, en observant le trafic Wi-Fi, on peut ainsi identifier une machine donnée quels que soient ses efforts pour ne pas laisser de traces (cf. « Wireless Device Identification with Radiometric Signatures »). Heureusement, tous les surveillants n'ont pas les moyens de placer ce genre de récepteurs. S'ils doivent se contenter de capter le trafic, sans pouvoir analyser le signal physique, les précautions recommandées plus loin dans ce RFC vont suffire.

Le profil d'« anonymat » décrit dans ce RFC n'est pas explicite. On ne peut pas distinguer les clients DHCP qui appliquent ce profil de ceux qui n'ont simplement pas mis en œuvre les options trop révélatrices. Il y avait eu une discussion à l'IETF sur une mention explicite, un bit dans la requête disant « je veux être anonyme et ne vous étonnez donc pas si je ne publie pas grand'chose ». Cette idée avait été rejetée avec l'idée que proclamer publiquement qu'on veut être anonyme peut être au contraire un excellent moyen de se distinguer, comme de sortir dans la rue avec un masque de Guy Fawkes. Au contraire, le vrai anonymat s'obtient en ne faisant rien de trop extraordinaire.

Enfin, comme toute mesure de sécurité, celles qui préservent la vie privée ont des inconvénients. La plus évidente est que l'« anonymat » va rendre plus difficile la gestion des réseaux. Si l'administrateur réseaux suit les machines sur le réseau local en les identifiant par leurs adresses MAC, il devra s'adapter. D'autre part, il y a un conflit entre la protection de la vie privée, qui requiert des changements fréquents d'adresse MAC, et le bon fonctionnement du réseau, qui demande qu'on limite le trafic DHCP (mais aussi ARP et NDP). Attention donc à ne pas changer d'adresse MAC « trop souvent ».

Autre inconvénient, le changement de l'identificateur DHCP par le client, s'il permet davantage de vie privée, empêchera d'obtenir des paramètres de connexion stables (comme l'adresse IP, cf. RFC 7618) dans le temps. On n'a rien sans rien !

Et la vie privée du serveur DHCP, on en parle ? On ne s'est préoccupé jusqu'à présent que du client. C'est parce que le RFC considère que c'est le client qui est aujourd'hui suivi à la trace, et c'est son cas qui nécessite des solutions urgentes. Pour le serveur, cela peut attendre (par exemple parce qu'un serveur qui veut être discret peut ne répondre qu'aux clients authentifiés au niveau 2).

Bien, assez de préliminaires, voyons maintenant le profil proposé. D'abord, pour IPv4 (section 3). Donc, le client qui veut minimiser la surveillance doit donc :

  • Dans le message DHCPDISCOVER, mettre les options « identificateur de client » et « paramètres demandés » mais rien d'autre. (Voir comme contre-exemple cette bogue de Tails.)
  • Dans un DHCPREQUEST, ajouter éventuellement la demande d'une adresse IP précise.

L'option « identificateur de client » (Client Identifier, RFC 2132, code 61) est, comme son nom l'indique, dangereuse pour la vie privée. Elle permet un suivi très efficace d'une machine, précisement ce qu'on voudrait empêcher. Ne pas la mettre n'est pas une solution car tous les clients DHCP l'incluent. Ne pas le faire serait se singulariser (voir la remarque sur Guy Fawkes plus haut). Notre RFC demande donc qu'on envoie cette option mais qu'on lui donne comme valeur l'adresse MAC (qui est déjà dans l'en-tête couche 2 du paquet). Cela contredit le RFC 4361, section 6.1, mais ce changement de politique reflète l'accent désormais mis sur la préservation de la vie privée. Si on n'a pas d'adresse MAC (cas de certaines liaisons point à point), on doit tirer au hasard (après avoir lu le RFC 4086 et la section 5 du RFC 7217) un identificateur.

Et l'autre option acceptable, la liste des paramètres demandés (Parameter Request List, RFC 2132, code 55) ? La liste doit être réduite au minimum, et ordonnée au hasard, pour éviter qu'on reconnaisse le type de client DHCP utilisé.

L'adresse MAC est indispensable, on ne peut pas ne pas la mettre dans le paquet, et, donc, il ne sert à rien de l'omettre du champ correspondant dans la requête DHCP, mais il est recommandé de la changer (et que le client DHCP utilise cette adresse dans son paquet, qu'il ne garde surtout pas l'ancienne).

Le champ « adresse IP du client » ne pose guère de problème de vie privée (puisque la même adresse IP figure dans l'en-tête IP du paquet) sauf si le client est nouveau sur ce réseau, l'adresse IP indiquée étant alors celle du précédent réseau. Donc : pensez à effacer l'adresse IP lorsque le matériel signale qu'on vient de changer de réseau. Pour la même raison, le profil anonyme ne comprend pas l'option « adresse IP souhaitée » (RFC 2132, code 50). Elle est certes bien pratique (permettant de conserver son adresse IP) mais très révélatrice.

Parmi les autres options, le nom de la machine (code 12) est très révélateur. Même si ce n'est pas un FQDN, il peut être très spécifique (« pc-de-jean-dupont »). Il ne doit pas être utilisé dans ce profil. Si on doit quand même le faire, le nom doit être choisi aléatoirement. Une méthode possible est de condenser un secret et l'adresse MAC, puis prendre la représentation en hexadécimal de six premiers octets (quelque chose comme echo -n "$SECRET" "$MACADDRESS" | sha256sum | cut -c 1-12 en shell Unix).

L'option Client FQDN (RFC 4702, code 81) est évidemment également à proscrire. Ou alors, il faut l'« anonymiser » avec la même méthode qu'au paragraphe précédent.

Le RFC 4578 décrit une option UUID, prévue pour PXE, et identifiant de manière unique un client DHCP. Normalement, on n'utilise PXE que dans des environnements contrôlés et sécurisés. Dans un cyber-café inconnu, télécharger son système d'exploitation serait une très mauvaise idée. Il ne faut donc utiliser cette option que dans un réseau que l'on sait sûr.

Enfin, les options indiquant le type de logiciel utilisé (comme Vendor Specific Information, code 43, ou Vendor Class, code 60 sont évidemment à rejeter.

Pour éviter le fingerprinting, le client ne devrait pas ajouter d'autres options, mêmes si celles-ci sont inoffensives du point de vue de la vie privée. En effet, si certains clients mettent telle option, quel que soit son contenu, ils diffusent une information. Et, si on envoie des options DHCP, leur ordre doit être tiré au hasard avant l'envoi, là encore, pour éviter de révéler le type de client utilisé (DHCP permet pas mal de choix, et le choix facilite le fingerprinting). Si on n'a pas de bon générateur de nombres aléatoires, un repli possible est d'envoyer toujours les options dans l'ordre de leur code : ainsi, tous les logiciels (qui sont dans ce cas) feront pareil.

La section 4 du RFC fait la même chose, mais pour IPv6. DHCP v6 a d'autres possibilités (comme l'existence de deux modes, avec ou sans état). Le profil est donc un peu plus compliqué mais bien des conseils sont identiques (par exemple ceux sur les options Client FQDN, sections 3.8 et 4.9), et je ne les répéterai donc pas ici. Dans le mode sans état, les clients configurent l'adresse avec d'autres mécanismes, comme le SLAAC et ne se servent de DHCP que pour récupérer des informations générales. Le choix entre les deux modes dépend d'options publiées dans les Router Advertisement (RFC 4861, section 4.2, les bits M et O).

Parmi les messages spécifiques à DHCP v6, Confirm (RFC 8415, section 16.5) est dangereux, car il contient de l'information sur le précédent réseau où on s'est connecté. En mode « anonyme », il ne faut pas l'envoyer, sauf si on est certains qu'on est toujours sur le même réseau (ce qui est une vérification pas toujours triviale, le RFC recommande d'utiliser 802.1X).

L'option Client Identifier (code 1) en DHCP v6 contient un identificateur unique, le DUID (DHCP Unique Identifier, RFC 8415, section 11). Elle rend donc le suivi d'un client très facile. Pour empêcher ce suivi, le profil demande d'utiliser le format 3, « adresse MAC », du DUID (RFC 8415, section 11.4), avec une adresses MAC changée comme indiquée plus haut. Dans les cas où cette option n'est pas exigée par le protocole (comme les Information-Request, RFC 8415, section 18.2.6, qui sont sans état), elle ne doit pas être envoyée.

DHCP v6 permet évidemment d'obtenir des adresses IPv6 (mais ce n'est pas le seul moyen, contrairement à ce qui se passe en IPv4). Une option semble intéressante pour la vie privée, la demande d'adresses temporaires (RFC 8415, section 13.2). Mais elle n'est pas si utile que ça : car peu de serveurs la mettent en œuvre (le client ne peut donc pas se reposer dessus), le renouvellement de ces adresses n'est pas spécifié, et le fait que le client doive la demander est déjà une fuite d'informations (« je veux être anonyme »). Elle est donc déconseillée.

Notre RFC met également en garde contre des options qui peuvent être amusantes mais qui sont rares : les utiliser revient, pour le client DHCP, à « sortir du lot ». C'est le cas par exemple de la demande de délégation de préfixe (RFC 8415), que le PC typique n'utilise pas.

Le RFC se termine par quelques considérations opérationnelles (section 5). La plus évidente, et la plus « gênante » est que l'application de ce profil va cache l'identité du client au serveur DHCP. C'est le but. Mais cela peut être ennuyeux. Des fonctions comme la publication de l'adresses du client dans le DNS, ou comme la relative stabilité des adresses IP (redonner la même adresse lorsqu'un client revient) ne seront plus possibles. On n'a rien sans rien.

D'autre part, les clients utilisant ce profil consommeront davantage de ressources. Par exemple, à chaque changement au niveau 2, ils réclameront une nouvelle adresse IP, alors que l'ancienne reste réservée, jusqu'à la fin du bail.

Et certains serveurs DHCP fascistes ne donnent une adresse IP qu'aux clients connus, interdisant ainsi l'anonymat. Pour ces raisons, le RFC recommande aux programmeurs de permettre la configuration du client DHCP, configuration allant jusqu'à permettre de débrayer l'anonymisation.

Ce profil a été mis en œuvre dans un client Microsoft, ce qui a donné lieu à un compte-rendu d'expérience à une réunion IETF.


Téléchargez le RFC 7844


L'article seul

RFC 7841: On RFC Streams, Headers, and Boilerplate

Date de publication du RFC : Mai 2016
Auteur(s) du RFC : J. Halpern, L. Daigle, O. Kolkman (Internet Society), Internet Architecture Board (IAB)
Pour information
Première rédaction de cet article le 29 mai 2016


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 7841 écrit par l'IAB les décrit et les précise.

Les éléments utilisés autrefois 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.) Cela avait été fait dans le RFC 5741, que notre RFC 7841 remplace.

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. En termes para-légaux, disons que l'IETF refuse toute responsabilité pour les RFC non-IETF. (À noter que, si tous les RFC ne sont pas des normes IETF, en revanche, toutes les normes IETF sont publiées sous forme d'un RFC.) Si vous tenez à tout connaitre sur les processus de l'IETF, et la publication des RFC, consultez les RFC 2026, RFC 8728, RFC 8729, RFC 5742, RFC 6410 et RFC 7127.

La section 3 liste les éléments qui forment la structure d'un RFC. Leur forme exacte, plus susceptible de changer, figure sur une page Web séparée. Il y a l'en-tête général (section 3.1) qui, pour notre RFC, est :

Internet Architecture Board (IAB)                        J. Halpern, Ed.
Request for Comments: 7841
Obsoletes: 5741                                           L. Daigle, Ed.
Updates: 7322
Category: Informational                                  O. Kolkman, Ed.
ISSN: 2070-1721
                                             Internet Architecture Board
                                                                   (IAB)
                                                              April 2016

indiquant qu'il est issu de la voie IAB, qu'il porte le numéro 7841, 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 « contribution indépendante ».

Après cet en-tête vient un paragraphe (section 3.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. ».

Cet en-tête indique également les relations de ce RFC avec d'autres RFC. Par exemple, notre RFC 7841 indique :

Obsoletes: 5741

car il remplace le RFC 5741, qui n'a désormais plus qu'un un intérêt historique.

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 8179, et l'ISSN des RFC, 2070-1721. Pour le reste du RFC, il faut utiliser le guide stylistique du RFC 7322.

Notre RFC ne décrit que les principes gouvernant ce boilerplate. Les détails, qui sont changeants, sont désormais sur une page Web dédiée à l'IAB. C'est l'un des gros changements depuis le RFC 5741. L'annexe A de notre RFC contient l'état initial de ces textes. Ainsi, un RFC de l'IETF sur le chemin des normes commencera par « This is an Internet Standards Track document. This document is a product of the Internet Engineering Task Force (IETF). It represents the consensus of the IETF community. It has received public review and has been approved for publication by the Internet Engineering Steering Group (IESG). »

Outre ce déplacement du texte effectif depuis le RFC (document rigide et stable) vers une page Web, le principal changement depuis le RFC 5741 est l'allègement de certaines règles de présentation, pour tenir compte du projet de réforme du format de publication des RFC (qui, dans le futur, ne seront plus publiés uniquement sous forme de texte brut).


Téléchargez le RFC 7841


L'article seul

RFC 7858: Specification for DNS over Transport Layer Security (TLS)

Date de publication du RFC : Mai 2016
Auteur(s) du RFC : Z. Hu, L. Zhu, J. Heidemann (USC/Information Sciences Institute), A. Mankin, D. Wessels (Verisign Labs), P. Hoffman (ICANN)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dprive
Première rédaction de cet article le 18 mai 2016


Traditionnellement, les requêtes DNS voyageaient sur le réseau en clair, visibles par tous. Ce n'est évidemment plus acceptable, notamment depuis les révélations de Snowden, et ce RFC normalise donc un mécanisme, DoT (DNS over TLS) qui permet de chiffrer les requêtes DNS pour en assurer la confidentialité vis-à-vis d'un éventuel surveillant.

Le chiffrement est le deuxième pilier de la protection des données, après la minimisation des données (qui, pour le DNS, est spécifiée dans le RFC 9156). Ce chiffrement est motivé notamment par le développement de la surveillance de masse (RFC 7258), par le souci de protéger la vie privée (RFC 6973) et par la prise de conscience des risques spécifiques au DNS (RFC 7626).

Il y avait plusieurs choix possibles pour le groupe de travail DPRIVE qui a produit ce RFC. Il pouvait utiliser une technique extérieure à l'IETF comme DNSCrypt. Il pouvait s'appuyer sur un protocole existant comme IPsec ou TLS. Et il pouvait développer un nouveau protocole (plusieurs propositions avaient été faites en ce sens). Finalement, le choix s'est porté sur un protocole facile à déployer, bien connu, et éprouvé, TLS. D'où le surnom de DoT (DNS over TLS) pour ce protocole. Pour résumer techniquement ce RFC (section 1) : on met les requêtes DNS sur un canal TLS lui-même évidemment transporté sur TCP. (Le groupe DPRIVE travaille également sur une future solution utilisant DTLS et donc UDP.) Outre la confidentialité, TLS permet de protéger les données contre une modification en cours de route.

Notons au passage que DNSSEC ne résout pas ces problèmes : son but est d'authentifier les réponses, pas de protéger contre l'espionnage.

Il y a deux liens à protéger dans une requête DNS, celui entre la machine de l'utilisateur et le résolveur, et celui entre le résolveur et les serveurs faisant autorité. La charte du groupe DPRIVE précisait qu'il fallait d'abord s'attaquer au premier problème, plus facile (une machine ne parle qu'à peu de résolveurs, et elle a une relation avec eux, alors qu'un résolveur parle à beaucoup de serveurs faisant autorité, qu'il ne connait pas.)

La section 3 décrit la gestion des connexions TLS. TLS tourne sur TCP (un de ses copains, DTLS, tourne sur UDP), et il faut donc utiliser ce protocole (notez que l'évolution récente du DNS fait de plus en plus de place à TCP, cf. RFC 7766). DNS-sur-TLS tourne sur un port fixe, le port 853 (les premières versions de ce protocole utilisaient un protocole de négociation de TLS, comme pour SMTP mais, trop compliqué et trop dangereux, il a été abandonné). Le serveur DNS-sur-TLS écoute donc sur le port 853, le client se connecte à ce port, et démarre tout de suite une session TLS (RFC 5246). Ensuite, il y fait circuler le DNS, encodé comme sur TCP (le message DNS précédé de deux octets indiquant sa taille, cf. RFC 1035, section 4.2.2). Comme pour tout usage de DNS sur TCP (RFC 7766), le client et le serveur ne doivent évidemment pas couper la connexion après une seule requête. S'ils le faisaient, les performances seraient catastrophiques, vu le temps qu'il faut pour établir la connexion TCP et la session TLS. Au contraire, la session doit être réutilisée (section 3.4) pour les requêtes ultérieures (et le RFC demande aussi qu'un serveur traite les requêtes en parallèle, pas séquentiellement dans leur ordre d'arrivée, section 3.3.) Un autre moyen de gagner du temps lors de l'établissement d'une nouvelle connexion TCP, moyen recommandé par notre RFC, est d'utiliser TCP Fast Open (RFC 7413).

Notez bien la règle : jamais de contenu chiffré sur le port 53, jamais de contenu en clair sur le port 853. Si le serveur ne répond pas aux requêtes sur le port 853, cela peut être parce qu'une affreuse middlebox bloque tout le trafic vers le port 853, ou tout simplement parce que ce résolveur ne gère pas encore DNS sur TLS. Le client doit alors décider, selon sa politique de sécurité, s'il se rabat sur du trafic DNS en clair ou bien s'il renonce à communiquer. Le RFC recommande que le client se souvienne des serveurs qui répondent sur le port 853, pour détecter un filtrage récemment apparu.

À noter aussi que je n'ai pas parlé encore d'authentification du serveur. Comment être sûr qu'on parle bien au serveur à qui on veut parler et pas au terrible Homme du Milieu ? Pour l'instant, gardez la question de côté, on y reviendra.

Dit comme cela, c'est peut-être un peu compliqué, mais l'un des gros avantages du choix de TLS est qu'il existe déjà des bibliothèques toutes faites pour ce protocole. Ajouter TLS à un client ou un serveur existant est donc relativement simple. (Plus simple que la gestion du RFC 7766, qui est un pré-requis pour DNS-sur-TLS.)

Revenons à l'authentification. A priori, elle est indispensable. Si on n'authentifie pas, on risque d'envoyer ses requêtes DNS à un serveur qui n'est pas le bon, et, dans ce cas, le chiffrement n'aura servi à rien. Pour se faire passer pour le bon serveur DNS, les attaquants actifs ont bien des moyens à leur disposition, comme d'injecter des fausses routes, comme en Turquie. Un chiffrement sans authentification ne protégerait que contre des attaquants strictement passifs.

Oui, mais l'authentification, c'est difficile. Il y a plein de pièges, de problèmes possibles, et d'argent à dépenser (par exemple pour acheter un certificat). Imposer dès le début une authentification stricte dans tous les cas aurait tué le projet dans l'œuf. Le choix a donc été de prévoir un certain nombre de profils d'authentification, que le client choisit, en fonction du degré de sécurité souhaité. (Le serveur, lui, n'authentifie pas le client, en tout cas aucun mécanisme n'est prévu pour cela.) Notre RFC propose deux profils d'authentification (section 4), et d'autres ont décrits par la suite dans le RFC 8310.

Le premier profil est celui « opportuniste » (opportunistic privacy). Le client DNS qui utilise ce profil va tenter de chiffrer, il peut même essayer d'authentifier mais, si cela échoue, il continue quand même à envoyer des requêtes DNS, se disant qu'il est au moins protégé contre les attaques passives.

Le second profil est celui de l'« épinglage de clé » (out-of-band key-pinned »). La clé publique (SPKI pour Subject Public Key Info) du serveur DNS est connue du client (par un mécanisme non spécifié dans ce RFC), et il ne se connecte à un serveur DNS-sur-TLS que s'il utilise une des clés correspondant à son adresse. C'est un mécanisme analogue à l'épinglage HTTP du RFC 7469. Une syntaxe possible, pour un /etc/resolv.conf sur Unix serait, par exemple (l'annexe A propose une autre syntaxe) :

domain example.net
nameserver 2001:db8:90e:241a::1  NjAwZGI5YTVhMzBiY2EzOWY1OTY5YzM0ZGYzMTllYTVkNmYxNjAwYjJmNzZhOGFhYTNhMDEyMzU4MTIwNjNkMwo= 
  

Où le dernier champ est le condensat de la clé publique.

Au passage, si vous voulez trouver le condensat de votre clé, vous pouvez le faire avec gnutls-cli (cela dépend de comment est fait l'échange de clés) ou bien, si le certificat est dans le fichier tmp.pem, avec cette commande utilisant OpenSSL :

openssl x509 -pubkey -in tmp.pem | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64

Ce mécanisme est sûr, empêchant toute attaque de l'Homme du Milieu. Il est peut-être même trop sûr, par exemple pour les réseaux qui utilisent ces horribles portails captifs qui font des attaques de l'Homme du Milieu pour vous rediriger vers le portail. Il peut donc être préférable de ne pas activer ce profil avant de s'être authentifié auprès du portail. (dnssec-trigger utilise un mécanisme analogue.)

J'ai déjà parlé des performances au moment de l'établissement de la connexion, et des problèmes de latence qui peuvent survenir en raison de l'utilisation de TCP et de TLS. La section 5 revient sur ces histoires (il est également recommandé de lire le rapport « T-DNS: Connection-Oriented DNS to Improve Privacy and Security »). Évidemment, une connexion TCP plus une requête DNS, c'est plus coûteux qu'une requête DNS tout court. La requête et la réponse DNS nécessitent deux voyages entre client et serveur, l'etablissement de la connexion TCP en nécessite trois à lui seul, et TLS deux de plus. On pourrait en déduire que DNS-sur-TLS-sur-TCP aura une latence plus élevée de 250 %. On peut réduire ce coût avec des trucs TCP qui réduisent le temps d'établissement de la connexion, comme le TCP Fast Open du RFC 7413 et avec des trucs TLS comme la reprise de session du RFC 5077. Mais, de toute façon, ce calcul n'est vrai que si on établit une connexion TCP par requête DNS, ce qui n'est pas conseillé, la bonne méthode étant au contraire, dans l'esprit du RFC 7766, de réutiliser les connexions.

D'autre part, TCP nécessite de stocker un état dans le serveur. Pour éviter que beaucoup de clients n'écroulent celui-ci, il faut donc ajuster les délais d'inactivité, pour couper les connexions TCP inutilisées.

La section 7 de notre RFC intéressera les ingénieurs qui se demandent pourquoi les choses sont comme elles sont et pourquoi un autre choix n'a pas été fait. Elle est consacrée à l'évolution de la solution de chiffrement du DNS, au sein du groupe de travail DPRIVE. Comme indiqué plus haut, le premier projet prévoyait de tout faire passer sur le port 53, avec un passage en TLS à la demande du client, lorsqu'il envoyait une requête DNS « bidon » avec un nouveau bit EDNS, TO (TLS OK), mis à un, et avec le QNAME (Query NAME) STARTTLS (reprenant un mot-clé utilisé par SMTP, dans le RFC 3207).

Cette méthode avait des avantages : elle permettait par exemple à un serveur d'accepter TLS quand il n'était pas trop chargé, et de le refuser autrement. Et, réutilisant le port existant, elle ne nécessitait pas de changer les ACL sur les pare-feux. Mais elle avait aussi des inconvénients : les affreuses middleboxes ont une longue habitude d'interférence avec EDNS et il n'était pas du tout sûr qu'elles laissent passer le bit TO. Et puis, même si le RFC ne le mentionne pas, il y avait un risque qu'une middlebox trop zélée ne fasse du DPI sur le port 53, s'aperçoive que ce qui passe n'est pas du DNS, et coupe la communication. Mais le principal problème de cette approche était qu'elle rendait les attaques par repli triviales. Un attaquant actif n'avait qu'à supprimer le bit TO et le client n'avait alors plus aucun moyen de savoir si l'absence de TLS était due à un serveur trop ancien, à une middlebox boguée... ou bien à une attaque par repli.

Une proposition alternative amusante avait été de mêler le trafic chiffré et non chiffré sur le port 53 sans signalisation : la structure de l'en-tête TLS est telle qu'une machine interprétant le TLS comme étant du DNS en clair aurait vu une réponse DNS (bit QR à 1) et il n'y aurait donc pas eu de confusion avec le trafic DNS en clair. Astucieux mais évidemment très fragile.

La section 8 de notre RFC synthétise les questions de sécurité. D'abord, TLS n'est évidemment pas une formule magique. Il y a eu plein d'attaques contre TLS (par exemple pour forcer un repli vers des algorithmes de chiffrement faibles), ou contre ses mises en œuvre (on pense évidemment tout de suite à OpenSSL). Pour éviter cela, outre le respect des bonnes pratiques TLS (RFC 7525), le client prudent tâchera de se souvenir quels serveurs acceptaient DNS-sur-TLS. Si un serveur qui l'acceptait ne répond tout à coup plus sur le port 853, c'est peut-être qu'un attaquant tente de forcer un repli sur le port 53, en clair. Le client prudent peut ainsi détecter une attaque possible. Si c'est un nouveau serveur, que le client ne connait pas, la marche à suivre dépend de la politique du client (sécurisé ou laxiste).

Quant aux attaques non-TLS (comme le blocage du port 853 mentionné ci-dessus), c'est également au client, en fonction de son profil de sécurité, de décider ce qu'il va faire (renoncer à communiquer, essayer un mécanisme de résolution alternatif, s'en foutre et tout passer en clair, etc).

Revenons à TLS pour noter que ce protocole ne fait pas d'effort pour dissimuler la taille des paquets. Un attaquant passif peut donc, en observant cette taille, et d'autres informations comme le temps écoulé entre deux paquets, en déduire certaines informations, malgré le chiffrement. L'option de remplissage du RFC 7830 permet de remplir les paquets avec des données bidons, afin de rendre cette analyse plus difficile.

Pour un bilan d'étape du projet « DNS et vie privée » à l'IETF, vous pouvez regarder mon exposé State of the "DNS privacy" project: running code à l'OARC.

Question mises en œuvre de ce RFC, où en est-on ? Aujourd'hui, le résolveur Unbound a le code nécessaire depuis longtemps (depuis la version 1.4.14). On peut génerer les clés nécessaires avec OpenSSL ainsi :

openssl req -x509 -newkey rsa:4096 \
      -keyout privatekeyfile.key -out publiccertfile.pem \
      -days 1000 -nodes    
  

et configurer le serveur ainsi :

server:
  interface: 2001:db8:1::dead:beef@853
  ssl-service-key: "/etc/unbound/privatekeyfile.key"
  ssl-service-pem: "/etc/unbound/publiccertfile.pem"
  ssl-port: 853
  

Unbound va alors activer DNS sur TLS au démarrage et annoncer fièrement « setup TCP for SSL [sic] service ». Les clients pourront alors l'interroger en DNS sur TLS.

Bon, mais quel client utiliser ? Dans la bibliothèque getdns, le logiciel d'exemple getdns_query sait faire du DNS sur TLS :

% ./getdns_query @2001:db8:1::dead:beef -s -a -A -l L www.bortzmeyer.org
...
Response code was: GOOD. Status was: At least one response was returned
  

(C'est l'option -l L qui lui indique de faire du TLS.)

Si on capture le trafic entre getdns_query et Unbound, on peut afficher le résultat avec tshark :

% tshark -n -d tcp.port==853,ssl -r /tmp/dnstls.pcap    
 4   0.002996  2001:db8:1::63a:671 -> 2001:db8:1::dead:beef  SSL Client Hello
 6   0.594206  2001:db8:1::dead:beef -> 2001:db8:1::63a:671  TLSv1.2 Server Hello, Certificate, Server Key Exchange, Server Hello Done
 8   0.734094  2001:db8:1::63a:671 -> 2001:db8:1::dead:beef  TLSv1.2 Client Key Exchange
16   0.751614  2001:db8:1::dead:beef -> 2001:db8:1::63a:671  TLSv1.2 Application Data
17   0.759223  2001:db8:1::63a:671 -> 2001:db8:1::dead:beef  TLSv1.2 Application Data
  

On voit un trafic TLS classique, chiffré. Notez que tshark, par défaut, ne sait pas que c'est du TLS sur le port 853 (cela sera fait lors de la prochaine version majeure). On lui indique donc explicitement (-d tcp.port==853,ssl).

Et si j'ai la flemme d'installer un Unbound configuré pour TLS, est-ce que je peux quand même tester un client DNS-sur-TLS ? Oui, si les serveurs de test publics listés en https://portal.sinodun.com/wiki/display/TDNS/DNS-over-TLS+test+servers veulent bien répondre.

Question client, vous avez aussi le démon Stubby. Vous le lancez en indiquant le résolveur à qui il va tout relayer en DNS-sur-TLS :

%  sudo stubby @145.100.185.16 -L
  

Et vous pouvez alors l'utiliser comme résolveur (il écoute par défaut sur 127.0.0.1.)

Et vous pouvez aussi utiliser Unbound comme client ! Par rapport à Stubby, il a l'avantage d'être un vrai résolveur, validant et avec un cache, et l'inconvénient de ne pas savoir authentifier le résolveur auquel il va parler. Pour configurer Unbound en client DNS-sur-TLS (et non plus en serveur comme dans l'exemple précédent) :

server:
  ...
  ssl-upstream: yes

forward-zone:
  name: "."
  forward-addr: 2001:4b98:dc2:43:216:3eff:fea9:41a@853
  forward-first: no
  

Android a une mise en œuvre de DNS-sur-TLS (cf. ce commit).

Si vous préférez développer en Go, l'excellente bibliothèque GoDNS gère DNS sur TLS (depuis janvier 2016) et vous permet de faire vos propres programmes. Par exemple, ce code Go :

c := new(dns.Client)
c.Net = "tcp-tls"
if *insecure {
        c.TLSConfig = new(tls.Config)
        c.TLSConfig.InsecureSkipVerify = true
}
in, rtt, err := c.Exchange(m, net.JoinHostPort(myResolver, "853"))

va ouvrir une connexion avec le serveur myResolver, sur le port 853, et utiliser TLS. Par défaut, la bibliothèque TLS de Go vérifie le certificat, et que le nom (ou l'adresse IP) dans le certificat correspond bien (ce qui est la bonne approche). Mais cela peut être embêtant si on n'a pas acheté de certificat. D'où l'option (dangereuse !) pour débrayer la vérification (les trois lignes qui commencent par if *insecure). Voici un exemple d'utilisation (au fait, le programme est en dns-tls.go, -k active l'option dangereuse) :

%  ./dns-tls  my-resolver internautique.fr  
Error in query: x509: certificate signed by unknown authority

%  ./dns-tls -k my-resolver internautique.fr 
(time 43051 µs) 2 keys. TC=false    

Téléchargez le RFC 7858


L'article seul

RFC 7837: IPv6 Destination Option for Congestion Exposure (ConEx)

Date de publication du RFC : Mai 2016
Auteur(s) du RFC : S. Krishnan (Ericsson), M. Kuehlewind (ETH Zurich), B. Briscoe (Simula Research Laboratory), C. Ralli (Telefonica)
Expérimental
Réalisé dans le cadre du groupe de travail IETF conex
Première rédaction de cet article le 15 mai 2016


Le mécanisme ConEx, normalisé dans le RFC 7713, permet d'informer les routeurs situés en aval qu'un flot de données se heurte à la congestion. Il y a plusieurs façons d'indiquer cette congestion, et ce RFC le fait par une option dans l'en-tête Destination Options d'IPv6.

En effet, le mécanisme décrit dans le RFC 7713 est abstrait : il spécifie des concepts, pas comment ils sont représentés sur le câble. Notre RFC 7837, au contraire, est concret : il indique comment mettre l'information ConEx dans des champs du paquet que les équipements réseau, notamment les routeurs, pourront lire. ConEx est actuellement un projet expérimental (et même très expérimental) et il n'est pas sûr qu'il soit déployé avec enthousiasme. En attendant, puisque c'est expérimental, le but est de récolter de l'information et, pour cela, il faut du code qui tourne, avec des paquets concrets (section 1 de notre RFC). Mettre l'information ConEx dans le champ Options d'IPv4 est délicat : ce champ est de taille limitée, et pose souvent des problèmes dans le réseau. L'idée est donc d'utiliser le protocole du futur, IPv6, et ses en-têtes d'extension (RFC 2460, section 4).

La section 3 détaille les choix techniques effectués et leurs raisons. Les sections 3.3 et 4 du RFC 7713 expliquent les contraintes d'encodage concret de ConEx dans les paquets. Ici, les exigences considérées ont été :

  • Les marques ConEx doivent être visibles par tous les nœuds ConEx du chemin (donc, pas question de les mettre tout au bout du paquet),
  • Pour que les paquets marqués arrivent à bon port, même en traversant les équipements actuels qui ne connaissent pas ConEx, il faut un mécanisme standard et déjà largement accepté (pas question de changer le format des paquets IP, cela empêcherait le déploiement incrémental),
  • La présence des marques ConEx ne doit pas ralentir le traitement des paquets (cf. section 5),
  • Les marques ConEx doivent pouvoir être protégées contre les manipulations ultérieures (exigence pas réellement satisfaite en pratique, sauf à utiliser IPsec).

Quatre solutions IPv6 avaient été envisagées par le groupe de travail à l'IETF :

  • Une option Hop-by-hop (RFC 2460, section 4.3).
  • Réutiliser le champ Flow label qui ne sert quasiment pas (cf. RFC 6437),
  • Créer un nouvel en-tête d'extension,
  • Une option Destination (RFC 2460, section 4.6), le choix qui a finalement été fait.

L'en-tête d'extension Hop-by-hop aurait été l'option logique puisqu'elle est examinée par chaque routeur, ce qui est bien ce qu'on veut pour ConEx. Elle aurait été conforme aux principes d'IPv6. Mais, dans les routeurs actuels, le traitement de cette option se fait de manière extrêmement lente (elle n'emprunte pas le chemin rapide dans le routeur, mis en œuvre en ASIC ou FPGA), ce qui viole la troisième exigence. Le choix de l'en-tête Destination, qui est normalement de bout en bout et que les intermédiaires ne sont pas censés regarder, est donc surprenant, mais justifié. Il viole un peu la première exigence (si le paquet est encapsulé, le routeur aura du mal à voir cet en-tête). Et, surtout, analyser la chaîne des en-têtes d'extension IPv6 est anormalement compliqué. Mais il n'y avait guère d'autre choix réaliste. En pratique, certains routeurs auront donc besoin d'un changement de leurs règles de traitement des en-têtes d'extension s'ils veulent voir les marques ConEx.

(Sur la survivabilité des en-têtes d'extension IPv6 dans l'Internet, voir l'étude de Mehdi Kouhen en février 2016 et le RFC 7872.)

La section 4 présente le format concret. La nouvelle option Destination se nomme CDO, pour ConEx Destination Option. Elle est mise dans un en-tête d'extension Destination Options (RFC 2460, section 4.6). Comme les autres options Destination, elle est encodée en TLV. Le type de l'option est 0x1E (30, valeur réservée aux expérimentations, non définitive), sa longueur est 1 (un seul octet, et encore, tous les bits ne sont pas utilisés) et sa valeur est composée de quatre bits (RFC 7713, notamment la section 2.1) : X (« je sais faire du ConEx »), L (« des paquets ont été perdus »), E (« de la congestion a été signalée par ECN ») et C (« pas (encore) de congestion, j'accumule des crédits »). Le dernier bit, C, est à utiliser avant qu'on détecte la congestion (RFC 7713, notamment la section 5.5).

Au passage, si vous écrivez des programmes en C qui veulent ajouter des options dans l'en-tête Destination, vous pouvez consulter mon article.

On a dit plus haut que la principale raison pour utiliser l'en-tête Destination et pas le Hop-by-Hop (qui aurait été plus logique), est le souci que les paquets restent sur le fast path des routeurs (le traitement fait par le matériel, par opposition au slow path, confié au processeur généraliste, bien plus lent). Mais le problème est que l'en-tête Destination, n'étant pas prévu pour être lu par les équipements réseau sur le chemin, peut se trouver n'importe où dans la chaîne des en-têtes (alors que l'en-tête Hop-by-hop est forcément au début, cf. RFC 2460, section 4.1). Et l'option CDO pourrait, en théorie, se trouver n'importe où dans l'en-tête Destination. Notre RFC est donc obligé de recommander (section 5) que l'option CDO soit la première dans l'en-tête Destination.

Reste à voir s'il sera effectivement possible de déployer cette option. L'ossification de l'Internet rend tout déploiement de ce type difficile (les en-têtes d'extension sont rares dans les paquets IPv6 actuels).


Téléchargez le RFC 7837


L'article seul

RFC 7786: TCP modifications for Congestion Exposure

Date de publication du RFC : Mai 2016
Auteur(s) du RFC : M. Kuehlewind (ETH Zurich), R. Scheffenegger (NetApp)
Expérimental
Réalisé dans le cadre du groupe de travail IETF conex
Première rédaction de cet article le 15 mai 2016


C'est après une très longue genèse (ce document avait été adopté par le groupe de travail il y a plus de quatre ans) que voici les protocoles concrets pour la signalisation de la congestion aux routeurs situés en aval. Ici, l'utilisation de ce système avec TCP.

ConEx (pour Congestion Exposure, signalement de la congestion) est décrit dans le RFC 6789. L'idée de base est d'informer le réseau qu'un flot de données rencontre de la congestion, afin que les éléments actifs de ce réseau puissent prendre des décisions intelligentes. ConEx est divisé en une spécification abstraite (RFC 7713) et une ou plusieurs spécifications de protocoles concrets. Ce RFC ne spécifie pas un encodage sur le câble, juste le changement de comportement des mises en œuvre de TCP. (Un autre RFC concret spécifie un encodage pour IPv6, le RFC 7837.)

Il n'y a pas besoin de négociation au début (section 1 du RFC), comme avec les options TCP. Les émetteurs qui connaissent ConEx utilisent les informations existantes (pertes de paquets et ECN, stockées dans deux compteurs différents, cf. la section 3 du RFC).

Pour bien utiliser ConEx, le TCP de l'émetteur a besoin d'informations. Bien qu'il ne soit pas indispensable, c'est mieux si SACK (RFC 2018) est disponible.

La section 2 du RFC résume les modifications chez l'émetteur TCP (le récepteur n'a pas besoin d'être changé pour ConEx). Le comportement de l'émetteur dépendra du fait que le récepteur met en œuvre (ou pas) SACK et ECN. L'émetteur est responsable du marquage des paquets (suivant l'encodage du RFC 7837) avec des signaux ConEx. Il doit tenir compte du nombre d'octets, pas du nombre de paquets (RFC 7141).

En cas de perte de paquets, l'émetteur va mettre le signal ConEx L (loss experienced). Dans certains cas (retransmission inutile parce que le paquet était bien arrivé, c'est l'accusé de réception qui s'était perdu), l'émetteur ne connait pas le nombre exact d'octets perdus. Il peut donc surestimer la congestion dans les signaux ConEx qu'il envoie. Pour avoir de meilleurs mesures, l'émetteur peut toujours mettre en œuvre les RFC 5682, RFC 3708 ou RFC 3522.

Si c'est par des marques ECN, et non pas par des pertes de paquets, que l'émetteur a appris qu'il y avait congestion, il va utiliser les marques ConEx E (ECN experienced).

Dans tous les cas (perte de paquets ou bien ECN), les paquets marqués ConEx devront également porter une marque X, qui indique que l'émetteur sait faire du ConEx (section 4 du RFC).

Un émetteur ConEx est aussi censé envoyer des crédits lorsqu'il n'y a pas de congestion. Ces crédits seront ensuite « consommés » lors des épisodes de congestion. Cela se fait avec le signal C (Credit).

Les paquets contenant les signaux ConEx peuvent se perdre, comme tous les paquets IP (section 5 du RFC). Cela peut mener à des pénalités injustes (un émetteur détecte qu'il y a congestion en aval, le signale avec un L ou un E, le paquet portant le signal est perdu, un routeur qui fait de l'audit ConEx se dit alors « ah, ah, il essaie de tricher, il n'a pas signalé la congestion »). Le problème étant du second ordre (si la probabilité de perdre un paquet est P, la probabilité qu'il y ait perte du paquet et perte du signal est de P au carré), on peut choisir de l'ignorer.

Plus délicat, le problème de la fraîcheur des informations ConEx (section 6 du RFC). Ces informations ne sont utiles que si elles sont très récentes (typiquement moins d'un RTT depuis que la congestion est apparue). L'émetteur doit donc faire attention à ne pas retarder les signaux ConEx. Parfois, il n'a pas trop le choix, par exemple si l'application arrive d'envoyer des données, il n'y aura pas de paquets à marquer.


Téléchargez le RFC 7786


L'article seul

RFC 7793: Add 100.64.0.0/10 prefixes to IPv4 Locally-Served DNS Zones Registry

Date de publication du RFC : Mai 2016
Auteur(s) du RFC : M. Andrews (ISC)
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 13 mai 2016


Il existe un registre des zones DNS qui doivent être gérées localement par le résolveur DNS et pour lesquelles les requêtes ne sont pas transmises aux serveurs de la racine. Ce nouveau RFC ajoute à ce registre les zones correspondant au préfixe IPv4 100.64.0.0/10, que le RFC 6598 avait réservé pour la numérotation des machines situées derrière les CGN.

Le but de ce registre est d'éviter de surcharger les serveurs racine avec des requêtes qui sont inutiles puisque les noms dans ces zones n'ont qu'une signification locale, et ne pourraient pas recevoir une réponse sensée de la racine. Le RFC 6303 avait donc créé ce registre des noms pour lesquels, par défaut, le résolveur DNS doit retourner NXDOMAIN (code indiquant que le nom n'existe pas) tout de suite. On y trouve par exemple la zone 10.in-addr.arpa, zone correspondant aux adresses IP du RFC 1918.

Le RFC 6598 avait réservé tout le préfixe 100.64.0.0/10 pour les CGN. Notre nouveau RFC met donc les zones 64.100.in-addr.arpa à 127.100.in-addr.arpa dans le registre des zones à servir localement. Au fur et à mesure des mises à jour des résolveurs (leur code, ou bien la configuration locale), toute requête PTR dans une de ces zones doit être traitée localement par le résolveur.

Ces zones sont déléguées aux serveurs de noms de l'IANA, pour attraper les requêtes qui ne suivent pas ces règles :

% dig +short NS 64.100.in-addr.arpa
a.iana-servers.net.
b.iana-servers.net.
c.iana-servers.net.

Sinon, aujourd'hui, par défaut, Unbound « délègue » ces zones à... localhost (si on veut un vrai contenu, il faut configurer explicitement ces zones) :

% dig +short NS 64.100.in-addr.arpa
localhost.
    
% dig +short  NS 64.100.in-addr.arpa 
64.100.IN-ADDR.ARPA.
    

Téléchargez le RFC 7793


L'article seul

RFC 7830: The EDNS(0) Padding Option

Date de publication du RFC : Mai 2016
Auteur(s) du RFC : A. Mayrhofer (nic.at GmbH)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dprive
Première rédaction de cet article le 11 mai 2016


Ce nouveau RFC fait partie de la série de ceux qui tentent d'améliorer la situation du DNS pour tout ce qui concerne la protection de la vie privée. Parmi les efforts dans ce domaine, il y a une possibilité de chiffrement des communications DNS, dans le RFC 7858 (DNS-sur-TLS). Elle utilise le protocole TLS. Ce dernier ne fait rien pour dissimuler la longueur des requêtes et réponses DNS. Or, de telles métadonnées peuvent suffire à identifier les requêtes faites. Il est donc important de compléter le chiffrement avec un mécanisme de remplissage (padding). C'est ce que permet la nouvelle option EDNS normalisée dans ce RFC.

Trouver la requête effectuée uniquement à partir de la taille de la réponse est d'autant plus facile que les données DNS ne sont pas confidentielles. Un espion qui soupçonne que M. Michu fait des requêtes pour tel nom de domaine peut faire la même requête, noter la taille de la réponse chiffrée, et voir s'il trouve la même taille dans les réponses reçues par M. Michu. Voilà pourquoi il faut ajouter aux requêtes et aux réponses un certain nombre d'octets, pour rendre plus difficile cette analyse des métadonnées.

Ce RFC est court car le mécanisme est très simple (section 3 du RFC). Ce mécanisme utilise une nouvelle option EDNS (EDNS est normalisé dans le RFC 6891.) Cette option porte le numéro 12 et sa partie « données » porte le remplissage. (Comme toute option EDNS, elle est encodée en TLV : un champ indique le type de l'option, ici, 12, un champ indique la longueur de l'option, et le dernier contient les données.)

Que mettre comme remplissage ? Cette question a été la plus discutée lors de la création de ce RFC (qui a été plutôt calme et consensuelle, pour le reste.) Le RFC précise que l'émetteur d'un message DNS devrait remplir avec des octets nuls (0x00). Si l'émetteur craint que certains traitements (par exemple de la compression, voyez cependant la section 6 qui demande de ne pas l'utiliser) appliqués avant le chiffrement ne suppriment l'essentiel du remplissage, il est autorisé à mettre une autre valeur. De toute façon, le récepteur doit accepter n'importe quelle valeur, pour permettre les évolutions futures. En pratique, il doit donc ignorer le contenu des données de cette option.

Pourquoi n'avoir pas simplement dit que l'émetteur pouvait mettre ce qu'il voulait, dans ce cas ? Parce qu'il semblait possible, dans ce cas, que des programmeurs naïfs utilisent de la variable non initialisée, et laissent ainsi fuiter le contenu de leur mémoire (comme dans la faille Heartbleed.) Et pourquoi n'avoir pas spécifié un remplissage avec des données aléatoires ? Parce que ce n'est pas normalement nécessaire : pour un observateur, le contenu chiffré doit apparaitre aléatoire, quel que soit le texte en clair (si TLS ne fournissait pas cette propriété, des tas d'attaques seraient possibles, par exemple à base de texte en clair connu.)

Voilà, l'essentiel du RFC tient dans cette courte section 3. Mais quelques détails suivent. Par exemple, quelle quantité d'octets mettre dans la nouvelle option ? Le RFC ne fournit pas de guide à ce sujet, il rappelle juste qu'il ne faut pas aboutir à des messages plus gros que ce que le client spécifiait dans son champ Payload size EDNS (souvent 4 096 octets mais cela dépend du client.) Des règles plus précises sur la politique de remplissage ont été normalisées par la suite dans le RFC 8467. Le serveur DNS ne doit évidemment pas utiliser cette option si la requête ne contenait pas d'EDNS. Si elle contenait de l'EDNS sans cette option, le serveur est libre de remplir ou pas. Si la requête contenait de l'EDNS avec l'option Padding, alors, le serveur doit effectuer du remplissage.

Quelques trucs à ne pas oublier en section 6 : le remplissage augmente la taille des paquets (évidemment). Cela mènera donc à un accroissement du trafic. Dans l'Internet d'aujourd'hui, où tous les États qui en ont les moyens procèdent à une surveillance massive de leurs citoyens (RFC 7258), c'est un petit prix à payer, pour l'avantage de compliquer le travail des surveillants.

Autre piège, l'option de remplissage ne doit être utilisée que si le trafic DNS est chiffré. Autrement, non seulement elle ne servirait à rien, mais elle augmenterait le risque d'attaques avec amplification.

À noter que, comme plein d'autres champs des messages DNS (comme par exemple le QNAME, le Query Name), cette option peut servir de canal caché. Peut-être verra-t-on un jour une mise en œuvre d'IP-sur-DNS utilisant cette option ?

Notez que cette technique est indépendante du protocole de chiffrement sous-jacent, puisqu'elle est faite au niveau applicatif. DNScrypt pourrait l'utiliser (sauf qu'il a son propre système de remplissage.)

Et les mises en œuvre de cette technique ? A-t-on du code qui tourne ? getdns a le remplissage depuis sa version 0.5.1 (cf. le Changelog.) GoDNS y travaille. Wireshark peut analyser cette option. La page officielle sur cette option de remplissage liste d'autres mises en œuvre.

Depuis la sortie de ce RFC, les clients et serveurs DNS ont peu à peu intégré cette option de remplissage. Voyons ici kdig avec le serveur public de Cloudflare :

% kdig +dnssec +tls +padding @1.1.1.1 A chatons.org
...
;; EDNS PSEUDOSECTION:
;; Version: 0; flags: do; UDP size: 1232 B; ext-rcode: NOERROR
;; PADDING: 301 B
    

Notez que 1.1.1.1 met du remplissage même si le client ne l'a pas demandé, ce que permet la section 4 du RFC.

Daniel Kahn Gillmor, qui avait programmé cette extension dans getdns, en a profité pour faire quelques statistiques :

Ethernet Frame sizes for packet containing DNS query

                Transport    |   query to   |     query to
                   used      |  example.com |  www.example.com
   --------------------------+--------------+-------------------
               cleartext UDP |   82 octets  |   86 octets
               cleartext TCP |  108 octets  |  112 octets
                TLS over TCP |  137 octets  |  141 octets
(padded to 512) TLS over TCP |  609 octets  |  609 octets
  

On voit que le remplissage brouille la différence de taille entre les deux requêtes. Mais restons prudents : le remplissage est une bonne technique pour rendre plus difficile l'analyse des métadonnées mais il n'est pas parfait. Lisez par exemple l'excellent « Peek-a-Boo, I Still See You : Why Efficient Traffic Analysis Countermeasures Fail ».


Téléchargez le RFC 7830


L'article seul

Google Chrome et son utilisation du DNS

Première rédaction de cet article le 8 mai 2016
Dernière mise à jour le 10 mai 2016


Une tribune sensationnaliste dans le Monde le 6 mai prétendait que « Google [avait] changé l'Internet » et portait une accusation précise : le navigateur Google Chrome utiliserait une racine DNS spécifique à Google. Passons sur le fond politique de l'article, est-ce qu'au moins les faits allégués sont exacts ?

Un petit mot au passage sur ce concept de « racine » (les explications dans la tribune publiée dans le Monde sont... floues). Un logiciel qui veut utiliser un nom de domaine (par exemple un navigateur Web qui veut aller voir https://www.laquadrature.net/fr) va devoir interroger le DNS, un système technique qui permet, à partir d'un nom de domaine, d'obtenir des informations techniques indispensables (comme l'adresse IP du serveur). Les noms de domaine sont organisés sous forme d'arbre, avec la racine représentée en haut (contrairement aux botanistes, les informaticiens mettent la racine des arbres en haut). L'interrogation du DNS est faite par un logiciel nommé résolveur, qui est en général indiqué automatiquement à la machine (c'est la plupart du temps une machine du FAI, mais on peut utiliser son propre résolveur). Le résolveur commence par la racine, d'où il est aiguillé vers les TLD puis de fil en aiguille vers tous les autres noms de domaine. On voit donc que qui contrôle la racine contrôle le DNS.

L'article publié dans le Monde dit « le navigateur Chrome de Google remplace sans avertissement l’annuaire de l’ICANN par le sien ». Au milieu de toutes les vagues affirmations de ce texte, voici un fait précis, qu'on peut contrôler. Cela prend cinq minutes à n'importe quel technicien. Avec un outil d'usage courant, tcpdump, on peut voir le trafic DNS de la machine. Lançons Chrome, tentons de visiter http://nic.la/ et observons ce trafic. (Les lignes suivantes sont triviales à interpréter pour le technicien ordinaire dont je parlais.)

11:38:24.549321 IP6 2001:691:1348:7::bad:209.27121 > 2001:67c:217c:6::2.53: 58483% [1au] A? nic.la. (35)
11:38:24.551217 IP6 2001:67c:217c:6::2.53 > 2001:691:1348:7::bad:209.27121: 58483- 0/8/9 (685)

Que voit-on ? La machine d'adresse IP 2001:691:1348:7::bad:209 a fait une requête DNS au serveur 2001:67c:217c:6::2, qui est bien un serveur de la racine (leurs adresses IP sont publiques et connues).

Amusant détail, je n'utilise personnellement pas la « racine ICANN » mais une racine « alternative », Yeti. Donc, même si on a fait un choix différent de la majorité, Chrome respecte ce choix (en fait, Chrome ne parle pas directement à la racine : comme tout bon logiciel, il parle au résolveur configuré par l'utilisateur, et ce résolveur a été configuré pour utiliser telle ou telle racine). Le complot s'effondre donc : le principal reproche fait à Google dans cet article ne repose sur rien. Alors que la vérification des faits prend quelques minutes à n'importe quel technicien, les auteurs de la tribune n'ont pas vérifié, ni demandé à un technicien de le faire.

Est-ce un accident isolé dans une tribune par ailleurs raisonnable ? Non, il y a beaucoup d'autres erreurs techniques. Par exemple, les auteurs affirment « [la racine de Google est] plus rapide puisque souvent délivré d'étapes de contrôle et de surveillance ». Enregistrer les requêtes (comme le fait la NSA) ne ralentit rien, cette affirmation est donc dénuée de sens.

Autre exemple du manque de rigueur de cette tribune, la mention du .google comme étant « la racine de Google » alors qu'il s'agit d'un banal TLD... Est-ce une distinction importante ou bien est-ce que je pinaille excessivement ? Oui, c'est important car cette erreur permet de juger le sérieux d'un texte. Imaginez un article portant sur la production laitière. L'article confond à un moment vaches et chèvres. Sans importance, puisqu'après tout ce sont bien deux mammifères produisant du lait ? Mais si un article sur ce sujet comportait une telle erreur, lui accorderait-on la moindre crédibilité ? C'est pareil ici : confondre TLD et racine, dans un article sur le DNS, est un signe d'extrême légèreté.

On notera aussi que des affirmations tout aussi fausses (« Cependant Google (et Chrome) utilise leur propre racine (copie de la racine ICANN) dont une est l’adresse IP 8.8.8.8 » se trouvent depuis longtemps sur le serveur Web de la société commerciale Open-Root, pour laquelle travaillent deux des auteurs. (8.8.8.8, alias Google Public DNS, est un résolveur DNS, qui n'a donc rien à voir avec une racine. Vaches et chèvres, encore.)

Ces erreurs techniques sont d'autant plus curieuses que, si on souhaite dire du mal de Google et mettre en garde contre le pouvoir dont jouit cette société, les exemples ne manquent pas. Google a un poids important, par sa part de marché, peut influencer ce que font les internautes, et ce poids important est certainement une question politique à traiter, comme toutes les fois où une boîte privée a trop de pouvoir. Alors, pourquoi rajouter des accusations fantaisistes ? Est-ce parce qu'il y a un risque que Chrome, un jour, fasse ce qui lui est reproché dans cette tribune ? Tout est possible mais ce ne serait pas très malin de la part de Google. En effet, l'utilisation d'une autre racine se voit (comme montré avec tcpdump plus haut). Ce ne serait pas très discret de la part de Google (la tribune parle de « substitution invisible », ce qui n'a pas de sens, vu cette visibilité du trafic réseau). D'autre part, pas mal d'entreprises utilisent en interne des TLD non-existants comme .corp, qui ne sont connus que de leurs résolveurs. Si Chrome n'utilisait pas ces résolveurs, ces TLD ne fonctionneraient pas.

Autre chose frappante, ce texte a largement circulé sur les réseaux sociaux, étant repris sans nuances, sans aucune vérification. On l'a par exemple vu cité sur le site de l'émission Arrêt sur Images. Apparemment, le fait d'être publié dans le Monde a un poids qui suffit à débrayer toute critique. (Alors qu'il s'agissait d'une tribune et pas d'un article, ce qui indique que le Monde n'a pas exercé de contrôle trop serré sur le contenu.)

Depuis, il y a eu une réponse à ce texte. Elle a été annoncée sur Twitter en utilisant le raccourcisseur d'URL de Google (goo.gl). Le site d'Open-Root utilise d'ailleurs le spyware Google Analytics. Cela indique leur niveau de cohérence (mais c'est courant chez les souverainistes : de grands discours anti-GAFA à la tribune, mais l'utilisation de tous leurs outils en pratique.) Sans compter la paranoïa « nous sommes attaqués de toute part », de la part de gens qui passent dans le Monde ou à la télé quand ils veulent, et qui sont invités à tous les colloques ministériels...

Bon, je critique cette réponse sur la forme, mais sur le fond ? Sur le fond, il n'y a rien à dire, parce qu'il n'y a pas d'éléments nouveaux : la réponse cite comme preuve que Google a son propre DNS... l'existence de Google Public DNS. Confondre un résolveur DNS public avec une racine, c'est comme l'expert en élevage cité plus haut qui confondrait vache et chèvre... C'est tellement désespérant que c'est au delà de toute discussion.

Pour les reste, pas de détails, pas de tcpdump montrant Chrome faire des requêtes à la soi-disant racine Google, rien.


L'article seul

A small DNS trick to see Sci-Hub despite censorship attempts

First publication of this article on 8 May 2016
Last update on of 9 December 2017


The service Sci-Hub is a great help for the scientists, allowing them to access to a lot of scientific papers that were before locked behind paywalls. The publishing companies keep trying to censor Sci-Hub and block access to this service, for instance by taking down domain names like it happened a few days ago with sci-hub.io. If you control your DNS resolver, you can easily restore access.

Sci-Hub's domain sci-hub.io was recently taken down. There are several ways to still use Sci-Hub, such as "domain hopping" (using another TLD such as sci-hub.bz) or using Tor (the address is scihub22266oqcxt.onion). But there is one which does not seem to have been publically documented yet.

For the rest of the article, we will rely on a local DNS resolver. ("local" does not imply it is on your own machine: it may be on the local network. The important point is that you can change its configuration.) A local resolver is a great tool against DNS censorship. By default, it does not see Sci-Hub domains (NXDOMAIN means "No Such Domain"). Let's test with dig:


% dig A sci-hub.io

; <<>> DiG 9.10.4 <<>> A sci-hub.io
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 45356
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 8, ADDITIONAL: 1
...
;; QUESTION SECTION:
;sci-hub.io.		IN A
...
;; Query time: 1408 msec
;; SERVER: ::1#53(::1)
...

    

OK, it failed, the domain being taken down. Let's configure our local resolver to work around the problem. Sci-Hub has a public name server that answers to the Sci-Hub domains. First, we'll be using the excellent program Unbound. We just add in unbound.conf:

server:
     domain-insecure: "sci-hub.io"
  
forward-zone:
     name:   "sci-hub.io"
     forward-addr: 80.82.77.83
     forward-addr: 80.82.77.84

and we restart Unbound and it works:


%  dig A sci-hub.io

; <<>> DiG 9.10.3-P4-Debian <<>> A sci-hub.io
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 22120
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;sci-hub.io.		IN A

;; ANSWER SECTION:
sci-hub.io.		3483 IN	A 80.82.77.83

;; AUTHORITY SECTION:
sci-hub.io.		3483 IN	NS ns1.sci-hub.cc.
sci-hub.io.		3483 IN	NS ns2.sci-hub.cc.

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Sun Dec 03 17:51:49 CET 2017
;; MSG SIZE  rcvd: 101
  

(DNS experts may discuss the use of forward-zone instead of stub-zone. The Sci-Hub servers accept recursive requests so both work. In my opinion, forward may be a bit more future-proof if the authoritative name server changes its IP address but a recursor stays in place at the old address.)

With Knot resolver, you just add a rule:

-- Sci-Hub
policy.add(policy.suffix(policy.STUB({'80.82.77.83', '80.82.77.84'}), policy.todnames({'sci-hub.io.'})))
    

to the configuration.

Doing the same with BIND is possible. Just put in its configuration file (somewhere/named.conf):

   zone "sci-hub.io" {
                 type forward;
                 forwarders {80.82.77.83; 80.82.77.84;};
   };
    

The trick is to use the fact that 80.82.77.83 also allows DNS zone transfers. You can therefore configure your BIND as a slave for sci-hub.io. Once BIND is authoritative for this domain, it won't check with DNSSEC:

    zone "sci-hub.io" {
	         type slave;
                 masters {80.82.77.83; 80.82.77.84;};
};

Note: the option dnssec-must-be-secure addresses a different issue and is not useful here.

I do not use dnsmasq but Canari Bleu does and says you have to add server=/sci-hub.io/80.82.77.83 in dnsmasq.conf.

Of course, this hack is far from perfect. It doesn't scale (imagine if there were dozens of censored domains to make accessible this way). It's brittle (the IP addresses can change without warning). But this sort of imperfect workarounds will become more and more common with the increase of politically or business-motivated censorship.


L'article seul

RFC 7819: Privacy considerations for DHCP

Date de publication du RFC : Avril 2016
Auteur(s) du RFC : S. Jiang (Huawei Technologies), S. Krishnan (Ericsson), T. Mrugalski (ISC)
Pour information
Réalisé dans le cadre du groupe de travail IETF dhc
Première rédaction de cet article le 3 mai 2016


Le protocole DHCP est bien connu : la grande majorité des machines « client » qui se connectent à l'Internet l'utilisent pour récupérer des éléments de configuration indispensables, comme l'adresse IP à utiliser. Mais peu de gens sont conscients que DHCP peut être dangereux pour la vie privée : le client DHCP n'est en effet pas passif, il envoie au serveur des informations qui peuvent permettre de suivre à la trace une machine mobile.

DHCP pour IPv4 est normalisé dans le RFC 2131. (Le RFC 7824 traite le cas de DHCP pour IPv6, qui pose des problèmes similaires.) Son principe de fonctionnement est simple : le client DHCP (la machine de M. Michu) envoie à la cantonade une requête pour demander des informations de configuration réseau, le serveur DHCP se reconnait, il répond avec ces informations. Voici une transaction DHCP, vue par tcpdump :

   21:32:13.284690 IP (tos 0x0, ttl 64, id 960, offset 0, flags [none], proto UDP (17), length 377)
    0.0.0.0.68 > 255.255.255.255.67: [udp sum ok] BOOTP/DHCP, Request from b8:27:eb:84:35:e3, length 349, xid 0x4feaaa6f, Flags [none] (0x0000)
	  Client-Ethernet-Address b8:27:eb:84:35:e3
	  Vendor-rfc1048 Extensions
	    Magic Cookie 0x63825363
	    DHCP-Message Option 53, length 1: Request
	    Client-ID Option 61, length 19: hardware-type 255, eb:84:35:e3:00:01:00:01:c7:92:bc:8a:b8:27:eb:ba:90:94
	    Requested-IP Option 50, length 4: 192.168.2.9
	    MSZ Option 57, length 2: 1500
	    Vendor-Class Option 60, length 46: "dhcpcd-6.9.0:Linux-4.4.8-2-ARCH:armv6l:BCM2708"
	    Hostname Option 12, length 5: "amour"
	    T145 Option 145, length 1: 1
	    Parameter-Request Option 55, length 14: 
	      Subnet-Mask, Classless-Static-Route, Static-Route, Default-Gateway
	      Domain-Name-Server, Hostname, Domain-Name, BR
	      NTP, Lease-Time, Server-ID, RN
	      RB, Option 119
	    END Option 255, length 0
21:32:13.299825 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto UDP (17), length 576)
    192.168.2.254.67 > 192.168.2.9.68: [udp sum ok] BOOTP/DHCP, Reply, length 548, xid 0x4feaaa6f, Flags [none] (0x0000)
	  Your-IP 192.168.2.9
	  Client-Ethernet-Address b8:27:eb:84:35:e3
	  Vendor-rfc1048 Extensions
	    Magic Cookie 0x63825363
	    DHCP-Message Option 53, length 1: ACK
	    Server-ID Option 54, length 4: 192.168.2.254
	    Lease-Time Option 51, length 4: 43200
	    Subnet-Mask Option 1, length 4: 255.255.255.0
	    Default-Gateway Option 3, length 4: 192.168.2.254
	    Domain-Name-Server Option 6, length 8: 192.168.2.254,149.20.64.21
	    BR Option 28, length 4: 192.168.2.255
	    END Option 255, length 0
	    PAD Option 0, length 0, occurs 264   
    

Malheureusement, dans la requête du client se trouvent plein de détails sur la machine demanderesse (section 1 du RFC). Compte-tenu de la sensibilité aux problèmes de vie privée (RFC 6973) et de l'ampleur de la surveillance de masse exercée par les États (RFC 7258), il était nécessaire de limiter cette fuite d'informations. Ce premier RFC va décrire le problème, et proposer quelques pratiques qui le limitent. Le RFC 7844 détaille un profil DHCP qui limite sérieusement la fuite. Dans une prochaine étape, il y aura peut-être des modifications au protocole DHCP mais ce n'est pas encore fait.

Pour cette analyse de sécurité, la section 2 de notre RFC introduit la notion d'identificateur stable. Un identificateur stable (stable identifier) est une information envoyée par le client DHCP qui change peu ou pas dans le temps (et qui peut donc permettre de tracer une machine mobile). La stabilité peut dépendre de la mise en œuvre logicielle utilisée. Ainsi, une adresse MAC est typiquement un identificateur stable mais, si macchanger est utilisé, ce n'est plus le cas. Un identificateur stable n'est pas forcément mondialement unique.

Le gros de ce RFC est la section 3, qui liste les identificateurs envoyés par le client DHCP. Le plus évident, car il est prévu pour cela, est l'option DHCP Client Identifier (RFC 2131, section 2, et RFC 2132, section 9.14). Il est en général stable (le RFC 1533, prédécesseur du RFC 2132, recommandait même d'utiliser une adresse MAC, mais on voit parfois un nom de domaine, ou bien un DUID - décrit dans le RFC 4361). Même si on utilise un logiciel comme macchanger pour changer d'adresse MAC, pas mal de mises en œuvre de DHCP utiliseront la valeur initiale et la stockeront... pour toujours.

Moins spectaculaire, plusieurs champs de la requête transportent des identificateurs fondés sur une adresse. C'est le cas de yiadrr, qui indique l'adresse IP actuelle du client ou chaddr qui indique l'adresse MAC. Plusieurs options font de même comme la Requested IP Address (qui permet d'indiquer l'adresse IP qu'on souhaiterait recevoir).

Autre option qui envoie un identificateur stable, et souvent unique, l'option Client FQDN (RFC 4702) qui transmet au serveur le FQDN.

Après les adresses et les noms de domaine, un autre danger se présente avec les options qui permettent au client d'indiquer le logiciel qu'il utilise. C'est le cas de l'option Vendor class (RFC 2132, section 9.13, une sorte d'équivalent du User-Agent: de HTTP, dans l'exemple plus haut, elle indique une machine ARM sous Linux), du Vendor-Identifying du RFC 3925, et de toutes les options Vendor-specific information (RFC 2132, section 8.4), qui peuvent indiquer le numéro de version du logiciel utilisé, sa configuration spécifique, etc. Certes, elles ne sont pas uniques (elles ne désignent pas une machine particulière) mais elles font quand même fuiter de l'information sur le client et, combinées avec d'autres informations, elles peuvent mener à une identification unique. Une option analogue est Client System Architecture Type (RFC 4578) qui indique le type exact d'architecture pour les clients DHCP qui vont démarrer sur le réseau (par exemple avec PXE), en téléchargeant une version particulière du système d'exploitation. Si l'architecture utilisée est un peu rare, cette option donne des informations précieuses à un observateur.

En lisant cette liste, le paranoïaque peut se dire que la NSA a envoyé des gens à l'IETF pour faire normaliser le plus grand nombre possible d'extensions indiscrètes, de façon à être sûr d'identifier tous les clients DHCP observés. Il y a même une option pour indiquer l'adresse (civile, dans le monde physique, pas sur le réseau), Civic Location, dans le RFC 4776. Il est vrai que, contrairement à la plupart des options listées ici, elle est fournie par le serveur et pas par le client, et ne permet donc pas de suivre un client à la trace. Mais elle peut permettre à un observateur de savoir où, dans le monde physique, se situe le client.

Outre tous ces champs et ces options par lesquels une information souvent excessive est transmise, DHCP dispose de certains mécanismes qui peuvent être utilisés pour compromettre la vie privée (section 4 du RFC). Par exemple, l'option Client FQDN du RFC 4702, citée plus haut, sert souvent à faire des mises à jour dynamiques du DNS (RFC 2136), et, dans ce cas, l'adresse IP du client DHCP (qui peut indiquer sa localisation) et son nom, identificateur stable, sont publiés dans le DNS, que tout le monde peut consulter. On peut connaitre les déplacements d'une machine simplement en consultant ce DNS public, sans avoir besoin d'espionner des milliers de réseaux. L'observateur peut être très discret et, en toute légalité, vous suivre.

Autre mécanisme dangereux, la stratégie d'allocation du serveur DHCP. Lorsqu'un client DHCP réclame une adresse IP, le serveur peut la choisir de plusieurs façons, et certaines ont des conséquences pour la vie privée :

  • Allocation itérative : le serveur alloue les adresses IP dans l'ordre de la plage d'adresses dont il dispose. Elle est très simple et très rapide mais fournit des adresses IP qui sont très prévisibles. En outre, avec ce système, les premières adresses de la plage seront plus souvent utilisées, ce qui rendra encore plus facile des activités comme la reconnaissance d'un réseau avant une attaque.
  • Allocation fondée sur un identificateur : le serveur a une table et y cherche un des identificateurs transmis par le client, allouant l'adresse trouvée dans la table. C'est très pratique pour l'administrateur système, car une machine donnée aura toujours la même adresse IP. Mais c'est nettement moins bon pour la vie privée du client, qui sera ainsi trivialement pistable, par son adresse IP fixe.
  • Allocation aléatoire : le serveur DHCP prend au hasard une adresse IP libre. C'est sans doute la meilleure méthode, du point de vue de la protection de la vie privée.

La taille très restreinte de l'espace d'adressage IPv4 complique le problème, en limitant les possibilités du serveur d'utiliser certaines stratégies d'allocation, comme l'allocation fondée sur un identificateur (le serveur DHCP n'a pas forcément assez d'adresses IP pour tous ses clients potentiels.)

Bon, OK, le client DHCP envoie des tas d'identificateurs stables. Mais en quoi est-ce dangereux ? Qu'est-ce qu'un observateur indiscret peut en faire (section 5 du RFC) ? Déjà, il peut découvrir le type de machine qu'est le client (directement, via des options comme Vendor Class, ou indirectement, via l'adresse MAC (dont le préfixe, l'OUI, dépend en général du matériel utilisé). L'espion peut aussi trouver le système d'exploitation utilisé.

Il peut aussi apprendre les réseaux que le client avait visité précédemment. Le client met en effet dans l'option Requested IP Address la précédente adresse IP qu'il avait obtenue. Si c'est une adresse publique (pas issue du RFC 1918), cela renseigne sur le précédent réseau utilisé.

L'observateur peut facilement trouver un identificateur stable à partir d'une requête DHCP (en combinant les options comme Client FQDN). Cela lui permet, s'il a accès au trafic de plusieurs serveurs DHCP, de suivre les déplacements d'une machine (c'est ce qui se produit dans les cas de surveillance massive, cf. RFC 7258.)

Dans certains cas, l'observateur n'a même pas besoin d'être présent sur le réseau du serveur DHCP : si on fait des mises à jour dynamiques du DNS, il lui suffit de faire des requêtes DNS pour suivre les changements d'adresse IP (et donc de réseau) du client.

Bref, un client DHCP en dit en général trop à son serveur, et cela permet aux machines mobiles d'être facilement pistées. Notre RFC ne fournit pas de solutions immédiates, une solution est décrite dans le RFC 7844, d'autres feront l'objet d'un futur travail.


Téléchargez le RFC 7819


L'article seul

RFC 7835: Locator/ID Separation Protocol (LISP) Threat Analysis

Date de publication du RFC : Avril 2016
Auteur(s) du RFC : D. Saucez (INRIA), L. Iannone (Telecom ParisTech), O. Bonaventure (Université catholique de Louvain)
Pour information
Réalisé dans le cadre du groupe de travail IETF lisp
Première rédaction de cet article le 30 avril 2016


Le protocole LISP (à ne pas confondre avec le langage de programmation) est un protocole à séparation de l'identificateur et du localisateur. Ces protocoles présentent des défis de sécurité particuliers et ce RFC est donc consacré à une étude détaillée des menaces et risques associés à LISP.

LISP est normalisé dans le RFC 6830. Il peut être utilisé dans un réseau interne ou bien sur l'Internet public et ce RFC étudie sa sécurité dans ce dernier cas, évidemment plus difficile.

Le RFC est en trois parties : la section 2 détaille le modèle de menaces (qui est l'attaquant), la section 3 expose les techniques que peut utiliser l'attaquant, la section 5 décrit les solutions possibles. Il s'agit bien de regarder les attaques génériques contre LISP, pas celles contre une mise en œuvre particulière de LISP, qui peut évidemment avoir ses bogues spécifiques.

Commençons donc par le modèle de menace (section 2). On suppose un attaquant situé quelque part sur l'Internet, éventuellement en plusieurs points de celui-ci. Il peut être sur le chemin des paquets (on path) ou pas (off path). Le premier est évidemment le plus dangereux. S'il est attaquant actif, il peut modifier des paquets et même faire des attaques de l'Homme du Milieu. Si l'attaquant est en dehors du chemin, cela va être plus difficile pour lui. Il ne peut pas modifier les paquets échangés, il peut par contre envoyer des paquets mais, pour que ceux-ci soient acceptés, il faudra qu'ils correspondent à ce qu'attendent les parties légitimes, ce qui fait que l'attaquant devra souvent deviner des informations et compter sur la chance.

Autre façon de classer les attaquants, il y a ceux qui sont internes à un site LISP et ceux qui sont externes. Les attaquants de l'intérieur sont plus dangereux car la machine qu'ils contrôlent (suite à une trahison ou un piratage) est a priori jugée de confiance.

Il faut aussi distinguer les attaquants permanents (live) des attaquants ponctuels (time-shifted). L'attaquant permanent est celui qui reste actif pendant toute la durée de l'attaque. Dès qu'il est neutralisé, l'attaque stoppe. L'attaquant ponctuel peut lancer une attaque, puis se retirer et les effets de l'attaque vont continuer. Ce genre d'attaques est évidemment bien plus dangereux.

L'attaquant peut viser le système de contrôle (control plane) de LISP ou bien son système de transmission des données (data plane). Un exemple typique est le mécanisme de correspondance (mapping) qui permet aux routeurs LISP de trouver le localisateur (le RLOC) en échange de l'identificateur (l'EID). Ce mécanisme de correspondance fait partie du système de contrôle. Si un attaquant veut détourner les paquets, il n'est pas obligé de trouver une faille dans le routage lui-même : s'il arrive à modifier les correspondances, il obtiendra le même résultat. (Comme le ferait une attaque DNS dans l'Internet classique.)

Plusieurs types d'attaques peuvent être faites contre un protocole réseau comme LISP. Il y a les attaques par rejeu, où un attaquant capture des paquets légitimes pour les rejouer intacts plus tard. Ces attaques marchent souvent, même quand les paquets sont protégés par de la cryptographie (l'attaquant n'a pas besoin de modifier les paquets, ni même de les comprendre). Il y a les manipulations de paquets (l'attaquant prend un paquet légitime et le réinjecte). Il y a la suppression complète des paquets.

Plus complexe et plus vicieux, il y a l'usurpation (spoofing). L'attaquant injecte des paquets prétendant venir d'une autre machine. C'est quelque chose qu'on voit souvent sur l'Internet. LISP est une technologie de tunnel et l'usurpation peut donc porter sur deux endroits : l'adresse externe, celle que voient les routeurs IP ordinaires (c'est le RLOC), et l'adresse interne, celle du paquet encapsulé (c'est l'EID). Identifier un usurpateur est bien plus compliqué lorsque des tunnels sont en jeu !

L'attaquant n'est pas forcément un usurpateur. Il peut très bien dire la vérité sur son adresse (rogue attack) par exemple parce qu'il se moque d'être identifié, ou bien parce qu'il est un zombie.

Autre type d'attaque, évidemment, les attaques par déni de service, où l'attaquant ne cherche pas à prendre le contrôle du système, mais à le paralyser (ou à le ralentir).

Parfois, la cible immédiate de l'attaque n'est pas la principale victime : dans les attaques par réflexion, un attaquant utilise un tiers pour renvoyer ses paquets vers la vraie victime. C'est surtout utilisé en combinaison avec l'amplification : lorsque la réponse est plus grosse que la question, un attaquant peut amplifier son trafic. En outre, pour LISP, le système de transmission est certainement bien plus rapide que celui de contrôle et il y a donc en théorie une possibilité d'attaquer le second avec le premier.

Et, bien sûr, il y a les attaques d'espionnage passif, où des grandes oreilles écoutent votre trafic pour vous surveiller, sans eux-mêmes envoyer de paquets. Grâce à Edward Snowden, l'ampleur de ce type d'attaques par les États est désormais bien connu (RFC 7258).

Bon, assez de théorie, comment fait-on avec LISP quand on est un méchant et qu'on veut effectuer une des attaques en question ? Rentrons désormais dans les détails techniques (qui nécessitent de connaitre un peu LISP : relisez les RFC 6830, RFC 7215, RFC 6832, RFC 6833 et RFC 6834). D'abord, le « glanage » (gleaning), la collecte passive d'informations sur les correspondances identificateur->localisateur (RFC 6830, section 6). Il peut être utilisé pour empoisonner le cache des correspondances d'un routeur : le méchant envoie un paquet LISP fabriqué, les routeurs innocents l'observent et enregistrent la correspondance entre l'EID et le RLOC dans leur cache et paf, le méchant a pu détourner le trafic futur. C'est un exemple d'attaque ponctuelle : l'attaquant envoie juste un paquet puis plus rien, mais l'effet persiste pendant toute la durée de vie de l'information dans le cache (quelques secondes, si on suit fidèlement les conseils du RFC 6830, section 6.2).

Autre exemple d'empoisonnement d'un routeur LISP avec de fausses informations, le champ LSB (Locator Status Bits), qui indique l'état (joignable ou pas) des machines situées sur le site de départ du paquet (RFC 6830, section 6.3). En envoyant un paquet usurpé avec un faux LSB, on peut tromper des routeurs innocents. On peut par exemple mettre tous les bits à zéro (qui signifie que le préfixe est injoignable par ce routeur), menant à une attaque par déni de service ou bien les mettre tous à zéro sauf un, menant à une surcharge de cet unique routeur. C'est également une attaque ponctuelle : ses effets se feront sentir même si l'attaquant est neutralisé.

Un point important de LISP est le test de la « joignabilité » (reachability, RFC 6830, section 6.3). LISP vérifie que la machine qui prétend être joignable, et par tel routeur, l'est effectivement. Un des outils pour cela est un numnique envoyé à l'autre machine et qu'elle doit renvoyer. Un attaquant qui arriverait à tricher avec la joignabilité pourrait pousser un routeur LISP d'entrée du tunnel (un ITR) à changer de routeur de sortie (l'ETR) au profit d'un routeur qui ne marche pas. Cela réaliserait une attaque par déni de service. Même s'il n'arrive pas à faire changer de routeur, il pourrait perturber le routage en envoyant des tas de numniques différents. (Rassurez-vous, cette attaque est plus dure à réussir qu'il ne semble, voyez la section 5.)

LISP permet que plusieurs espaces d'adressage coexistent, différenciés par leur instance ID indiquée dans l'en-tête (RFC 6830, section 5.5). Elle n'est pas authentifiée et un attaquant peut donc envoyer des paquets à une autre instance ID que la sienne.

LISP permet de l'interconnexion avec des réseaux non-LISP (RFC 6832). Ces mécanismes ont des attaques très similaires à celles qu'on peut faire contre LISP lui-même. Par exemple, un paquet avec une adresse source usurpée peut être transmis sur l'Internet par la passerelle LISP.

Mais les pires attaques se situeront sans doute sur le système de correspondance (mapping). Le point central de tous les systèmes à séparation de l'identificateur et du localisateur est de découpler deux fonctions qui, dans IP, sont confondues. Cela suit un grand principe de l'informatique : « tout problème peut être résolu en ajoutant un degré d'indirection ». Sauf que cette séparation se paie en sécurité : il faut bien, à un moment, faire correspondre identificateur et localisateur et, là, cette nouvelle fonction, la correspondance, offre de nouvelles possibilités d'attaque.

Ainsi, les messages Map-Request (RFC 6830, section 6) peuvent être utilisés de plusieurs façons. Envoyés en masse, à un système de contrôle qui est bien moins rapide que le système de transmission, ils peuvent saturer les routeurs. Comme la réponse (Map-Reply) est plus grosse que la question, ils peuvent servir à des attaques par amplification.

Et si un attaquant réussit à fabriquer de fausses réponses (Map-Reply) et à les faire accepter ? Il devra pour cela mettre le numnique correct dans ses paquets. Comme il fait 64 bits, si on a suivi les bons principes du RFC 4086 pour le générer, un attaquant qui n'est pas sur le chemin (et doit donc deviner le numnique) n'a que peu de chances de réussir. Mais attention, le numnique n'est pas une signature : il indique juste que le paquet est bien une réponse à une question posée. Si l'attaquant peut modifier les paquets, il peut empoisonner le cache de correspondance du routeur. Variante de cette attaque, si le méchant est un routeur légitime (rogue attack), il peut répondre, mais avec de fausses réponses. Il ne peut pas annoncer des préfixes quelconques mais il peut annoncer des préfixes plus généraux que ceux qu'il gère réellement (par exemple annoncer qu'il gère 192.0.2.0/24 alors qu'il ne contrôle que 192.0.2.0/26), ce qui lui permet de détourner le trafic.

Enfin, il y a les Map-Register, ces messages envoyés par les routeurs aux serveurs de correspondance pour les informer des préfixes gérés (RFC 6833, section 4.2). Ils sont authentifiés donc, normalement, un attaquant quelconque ne peut pas les usurper. Mais il reste des attaques résiduelles comme l'annonce de préfixes plus généraux que les siens.

Au passage, un problème de sécurité qu'on oublie parfois est celui de la vie privée (section 4). Les correspondances LISP sont publiques (comme les tables BGP dans l'Internet classique) et il ne faut donc pas oublier qu'on ne peut pas participer à LISP discrètement.

Et pour finir, les solutions (section 5). Comment faire pour éviter ces menaces ? Le RFC donne des conseils très généraux (« déployer soigneusement », « appliquer les règles habituelles de sécurité ») mais aussi des indications plus précises et spécifiques à LISP. Clairement, le plan de contrôle est la partie la plus sensible. Il est donc important d'utiliser les techniques d'authentification décrites dans le RFC 6833 (voir notamment sa section 6). Des extensions de sécurisation de LISP sont en cours de développement.

D'autre part, les conseils de sécurité du RFC 6830 doivent être suivis. Par exemple, quand ce RFC écrit qu'il faut limiter le rythme des Map-Request, cela doit être appliqué.

L'information obtenue par examen des paquets (comme le glanage cité plus haut) n'est évidemment pas de confiance : à n'utiliser que pour le flot de données qui contenait cette information, ou alors à vérifier avant. (Voir aussi « How to mitigate the effect of scans on mapping systems ».)


Téléchargez le RFC 7835


L'article seul

RFC 7857: Network Address Translation (NAT) Behavioral Requirements Updates

Date de publication du RFC : Avril 2016
Auteur(s) du RFC : R. Penno (Cisco), S. Perreault (Jive Communications), M. Boucadair (Orange), S. Sivakumar (Cisco), K. Naito (NTT)
Réalisé dans le cadre du groupe de travail IETF tsvwg
Première rédaction de cet article le 29 avril 2016


Le mécanisme de traduction d'adresses IPv4 connu sous le nom de NAT (et qui devrait plutôt être appelé NAPT pour Network Address and Port Translation, car il ne se contente pas de traduire les adresses IP) cause beaucoup de problèmes, car il casse le modèle normal de fonctionnement d'IP, modèle de bout en bout. Pour limiter les problèmes dus à ce mécanisme, plusieurs RFC posent certaines exigences que doivent respecter (en théorie) les routeurs NAT. Ce nouveau document met à jour certaines de ses exigences. Il met donc légèrement à jour les règles des RFC 4787, RFC 5382 et RFC 5508.

Ce RFC de maintenance ne s'applique qu'au « NAT44 » traditionnel, où une adresse IP publique n'est partagée que par les membres d'un même foyer, ou bien les employés d'une même entreprise. Pour le CGN, les exigences sont dans le RFC 6888.

D'abord, le suivi de connexions TCP (section 2 du RFC). Notre RFC formalise rigoureusement la machine à états que doit suivre un routeur NAT (elle est proche de celle du RFC 6146). Le RFC 5382 spécifiait bien des délais pour certains états mais sans décrire précisement la machine complète. Par exemple, l'exigence 5 du RFC 5382 donne un délai pour le temps minimum d'attente avant de considérer une connexion partiellement ouverte, ou fermée, comme abandonnée, mais il n'était pas clair si ces deux cas devaient avoir le même délai. Notre RFC tranche donc : le cas des connexions partiellement ouvertes et celui des connexions fermées sont différents et les délais devraient pouvoir être configurés différemment.

Et les paquets TCP RST (ReSeT), on en fait quoi ? Notre RFC précise clairement (suivant ce que faisait déjà le RFC 6146) qu'un paquet RST doit être considéré comme détruisant la connexion TCP et donc comme mettant fin à la correspondance dans le routeur NAT (après un délai, pour tenir compte du fait que le paquet RST a pu être reçu par le routeur NAT mais pas par la machine terminale). Attention, il faut d'abord vérifier que ce paquet RST correspond bien à une connexion existante, sinon, on permet des attaques par déni de service faciles (RFC 5961).

Les RFC 4787 et RFC 5382 précisaient qu'on pouvait utiliser le même couple {adresse IP externe, port externe} pour des connexions allant vers des machines extérieures différentes. Mais ils ne traitaient que du cas où il n'y avait qu'une machine interne qui allait vers ces machines extérieures. Désormais, on précise (section 3 de notre RFC) que cette utilisation est également valables si plusieurs machines internes se connectent. Sans cette règle, il faudrait beaucoup plus de ports externes disponibles, ce qui poserait un problème avec les environnements où le facteur de partage d'adresses est important (cf. RFC 6269).

Est-ce qu'un routeur NAT doit/peut utiliser les mêmes correspondances pour UDP et TCP (section 5 de notre RFC) ? Ce n'est pas précisé dans les RFC 4787 (exigence 1) et RFC 5382 (exigence 1). On fait une connexion TCP sortante, est-ce qu'un paquet UDP sortant va réutiliser la même correspondance ? La règle est désormais explicite : non, il ne faut pas ; par défaut, les correspondances doivent être spécifiques à un protocole (donc, différentes pour UDP et TCP).

Autre piège du NAT, le fait qui peut parfois changer une distribution aléatoire des ports en une distribution prévisible. Cela pose un problème pour certaines méthodes de sécurité qui dépendent du caractères imprévisible (par exemple le RFC 5452). Notre RFC reprend (section 9) une recommandation de la section 4 du RFC 6056 : un routeur NAT ne doit pas choisir les ports de sortie de manière prévisible ou régulière.

Comme d'habitude, la fragmentation est une source d'ennuis (section 10). Notre RFC rappelle donc qu'il faut suivre les règles de la section 5.3.1 du RFC 6864, notamment sur le caractère unique et imprévisible de l'identificateur de fragment.

Le routeur NAT voit parfois passer des paquets en « épingle à cheveux » (hairpinning). Cela désigne les paquets (section 12) qui, venus du réseau interne, y retournent, après être passés par le routeur. Si le réseau interne est 172.17.42.0/24, et qu'un serveur HTTP est sur la machine 172.17.41.1 et accessible de l'extérieur en 192.0.2.71, alors, une machine interne qui tente d'aller en http://192.0.2.71/ va envoyer des paquets qui iront au routeur NAT, prendront un virage en épingle à cheveux et reviendront dans le réseau interne, vers 172.17.41.1. Historiquement, pas mal de routeurs NAT étaient incapables de gérer ce cas. La situation est désormais meilleure mais il reste des cas limites. Ainsi, l'exigence 7 du RFC 5508 devait rappeler que le virage en épingle à cheveux était possible même en ICMP. Notre RFC insiste sur le respect de cette règle.

Enfin, la sécurité (section 13). Notre RFC estime que ses exigences renforcées vont améliorer la sécurité. Par exemple, des règles strictes (sections 7 et 11) sur la suppression des correspondances dans la table du routeur NAT évitent qu'un attaquant puisse garder ouvertes des correspondances qui devraient être fermées (et la mémoire récupérée). Les règles sur les ports sources imprévisibles de la section 9 rendront (entre autres) plus difficile le suivi des machines situées derrière un routeur NAT.

Notez enfin qu'il y a des gens qui prétendent avoir un brevet sur certaines de ces recommandations...


Téléchargez le RFC 7857


L'article seul

Le mystère DNS Free rebondit

Première rédaction de cet article le 24 avril 2016


J'ai déjà parlé ici de la bogue DNS de Free affectant certains domaines signés avec DNSSEC. Six mois après, elle n'a pas été réparée et le problème se montre en fait encore plus complexe qu'à première vue.

Le problème a été signalé sur la liste FRnog et analysé par Rémy Duchet. En gros, certains usagers de Free n'arrivent pas à aller en http://test-yann.myshopify.com/. Si on regarde avec dig, on voit bien un problème DNS (ici, j'interroge explicitement un des résolveurs DNS officiels de Free, puisque j'ai un résolveur local) :


% dig @212.27.40.240 test-yann.myshopify.com 

; <<>> DiG 9.9.5-9+deb8u6-Debian <<>> @212.27.40.240 test-yann.myshopify.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 393
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;test-yann.myshopify.com. IN A

;; Query time: 27 msec
;; SERVER: 212.27.40.240#53(212.27.40.240)
;; WHEN: Sun Apr 24 17:00:03 CEST 2016
;; MSG SIZE  rcvd: 52

    

Ah, en effet, nous avons un problème (SERVFAIL = Server Failure). Avec d'autres résolveurs de Free, pas de problème. Et ça varie dans le temps (en d'autres termes, des fois, ça marche, des fois, ça marche pas). On peut également tester avec les sondes RIPE Atlas, dans l'AS de Free, 12322 :

% atlas-resolve -r 500 --as 12322 -t A test-yann.myshopify.com
[ERROR: SERVFAIL] : 61 occurrences 
[23.227.38.68 23.227.38.69 23.227.38.70 23.227.38.71] : 133 occurrences 
[TIMEOUT(S)] : 1 occurrences 
Test #3682131 done at 2016-04-24T14:57:13Z

Cela montre bien que certains résolveurs de Free ont le problème SERVFAIL mais pas tous.

Si on essaie avec l'option +cd (Checking Disabled, couper la validation DNSSEC), tout marche :


% dig +cd @212.27.40.240 test-yann.myshopify.com 

; <<>> DiG 9.9.5-9+deb8u6-Debian <<>> +cd @212.27.40.240 test-yann.myshopify.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 18276
;; flags: qr rd ra cd; QUERY: 1, ANSWER: 22, AUTHORITY: 4, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;test-yann.myshopify.com. IN A

;; ANSWER SECTION:
test-yann.myshopify.com. 1800 IN CNAME shops.shopify.com.
test-yann.myshopify.com. 1800 IN RRSIG CNAME 5 2 600 (
				20160519013040 20160419013040 12663 myshopify.com.
				K3oRwkmXUkzNYbFO1jNLGLrSkhaRRBnKeGvld9YdcZo+
				nUOpJzGUECTzrzOTBGpbGXdJB5M3nJ6pebAGpr46m5Rk
				HfG3+FOdgCRS+CG5lpu0+KC8w80718ywOFO8LROdIjwm
				h4swblM+0Aft4o1lj5ChnCBefWgn2Cs4qSqMT0g= )
test-yann.myshopify.com. 1800 IN RRSIG CNAME 5 2 600 (
				20160519013040 20160419013040 39852 myshopify.com.
				lBsyv5zrQ4twd4LNzLrdQpHWyxL9SQGM2wfhVR/GfnWE
				TXNV3wyW5bIwRDySbmdRg9RLiz9h1sBFByIeITYEJeKv
				7daLBZSwoI7551mz0jJX5fMgEuW7FEFOP25pYb6p5o1r
				1VFvc47+X8qTLaV5j0Uz+PXJjFBvF7GB4i3gFb0= )
test-yann.myshopify.com. 1800 IN CNAME shops.shopify.com.
test-yann.myshopify.com. 1800 IN RRSIG CNAME 5 2 600 (
				20160519013040 20160419013040 12663 myshopify.com.
				K3oRwkmXUkzNYbFO1jNLGLrSkhaRRBnKeGvld9YdcZo+
				nUOpJzGUECTzrzOTBGpbGXdJB5M3nJ6pebAGpr46m5Rk
				HfG3+FOdgCRS+CG5lpu0+KC8w80718ywOFO8LROdIjwm
				h4swblM+0Aft4o1lj5ChnCBefWgn2Cs4qSqMT0g= )
test-yann.myshopify.com. 1800 IN RRSIG CNAME 5 2 600 (
				20160519013040 20160419013040 39852 myshopify.com.
				lBsyv5zrQ4twd4LNzLrdQpHWyxL9SQGM2wfhVR/GfnWE
				TXNV3wyW5bIwRDySbmdRg9RLiz9h1sBFByIeITYEJeKv
				7daLBZSwoI7551mz0jJX5fMgEuW7FEFOP25pYb6p5o1r
				1VFvc47+X8qTLaV5j0Uz+PXJjFBvF7GB4i3gFb0= )
test-yann.myshopify.com. 1800 IN CNAME shops.shopify.com.
test-yann.myshopify.com. 1800 IN RRSIG CNAME 5 2 600 (
				20160519013040 20160419013040 12663 myshopify.com.
				K3oRwkmXUkzNYbFO1jNLGLrSkhaRRBnKeGvld9YdcZo+
				nUOpJzGUECTzrzOTBGpbGXdJB5M3nJ6pebAGpr46m5Rk
				HfG3+FOdgCRS+CG5lpu0+KC8w80718ywOFO8LROdIjwm
				h4swblM+0Aft4o1lj5ChnCBefWgn2Cs4qSqMT0g= )
test-yann.myshopify.com. 1800 IN RRSIG CNAME 5 2 600 (
				20160519013040 20160419013040 39852 myshopify.com.
				lBsyv5zrQ4twd4LNzLrdQpHWyxL9SQGM2wfhVR/GfnWE
				TXNV3wyW5bIwRDySbmdRg9RLiz9h1sBFByIeITYEJeKv
				7daLBZSwoI7551mz0jJX5fMgEuW7FEFOP25pYb6p5o1r
				1VFvc47+X8qTLaV5j0Uz+PXJjFBvF7GB4i3gFb0= )
test-yann.myshopify.com. 1800 IN CNAME shops.shopify.com.
test-yann.myshopify.com. 1800 IN RRSIG CNAME 5 2 600 (
				20160519013040 20160419013040 12663 myshopify.com.
				K3oRwkmXUkzNYbFO1jNLGLrSkhaRRBnKeGvld9YdcZo+
				nUOpJzGUECTzrzOTBGpbGXdJB5M3nJ6pebAGpr46m5Rk
				HfG3+FOdgCRS+CG5lpu0+KC8w80718ywOFO8LROdIjwm
				h4swblM+0Aft4o1lj5ChnCBefWgn2Cs4qSqMT0g= )
test-yann.myshopify.com. 1800 IN RRSIG CNAME 5 2 600 (
				20160519013040 20160419013040 39852 myshopify.com.
				lBsyv5zrQ4twd4LNzLrdQpHWyxL9SQGM2wfhVR/GfnWE
				TXNV3wyW5bIwRDySbmdRg9RLiz9h1sBFByIeITYEJeKv
				7daLBZSwoI7551mz0jJX5fMgEuW7FEFOP25pYb6p5o1r
				1VFvc47+X8qTLaV5j0Uz+PXJjFBvF7GB4i3gFb0= )
test-yann.myshopify.com. 1800 IN CNAME shops.shopify.com.
test-yann.myshopify.com. 1800 IN RRSIG CNAME 5 2 600 (
				20160519013040 20160419013040 12663 myshopify.com.
				K3oRwkmXUkzNYbFO1jNLGLrSkhaRRBnKeGvld9YdcZo+
				nUOpJzGUECTzrzOTBGpbGXdJB5M3nJ6pebAGpr46m5Rk
				HfG3+FOdgCRS+CG5lpu0+KC8w80718ywOFO8LROdIjwm
				h4swblM+0Aft4o1lj5ChnCBefWgn2Cs4qSqMT0g= )
test-yann.myshopify.com. 1800 IN RRSIG CNAME 5 2 600 (
				20160519013040 20160419013040 39852 myshopify.com.
				lBsyv5zrQ4twd4LNzLrdQpHWyxL9SQGM2wfhVR/GfnWE
				TXNV3wyW5bIwRDySbmdRg9RLiz9h1sBFByIeITYEJeKv
				7daLBZSwoI7551mz0jJX5fMgEuW7FEFOP25pYb6p5o1r
				1VFvc47+X8qTLaV5j0Uz+PXJjFBvF7GB4i3gFb0= )
test-yann.myshopify.com. 1800 IN CNAME shops.shopify.com.
test-yann.myshopify.com. 1800 IN RRSIG CNAME 5 2 600 (
				20160519013040 20160419013040 12663 myshopify.com.
				K3oRwkmXUkzNYbFO1jNLGLrSkhaRRBnKeGvld9YdcZo+
				nUOpJzGUECTzrzOTBGpbGXdJB5M3nJ6pebAGpr46m5Rk
				HfG3+FOdgCRS+CG5lpu0+KC8w80718ywOFO8LROdIjwm
				h4swblM+0Aft4o1lj5ChnCBefWgn2Cs4qSqMT0g= )
test-yann.myshopify.com. 1800 IN RRSIG CNAME 5 2 600 (
				20160519013040 20160419013040 39852 myshopify.com.
				lBsyv5zrQ4twd4LNzLrdQpHWyxL9SQGM2wfhVR/GfnWE
				TXNV3wyW5bIwRDySbmdRg9RLiz9h1sBFByIeITYEJeKv
				7daLBZSwoI7551mz0jJX5fMgEuW7FEFOP25pYb6p5o1r
				1VFvc47+X8qTLaV5j0Uz+PXJjFBvF7GB4i3gFb0= )
shops.shopify.com.	1800 IN	A 23.227.38.71
shops.shopify.com.	1800 IN	A 23.227.38.69
shops.shopify.com.	1800 IN	A 23.227.38.70
shops.shopify.com.	1800 IN	A 23.227.38.68

;; AUTHORITY SECTION:
shopify.com.		6458 IN	NS ns4.p19.dynect.net.
shopify.com.		6458 IN	NS ns3.p19.dynect.net.
shopify.com.		6458 IN	NS ns1.p19.dynect.net.
shopify.com.		6458 IN	NS ns2.p19.dynect.net.

;; Query time: 41 msec
;; SERVER: 212.27.40.240#53(212.27.40.240)
;; WHEN: Sun Apr 24 17:44:13 CEST 2016
;; MSG SIZE  rcvd: 2376

    

On a la réponse mais on voit bien qu'il y a un problème : ces enregistrements DNS CNAME (Canonical Name) répétés ne sont pas normaux. Il ne sont pas dans les serveurs faisant autorité pour le domaine :


%  dig @ns1.p19.dynect.net test-yann.myshopify.com  

; <<>> DiG 9.9.5-9+deb8u6-Debian <<>> @ns1.p19.dynect.net test-yann.myshopify.com
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 7499
;; flags: qr aa rd; QUERY: 1, ANSWER: 3, AUTHORITY: 3, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;test-yann.myshopify.com. IN A

;; ANSWER SECTION:
test-yann.myshopify.com. 600 IN	CNAME shops.shopify.com.
test-yann.myshopify.com. 600 IN	RRSIG CNAME 5 2 600 (
				20160519013040 20160419013040 12663 myshopify.com.
				K3oRwkmXUkzNYbFO1jNLGLrSkhaRRBnKeGvld9YdcZo+
				nUOpJzGUECTzrzOTBGpbGXdJB5M3nJ6pebAGpr46m5Rk
				HfG3+FOdgCRS+CG5lpu0+KC8w80718ywOFO8LROdIjwm
				h4swblM+0Aft4o1lj5ChnCBefWgn2Cs4qSqMT0g= )
test-yann.myshopify.com. 600 IN	RRSIG CNAME 5 2 600 (
				20160519013040 20160419013040 39852 myshopify.com.
				lBsyv5zrQ4twd4LNzLrdQpHWyxL9SQGM2wfhVR/GfnWE
				TXNV3wyW5bIwRDySbmdRg9RLiz9h1sBFByIeITYEJeKv
				7daLBZSwoI7551mz0jJX5fMgEuW7FEFOP25pYb6p5o1r
				1VFvc47+X8qTLaV5j0Uz+PXJjFBvF7GB4i3gFb0= )

;; AUTHORITY SECTION:
test-winkel.myshopify.com. 60 IN NSEC test1012345.myshopify.com. CNAME RRSIG NSEC
test-winkel.myshopify.com. 60 IN RRSIG NSEC 5 3 60 (
				20160519013040 20160419013040 12663 myshopify.com.
				BHS+QE4Pdu0qFdTW2XHN4Z6mbiqu3eb89UhwO3f5/C7W
				vpQmlNEmuYNlUlAHgUWbXvCwmDr+9k0bVZuiZh0UuSCp
				pveXWvYzr6nJjCRy5CZoUJy6C60Dyt1LfW2kCNTXUdjX
				Vp8HwMlKN0np6jxe2o/ryU/BphzdYA1OEmqp9/0= )
test-winkel.myshopify.com. 60 IN RRSIG NSEC 5 3 60 (
				20160519013040 20160419013040 39852 myshopify.com.
				I8LqnvjOSLhivVteqv6gqeeytZ9YZU9heYIj/hNfYUz+
				vOQ2PQBCk7N0ujbI9vWpFkj+3YSNnsxBshxjVZfWQoLp
				Cpde8Ir+zP8WK95/04VQBpU1HjI7QBAARkPCD0YCnTBY
				U/hTVe6gcB43c9CFAUaJ5qynRmnTZFIsvtcGBz8= )

;; Query time: 22 msec
;; SERVER: 2001:500:90:1::19#53(2001:500:90:1::19)
;; WHEN: Sun Apr 24 17:45:54 CEST 2016
;; MSG SIZE  rcvd: 831

Donc, ce sont les résolveurs de Free qui les ont inventé. La bogue est clairement de la responsabilité de Free.

Dans mon article précédent, j'avais émis l'hypothèse que le problème était lié à l'utilisation de NSEC3 (RFC 5155) et des jokers. Ici, la zone est signée avec NSEC, pas NSEC3 (ce qui est curieux, d'ailleurs, puisque cela permet de connaitre la liste des clients de shopify.com), donc NSEC3 ne semble pas responsable. On retrouve par contre les jokers, dont l'interaction avec DNSSEC est régulièrement une source d'ennuis. D'une façon ou d'une autre, une combinaison de caractéristiques de la zone myshopify.com déclenche la bogue, multiplie les CNAME (la réponse du résolveur de Free a une taille supérieure à la MTU d'Ethernet...), l'enregistrement NSEC obligatoire est supprimé, et paf.

En résumé, je ne sais pas quel logiciel résolveur utilise Free (aucun des logiciels que je connais, comme Unbound ou BIND, ne montre ce comportement) mais il est bogué et devrait impérativement être réparé, si on veut que DNSSEC soit plus largement utilisé.

Et du côté de l'utilisateur ordinaire, que peut-on faire ? Le client final peut utiliser son propre résolveur (ce qui est une bonne idée, de toute façon), le webmestre qui veut publier des choses accessibles aux utilisateurs de Free ne peut pas grand'chose, à part peut-être configurer sa zone DNS de manière plus conservatrice (les jokers sont presque toujours une mauvaise idée).


L'article seul

RFC 7788: Home Networking Control Protocol

Date de publication du RFC : Avril 2016
Auteur(s) du RFC : M. Stenberg, S. Barth (Independent), P. Pfister (Cisco)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF homenet
Première rédaction de cet article le 23 avril 2016


Ce nouveau protocole, HNCP (Home Networking Control Protocol), est conçu pour la domotique. Son rôle est de distribuer de l'information de configuration (les services comme celui d'impression, par exemple) à toutes les machines de la maison. C'est un profil (une instance particulière) du protocole DNCP du RFC 7787.

Cet HNCP est issu du projet Homenet, visant à créer à la maison des réseaux non gérés (M. Michu a autre chose à faire) et non limités à un seul lien (donc, avec des routeurs). L'architecture d'Homenet est décrite dans le RFC 7368. Dans ce cadre Homenet, HNCP doit permettre de :

  • découvrir les frontières du réseau (qu'est-ce qui est extérieur et qu'est-ce qui est intérieur), ce qui sera nécessaire pour la sécurité,
  • distribuer les préfixes IP (RFC 7695),
  • fournir l'accès à un service de résolution de noms.

HNCP n'est pas un protocole de routage (quoique on puisse considérer que le routage, c'est distribuer de l'information de configuration, mais HNCP n'est pas prévu pour cela), il faut l'utiliser avec un protocole de routage comme Babel (RFC 8966).

Comme HNCP est un profil de DNCP, il en hérite les caractéristiques (RFC 7787). Par exemple, il n'est pas adapté à de l'information très changeante. C'est pour cela que, pour la résolution de noms, HNCP distribue les adresses des serveurs de noms, mais n'assure pas cette fonction lui-même.

Le RFC sur DNCP décrit les points laissés libres dans DNCP et qu'un profil de DNCP doit spécifier (RFC 7787, section 9). La section 3 de notre RFC sur HNCP précise ces points :

  • HNCP est transporté sur UDP, port 8231, sur IPv6, bien sûr.
  • Le trafic est sécurisé par DTLS, port 8232.
  • HNCP ne marche que sur des réseaux capables de multicast, comme Ethernet (ce qui permet de découvrir les voisins facilement). Il est recommandé que l'identificateur d'interface soit dérivé de l'adresse IPv6.
  • L'identificateur de chaque nœud du réseau est choisi au hasard. (En cas - improbable - de collision, on recommence avec un nouvel identificateur.)
  • La fonction de condensation utilisée est MD5 (RFC 1321).
  • Les paramètres Trickle (RFC 6206) sont k=1, Imin=200ms, Imax=7.

Je n'ai pas d'expérience pratique avec HNCP donc je vais passer rapidement sur le reste du RFC. Parmi les points amusants à noter :

  • HNCP permet la configuration complète des adresses IP (section 6). Les nœuds situés aux frontières du réseau domestique apprennent du FAI les préfixes IP publics à utiliser (par exemple en DHCP, cf. RFC 8415), et les diffusent en HNCP. L'algorithme du RFC 7695 est utilisé pour répartir ces préfixes en sous-préfixes pour les différents liens (rappelez-vous que HNCP permet d'avoir un réseau domestique composé de plusieurs liens séparés par des routeurs.)
  • Les adresses IP des nœuds sont typiquement attribuées par le mécanisme du RFC 7217, qui dérive une adresse d'un certain nombre de paramètres du réseau local et de la machine qui se configure. (Ce qui permet d'avoir des adresses IP stables mais imprévisibles et qui ne permettent pas de traçabilité quand on change de réseau.) Les machines non-HNCP (section 7) sont, elles, configurées par les moyens classiques, comme SLAAC (RFC 4861).
  • La résolution de noms et la découverte des services sont évidemment des fonctions essentielles. L'utilisateur ne s'amuserait pas s'il devait manipuler des adresses IPv6. Chaque routeur HNCP fournit un nom pour les réseaux qu'il gère et le diffuse en HNCP. Il a aussi un nom pour lui-même. Le suffixe utilisé était .home, remplacé depuis par home.arpa par le RFC 8375.

Comme tous les protocoles instanciés à partir de DNCP, HNCP transporte l'information sous forme de TLV (section 10). Ces TLV peuvent être emboîtés (un sous-TLV dans la partie Valeur d'un TLV). Parmi les TLV possibles (la liste complète est dans un registre IANA), on trouve :

  • « Version HNCP », type 32, qui permet d'indiquer aux voisins quelle version de HNCP on gère. Cela ne se fait pas sous forme d'un numéro de version mais sous forme d'un groupe de bits décrivant les capacités du nœud HNCP.
  • « Connexion extérieure », type 33, rassemble les informations envoyées par un FAI, et que le réseau local doit connaitre. « Préfixe délégué », type 34, sous-TLV du précédent, indique les préfixes IP.
  • « Nom de domaine », type 40, est le suffixe qui sera utilisé pour nommer les machines et services, alors que « Nom de machine », type 41, indique le nom d'une machine et son adresse IP.
  • Etc (il y en a beaucoup).

La section 11 du RFC résume les exigences qui pèsent sur les nœuds d'un réseau HNCP. En plus de gérer le protocole HNCP lui-même, ils doivent aussi, s'ils sont routeurs, respecter le RFC 7084, qui spécifie les règles (légèrement assouplies dans notre RFC sur HNCP) que doivent suivre les routeurs IPv6 situés chez l'utilisateur.

Enfin, un petit mot sur la sécurité (section 12) : HNCP est conçu pour être simple pour l'utilisateur et pour marcher tout seul. Sa sécurité sera donc forcément très faible : un réseau à la maison sans administrateur système professionnel offrira plein de trous à un éventuel attaquant (le RFC 7368 parle de la sécurité des réseaux domotiques). On ne peut pas avoir à la fois le beurre (l'auto-configuration) et l'argent du beurre (la sécurité).

Quelles sont les mises en œuvre de HNCP aujourd'hui ? Il y a, en logiciel libre, hnetd (qui est accessible également sous forme de paquetages pour OpenWrt, depuis la version Barrier Breaker - 14.07 - en juillet 2014). hnetd fait partie du projet HomeWrt. Complètement indépendant de hnetd, il existe également shncpd. On peut aussi citer pysyma, écrit en Python.

En non-libre, il y a du HNCP en cours de développement dans des environnements aussi différents que les routeurs Cisco ou D-Link, les systèmes Nest, le système Xfinity de Comcast... Il parait même que c'est prévu pour les Freebox mais je n'ai pas trouvé de détails à ce sujet. D'autre part, HNCP est apparemment cité dans la spécification (fermée et non publique) Thread.

Les protocoles Homenet sont en développement depuis longtemps et, si vous allez à des salons ou des conférences, vous avez certainement vu des démonstrations utilisant HNCP.

Et si vous aimez l'histoire des protocoles, notez que HNCP, à l'origine, était prévu pour assurer l'auto-configuration de routeurs dans un réseau OSPF (RFC 7503). Cette idée d'« auto-configuration OSPF » n'a pas rencontré un grand succès car tout le monde n'aime pas OSPF et aurait préféré découpler le routage (OSPF, Babel, etc) de la distribution d'informations. HNCP, protocole limité à cette distribution, était né. Il a ensuite été abstrait dans le protocole DNCP (RFC 7787), dont HNCP n'est qu'un profil.


Téléchargez le RFC 7788


L'article seul

RFC 7787: Distributed Node Consensus Protocol

Date de publication du RFC : Avril 2016
Auteur(s) du RFC : M. Stenberg, S. Barth (Independent)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF homenet
Première rédaction de cet article le 23 avril 2016


Ce nouveau protocole DNCP (Distributed Node Consensus Protocol) est prévu notamment pour les réseaux non organisés comportant beaucoup de petites machines, comme on peut en trouver en domotique (Internet des Trucs et tout ça). Il s'appuie sur l'algorithme Trickle (RFC 6206) pour distribuer dans le réseau des informations quelconques. Aucune machine ne joue un rôle particulier dans DNCP : pas de maître ou de racine. DNCP est un algorithme générique, et son utilisation effective nécessite la définition d'un profil, comme HNCP (Home Networking Control Protocol, RFC 7788) dans le cas du réseau « Homenet ».

L'information distribuée par DNCP est sous forme de TLV. Chaque tuple TLV fait 64 ko au maximum et, une fois que l'algorithme a convergé, tous les nœuds du réseau ont la même base de tuples : le réseau est synchronisé. L'état d'un nœud (l'ensemble des tuples qu'il connait) est représenté par un condensat des données (nommé network state hash). Au début, chaque nœud ne connait que ses propres tuples et son état reflète cela. Il diffuse cette information avec Trickle et chaque nœud apprend alors que la synchro n'est pas complète (puisqu'il existe des nœuds avec un condensat différent). Puis chaque nœud modifie l'état (le condensat) en intégrant les tuples des autres nœuds. À la fin, tous les nœuds ont le même état et trouvent donc le même condensat. Ils sont alors heureux et synchronisés. En situation stable, DNCP ne transmet que les condensats (pour que les nœuds puissent vérifier qu'il n'y a pas eu de changement), pas les données, ce qui le rend assez frugal.

DNCP est donc utile pour tous les cas complètement répartis, où des machines sans chef veulent se coordonner. Cela peut servir, par exemple, pour l'affectation automatique des préfixes IP dans un réseau non géré (RFC 7695). DNCP est à l'origine issu d'un projet moins général, le projet « Homenet » de l'IETF ; le groupe Homenet s'est aperçu que le protocole de synchronisation pouvait avoir son utilité en dehors de la domotique et a créé DNCP (et un protocole concret pour Homenet, HNCP).

Comme indiqué plus haut, DNCP est abstrait : plusieurs choix techniques essentiels sont laissés à de futurs profils (comme HNCP, décrit dans le RFC 7788). Parmi ces choix :

  • le mécanisme de transport (TCP, UDP, SCTP),
  • la sécurité (utiliser TLS ou pas),
  • le fait de ne fonctionner que sur un seul lien réseau, ou bien d'être capable de passer par des routeurs.

DNCP est très chouette mais le RFC précise qu'il ne peut pas servir à tout. Quelques exemples de cas où DNCP n'est pas adapté :

  • Si on a des données de grande taille (DNCP les limite à 64 ko),
  • Si on a beaucoup de voisins, et que la diffusion n'est pas possible,
  • Si les données changent tout le temps (DNCP est optimisé pour être économe dans l'état stable),
  • Si beaucoup de nœuds ont des contraintes de mémoire (DNCP nécessite de stocker toutes les données).

Si on a des données qui changent très souvent, il peut être préférable d'utiliser DNCP pour publier l'adresse d'un serveur où récupérer ces données.

DNCP est résumé en section 3 du RFC. Les nœuds sont découverts automatiquement (la méthode exacte dépend du profil) ou manuellement, et leur joignabilité est vérifiée. Les TLV peuvent être des demandes d'information ou bien les données elles-mêmes.

Chaque nœud commence par calculer le condensat des données (la fonction utilisée depend du profil) qu'il veut publier. Il l'annonce ensuite à ses voisins. Quand un voisin annonce un condensat différent, le nœud sait que le réseau n'est pas encore synchronisé. Il demande alors au voisin toutes ses données, les ajoute à sa base, met à jour son condensat et recommence.

Pour jouer son rôle, le nœud DNCP a besoin de quelques informations (section 5). Il a un identificateur unique (la façon doit il est choisi dépend du profil), ses données à publier, une ou plusieurs instances Trickle (le terme ne vient pas du RFC 6206 mais est défini ici : c'est un état Trickle autonome, avec les valeurs des paramètres Trickle), etc. Le nœud a également en mémoire un ensemble de voisins avec, pour chacun, son identificateur, son adresse IP, etc.

Les TLV et leur format sont décrits en section 7 : un type de deux octets, une longueur de deux octets et la valeur. Des TLV peuvent être inclus dans les TLV. Quelques exemples de types : REQ-NETWORK-STATE (type 1) sert à demander l'état du réseau (le condensat de tous les tuples), NETWORK-STATE (type 4) sert pour les réponses à ces requêtes et donne l'état du réseau, etc. L'ensemble des valeurs possibles figure dans un registre IANA.

La section 8 discute de la sécurité de DNCP. Le traitement de celle-ci dépend essentiellement du profil, qui peut décider, par exemple, d'utiliser TLS ou DTLS.

La section 9 discute en détail ce qu'on attend des profils, ce que doivent définir les protocoles concrets qui réalisent DNCP :

  • S'ils utilisent l'unicast ou le multicast.
  • Le protocole de transport, UDP ou TCP.
  • S'ils utilisent TLS pour la sécurité.
  • Quels TLV sont acceptés ou refusés.
  • Quelles valeurs ont les paramètres Trickle.
  • Quelle est la fonction de condensation.
  • Etc.

Des indications sur les choix à faire sont présentées dans l'annexe B. Par exemple, si on utilise UDP, il est recommandé que les données restent d'une taille inférieure à une MTU typique, notamment pour éviter la fragmentation. D'un autre côté, UDP donne davantage de contrôle sur l'envoi des données (mais pas forcément sur leur réception).

Un exemple de profil figure dans l'annexe A. On peut aussi regarder un vrai profil, dans le RFC 7788, qui normalise HNCP. Le profil d'exemple est pour un protocole fictif nommé SHSP (il a existé un projet de protocole nommé Simple Home Status Protocol mais qui semble abandonné, et sans lien avec ce SHSP fictif), un protocole pour l'automatisation de la maison. Ses choix sont :

  • Uniquement IPv6,
  • Unicast en TCP et multicast en UDP,
  • Zéro sécurité (ne doit être utilisé que sur des liens sûrs),
  • L'identificateur d'un nœud est un nombre de 32 bits choisi aléatoirement (en cas de collision, les deux machines en choisissent un autre),
  • Les paramètres quantitatifs de Trickle font que, dans l'état stable, au moins un paquet multicast est émis toutes les 25 secondes,
  • La fonction de condensation est une classique SHA-256,
  • Etc.

Téléchargez le RFC 7787


L'article seul

RFC 7806: On Queuing, Marking, and Dropping

Date de publication du RFC : Avril 2016
Auteur(s) du RFC : F. Baker, R. Pan (Cisco)
Pour information
Réalisé dans le cadre du groupe de travail IETF aqm
Première rédaction de cet article le 21 avril 2016


Au cœur de l'Internet se trouvent les routeurs, et la façon dont ils traitent les paquets IP est cruciale pour le bon fonctionnement du réseau. C'est particulièrement important lorsque le trafic augmente et que les files d'attente dans les routeurs se remplissent. Que faire, alors ? Ce nouveau RFC discute des stratégies des routeurs confrontés à des files d'attente bien remplies.

Pas de « bonne » ou de « mauvaise » méthode dans ce RFC mais une discussion des possibilités. Il y a longtemps que le sujet est discuté, souvent avec des termes dangereux, car trop chargés, comme « juste » (qu'est-ce qui est juste ? Quels paquets jeter lorsque la file d'attente est pleine ? Les plus anciens ? Les plus gros ? Ceux venant de certains réseaux ?) Ainsi, le RFC 970 parle de gestion juste de la file d'attente... Le problème (à part la question de philosophie « qu'est-ce que la justice ? ») est que toute politique de gestion de la file d'attente peut entrainer des adaptations non souhaitées de la part des machines connectées au réseau (si on jette en priorité les paquets les plus gros, on encourage les machines à envoyer des paquets plus petits, comme dans le Silly Window Syndrome).

Sur la question de principe de l'équité ou de la justice, il faut toujours lire l'article de référence, « Flow Fairness: Dismantling a Religion ».

Historiquement, des modèles de trafic peu réalistes avaient été utilisés. Par exemple, certains modèles partent du débit moyen d'un flot tout au long de son existence et raisonnent là-dessus. Mais le trafic Internet est tout, sauf moyen. Il est plutôt en quanta, avec des sursauts brusques. Par exemple, une caméra va envoyer trente images par seconde et cela se traduira par beaucoup de données lorsqu'une nouvelle image est disponible, puis un silence d'un trentième de seconde avant l'image suivante.

Au passage, j'ai parlé de flot sans l'expliquer. Le terme est courant dans les discussions réseau mais souvent assez flou. Cela peut désigner une session du protocole de transport (identifiée par le fameux tuple à cinq éléments du RFC 2990), tous les paquets entre deux machines données, tous les paquets vers une machine donnée...

Autre question pratique dès qu'on discute d'équité entre les flots, comment est-ce qu'on la mesure, pour déterminer si elle est respectée ou pas ? Le RFC 7141, entre autres, se penche sur cette question.

Le gros du RFC est formé par la section 3, qui discute des outils habituels de gestion des paquets par les routeurs : mettre en file d'attente (queuing), marquer les paquets (marking) et les jeter (dropping). Tous ces outils sont indispensables (tant que la mémoire des routeurs sera finie, et donc les files d'attente n'auront pas une taille illimitée, il faudra parfois jeter des paquets) et sont interprétés par le reste du réseau comme des signaux indiquant l'approche ou le début de la congestion.

Ce RFC discute de divers concepts, il ne spécifie pas un algorithme. Pour un exemple d'algorithme récent de gestion des files d'attente des routeurs, voir FQ-Codel, même s'il ne suit pas forcément les avis du RFC (CoDel a été finalement publié dans le RFC 8289.)


Téléchargez le RFC 7806


L'article seul

RFC 7838: HTTP Alternative Services

Date de publication du RFC : Avril 2016
Auteur(s) du RFC : M. Nottingham (Akamai), P. McManus (Mozilla), J. Reschke (greenbytes)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF httpbis
Première rédaction de cet article le 15 avril 2016


Une nouveauté dans le monde HTTP : ce RFC décrit un mécanisme permettant d'indiquer des endroits alternatifs où trouver le contenu demandé. Ce n'est pas une classique redirection : l'URI reste le même, on découple simplement l'identificateur (l'URI) et le localisateur (l'endroit où chercher et le protocole à utiliser).

Ce concept est assez nouveau dans le monde HTTP (section 1 du RFC). En effet, le RFC 7230 tend à mélanger l'identificateur d'une ressource (http://www.example.com/foo/bar) et les moyens d'y accéder (la même ressource peut aussi être en https://www.example.com/foo/bar voire sur un miroir à un URL très différent). Le but du mécanisme de ce nouveau RFC 7838 est de séparer plus clairement identificateur et localisateur.

Quelques exemples pratiques sont donnés dans cette section 1 :

  • Le serveur d'origine peut vouloir rediriger vers un serveur de secours si lui-même est sous forte charge, ou bien s'il sait qu'il existe un serveur plus proche de ce client particulier.
  • Le serveur d'origine peut rediriger le client vers une connexion sécurisée (avec HTTPS, cf. RFC 8164) ou vers un protocole plus moderne (HTTP 2, cf. RFC 7540).
  • Le serveur d'origine peut renvoyer certains clients à des serveurs spécialisés, par exemple pour le cas de clients ne gérant pas certaines options comme SNI (RFC 6066, section 3).

Actuellement, ce genre de choses est fait par des redirections HTTP explicites (codes 301, 302, 307 ou 308, voir le RFC 7231, section 6.4). L'URL vers lequel on est redirigé est montré par le navigateur (ce qui n'est clairement pas une bonne idée dans le cas de redirections temporaires comme 307). Autre façon de faire, un relais, qui se connecte au serveur effectif, sans le dire du tout au client HTTP. Les « services alternatifs » de ce RFC 7838 sont situés entre les deux façons : annoncés au client HTTP mais pas mémorisés et pas montrés à l'utilisateur (l'URI ne change pas). Le contexte de sécurité n'est pas modifié (si l'URI commençait par le plan https://, le service alternatif devra donc présenter un certificat valide), le champ Host: de la requête HTTP contiendra toujours le nom original (notez qu'il existe désormais un champ Alt-Used: pour indiquer le nom alternatif, cf. section 5). Normalement, l'utilisateur ne verra donc pas qu'on utilise un service alternatif (ceci dit, comme son logiciel client, lui, est au courant, des options de débogage pourront permettre de l'afficher, contrairement à ce qui se passe avec un relais).

La solution est en deux parties : des concepts abstraits (section 2) puis des mécanismes concrets pour les différents protocoles, dans les sections 3 et 4. Commençons par le cadre abstrait. Un « service alternatif » existe lorsqu'un serveur d'origine (concept lui-même défini dans le RFC 6454, section 4) sait que ses ressources sont accessibles avec une combinaison {protocole, serveur, port} différente. Un tel service alternatif fait autorité (au sens du RFC 7230, section 9.1), ce n'est pas un simple miroir, ni un cache. Notez que la granularité est pour une origine complète (la combinaison {protocole, serveur, port}) : on ne peut pas faire un service alternatif qui couvrirait uniquement le chemin /foo de l'URI.

Un exemple de service alternatif ? Mettons que l'origine soit {http, www.example.com, 80} et que les mêmes ressources soient accessibles en HTTP 2 à {h2, new.example.com, 81}, alors on peut dire que ce {h2, new.example.com, 81} est un service alternatif de l'origine.

Notez que j'ai appelé « protocole » le premier membre du tuple. Ce n'est pas le plan (scheme) dans l'URI (plan que pas mal de gens appellent à tort protocole). En effet, cette valeur est plus spécifique que le plan, elle peut inclure des détails techniques supplémentaires (par exemple, lorsque le plan est http://, on peut y accéder avec les protocoles http ou h2, ce second désignant HTTP 2.) Le protocole, pour les services alternatifs, est un nom ALPN (RFC 7301 et le registre IANA ALPN).

Le tuple {protocole, serveur, port} peut être accompagné d'une durée de vie, indiquant combien de temps le client HTTP peut garder en mémoire l'information sur le service alternatif.

Au passage, un mot de sécurité : le client doit évidemment être conscient que, si la communication n'est pas sécurisée (par exemple par TLS), il peut être envoyé vers un faux service alternatif (section 9). Si le service d'origine n'a pas TLS mais que le service alternatif l'a, et présente un certificat au nom du service d'origine, c'est bon. Si aucun des deux n'a TLS, le risque d'avoir été trompé est bien plus élevé. Il n'est donc pas forcément prudent d'utiliser les services alternatifs sans TLS.

Notons enfin que les services alternatifs sont optionnels. Le client n'est pas obligé de les utiliser (d'autant plus que les clients HTTP actuels ne gèrent pas ces services et n'utiliseront donc pas les alternatives, tant qu'ils n'ont pas été mis à jour). Le serveur d'origine doit donc rester prêt à assurer les requêtes.

Maintenant, les mécanismes pour signaler ces services alternatifs. En HTTP 1, en utilise l'en-tête Alt-Svc: (section 3, et désormais dans le registre IANA). La réponse contient, par exemple :

Alt-Svc: h2="new.example.org:80"      
    

Cela indique que le client devrait plutôt aller voir avec le protocole h2 (HTTP 2), sur la machine new.example.org. Si on ne change que le protocole et le port, on pourrait avoir :

Alt-Svc: h2=":8000"
    

Il peut y avoir plusieurs valeurs, dans l'ordre des préférences décroissantes :

Alt-Svc: h2="alt.example.com:8000", h2=":443"
    

Par défaut, le service alternatif peut être mémorisé par le client pendant 24 h. Si on veut changer cette durée, on utilise le paramètre ma (Maximum Age, en secondes) :

Alt-Svc: h2=":443"; ma=3600
     

Si le serveur veut qu'on oublie tout ce qu'on a mémorisé sur les services alternatifs, et n'a pas envie d'attendre l'expiration des caches, il envoie la valeur spéciale clear :

Alt-Svc: clear
    

À part ce paramètre ma, et un autre paramètre persist (qui indique que, contrairement au comportement par défaut, le client HTTP ne devrait pas vider cette information de son cache si sa configuration réseau change), d'autres paramètres sont possibles dans le futur. Ils devront passer par le procédure « Examen par un expert » du RFC 5226 et seront mis dans le registre IANA.

Et si on utilise HTTP 2, où on est en binaire et plus en texte, et où les en-têtes sont représentés d'une façon complètement différente ? Dans ce cas, on se sert de trames du type ALTSVC (section 4). C'est une extension au protocole original. La trame ALTSVC a le type 0xa (10, dans le registre IANA) et contient un champ Longueur (de l'origine), l'origine, et le service alternatif sous une syntaxe identique à celle de la section précédente.

On l'a vu, le service alternatif fait normalement autorité et doit donc gérer les mêmes ressources. Que se passe-t-il si un serveur maladroit redirige vers une machine qui n'est pas configurée comme service alternatif ? Idéalement, cette machine ne faisant pas autorité doit répondre 421 (RFC 7540, section 9.1.2). Le client doit alors réessayer avec un autre service alternatif, s'il existe, ou bien avec le serveur d'origine. (Aujourd'hui, je crois qu'il est plus fréquent que la machine ne faisant pas autorité renvoie les ressources de sa configuration par défaut.)

Un petit mot d'histoire : ce système des services alternatifs vient d'une solution spécifique à Chrome qui se nommait Alternate-Protocol:. Un bon article de synthèse sur ces services alternatifs est celui de l'auteur du RFC.


Téléchargez le RFC 7838


L'article seul

RFC 7842: Requirements for Improvements to the IETF Email List Archiving, Web-Based Browsing, and Search Tool

Date de publication du RFC : Avril 2016
Auteur(s) du RFC : R. Sparks (Oracle)
Pour information
Première rédaction de cet article le 13 avril 2016


Un des gros avantages de travailler à l'IETF est qu'il existe un ensemble d'outils de travail en groupe très perfectionnés, permettant de gérer un grand nombre de documents qui changent tout le temps. Dans la plupart des SDO, ou organisations similaires, on a juste des piles de documents Word (ou, dans les dernières années, Google Docs) inexploitables. Comme le gros du travail IETF est fait sur des listes de diffusion, un des outils les plus cruciaux est le moteur de recherche dans ces listes de diffusion. Mais aucun outil n'est parfait et ce nouveau RFC est une liste de points à améliorer dans l'outil actuel, liste fondée sur l'expérience récente.

Ce https://mailarchive.ietf.org/ permet notamment de retrouver un ou plusieurs messages, parmi les centaines de messages échangés sur les listes IETF chaque jour. Voici un exemple de recherche de « tcp encryption eliot » (Eliot = Eliot Lear, auteur entre autres des RFC 1918, RFC 4192, RFC 6557...). On y voit la liste des messages correspondants en haut à droite, à gauche les noms des listes (en général, des groupes de travail IETF) où les messages apparaissent, en bas à droite l'URL stable du message en cours (ce qui permet des références précises lorsqu'on affirme « Brian Trammel a dit que ») : mailarchive-ietf-general.png

L'outil actuel avait eu comme cahier des charges le RFC 6778 et avait été déployé en janvier 2014. Notre nouveau RFC liste les améliorations souhaitées.

Par exemple, lorsqu'on choisit « Group by Thread », la liste résultante est plate, sans hiérarchie. Cela rend difficile de voir où un fil de discussion commence et où il finit : mailarchive-ietf-thread.png

Notre RFC demande que, dans les améliorations de l'outil, l'affichage montre la hiérarchie.

Autre problème, il n'y a pas actuellement de boutons de navigation (message suivant/précédent par date, ou suivant le fil de discussion), que cela soit dans la liste des messages affichés, ou bien lorsqu'on regarde un seul message. Le RFC demande que ces boutons soient ajoutés.

C'est en lisant ce RFC que j'ai appris qu'on pouvait changer la taille de la fenêtre où s'affiche la liste des messages. Je la croyais fixe, et c'était apparemment le cas de bien des utilisateurs. Le RFC demande donc qu'on rende cette possibilité d'agrandissement plus évidente (personnellement, je n'ai pas trouvé). En prime, la façon dont est faite la troncation aujourd'hui ne semble pas rationnelle. Ici, on voit bien que les sujets sont coupés (et la fin remplacée par des ellipses) sans vraiment de raison. mailarchive-ietf-ellipsis.png

Le service actuel est difficile à utiliser sur un petit écran, comme celui des phono sapiens puisque les divers éléments de l'interface sont toujours présents. Pour une interface riche, il vaudrait mieux être responsive, ce que demande le RFC (par exemple, on pourrait supprimer le menu des filtres quand l'écran est trop petit).

Par contre, sur des grands écrans, l'interface actuelle est au contraire trop économe et sous-utilise l'écran.

Enfin, notre RFC regrette que l'interface actuelle ne marche guère sans JavaScript. La prochaine version doit évidemment être capable de fonctionner sans JavaScript, quitte à accepter quelques fonctions en moins (comme les filtres appliquées dynamiquement).

Reste à développer, maintenant... Je n'ai pas encore vu d'appel d'offres.


Téléchargez le RFC 7842


L'article seul

RFC 7828: The edns-tcp-keepalive EDNS0 Option

Date de publication du RFC : Avril 2016
Auteur(s) du RFC : P. Wouters (Red Hat), J. Abley (Dyn), S. Dickinson (Sinodun), R. Bellis (ISC)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 11 avril 2016
Dernière mise à jour le 12 avril 2016


Historiquement, le DNS utilisait surtout UDP et le transport sur TCP ne servait qu'à des cas particuliers, comme lorsqu'un client DNS ré-essayait avec TCP de récupérer des données trop grosses pour UDP. Depuis le RFC 7766, ce n'est clairement plus le cas : TCP est désormais aussi utilisable qu'UDP pour le DNS. Mais les mises en œuvre typique du DNS sur TCP ont des restrictions, par exemple des délais maximum d'attente avant de « raccrocher » qui sont trop courtes, de l'ordre de quelques secondes lorsqu'il n'y a plus de trafic sur la connexion. Ce nouveau RFC propose un mécanisme EDNS permettant au client DNS de signaler au serveur qu'il souhaite garder la connexion ouverte, si le serveur est d'accord, s'il vous plait. (Notez qu'il existe une autre façon d'indiquer le temps pendant lequel on souhaite garder la session, celle des DSO du RFC 8490 ».)

Utiliser une connexion TCP par requête DNS serait en effet très inefficace, notamment question latence. Il faudrait effectuer la triple poignée de mains TCP à chaque requête. Le DNS sur TCP n'est envisageable que si les connexions restent ouvertes et que la même connexion peut servir pour plusieurs requêtes. Dans ce cas, lorsque la connexion a déjà été ouverte, la latence peut être aussi faible qu'avec UDP, voire meilleure (dans le cas de données de grande taille, par exemple avec DNSSEC, plus besoin d'essayer d'abord sur UDP). Reste une question pour le serveur DNS : faut-il laisser la connexion ouverte dès qu'il n'y a plus de requêtes à traiter ? Cette nouvelle option EDNS edns-tcp-keepalive permet au client DNS d'indiquer que, lui, il est prêt à réutiliser la connexion et qu'il souhaite qu'on la garde ouverte.

Le serveur souhaite économiser ses ressources (mémoire, notamment). Contrairement à UDP, TCP nécessite que le serveur garde un état. Imaginons que chaque connexion TCP prenne une entrée dans un grand tableau des connexions TCP en cours. Si c'était « open bar » pour les clients, qu'ils puissent ouvrir autant de connexions qu'ils veulent, et les garder éternellement ensuite, le tableau serait vite rempli, menant à un déni de service. (Et si vous pensez qu'à la place du tableau, une structure de données dynamique, grossissant automatiquement, résoudrait le problème, rappelez-vous que la mémoire du serveur est finie...) Le serveur choisit donc s'il garde les connexions ouvertes, et combien de temps.

Au passage, la section 1 du RFC rappelle aussi qu'UDP a des problèmes sérieux, notamment parce qu'il permet des attaques par réflexion et parce qu'il implique, pour les grosses données, de la fragmentation, qui est en général une source d'ennuis (voir par exemple «  Fragmentation Considered Poisonous de Herzberg et Shulman). D'où cet encouragement, depuis des années, à utiliser de plus en plus TCP.

La section 3 est la partie centrale du RFC, la spécification de la nouvelle option. Elle utilise EDNS (RFC 6891). Elle permet d'indiquer le délai d'attente avant la fermeture de la connexion, délai qui commence à courir lorsque la connexion devient inactive (« idle », cf. la section 3 du RFC 7766).

L'option se nomme edns-tcp-keepalive et a reçu le code 11 (stocké dans le registre des options EDNS). Elle prend un seul argument, encodé sur deux octets, TIMEOUT qui indique la durée du délai de garde, exprimée en unités de 100 millisecondes. Cette valeur n'apparait que dans les réponses du serveur, pas dans les requêtes du client. Si TIMEOUT vaut 600, cela signifie que les connexions restent ouvertes pendant une minute après la dernière requête reçue.

Ensuite, une fois cette option définie, comment on s'en sert ? Elle ne doit évidemment pas être utilisée sur UDP, où elle n'aurait aucune signification. Le client doit utiliser cette option pour signaler qu'il souhaiterait garder cette connexion ouverte (il ne doit pas indiquer de valeur pour TIMEOUT). Le serveur utilise cette option pour indiquer le temps pendant lequel il va garder la connexion (rappelez-vous que le client peut demander ce qu'il veut, c'est le serveur qui décide). Le client est censé « raccrocher » juste avant l'expiration de ce délai. Une valeur de 0 pour TIMEOUT signifie « raccroche tout de suite » (un serveur l'envoie, par exemple, lorsqu'il est soumis à un fort stress et n'a plus de ressources disponibles.)

Au passage, si le serveur n'a plus envie de supporter cette connexion, pourquoi ne raccroche-t-il pas lui-même, au lieu de demander au client de le faire ? C'est parce que le pair TCP qui ferme la connexion le premier passe ensuite en état TIME-WAIT (RFC 793, section 3.5) et que cela l'oblige à garder un état pendant deux fois la durée de vie maximale d'un segment TCP (soit quatre minutes en tout). Il vaut donc mieux demander au client de le faire. Par contre, après avoir envoyé le TIMEOUT=0, le serveur va avoir un délicat arbitrage à faire entre attendre que le client raccroche et fermer de lui-même la connexion (et donc garder une prise en état TIME-WAIT) quand le client n’obtempère pas suffisamment vite.

La section 5 du RFC recommande d'ailleurs aux serveurs de suivre l'activité de leurs clients et de « punir », d'une façon ou d'une autre, ceux qui violeraient ces règles, par exemple en continuant à envoyer des requêtes alors qu'on leur a demandé de raccrocher.

J'insiste mais cela vaut la peine d'être dit et répété : cette option edns-tcp-keepalive ne diminue pas la liberté des clients et des serveurs DNS. En cas de problème (tableau des connexions TCP en cours presque plein, par exemple), clients et serveurs sont libres de couper les connexions TCP plus tôt, ce qu'on appelle le « TCP session management ».

Comme d'habitude avec toute nouvelle option, on peut s'attendre à des problèmes avec les stupides middleboxes. Une requête contenant cette option peut ainsi être jetée alors qu'elle ne l'aurait pas été sans l'option. Une stratégie de repli comme celle de la section 6.2.2 du RFC 6891 peut donc être utile.

Merci à Kim-Minh Kaplan pour d'utiles précisions sur TCP.


Téléchargez le RFC 7828


L'article seul

RFC 7805: Moving Outdated TCP Extensions and TCP-related Documents to Historic and Informational Status

Date de publication du RFC : Avril 2016
Auteur(s) du RFC : A. Zimmermann (NetApp), W. Eddy (MTI Systems), L. Eggert (NetApp)
Pour information
Réalisé dans le cadre du groupe de travail IETF tcpm
Première rédaction de cet article le 11 avril 2016


Un peu de nettoyage dans l'imposante bibliothèque des RFC sur le protocole TCP. Bien des extensions à TCP n'ont jamais connu de déploiement réel dans la nature et d'autres, qui ont été déployées, ne sont plus utilisées depuis longtemps. Un grand nombre de RFC sont donc reclassifiés « intérêt historique seulement » ou bien « pour information ». Cela concerne surtout des vieux RFC, qui étaient bien oubliés de toute façon.

Le RFC 7414 (le guide des normes sur TCP) avait déjà fait cette classification mais sans mentionner le changement de statut dans la base de l'éditeur des RFC. C'est désormais chose faite. Il y a aussi des RFC très anciens qui n'avaient jamais été classés comme le RFC 675, la première norme TCP, à l'époque où les RFC n'avaient pas de statut clair. Remplacé par le RFC 793 (avec des modifications sérieuses du format des paquets), ce RFC 675 est désormais « intérêt historique seulement ». (À noter que le précédent grand nettoyage de TCP était dans le RFC 6247.)

Dans la liste, le RFC 1078 (TCPMUX) a suscité quelques controverses car il est apparemment mis en œuvre dans certains systèmes d'exploitation (la partie serveur, pas la partie client, qui semble absente). On ne peut donc pas le caractériser comme « non déployé ». Néanmoins, les failles, notamment de sécurité, de TCPMUX font que le RFC 1078 se retrouve lui aussi classé « intérêt historique seulement ». Notre RFC donne la liste des problèmes techniques qu'il pose.

Ce sort touche aussi des RFC récents comme le RFC 6013, proposition d'une ouverture de connexion TCP plus rapide et plus légère, publiée en 2011, implémentée, mais jamais déployée, et remplacée depuis par des RFC qui ont eu plus de succès comme le RFC 7413.

D'autres RFC sont seulement classés « pour information ». C'est le cas du RFC 700 car il ne décrivait pas un protocole mais était une analyse des premiers résultats du déploiement de TCP, ou du RFC 814, un important document de réflexion sur des concepts comme les adresses, les ports et les routes, toujours d'actualité, mais qui n'avait jamais reçu de classement auparavant. Parmi les autres RFC désormais classés, le RFC 889, qui était également un compte-rendu d'expérience sur la variation de certains paramètres numériques de TCP, comme le délai maximal d'attente. Faisons enfin une place à part pour le très utile RFC 1071 qui n'est pas abandonné, bien au contraire, juste classé comme « pour information ».


Téléchargez le RFC 7805


L'article seul

RFC 7807: Problem Details for HTTP APIs

Date de publication du RFC : Mars 2016
Auteur(s) du RFC : M. Nottingham (Akamai), E. Wilde
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF appsawg
Première rédaction de cet article le 1 avril 2016


Lorsqu'on fait une requête HTTP, on récupère un code à trois chiffres qui indique notamment si tout s'est bien passé (si le code commence par 2, c'est bon, s'il commence par 4 ou 5, c'est qu'il y a un problème). Ces codes ne sont pas toujours assez fins et bien des API de services REST (donc reposant sur HTTP) voudraient des précisions. Plutôt que de créer un nouveau code, ce RFC propose un mécanisme qui permet d'envoyer du JSON normalisé indiquant tous les détails sur le problème survenu. (Ce RFC a depuis été remplacé par le RFC 9457.)

Les codes de statut de HTTP sont définis dans la section 6 du RFC 7231. Parmi les plus célèbres, on note 200 (qui veut dire que tout s'est bien passé) ou 404 (qui indique que le serveur n'a pas trouvé la ressource demandée). Si le serveur veut fournir des détails, il envoie traditionnellement de l'HTML dans le corps de sa réponse. Le navigateur Web peut alors l'afficher. Mais si la requête n'était pas envoyée par un humain derrière son navigateur, si elle venait d'un client REST ? HTML ne convient alors pas et il faut passer à une information analysable par une machine. C'est ce que fait ce RFC, qui définit deux formats, un en JSON (RFC 8259) et un en XML. Le client REST va donc avoir un résumé simple (le code de statut) et tous les détails nécessaires s'il le souhaite. « Comprenant » l'erreur exacte, le client pourra même, dans certains cas, la corriger.

Le RFC utilise surtout des exemples avec l'erreur 403 Forbidden mais j'ai préféré me servir de 402 Payment required. Ce code n'a jamais été clairement documenté (il est marqué « réservé pour un usage futur » dans le RFC 7231, section 6.5.3) et c'est sans doute pour cela que notre RFC ne l'utilise pas, mais je le trouve plus rigolo. Voici par exemple une page Web payante :

% wget https://www.bortzmeyer.org/faut-vraiment-payer.html
--2016-03-26 15:54:00--  https://www.bortzmeyer.org/faut-vraiment-payer.html
Resolving www.bortzmeyer.org (www.bortzmeyer.org)... 2001:4b98:dc0:41:216:3eff:fece:1902, 2605:4500:2:245b::42, 204.62.14.153
Connecting to www.bortzmeyer.org (www.bortzmeyer.org)|2001:4b98:dc0:41:216:3eff:fece:1902|:443... connected.
HTTP request sent, awaiting response... 402 Payment Required
2016-03-26 15:54:00 ERROR 402: Payment Required.

On peut envisager plein de choses dans cette réponse analysable par une machine, comme un URI unique pour ce problème donné, qui pourrait être, par exemple, transmis au support pour faciliter la communication. Ou bien un URI d'un service REST de paiement permettant d'envoyer l'argent souhaité. Mais, naturellement, l'utilisation de cette réponse est facultative : parfois, le code de statut est suffisant et il n'y a rien à ajouter (c'est souvent le cas du 404), et parfois il vaut mieux utiliser un format spécifique à l'application utilisée (c'est d'ailleurs le cas pour toutes les API développées avant ce RFC). Ceci dit, pour les nouvelles applications, le mécanisme décrit dans ce RFC peut être très utile, pour doter toutes les applications d'un mécanisme commun de signalement des erreurs et problèmes.

Le modèle de données utilisé est celui de JSON et le type MIME est application/problem+json. Comme je l'ai dit plus haut, il y a aussi une version XML mais la référence est le JSON. La section 3 du RFC décrit ce modèle. Commençons par un exemple, une API qui demandait entre autres d'indiquer un âge et à qui on a envoyé un nombre négatif :

HTTP/1.1 400 Bad Request
Content-Type: application/problem+json
Content-Language: en

{
   "type": "https://example.net/validation-error",
   "title": "Your request parameters didn't validate.",
   "invalid-params": [ {
                         "name": "age",
                         "reason": "must be a positive integer"
                       }
                     ]
}
 

Ce message d'erreur est de type https://example.net/validation-error, une explication en langue naturelle est donnée par le membre title, et la liste des paramètres invalides est donnée dans le membre (une extension à la norme) invalid-params.

Quels sont les membres possibles de l'objet JSON renvoyé ?

  • type est un URI (il est donc unique) servant d'identificateur au problème, par exemple lorsqu'on va écrire au support. Il est recommandé qu'il soit déréférençable (c'est-à-dire qu'on puisse le visiter avec un navigateur Web et obtenir des informations sur le problème en question). S'il est absent, sa valeur par défaut est le très vide about:blank (RFC 6694, section 3).
  • title est un titre conçu pour des humains, par exemple pour les messages d'erreurs présentés à l'utilisateur. Étant en langue naturelle, il est, contrairement au type, ambigu. Il peut être adapté à la langue de l'utilisateur, via l'habituelle négociation de contenu de HTTP. detail (absent dans l'exemple ci-dessus) le complète éventuellement. Le RFC précise que detail est fait pour l'utilisateur, pas pour le programmeur qui a conçu le service. Il devrait donc contenir des informations aidant l'utilisateur à corriger sa requête, pas des informations de débogage (pas de pile d'appels Java, par exemple...) D'ailleurs, envoyer ces informations de débogage poserait un problème de sécurité (cf. section 5).
  • instance (absent dans l'exemple) est un URI qui, contrairement à type, n'identifie pas la classe du problème mais une instance particulière. Si http://example.com/not-enough-credit indique la classe « pas assez d'argent », https://example.com/account/12345/msgs/abc va indiquer le problème d'argent d'un compte particulier.

Notez que type et instance peuvent être des URI relatifs.

Voici maintenant un exemple sur mon blog (c'est conçu comme une application REST donc les résultats sont toujours en JSON et, en effet, ce n'est pas en HTTPS, ce serait intolérable en production) :


% curl -v https://www.bortzmeyer.org/apps/payme     
...
< HTTP/1.1 402 Payment required
...
< Content-Length: 253
< Content-Type: application/problem+json
< 
{
  "type": "http://errors.bortzmeyer.org/nopay", 
  "detail": "Bitcoin address 1HtNJ6ZFUc9yu9u2qAwB4tGdGwPQasQGax, Ethereum address 0xbe1f2ac71a9703275a4d3ea01a340f378c931740, Flattr https://flattr.com/profile/bortzmeyer", 
  "title": "You must pay"
}

% curl -v https://www.bortzmeyer.org/apps/payme\?pay=30
...
< HTTP/1.1 200 OK
< Content-Length: 36
< Content-Type: application/json
< 
{
  "title": "OK, 30 credits paid"
}

    

Le code Python WSGI correspondant est :

 def payme(start_response, environ):
    form = cgi.parse_qs(environ['QUERY_STRING'])
    response_headers = []
    amount = 0
    if form.has_key("pay"):
        try:
            amount = int(form["pay"][0])
        except ValueError: # Bad syntax
            amount = 0
    if amount > 0:
        status = '200 OK'
        response_headers.append(('Content-type', 'application/json'))
        output = json.dumps({"title": "OK, %i credits paid" % amount}, indent=2)
    else:
        status = '402 Payment required'
        response_headers.append(('Content-type', 'application/problem+json'))
        output = json.dumps({"type": "http://errors.bortzmeyer.org/nopay",
                             "title": "You must pay",
                             "detail": "Bitcoin address 1HtNJ6ZFUc9yu9u2qAwB4tGdGwPQasQGax, Ethereum address 0xbe1f2ac71a9703275a4d3ea01a340f378c931740, Flattr https://flattr.com/profile/bortzmeyer"},
                             indent=2)
    response_headers.append(('Content-Length', str(len(output))))
    start_response(status, response_headers)
    return [output]     
    

Si vous n'avez pas ce que vous voulez dans les membres prévus, vous pouvez étendre l'objet JSON. Les clients doivent donc ignorer les membres inconnus. C'est le cas du invalid-params dans l'exemple, qui n'est pas un membre standard.

Bien, maintenant, vous êtes programmeur dans une start-up, vous créez un nouveau service qui a une API, un nom de domaine en .io, un business plan pipeau et vous vous demandez si vous devez utiliser ce RFC et comment. La section 4 du RFC fournit quelques conseils. D'abord, je le répète, ce n'est pas un outil de débogage pour vous, ne serait-ce que pour des raisons de sécurité (cf. section 5). C'est un outil pour aider vos utilisateurs. Ensuite, si le problème est un problème classique et standard, il est inutile de se servir de ce RFC. Si l'utilisateur demande une ressource qui n'existe pas, le traditionnel et générique 404 (RFC 7231, section 6.5.4) convient parfaitement et je ne vois pas de raison d'ajouter des détails analysables par une machine (dans une page HTML d'erreur, c'est différent, on peut fournir des conseils aux visiteurs, mais rappelez-vous que ce RFC est pour les API, quand le client est un programme).

D'autre part, une application peut avoir de très bonnes raisons d'utiliser un format à elle pour décrire en détail les problèmes. (Sans compter les applications existantes qui ne vont évidemment pas modifier la définition de leur API juste pour coller à ce RFC.)

En revanche, une application nouvelle, qui n'a pas de format d'erreur établi, a tout intérêt à utiliser le cadre de ce RFC plutôt que de réinventer la roue. Dans ce cas, vous allez devoir définir :

  • L'URI qui servira de type (le seul type prédéfini est about:blank),
  • Le code de statut HTTP qui l'accompagne,
  • Les éventuelles extensions (comme le membre invalid-params plus haut).

Ces extensions peuvent utiliser les liens de HTTP (RFC 8288).

Le format principal décrit par ce RFC utilise JSON. Mais, comme il y a des goûts différents, il y a aussi une variante XML, décrite dans l'annexe A. Elle est spécifiée en Relax NG. Le modèle de données étant le même, cela donne à peu près :

   start = problem

   problem =
     element problem {
       (  element  type            { xsd:anyURI }?
        & element  title           { xsd:string }?
        & element  detail          { xsd:string }?
        & element  status          { xsd:positiveInteger }?
        & element  instance        { xsd:anyURI }? ),
       anyNsElement
     }
     

Et le résultat serait :


HTTP/1.1 400 Bad Request
Content-Type: application/problem+xml
Content-Language: en

<?xml version="1.0" encoding="UTF-8"?>
<problem xmlns="urn:ietf:rfc:XXXX">
   <type>https://example.net/validation-error</type>
   <title>Your request parameters didn't validate.</title>
   <invalid-params><param><name>age</name><reason>must be a positive integer</reason></param></invalid-params>
</problem>

     

On a presque fini, quelques petits mots sur la sécurité en section 5 : attention à ne pas laisser fuiter de l'information qui pourrait aider un attaquant à préparer son attaque. Il faut notamment se méfier des détails de mise en œuvre (du genre afficher la requête SQL qui a échoué...)

Les deux nouveaux types MIME, application/problem+json et application/problem+xml figurent désormais dans le registre IANA.

Les développeurs d'API n'ont pas attendu ce RFC pour renvoyer des messages d'erreurs structurés, utilisant d'autres schémas (voici, par exemple, les erreurs possibles de l'API Github). Un concurrent sérieux à ce RFC est, par exemple, http://jsonapi.org/ qui a son propre mécanisme de signalement d'erreur.


Téléchargez le RFC 7807


L'article seul

RFC 7808: Time Zone Data Distribution Service

Date de publication du RFC : Mars 2016
Auteur(s) du RFC : M. Douglass (Spherical Cow Group), C. Daboo (Apple)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF tzdist
Première rédaction de cet article le 1 avril 2016


Ah, les fuseaux horaires... Quelle source infinie de complications pour le programmeur, pour l'administrateur système de machines situées partout dans le monde, ou tout simplement pour le voyageur ou l'organisateur de télé-réunions internationales... Comme tout serait plus simple si, comme dans le roman d'Asimov « Les cavernes d'acier », les hommes vivaient en permanence sous terre, utilisant un temps uniforme. Mais, en attendant ce futur béni, il faut bien gérer les fuseaux horaires (time zones). Il existe une base de données officielle de ces fuseaux, il ne reste plus qu'à la distribuer efficacement, pour que toute machine connectée à l'Internet ait la même information. C'est le but du protocole normalisé dans ce RFC.

Que contient une base de données des fuseaux horaires (section 1 du RFC) ? Typiquement une liste de ces fuseaux avec, pour chacun d'entre eux, son décalage par rapport à UTC et ses règles concernant l'heure d'été. Les fuseaux ne suivent pas strictement le méridien, ils collent en général à des frontières inter ou intra-étatiques. Les fuseaux eux-même, et leurs décalages avec UTC, sont très stables. Mais les règles concernant l'heure d'été changent, elles, souvent. Il y a aussi le problème des secondes intercalaires, qui sont ajoutées (ou, en théorie, retirées) par l'IERS de manière imprévisible (car la rotation de la Terre n'est pas prévisible). La base actuelle représente un travail d'érudition formidable.

Au passage, un point de terminologie. Le RFC parle de « time zone » là où on dit en général en français « fuseau horaire ». Le terme français n'est pas idéal car il fait penser à un fuseau allant d'un pôle à l'autre (et englobant donc des pays différents, ayant des heures d'été différentes) alors qu'une time zone est plus restreinte. Il faut donc bien se rappeler qu'on parle ici de zones limitées à un pays, et ayant des règles (décalage avec UTC, heure d'été) uniformes. Il faut donc peut-être mieux dire « zone » ou « zone horaire » en français.

Cette information est essentielle pour les protocoles et les formats qui gèrent le temps, comme iCalendar (RFC 5545), ainsi que pour les systèmes d'exploitation. Il faut donc maintenir à jour la base de données et, jusqu'à ce RFC, il n'existait pas de mécanisme standard pour cela. Par exemple, pour un système d'exploitation comme Debian, la mise à jour se fait typiquement via le mainteneur d'un paquetage « base des fuseaux horaires » (chez Debian, le paquetage se nomme tzdata), qui introduit les changements dans son paquetage, paquetage qui est ensuite installé sur chaque machine lorsque l'administrateur système décide des mises à jour. Si le système est vieux et plus maintenu, ce sera à l'administratreur système local de « patcher » ses fichiers. Parfois, des paquetages viennent avec leur propre base des fuseaux horaires, distincte de celle du système, pour compliquer un peu les choses.

Au passage, signalons que ce RFC normalise le protocole mais qu'il faut également disposer d'une source de données de référence. Il en existe une à l'IANA, décrite dans le RFC 6557.

La section 2 décrit à grands traits l'architecture du système. Tout en amont, des contributeurs envoient des données sur les fuseaux horaires, elles sont agrégées par le fournisseur de référence (root provider, par exemple l'IANA citée plus haut). Ce fournisseur l'envoie ensuite aux clients (par exemple par le protocole de ce RFC). Le schéma du RFC est un peu plus compliqué, supposant que divers intermédiaires pourraient apparaitre. Notez que le protocole décrit ici est entre fournisseur et clients. En amont (entre contributeurs et fournisseur), il n'y a pas de mécanisme spécifié.

La section 3 de notre RFC définit la terminologie. Une zone (time zone) se caractérise donc par un ensemble de règles uniformes. La zone a un nom (utilisé par exemple dans la propriété TZID du RFC 5545) mais il n'existe pas de norme pour cela. Chaque fournisseur pourrait utiliser son schéma de nommage. Ainsi, la base IANA utilise un nom de région, une barre oblique et un nom de pays ou de ville comme Europe/Paris ou Indian/Cocos. En tout cas, il faut se méfier des abréviations ambigues, n'ayant souvent qu'une signification locale, comme PST (qui peut désigner trois zones différentes).

L'information sur les zones change (autrement, on n'aurait pas besoin d'un protocole pour télécharger les mises à jour) et il est donc important d'avoir un numéro de version permettant de savoir si on a bien la dernière version. Il peut être global à la base, ou bien spécifique à chaque zone.

Maintenant, le protocole lui-même (section 4 du RFC). Il repose, comme souvent de nos jours, sur le couple « HTTP (RFC 7230) et JSON (RFC 8259) », ce dernier servant à représenter les méta-données sur les zones. Les ressources auxquelles on accède en HTTP utilisent les gabarits d'URI du RFC 6570. Et les données elle-mêmes, les informations sur une zone horaire, en quoi sont-elles codées ? Le format par défaut est celui d'iCalendar (RFC 5545). Mais on peut aussi utiliser la représentation en XML du RFC 6321 ou celle en JSON du RFC 7265. La classique négociation de contenu de HTTP (RFC 7231, section 5.3.2) sert au client à choisir son format parmi ceux que le serveur veut bien fournir.

La base peut être assez grosse et les clients vouloir la toute dernière version. La charge sur le réseau des fournisseurs risquerait alors de devenir insupportable. C'est pourquoi il est possible de faire des requêtes conditionnelles, de façon à ne récupérer des données que si elles sont nouvelles. Là encore, c'est du classique HTTP avec les Etags (RFC 7232). Un client peut alors interroger le serveur du fournisseur une fois par jour (valeur recommandée par le RFC) sans risque de saturer le réseau.

Si le client reçoit uniquement le décalage avec UTC et les règles pour l'heure d'été, calculer une heure dans le futur peut être délicat car ces règles sont complexes. Le protocole prévoit donc la possibilité pour le client de demander au serveur de faire ces calculs et de lui envoyer les résultats.

Et si ça ne marche pas, que le serveur, pour une raison ou pour une autre, ne peut pas envoyer ce qui lui est demandé ? Il doit alors utiliser les erreurs structurées du RFC 7807 pour signaler ce qui ne va pas. (Les types d'erreurs possibles figurent dans un registre IANA.)

Comment est-ce qu'un client de ce protocole trouve le serveur ? Il doit de toute façon connaître le nom de domaine de son fournisseur, supposons ici example.net. Ensuite, il y a au moins deux méthodes :

  • Utiliser les enregistrements SRV (RFC 2782), en demandant _timezone._tcp.example.net. Il obtiendra ainsi le nom du serveur et le port à utiliser. Un enregistrement supplémentaire, sous le même nom que l'enregistrement SRV, de type TXT, indique un éventuel chemin à ajouter dans l'URI.
  • Ou bien utiliser les URI .well-known du RFC 8615, en faisant une requête HTTP pour la ressource timezone.

La section 5 du RFC décrit ensuite les actions que le serveur peut effectuer à la demande. Elles sont spécifiées en utilisant les gabarits du RFC 6570. Donc, par exemple, un gabarit {/service-prefix}/capabilities indique que le client doit ajouter /capabilities au préfixe de chemin découvert comme indiqué précédemment. Prenons un exemple complet : le client sait que son fournisseur de zones horaires est example.net. Il fait deux requêtes DNS et obtient deux enregistrements :

_timezone._tcp.example.net. SRV 0 1 8081 tz.example.com.
_timezone._tcp.example.net. TXT "path=/timezones"
    

S'il cherche à déterminer les capacités du serveur, il va alors faire une requête à l'URL http://tz.example.com:8081/timezones/capabilities.

C'est quoi, ces capabilities que je viens d'utiliser dans l'exemple ? C'est la première des actions possibles sur un serveur. Comme son nom l'indique, elle renverra un objet JSON contenant un membre actions qui sera la liste des actions possibles sur ce serveur (avec, pour chacune, le gabarit d'URI à utiliser). Une liste des actions standards possibles figure dans un registre IANA.

L'action list, elle, donne la liste des zones horaires connues du serveur. Et l'action get renvoie les données pour une zone précise. Son gabarit est {/service-prefix,data-prefix}/zones{/tzid}{?start,end} (tzid étant l'identificateur de la zone, par exemple Pacific/Noumea) et un exemple d'utilisation est :

[Requête]
      
GET /timezones/zones/America%2FNew_York HTTP/1.1
Host: tz.example.com:8081
Accept:text/calendar

[Réponse]

HTTP/1.1 200 OK
Date: Wed, 4 Jun 2008 09:32:12 GMT
Content-Type: text/calendar; charset="utf-8"
Content-Length: xxxx
ETag: "123456789-000-111"

BEGIN:VCALENDAR
...
BEGIN:VTIMEZONE
TZID:America/New_York
...
END:VTIMEZONE
END:VCALENDAR      
    

Les codes d'erreur habituels de HTTP sont utilisés donc, par exemple, si on demande un tzid inconnu, on récupérera un beau 404, mais avec le corps de la réponse en JSON, suivant le RFC 7807 :

[Requête]
      
GET /timezones/zones/Atlantid%2FPlutopolis HTTP/1.1
Host: tz.example.com:8081
Accept:text/calendar

[Réponse]

HTTP/1.1 404 Not Found
Date: Wed, 4 Jun 2008 09:32:12 GMT
Content-Type: application/problem+json; charset="utf-8"
Content-Language: en
Content-Length: xxxx

{
     "type": "urn:ietf:params:tzdist:error:tzid-not-found",
     "title": "Time zone identifier was not found on this server",
     "status": 404
}

Il existe plusieurs autres actions, comme expand qui dit au serveur de faire les calculs d'heure d'été lui-même, ou find, qui permet de chercher une zone par une partie de son nom.

Notez bien qu'il n'y a pas d'URI fixe et pré-déterminé pour les actions : il faut utiliser les gabarits pour les générer.

Les détails des objets JSON qui peuvent être renvoyés en réponse à ces actions figurent en section 6 de notre RFC.

Et la sécurité ? Elle est cruciale car, si on peut changer la connaissance qu'une machine a de l'heure, plein d'attaques deviennent possibles (fausser les estampilles temporelles dans les journaux, activer ou désactiver un certificat, etc). Il faut donc prendre soin d'utiliser un fournisseur fiable, et de récupérer la base de manière sécurisée. (HTTPS, forcément, et avec vérification sérieuse de l'identité du serveur, en suivant le RFC 6125 ou bien le RFC 6698).

Il n'y a apparemment pour le moment qu'une mise en œuvre, dans le système de calendrier Bedework. Je ne connais pas encore de service disponible qui serve la base de données suivant ce protocole (c'est pour cela que je ne montre pas d'exemple réel). Notamment, l'IANA ne le fait pas (ce n'était pas demandé dans le RFC). Il existe des services qui distribue la base, mais avec un autre protocole, comme https://timezonedb.com/api.


Téléchargez le RFC 7808


L'article seul

RFC 7801: GOST R 34.12-2015: Block Cipher "Kuznyechik"

Date de publication du RFC : Mars 2016
Auteur(s) du RFC : V. Dolmatov (Research Computer Center MSU)
Pour information
Première rédaction de cet article le 25 mars 2016


Encore un algorithme de cryptographie venu de l'Est, avec cette spécification sous forme de RFC d'un algorithme GOST, connu sous le petit nom de « Kuznyechik » (dans la transcription anglo-saxonne), et, plus formellement, sous celui de GOST R 34.12-2015. C'est un algorithme de chiffrement symétrique par blocs.

Comme d'autres algorithmes de cryptographie normalisés par GOST, Kuznyechik a été développé en partie par le secteur public (Service des communications spéciales et d'information du Service fédéral de protection de la Fédération de Russie) et par le secteur privé (InfoTeCS). Le décret n° 749 du 19 juin 2015, pris par l'Agence fédérale pour la régulation technique et la métrologie en a fait un algorithme russe officiel. C'est donc apparemment un concurrent d'AES.

Les sections 3 et 4 du RFC décrivent l'algorithme en détail. Pour les connaisseurs en cryptographie seulement, d'autant plus que le format actuel (c'est en cours de révision) des RFC n'est pas idéal pour décrire des mathématiques, il vaut mieux utiliser la version en anglais de la norme russe. Des vecteurs de test figurent en section 5.

Merci à André Sintzoff, qui sait utiliser Canard, canard, va.


Téléchargez le RFC 7801


L'article seul

RFC 7742: WebRTC Video Processing and Codec Requirements

Date de publication du RFC : Mars 2016
Auteur(s) du RFC : A.B. Roach (Mozilla)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF rtcweb
Première rédaction de cet article le 24 mars 2016


Ce court RFC expose les exigences portant sur les codecs vidéo de WebRTC. Le point principal était le choix du codec obligatoire. Après une très longue et très amère discussion à l'IETF, le choix a été plus politicien que technique : le codec H.264 est obligatoire au même titre que VP8.

Le système WebRTC (voir le RFC 7478) permet de faire de la vidéoconférence, notamment entre deux navigateurs Web. Il permet aux parties qui communiquent de choisir le codec. Un point important des protocoles IETF est que, lorsqu'il existe un tel choix, au moins un des choix doit être mis en œuvre dans toutes les implémentations. Le but est d'assurer l'interopérabilité, en vérifiant que les programmes ont tous au moins un codec en commun.

Mais quel codec choisir ? Il y avait deux concurrents, un codec de l'UIT, H.264 (normalisé ici), qui avait la faveur des compagnies de télécommunication traditionnelles, et un codec issu de l'Internet, VP8 (RFC 6386), qui était le plus apprécié par les entreprises Internet et par le monde du logiciel libre. Le débat a été très long et très houleux à l'IETF. Le problème n'était pas uniquement sentimental, il portait également sur les innombrables brevets qui verrouillent H.264 (son concurrent VP8 a aussi des brevets, mais avec une licence très libérale pour la plupart). Quant aux critiques sur VP8, elles portaient surtout sur sa relative jeunesse (en fait, certaines entreprises avaient investi pas mal dans H.264 et ne voulaient pas recommencer).

Le débat a donc duré, générant plus de mille messages sur la liste de diffusion du groupe de travail, et occupant une bonne partie des réunions physiques de l'IETF (réunions IETF 81, 82, 85, 86, et 88...), affectant notablement la patience des participants. Des tas de solutions ont été proposées pour sortir de l'affrontement, y compris un inhabituel vote (dans ce message, MTI = Mandatory To Implement). Le sujet est revenu sur le tapis et revenu encore. La solution, adoptée à la réunion IETF 91 à Honolulu, a finalement été de prendre les deux.

Notez bien que ce RFC n'est pas la description complète de WebRTC, loin de là. C'est juste le cahier des charges minimum des codecs (le cahier des charges du transport des données a été publié dans le RFC 8834).

D'abord, les considérations générales, indépendantes du codec (section 3). Par exemple, l'espace de couleur à utiliser est sRGB. Cette section conseille également sur l'utilisation de la caméra de capture : si elle le permet, il est recommandé d'utiliser ses capacités propres, comme la mise au point automatique, ou le réglage automatique de la luminosité. Le RFC rappelle également que la résolution de la source peut changer en cours de route (parce que la source est une fenêtre de l'écran qui change soudain de taille, ou bien parce que la source est la caméra d'un mobile qui change soudain d'orientation, cf. section 4) et que WebRTC doit donc s'y adapter.

La section 5 est le morceau sensible du RFC : la description du, ou plutôt des, codecs obligatoires. Le principe est que toute mise en œuvre de WebRTC doit accepter VP8 et H.264. Une note du RFC précise que, si le problème des brevets s'arrange pour un des codecs et pas pour l'autre, cette décision pourra être reconsidérée et un des codecs devenir optionnel (évidemment, tout le monde pense à H.264, beaucoup plus lardé de brevets avec licences hostiles). À noter que des codecs comme Theora ont été discutés, et sont possibles dans WebRTC, mais sans qu'il ait vraiment été envisagé de les rendre obligatoires.

La section 6 précise ensuite quelques exigences techniques pour chacun des codecs. Notamment, plusieurs options de H.264 ont une valeur fixe en WebRTC, pour simplifier la tâche des programmeurs. (H.264 a bien trop de variables possibles.)


Téléchargez le RFC 7742


L'article seul

RFC 7763: The text/markdown Media Type

Date de publication du RFC : Mars 2016
Auteur(s) du RFC : S. Leonard (Penango)
Pour information
Réalisé dans le cadre du groupe de travail IETF appsawg
Première rédaction de cet article le 23 mars 2016


Le format Markdown est un excellent format léger de marquage de textes, permettant d'enrichir un texte, sans pour autant avoir à apprendre un gros langage de marquage comme LaTeX. Markdown est très bien adapté aux courts rapports, aux articles simples, aux fichiers README, à la génération de pages Web... Markdown a de nombreuses variantes et le but de ce nouveau RFC n'est pas de normaliser Markdown (une tâche probablement impossible) mais juste d'enregistrer un type MIME pour ce format, text/markdown. Donc, on décrit, on ne normalise pas.

Markdown est un langage de marquage du texte, comme ReST (utilisé dans le livre CNP3) ou comme les langages des Wiki. On peut donc éditer du Markdown avec n'importe quel éditeur (mes lecteurs ne seront pas surpris d'apprendre que j'utilise Emacs). Le source Markdown est donc du texte lisible tel quel, sans logiciel spécifique, mais un logiciel peut le traiter pour produire une forme plus agréable et plus efficace, par exemple du HTML pour publication sur le Web.

Voici un exemple de document Markdown n'utilisant, sauf erreur, que les constructions communes à toutes les variantes : test1.md. On peut le traiter, par exemple avec discount, une mise en œuvre simple de Markdown, en C, qui ne peut produire que du HTML :


% markdown  test1.md 
<h1>Début</h1>

<p>Un test très simple
en Markdown.</p>
...
<h2>Suite</h2>
...

Mais on peut aussi utiliser le bien plus riche Pandoc, qui a de nombreuses extensions à Markdown, et peut produire beaucoup de formats de sortie, ici du PDF, via LaTeX :

% pandoc --to latex --latex-engine=xelatex -o test1.pdf test1.md
% evince test1.pdf
...

Un point important de Markdown est qu'il n'y a jamais d'erreur de syntaxe (section 1 du RFC) : tout fichier texte est un fichier Markdown légal (même s'il ne donne pas toujours le résultat attendu par son auteur). C'est donc un monde très différent de LaTeX ou de XML (au passage, ce blog est écrit en XML). Markdown se veut un langage léger, imposant peu de contraintes et peu d'apprentissage. Avec Markdown, on a toujours un résultat, même suboptimal. Ce n'est pas considéré comme un problème. Si on veut du « sérieux », il faut utiliser LaTeX ou DocBook.

La « spécification » de Markdown est très grossière, et laisse le doute sur beaucoup de points mais le choix de l'IETF a été de ne pas essayer d'en écrire une correcte : Markdown est fait ainsi.

Un autre point important est le grand nombre de variantes, souvent incompatibles. L'auteur original, John Gruber, a toujours refusé de permettre des évolutions du langage et chacun a donc ajouté les siennes. Il y a eu plusieurs tentatives de normalisation (la principale étant CommonMark), mais sans résultat clair. Au début du processus long et compliqué qui a abouti à ce RFC, il était question de faire une nouvelle tentative, sous la houlette de l'IETF cette fois. Mais le projet RFC s'est assez vite rabattu sur une ambition plus modeste : enregistrer le type MIME et documenter (partiellement) l'état de Markdown. Un autre RFC, le RFC 7764, décrit les usages de Markdown. La discussion a été d'autant plus chaude que la « communauté » Markdown est largement extérieure à l'IETF.

On pourrait dire que Markdown n'est pas un langage, mais une famille de langages, ayant des éléments communs. Un bon exemple de la variété de Markdown est, par exemple, le cas des métadonnées. Pandoc permet d'écrire en début de fichier :

% Document title
% Document author
% Document date

Mais d'autres variantes de Markdown ne vont pas comprendre ces métadonnées, les laissant telles quelles. Autre exemple de variété, les commentaires, pour lesquels il n'existe pas de solution standard (il y a un bon article sur StackOverflow qui discute les différentes possibilités.)

Cet enregistrement du type MIME de Markdown s'inspire de celui de text/troff, un type pour un autre langage de marquage (RFC 4263). Après tout, beaucoup de gens considèrent que Markdown est « le troff d'aujourd'hui ».

La section 2 de notre RFC décrit formellement l'enregistrement du type MIME text/markdown et de l'extension associée, .md (.markdown est également accepté). Ce type a plusieurs paramètres possibles (les paramètres sont mis après un point-virgule, par exemple text/markdown; charset=UTF-8; variant=Original va désigner du Markdown à la syntaxe originale de Gruber, encodé en UTF-8).

Premier paramètre, et obligatoire (RFC 6838, section 4.2.1), charset, qui désigne l'encodage du texte. Les autres paramètres sont facultatifs.

Le plus important est sans doute variant qui désigne le dialecte Markdown particulier utilisé. Ce fut l'une des plus chaudes discussions à l'IETF avant la sortie de ce RFC. Notamment, fallait-il un registre IANA des variantes (une sorte de catalogue des dialectes) ou bien laisser les auteurs mettre ce qu'ils veulent, ce qui correspondait mieux au côté très peu organisé de la « communauté » Markdown, très informelle ? (Différentes versions du draft qui a mené à ce RFC faisaient des choix différents.) Le paramètre variant a finalement un registre (section 6.1) mais l'émetteur n'est pas obligé de se limiter aux valeurs de ce registre. Il faut considérer la valeur de ce paramètre comme une simple indication. Parmi les valeurs actuellement enregistrées : Original (le Markdown des débuts, celui de Gruber), GFM (celui de GitHub), pandoc (celui de ce logiciel), CommonMark (le candidat à la normalisation) etc. Notez que ce paramètre variant, au gré des évolutions du draft à l'IETF, s'est nommé syntax, flavor, processor...

Des valeurs sont interdites dans ce registre : Standard, Common et Markdown ne peuvent être enregistrés comme variantes. C'est parce que « une partie de la communauté » (en réalité Gruber seul) a protesté contre la volonté de déclarer une variante particulière comme étant « standard » ou « officielle ».

Et si on veut ajouter une entrée à ce registre des variantes de Markdown ? La politique d'enregistrement est le « Premier Arrivé, Premier Servi » du RFC 5226, donc très légère. Il suffit d'indiquer deux-trois trucs sur la variante et roulez, jeunesse. Dans des versions initiales de ce RFC, le gabarit d'enregistrement d'une variante était bien plus complexe, bien trop détaillé, avec des infos très volatiles comme currently maintained ou anticipated output types mais il est maintenant réduit à seulement cinq champs obligatoires.

Un des projets qui avaient été lancés était celui d'enregistrer non pas les noms des variantes mais leurs caractéristiques (« permet les notes de base de page », « permet la création automatique de liens hypertexte »). À la réunion IETF 90, la proposition était de pouvoir écrire des choses comme text/markdown;variations=footnotes,line_blocks pour désigner du texte Markdown utilisant les notes de bas de page et les blocs de lignes considérés comme un paragraphe. Une telle approche aurait nécessité la constitution d'un catalogue compliqué, et aurait imposé aux auteurs de garder trace de quelles extensions ils utilisent. Elle n'a finalement pas été retenue.

L'enregistrement d'un type MIME nécessite une analyse de ses risques de sécurité. Rien d'extraordinaire ici, le RFC note juste que du texte avec du marquage ne présente guère de risque (contrairement à un format comme TrueType qui inclut un langage de Turing). Attention toutefois : ce que le processeur Markdown ne comprend pas, il l'envoie verbatim dans le format de sortie (ce truc est souvent utilisé pour mettre du HTML spécifique, ou du JavaScript, lorsqu'on utilise Markdown pour produire des pages Web). Du logiciel malveillant peut donc être copié ainsi.

Et la section sur l'interopérabilité rappelle ce qui a été dit plus haut : les différents Markdown vont donner des résultats différents, d'autant plus différents qu'ils utilisent des techniques spécifiques d'une variante.

Et si on veut indiquer un point précis d'un document Markdown ? Contrairement à HTML, Markdown n'a pas d'identificateurs de fragments d'un texte (section 3 du RFC). Mais on peut réutiliser une partie de la syntaxe du RFC 5147 : en terminant un URI par #lines=N, on accède (si le logiciel client connait le RFC 5147) à la Nième ligne du document Markdown.

À noter qu'on peut écrire des RFC en Markdown : c'est expliqué dans le RFC 7328 et c'est utilisé, par exemple, pour ceux du groupe Human Rights Protocol Considerations de l'IRTF (ce groupe est typiquement moins geek que la moyenne de l'IETF/IRTF).

Un exemple plus important que l'exemple un peu artificiel test1.md que je donnais au début est mon rapport sur la panne DNS d'Oleane. On peut le traiter avec Pandoc et un Makefile comme :

TARGETS=panne-dns-oleane-2016.pdf panne-dns-oleane-2016.html

all: ${TARGETS}

%.pdf: %.md
	pandoc --latex-engine=xelatex -o $@ $^

%.html: %.md
	pandoc -o $@ $^

clean:
	rm -f ${TARGETS}
    

Markdown est souvent présent dans les « micro-éditeurs » qui permettent de remplir des documents via le Web. C'est le cas à GitHub où les gists dont le nom se termine par .md sont automatiquement convertis. C'est ainsi que j'ai fait un gist de ce rapport (cliquez sur le bouton Raw pour avoir le source).

Quelques lectures sur Markdown :


Téléchargez le RFC 7763


L'article seul

RFC 7816: DNS query name minimisation to improve privacy

Date de publication du RFC : Mars 2016
Auteur(s) du RFC : S. Bortzmeyer (AFNIC)
Expérimental
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 23 mars 2016


La meilleure façon de protéger les données contre la surveillance, c'est de ne pas avoir de données. Ce principe de base de la protection de la vie privée est souvent oublié. C'est pourtant un des deux piliers de la confidentialité, avec la protection technique des données. Le DNS a pendant longtemps transmis trop de données, et ce RFC décrit une technique qui va limiter les fuites, la QNAME minimisation, ou « réduction de la question posée ». (Il a depuis été remplacé par le RFC 9156.) Demandez à votre FAI ou à votre service informatique de l'activer !

Si vous regardez les vidéos sur le fonctionnement du DNS (comme celle-ci) ou lisez les textes expliquant « le DNS pour les nuls », vous y trouverez souvent une fausse explication de la résolution DNS, où les serveurs faisant autorité ne reçoivent que la question strictement nécessaire. Ainsi, dans la vidéo citée ci-dessus, le serveur de la racine reçoit une question où ne figure que le TLD. Mais la réalité du DNS, aujourd'hui, est tout autre : les serveurs faisant autorité reçoivent la totalité de question originale. Ainsi, si vous visitez www.alcooliques-anonymes.fr, la racine voit que vous vous intéressez à l'alcoolisme, alors que ce n'était nullement nécessaire pour son travail (puisqu'elle ne connait que les TLD). Si votre logiciel BitTorrent demande _bittorrent-tracker._tcp.domain.example, les serveurs faisant autorité pour .example sauront que vous faites du BitTorrent, alors qu'ils ne connaissaient que les domaines situés immédiatement sous .example. Le RFC 7626 décrit plus en détail les problèmes de vie privée liés au DNS.

Dans le dernier cas, pour que la résolution se passe bien, il aurait suffit de demander à la racine « quels sont les serveurs de noms de .example » et à ces serveurs « quels sont les serveurs de noms de domain.example ». C'est le principe de base de la QNAME minimisation.

Bien sûr, on pourrait chiffrer le trafic DNS (et le groupe de travail DPRIVE de l'IETF travaille précisément sur ce sujet). Mais cela ne protège que contre un tiers écoutant le réseau : les serveurs faisant autorité verraient quand même les données et pourraient en faire ce qu'ils veulent. C'est pour cela qu'un principe de base en matière de protection de la vie privée est de marcher sur deux jambes (RFC 6973) : minimiser les données envoyées et les protéger. Lorsqu'on parle de vie privée, pas mal d'informaticiens réagissent en criant « cryptographie ! » alors que celle-ci ne protège pas contre tout et notamment pas contre le serveur à qui on parle.

Et pourquoi est-ce que les résolveurs DNS envoyaient la question complète (full QNAMEQNAME veut dire Query NAME) ? Uniquement parce que la protection de la vie privée n'était pas tellement prise en compte à l'époque ? Pas uniquement : il y avait quelques raisons techniques spécifiques à l'époque (le RFC les détaille mais, surtout, il ne faut pas oublier que toutes les décisions concernant le DNS n'ont pas forcément été mûrement réfléchies).

La section 2 décrit la QNAME minimisation. Elle est mise en œuvre dans le résolveur DNS (aucun changement n'est fait dans le serveur faisant autorité, la QNAME minimisation ne change pas le protocole DNS). Avant, lorsqu'il recevait une requête demandant l'adresse IPv6 pour _foobar._tcp.sub.internautique.fr et qu'il connaissait les serveurs faisant autorité pour .fr, mais pas ceux faisant autorité pour internautique.fr, le résolveur envoyait à l'AFNIC une requête avec comme QNAME (Query NAME) le nom complet _foobar._tcp.sub.internautique.fr et comme QTYPE (Query TYPE) AAAA (indiquant une demande d'adresse IPv6). Désormais, le résolveur moderne qui met en œuvre la QNAME minimisation enverra une requête avec le QNAME internautique.fr et le QTYPE NS (demande des serveurs de noms). Plus rigoureusement, la requête est faite avec un QNAME qui est l'original, où on a retiré les premiers composants, jusqu'à un seul composant de plus que celui pour lequel on connait les serveurs faisant autorité.

Les experts en DNS ont noté un problème : il n'y a pas forcément un jeu de serveurs faisant autorité pour chaque composant. Si je prends www.st-cyr.terre.defense.gouv.fr, il n'y a par exemple aujourd'hui pas de serveurs de noms pour gouv.fr, ce sont ceux de .fr. En termes techniques, il n'y a pas de limite de zone (zone cut, cf. RFC 2181, section 6) à chaque composant. Dans le cas de ce dernier nom, il y a une limite de zone entre la racine et .fr, une autre entre fr et defense.gouv.fr mais pas entre .fr et gouv.fr. Un résolveur qui veut faire de la QNAME minimisation doit donc tenir compte des limites de zone. S'il valide avec DNSSEC, pas de problème, il les connait déjà, car leur connaissance est nécessaire au bon fonctionnement de DNSSEC. Sinon, il doit les trouver tout seul, par exemple avec l'algorithme de l'annexe A.

Est-ce un changement « légal » du fonctionnement du résolveur DNS ? La section 4 discute ce problème et conclut que oui. La QNAME minimisation est permise par les RFC existants (RFC 1034, section 5.3.3 et RFC 1035, section 7.2). C'est un changement unilatéral de la part du résolveur, ne nécessitant pas de changement dans les serveurs faisant autorité. Comme c'est un changement unilatéral, différents résolveurs pourront choisir de la mettre en œuvre de façon légèrement différente. L'annexe B décrit certaines de ces alternatives, comme d'utiliser des requêtes « traditionnelles » avec le nom de domaine complet, au démarrage du résolveur, attendant que le cache soit peuplé pour passer à la QNAME minimisation, qui préserve la vie privée mais peut nécessiter davantage de paquets.

La QNAME minimisation ne change pas le protocole DNS. Elle ne pose donc pas de problème avec les vieux serveurs. En théorie car, en pratique, il existe pas mal de serveurs incorrects qui ne suivent pas les règles et poseront quelques problèmes (section 3 du RFC, voir aussi un intéressant exposé et un « storify » d'une discussion.) Le problème n'est en général pas dû aux serveurs en logiciel libre sérieux qui forment l'essentiel de l'infrastructure du DNS (BIND, NSD, Knot...) mais plutôt aux appliances boguées que certains s'obstinent à placer devant des serveurs qui marcheraient parfaitement autrement.

C'est par exemple le cas de certains répartiteurs de charge qui répondent aux requêtes pour certains QTYPE mais qui échouent lorsque le QTYPE vaut NS (répondant, par exemple REFUSED). Pire, certains ne répondent pas du tout, comme ceux de www.ratp.fr. Il s'agit bien d'une bogue, et qui cause plein de problèmes, pas seulement à la QNAME minimisation.

Un autre problème est celui des serveurs bogués (comme djbns) qui ne réagissent pas correctement aux ENT. Qu'est-ce qu'un ENT ? Un Empty Non-Terminal (terme décrit dans le RFC 8499, section 7) est un domaine qui n'a pas d'enregistrements DNS mais qui a des sous-domaines qui en ont. gouv.fr, cité plus haut, est un ENT mais ceux-ci sont particulièrement fréquents sous ip6.arpa. Normalement, la bonne réponse à un ENT est le code NOERROR, sans enregistrements (ce qu'on appelle parfois NODATA, bien que ce dernier ne soit pas un code de retour explicite dans le DNS). Mais certains serveurs boguées répondent à la place NXDOMAIN, code qui indique normalement que le domaine n'existe pas (ce qui est faux). Voici ce que répond djbdns à une requête sur l'ENT temporary.cr.yp.to :


% dig A temporary.cr.yp.to
...
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 23636

    

C'est bien un ENT puisqu'il y a des noms en dessous (par exemple pairings.temporary.cr.yp.to). Le résolveur qui se fierait à ce NXDOMAIN croirait alors que sa recherche est terminée et que le nom demandé n'existe pas. C'est pour cela que les mises en œuvre existantes de la QNAME minimisation ont des comportements spécifiques pour les réponses NXDOMAIN, pour contourner cette bogue.

La protection de la vie privée fait qu'on enverra moins de données. C'est bien le but. Résultat, les serveurs faisant autorité et les sniffeurs recevront moins d'information. Cela peut gêner certains gros silos de données, qui exploitaient cette information.

Et les performances ? Elles seront parfois meilleures et parfois pires, avec la QNAME minimisation. Meilleures car le résolveur enverra moins de requêtes aux serveurs faisant autorité. Aujourd'hui, si un résolveur reçoit trois requêtes successives, pour A.example, B.example et C.example, les trois requêtes seront envoyées aux serveurs racine, et donneront toutes les trois un NXDOMAIN (puisque .example n'est pas délégué). Avec la QNAME minimisation, seule la première requête déclenchera une demande à la racine, pour le nom example. Cela suffira au résolveur.

Par contre, les performances peuvent se dégrader dans certains cas. Si un nom comporte beaucoup de composants (c'est fréquent dans ip6.arpa), la recherche initiale des limites de zone nécessitera bien plus de paquets. Ceci dit, cela ne durera que le temps de remplir le cache, tout ira plus vite après, une fois que le résolveur connaitra les limites de zone.

Ce RFC est issu du projet « DNS privacy », lancé initialement au CENTR, puis passé à l'IETF (le premier RFC de ce projet avait été le RFC 7626 ; comme lui, cette idée de QNAME minimisation était née dans un avion de la KLM).

À noter que Verisign a un brevet dont ils prétendent qu'il couvre la QNAME minimisation. Ils promettent une licence (attention, le diable est dans les détails) gratuite et non-discriminatoire. Ces brevets ont bien perturbé la réflexion du groupe de travail. Personnellement, je pense que ce brevet n'a pas de sens : l'idée de QNAME minimisation est évidente et avait déjà été discuté plusieurs fois, mais sans laisser de trace écrite précise, ce qui permet à Verisign de prétendre qu'il n'y a pas de prior art. Ce n'est sans doute pas un hasard si les deux premières mises en œuvre de la QNAME minimisation ont été faites en Europe, où il n'y a (normalement) pas de brevet logiciel. Ceci dit, lors des discussions sur la licence de ces brevets, en marge de la réunion IETF d'Honolulu, c'est Verisign qui a payé les boissons, reconnaissons-leur ce mérite.

La QNAME minimisation est mise en œuvre dans Unbound et dans le résolveur Knot (ce dernier n'étant pas encore officiellement publié). Pour Knot (qui le fait par défaut), voici le résultat vu par tcpdump d'une requête dig -x d'une adresse IPv6. Par exemple, le serveur racine n'a reçu qu'une demande pour .arpa. Notez aussi que Knot fait varier la casse (une protection contre certains empoisonnements) :

02:36:39.673268 IP6 2400:8900::f03c:91ff:fe69:60d3.54216 > 2001:e30:1c1e:1::333.53: 38773% [1au] NS? aRpA. (33)
02:36:40.114074 IP6 2400:8900::f03c:91ff:fe69:60d3.59934 > 2001:dc3::35.53: 22056% [1au] NS? Ip6.aRPa. (37)
02:36:40.428545 IP6 2400:8900::f03c:91ff:fe69:60d3.47793 > 2001:500:86::86.53: 43002% [1au] NS? 2.ip6.arPA. (39)
...

Pour se protéger contre les serveurs bogués dont je parlais plus haut (ceux qui répondent NXDOMAIN en cas d'ENT), Knot réessaie avec le QNAME complet lorsqu'il reçoit un NXDOMAIN (les deux dernières lignes). Mauvais pour la vie privée mais sans doute nécessaire aujourd'hui (ici, par la faute d'Akamai) :

02:34:45.050913 IP 106.186.29.14.51228 > 128.175.13.17.53: 24014% [1au] A? WwW.UpENn.edU. (42)
02:34:45.227102 IP 128.175.13.17.53 > 106.186.29.14.51228: 24014*- 2/0/1 CNAME www.upenn.edu-dscg.edgesuite.net., RRSIG (270)
02:34:45.228413 IP6 2400:8900::f03c:91ff:fe69:60d3.46525 > 2001:503:231d::2:30.53: 52576% [1au] NS? edGeSUItE.NEt. (42)
02:34:45.297319 IP6 2001:503:231d::2:30.53 > 2400:8900::f03c:91ff:fe69:60d3.46525: 52576- 0/17/15 (1034)
02:34:45.298284 IP 106.186.29.14.45604 > 23.61.199.64.53: 22228 [1au] NS? EdU-DScG.EdGesUITe.nET. (51)
02:34:45.373238 IP 23.61.199.64.53 > 106.186.29.14.45604: 22228 NXDomain*- 0/1/1 (114)
02:34:45.373795 IP 106.186.29.14.34320 > 72.246.46.66.53: 1355 [1au] A? WWW.UPenN.edu-dSCG.EdgESuItE.net. (61)

Un autre exemple de ce repli sur les requêtes classiques est donné ici, lorsque je demande www.long.verylong.detail.example. Comme le TLD .example n'existe pas, Knot débraye hélas la QNAME minimisation :

20:08:49.615421 IP6 2400:8900::f03c:91ff:fe69:60d3.51723 > 2001:1398:1:21::8001.53: 19881% [1au] NS? ExaMpLE. (36)
20:08:49.900009 IP6 2400:8900::f03c:91ff:fe69:60d3.59917 > 2001:6d0:6d06::53.53: 40708% [1au] AAAA? www.LONg.VeRylONG.DEtaIl.eXamPLE. (61)

Même chose avec un ENT où la réponse est pourtant correcte. Knot se méfie et réessaie sans QNAME minimisation :

20:14:15.479872 IP6 2400:8900::f03c:91ff:fe69:60d3.45418 > 2001:67c:1010:11::53.53: 18200% [1au] NS? gOUV.Fr. (36)
20:14:15.740424 IP 106.186.29.14.33850 > 194.0.36.1.53: 54260% [1au] A? www.ST-cYr.TerRE.DeFeNSe.GouV.fR. (61)

Lorsque le cache commence à être rempli, Knot a besoin de moins de requêtes. Ici, je lui ai demandé l'adresse de www.bortzmeyer.org, et il connaissait déjà les serveurs de .org, il passe donc directement à la question « quels sont les serveurs de noms de bortzmeyer.org ? » :

20:08:20.420757 IP 106.186.29.14.41889 > 199.249.120.1.53: 39126% [1au] NS? bOrtzMEYeR.oRg. (43)
20:08:20.941797 IP 106.186.29.14.35536 > 217.70.190.232.53: 33709% [1au] AAAA? Www.bOrtZmEyER.Org. (47)

Unbound a la QNAME minimisation depuis la version 1.5.7 (sortie en décembre 2015, cf. l'historique de ce travail). Ce n'est pas activé par défaut, il faut mettre dans la configuration :

server:
    qname-minimisation: yes

(Un pcap est disponible.) Pour vérifier si votre résolveur met bien en œuvre la QNAME minimisation, vous pouvez tester avec le domaine qnamemintest.internet.nl. Ici, le résolveur est un Unbound récent :

% dig +nodnssec +short TXT qnamemintest.internet.nl
a.b.qnamemin-test.internet.nl.
"HOORAY - QNAME minimisation is enabled on your resolver :)!"

Avec un résolveur traditionnel (ici, Verisign Public DNS, qui utilise Unbound mais une vieille version) :

% dig @64.6.64.6 +nodnssec +short TXT qnamemintest.internet.nl
a.b.qnamemin-test.internet.nl.
"NO - QNAME minimisation is NOT enabled on your resolver :("

À noter qu'à la réunion de l'OARC à Buenos Aires, Ralph Dolmans a présenté un très intéressant exposé technique sur la mise en œuvre de la QNAME minimisation dans Unbound.

Questions articles sur la QNAME minimisation, notez celui de Robert Graham.


Téléchargez le RFC 7816


L'article seul

RFC 7764: Guidance on Markdown: Design Philosophies, Stability Strategies, and Select Registrations

Date de publication du RFC : Mars 2016
Auteur(s) du RFC : S. Leonard (Penango)
Pour information
Réalisé dans le cadre du groupe de travail IETF appsawg
Première rédaction de cet article le 23 mars 2016


Ce RFC est un complément du RFC 7763, qui enregistrait le type MIME text/markdown. Il contient tout ce qui ne tenait pas dans le RFC original, c'est donc un pot-pourri de considérations philosophiques, de descriptions des variantes les plus courantes de Markdown, de techniques de stockage local de contenus en Markdown...

Le RFC 7763 était plus sec, contenant uniquement ce qui était nécessaire à l'enregistrement de text/markdown. Cet autre RFC est plus disert, expliquant d'abord (section 1) la philosophie de Markdown, et ses usages. Rappelons donc que Markdown est un format de marquage du texte. Lorsqu'on veut stocker des textes (romans, rapports techniques, articles scientifiques, lettres d'amour, etc) sur un système informatique, on a plusieurs solutions : elles vont du texte brut à un format binaire. Le texte brut est le stockage des seuls caractères Unicode (cf. RFC 6838, section 4.2.1 : le texte est distribué sur l'Internet avec un type MIME text/quelquechose, par exemple text/plain pour le texte brut). Son gros avantage est qu'il est lisible et modifiable avec n'importe quel logiciel. Bon, en fait, le texte brut n'est jamais tout à fait brut. Il contient quelques caractères de contrôle comme le saut de ligne ou la marque d'un nouveau paragraphe (U+2029 en Unicode, mais ce séparateur de paragraphe n'est que rarement géré par les logiciels).

À l'autre extrémité se trouve les formats binaires : lisibles et modifiables uniquement par des applications spécifiques (et c'est pour cela qu'ils sont distribués avec le type MIME application/quelquechose).

Entre les deux se trouvent le texte formaté ou marqué. Il s'agit à première vue de texte brut mais il inclut en fait quelques marques qui ont une signification non prévue par le jeu de caractères. Un exemple classique est la mise en évidence qui, en Markdown, se fait en encadrant le texte avec des étoiles : « il est *très* important de comprendre que... » Le texte reste lisible sans logiciel spécifique (d'autant plus qu'ici, Markdown reprend une ancienne convention d'écriture largement utilisée sur l'Internet). Et n'importe quel éditeur (et n'importe quel clavier) permet de créer un tel texte.

On sépare souvent les formats de texte marqués en formats stricts (markup) et formats légers (lightweight markup). Les premiers sont plus proches des formats binaires, dans la mesure où ils ont des marques bien séparées du texte, et suivent une syntaxe rigide. Ce sont par exemple XML et LaTeX. Cette syntaxe rigide permet de vérifier la qualité technique du document et mène à une meilleure interopérabilité. Mais elle peut être pénible pour les utilisateurs débutants ou occasionnels. Plus proches du texte brut, les formats de texte marqué légers ont des marques plus discrètes, et ont souvent une syntaxe moins formelle, plus tolérante (un cas extrême est Markdown, qui ne connait même pas la notion d'erreur de syntaxe). Ils sont conçus pour être facilement accessibles au nouvel utilisateur (ou à celui qui n'a pas pratiqué depuis longtemps). Jeff Atwood qualifiait ces formats légers d'« humains ».

Markdown est issu d'un langage originellement développé par John Gruber (et Aaron Swartz). Il a été rapidement un grand succès, notamment pour les tâches simples (comme de saisir un commentaire ou un rapport de bogue dans un formulaire Web). Et il a connu de nombreuses extensions. Beaucoup de programmes et de langages savent traiter le Markdown, chacun avec sa variante particulière.

Markdown est clairement dans le camp de l'« informalité ». Un des événements fondateurs fut un problème avec de nombreux flux de syndication rendus invalides juste par un article contenant du code incorrect (la norme XML dit bien qu'une fois qu'une erreur apparait dans un fichier XML, le processeur ne doit pas continuer). Avec Markdown, cela ne risque pas d'arriver, tout texte est du Markdown légal. Cela ressemble au fameux principe de robustesse des protocoles réseau. (À noter que ce principe a été suivi, en pratique, par la plupart des navigateurs Web, lorsqu'il s'agit d'analyser du HTML. Résultat, les auteurs se sont habitués à taper n'importe quoi et le Web est aujourd'hui une poubelle de fichiers HTML bourrés d'erreurs.) Lorsqu'on soumet un fichier Markdown à un processeur, cela « marche » toujours. Si on n'est pas satisfait du résultat, on modifie le source et on réessaie (cf. « The Talk Show: Ep. 88: 'Cat Pictures' (Side 1) ».) Pas de processus de validation, comme en XML ou HTML strict, seul le résultat compte.

Malgré ou bien à cause de ce principe, Markdown est un grand succès. On le trouve utilisé partout et il est probablement le plus populaire des langages de marquage « légers ». On peut l'éditer avec n'importe quel logiciel et lire le source, même sans avoir subi aucun apprentissage de sa syntaxe. Des gens utilisent Markdown pour des articles scientifiques, l'écriture de scénarios, ou pour faire des maths, le domaine qui était autrefois le bastion de LaTeX. (Personnellement, je m'en sers pour les rapports de bogue sur GitHub, les README de logiciels, les rapports techniques internes à mon employeur, LaTeX ou DocBook prenant le relais pour les choses plus « sérieuses ». Markdown avec les sites qui le gèrent permet aussi de faire du mini-blogging très simplement et très rapidement. Regardez aussi le témoignage de Yann Houry.)

Depuis le RFC 7763, il existe un type MIME pour identifier Markdown, text/markdown. (Une extension de nom de fichier comme .md ne suffit pas : tout le contenu n'est pas forcément dans des fichiers.) Un seul type MIME décrit toutes les variantes puisque n'importe quel processeur pourra traiter n'importe quelle variante (même si le résultat ne sera pas toujours celui voulu.) À noter que la plupart des variantes de Markdown n'ont pas de mécanisme pour mettre les métadonnées : il faut les placer à l'extérieur.

Comment préserver ce type MIME lorsque du contenu Markdown est copié sur l'Internet ? Parfois, la copie ne préserve pas cette information et Markdown n'a pas l'équivalent du <?xml version="1.0"> qui, au début des contenus en XML, indique sans ambiguité qu'il s'agit de XML (il a été proposé de l'introduire mais cela peut casser les mécanismes de métadonnées existants). Utiliser le contexte (le répertoire où se trouve un fichier, par exemple...) est casse-gueule car, justement, l'envoi d'un document fait facilement perdre le contexte. La section 2 du RFC propose et discute plusieurs stratégies. Utiliser le nom de fichier, lorsqu'on passe par des fichiers, est possible. mon-roman.md est un texte en Markdown, on le sait par l'extension. Et la variante ? On peut l'indiquer avant, par exemple mon-roman.pandoc.md si le texte est écrit dans la variante Pandoc. Si le système de fichiers permet de stocker des attributs ou métadonnées, c'est une autre bonne solution.

Mais il y en a d'autres. Une solution, suggérée par le RFC 6533, est de stocker les métadonnées et notamment l'en-tête MIME dans un fichier séparé, conventionnellement nommé. Si le fichier texte est mon-roman.md, le fichier des métadonnées pourrait être mon-roman.md.headers.

Ou alors dans le même fichier ? L'idée est de transformer le fichier Markdown en un fichier au format IMF (Internet Message Format, spécifié dans le RFC 5322) en mettant des en-têtes d'abord, puis le contenu en Markdown :

MIME-Version: 1.0
Content-Type: text/markdown; charset=utf-8
Date: Wed, 10 Feb 2016 20:59:06 +0100 (CET)
    
Exemple d'un fichier « armé »
=============================

Notez la ligne vide qui sépare les en-têtes du corps.

Il est *important* que son extension ne soit pas .md ou .markdown, ce
n'est plus du Markdown pur mais de l'IMF, son extension doit donc être
.eml ou .msg.

...
    

Le RFC contient plein d'autres stratégies rigolotes pour résoudre ce problème. Par exemple, on pourrait, lors de la réception, voire de l'envoi, d'un contenu en Markdown, générer/envoyer un script qui contienne les commandes permettant de le traiter convenablement. Ou on pourrait carrément envoyer le résultat du traitement, et pas le Markdown : si on veut juste que le destinataire puisse lire, pas la peine de lui envoyer le « source », on pourrait juste lui transmettre le XHTML (je ne suis pas sûr d'être d'accord avec cette curieuse idée : un des gros avantages de Markdown est qu'il est lisible même si on n'a aucun logiciel spécifique, et si on n'a jamais entendu parler de ce format).

Cette section 2 se termine avec le cas des VCS. Subversion offre un excellent mécanisme de stockage et de versionnement des méta-données. Il suffit donc de définir la métadonnée standard svn:mime-type et on ne risque plus de perdre cette information :

% svn propset svn:mime-type text/markdown mon-roman.md 
property 'svn:mime-type' set on 'mon-roman.md'

% svn commit -m "Type indiqué" mon-roman.md
...
    

Hélas, git n'a, lui, aucun moyen propre de stocker les métadonnées. Il faut donc recourir à une autre des stratégies mentionnées plus haut (fichier d'en-têtes avec un nom conventionnel, extension du fichier, etc).

La section 3 de notre RFC est consacrée aux formulaires d'enregistrement des différentes variantes de Markdown, désormais mémorisées à l'IANA. Cette section est utile si vous voulez vous renseigner sur une variante particulière, mais aussi si vous avez développé votre propre variante (sans doute une mauvaise idée mais les programmeurs adorent réinventer la roue) et que vous voulez l'enregistrer à l'IANA. Vous pouvez alors utiliser les cas de cette section comme exemples concrets, avant d'écrire votre propre demande.

Prenons par exemple la variante que j'utilise le plus souvent, Pandoc. Contrairement au Markdown originel, elle ne vise pas uniquement la génération de HTML mais également des tas d'autres formats de sortie. Elle a des tas d'extensions par rapport à l'original, comme les tableaux ou bien les notes de bas de page. Sa fiche contient :

   Identifier: pandoc

   Name: Pandoc

   ...
   
   Extensions to turn off (on by default):

                   escaped_line_breaks
                   blank_before_header
                   header_attributes
		   ...
		   
   References:
   <http://johnmacfarlane.net/pandoc/README.html#pandocs-markdown>

   Contact Information:
     (individual) Prof. John MacFarlane <jgm@berkeley.edu>
                              <http://johnmacfarlane.net/>
    

Les autres variantes enregistrées via cette section 3 sont MultiMarkdown, GitHub, Fountain, CommonMark, Markdown for RFCs, Pandoc for RFCs (RFC 7328) et PHP Markdown (utilisé par plusieurs CMS comme Drupal).

La section 4 de notre RFC fournit des exemples de ces différentes variantes et de ce qu'elles apportent. Par exemple, la variante GitHub apporte la transformation automatique des URL en liens hypertexte.


Téléchargez le RFC 7764


L'article seul

Exposé « Objets qui communiquent entre eux ou bien esclaves du cloud ? » aux journées FedeRez

Première rédaction de cet article le 19 mars 2016
Dernière mise à jour le 27 juin 2016


FedeRez est la fédération nationale des associations d'étudiants qui gèrent des réseaux informatiques. Elle tient des journées annuelles et, à celles de 2016 dans un coin perdu de la grande banlieue parisienne, j'ai fait un exposé sur le thème « Objets qui communiquent entre eux ou bien esclaves du cloud ? ».

Voici les transparents de mon exposé :

L'enregistrement vidéo est disponible ici.


L'article seul

RFC 7776: IETF Anti-Harassment Procedures

Date de publication du RFC : Mars 2016
Auteur(s) du RFC : P. Resnick (Qualcomm Technologies), A. Farrel (Juniper Networks)
Première rédaction de cet article le 13 mars 2016


La question du harcèlement dans le cadre des activités professionnelles (ou autres, d'ailleurs) est maintenant largement reconnue comme cruciale et toute organisation doit se demander « que dois-je faire ? » L'IETF décrit dans ce RFC ses procédures à ce sujet, avec notamment le rôle de l'ombudsteam, l'équipe de justice privée qui doit traiter les cas de harcèlement signalés.

Tout groupe humain est évidemment confronté au problème des comportements négatifs, les trolls, par exemple. L'IETF a eu sa dose, bien que mon impression soit que le problème est nettement moins grave que dans certains groupes, comme chez certains gamers. Mais c'est difficile à dire, c'est un domaine où on n'a pas facilement des statistiques précises. L'IETF a donc son « guide des bonnes manières » (RFC 7154), et les documents de cuisine procédurale interne (RFC 2418 et RFC 3934) prévoient la gestion des cas les plus sérieux. Ces documents se focalisent sur les comportements négatifs qui impactent directement le travail de l'IETF, et le mettent en péril (par exemple, un troll qui assomme le groupe de travail de longs messages répétés en quantité et n'apportant pas de contenu). Mais il y a aussi, et c'est le sujet de ce nouveau RFC, des pratiques négatives qui ne gênent pas directement l'IETF mais peuvent pourrir la vie des participant·e·s qui en sont victimes, par exemple du harcèlement sexuel lors d'une réunion physique. Ces pratiques sont évidemment interdites (déclaration de l'IESG) mais il restait à préciser quoi faire en cas de violation de cette règle.

Il faut noter (et c'est oublié dans la plupart des ces guides de bonnes manières d'origine états-unienne qui fleurissent dans beaucoup de conférences informatiques) que le harcèlement est déjà interdit par la loi dans la plupart des pays où l'IETF tient ses réunions. Comme le note le RFC, les règles de l'IETF ne remplacent pas la loi. Nul besoin d'une déclaration de l'IESG pour interdire, par exemple, les insultes racistes ou le harcèlement sexuel à une réunion IETF. C'est pour cela que la plupart de ces codes of conduct sont inutiles. Celui de l'IETF est très orienté par ses origines états-uniennes, mêlant la demande d'un comportement « professionnel » (comme si le harcèlement n'était fait que par des amateurs) et le puritanisme (« sexual imagery in public presentations », sachant qu'aux États-Unis, la vue d'un torse nu est déjà de la sexual imagery).

La déclaration de l'IESG citée plus haut donne une définition du harcèlement, définition forcément très large (il y a hélas bien des formes de harcèlement, et bien des raisons pour lesquelles un·e participant·e à l'IETF peut être pris·e pour cible). Le problème est-il fréquent à l'IETF ? Je n'ai jamais entendu parler d'un cas précis (contrairement aux cas documentés qui sont arrivés à DEFCON), mais, évidemment, toutes les victimes ne se signalent pas publiquement et le harcèlement est donc très difficile à mesurer scientifiquement.

En première ligne dans ce RFC est l'ombudsteam. Je n'ai pas essayé de traduire ce terme, d'origine suédoise (ombudsman, devenu en anglais ombudsperson pour éviter d'exclure les femmes, puis ombusteam pour marquer son caractère collectif). Disons que c'est une équipe chargée de gérer les cas d'accusation de harcèlement, et c'est la principale ligne de défense de l'IETF dans ces cas.

L'ombudsteam est composé d'au moins trois personnes. Elles sont désignées - pour deux ans, renouvelable - par le président de l'IETF (actuellement Jari Arkko), éventuellement après consultations. Il est recommandé de suivre une certaine diversité (éviter un ombudsteam qui serait uniquement composé d'hommes blancs d'âge mûr et issus des classes dominantes, comme l'est l'auteur de ces lignes...) et de faire en sorte qu'au moins un des membres soit un participant actif à l'IETF. Il n'est donc pas nécessaire, ni même souhaitable, que l'ombudsteam soit sélectionné uniquement en interne. L'idéal, demande le RFC, est que l'ombudsteam rassemble des compétences variées, par exemple des gens qui connaissent très bien l'IETF, des gens qui sont des experts en médiation et en gestion de conflits, etc.

Les membres de l'ombudsteam ne sont pas payés pour leur activité. (À mon humble avis, cela est en contradiction avec l'objectif d'avoir de la diversité : s'ils ne sont pas payés, on n'aura que des gens favorisés socialement.)

Si quelqu'un n'est pas content de la désignation de telle ou telle personne, il peut en appeler à l'IESG (section 6.5.4 du RFC 2026).

L'ombudsteam dispose d'une page Web officielle. La liste des membres du ombudsteam a été publiée deux semaines après le RFC.

Une fois l'ombudsteam constitué, que se passe-t-il en cas de plainte (section 4) ? La victime, ou un témoin du harcèlement, contacte l'ombudsteam, en présentiel ou bien par courrier (ombuds@ietf.org). Tout participant·e à l'IETF peut contacter l'ombudsteam, soit pour une plainte formelle, soit pour solliciter un avis.

Les pratiques de l'ombudsteam seront en grande partie définies par l'ombudsteam, qui est supposé en discuter avec l'IESG puis publier ses principes de fonctionnement. Au minimum, le RFC demande à l'ombudsteam que :

  • Les membres de l'ombudsteam soient présents aux réunions physiques de l'IETF, pour permettre des prises de contact AFK.
  • L'ombudsteam travaille dans la plus stricte confidentialité. Il s'agit de protéger aussi bien le ou la signaleur d'un harcèlement (qui peut hésiter à se plaindre, par exemple par crainte de représailles) que celui ou celle qui en est accusé, peut-être à tort (la section 8 revient en détail sur cette exigence de confidentialité). C'est une exception à la règle habituelle de l'IETF comme quoi tout doit se dérouler en public (une autre exception est le NomCom, cf. RFC 7437).
  • L'ombudsteam ne doit évidemment prendre aucune décision sans avoir entendu les deux parties - pas seulement celle qui signale le harcèlement.
  • Si les accusations s'avèrent infondées, aucune sanction ne doit être prise contre celui ou celle qui a signalé à tort, mais de bonne foi. Autrement, les problèmes ne seraient jamais remontés.
  • L'ombudsteam doit garder des traces écrites de toute son activité, ce qui n'est pas techniquement trivial, vues les exigences de confidentialité.

Bon, donc, des gens signalent des problèmes à l'ombudsteam, l'ombudsteam investigue, se réunit, discute et à la fin, il peut décider quoi ? La section 5 décrit les solutions disponibles pour l'ombudsteam :

  • Dans certains cas, les processus existants avant ce RFC peuvent être utilisés (voir par exemple les RFC 2418 et RFC 3934).
  • Dans les autres cas, l'ombudsteam doit chercher si une médiation entre les parties est possible, débouchant sur un accord qui empêchera la répétition des faits.
  • Dans les cas les plus graves, l'ombudsteam peut décider de sanctions, comme l'exclusion de tout ou partie des activités de l'IETF. Par exemple, le participant convaincu de harcèlement peut être banni d'une réunion et/ou des futures réunions.

Ces sanctions les plus sérieuses peuvent provoquer des problèmes délicats si le harceleur occupait une position de responsabilité à l'IETF. Bien sûr, ces personnes en position de responsabilité (président d'un groupe de travail, par exemple) n'ont pas d'immunité. Mais il ne faut pas non plus que l'ombudsteam puisse empêcher, de facto, un responsable de tenir son rôle. Une possibilité est, dans ce cas, que l'ombudsteam fasse jouer les procédures de révocation normales de l'IETF (RFC 7437, notamment la section 7). Dans le cas d'un poste qui passe par le NomCom (Nominating Commitee), l'ombudsteam demande alors le lancement de la procédure de révocation, et n'a pas besoin pour cela d'une pétition de 20 participants (RFC 7437, section 7.1). Dans le cas de poste pourvus par l'ISOC, l'IAB ou un autre organisme, l'ombudsteam peut demander à cet organisme la révocation du harceleur. Idem si le poste a été pourvu via un directeur de zone (AD, Area Director) ou un président de groupe de travail.

On le voit, l'ombudsteam dispose d'un large pouvoir, sans contrôle (en raison de l'obligation de confidentialité) et la section 5.1 du RFC dit bien que les organismes à qui l'ombudsteam demande une révocation doivent, sauf raison très sérieuse, donner suite à cette demande. Mais que se passe-t-il si quelqu'un est en désaccord avec l'ombudsteam ? La section 6 traite ce problème.

Après discussion avec l'ombudsteam la question doit être remontée au président de l'IETF. Si celui-ci préfère ne pas être impliqué (voir par exemple la section 7, sur les conflits d'intérêt), il peut demander à l'IESG de désigner un de ses membres pour jouer son rôle (les protocoles réseaux, c'est compliqué, mais la bureaucratie interne de l'IETF, c'est pire). Si la discussion entre le président et l'ombudsteam ne débouche pas sur une solution, un mécanisme formel d'appel est prévu. Le groupe qui étudiera l'appel est composé du président de l'IETF et de deux membres de l'IESG qu'il·elle a choisi. Ce groupe peut évaluer la question sur le fond. S'il y a un problème de forme, il existe un dernier mécanisme d'appel auprès de l'ISOC. Notez que les procédures ont été légèrement mises à jour par le RFC 8716.

Le RFC se termine par une jolie citation d'Aung San Suu Kyi : « Human beings the world over need freedom and security that they may be able to realize their full potential. »


Téléchargez le RFC 7776


L'article seul

RFC 7721: Privacy Considerations for IPv6 Address Generation Mechanisms

Date de publication du RFC : Mars 2016
Auteur(s) du RFC : A. Cooper (Cisco), F. Gont (Huawei Technologies), D. Thaler (Microsoft)
Pour information
Réalisé dans le cadre du groupe de travail IETF 6man
Première rédaction de cet article le 11 mars 2016


Il y a eu pas mal de trollage depuis les débuts d'IPv6, au sujet de son mécanisme de génération d'adresses, et des risques qu'il pouvait poser pour la vie privée. Ces débats étaient souvent motivés par une inquiétude de la nouveauté, davantage que par une réelle analyse des menaces. Plus d'un amateur a écrit sur les forums qu'IPv6 était un complot contre la vie privée, alors même que son navigateur Web faisait fuiter bien davantage d'informations personnelles. Ce nouveau RFC analyse l'état actuel des mécanismes de génération des adresses IPv6, leurs avantages et leurs inconvénients en terme de protection de la vie privée, et les compromis à faire lors du choix d'un mécanisme donné.

IPv6 permet des nouvelles façons d'allouer des adresses. Outre les méthodes qui existaient déjà en IPv4, comme l'allocation statique, et celle via DHCP, il permet une méthode dite « sans état ». Dans ce cas, le routeur annonce le préfixe IP du lien, et les machines ajoutent à ce préfixe un suffixe qui les identifie de manière unique sur le lien. Ainsi, on peut obtenir une adresse globale sans qu'un serveur ait besoin de maintenir un état des allocations faites.

Au début d'IPv6, des formulations malheurseuses dans les RFC ont pu faire croire que ce suffixe, l'IID (Interface IDentifier) était forcément dérivé de l'adresse MAC de la machine, mais cela n'a jamais été obligatoire (le RFC 7136 a clarifié ce point). D'autre part, on peut noter que préfixe et suffixe ont en général la même longueur, qui est de 64 bits, pour les raisons expliquées dans le RFC 7421.

Aujourd'hui, la liste complète des mécanismes possibles d'allocation d'adresses IPv6 est :

  • Manuelle, en fixant l'IID en partant de 1 (méthode dite low byte), ou bien selon une adresse IPv4 de la machine, ou encore selon un port (serveurs DNS dont l'adresse IPv6 se termine par :53...), ou enfin en utilisant un mot rigolo, en profitant de l'hexspeak.
  • Via la SLAAC, Stateless Address Auto-Configuration, en fabriquant l'IID à partir de l'adresse MAC (RFC 2464), d'une clé cryptographique (RFC 3972), d'un nombre temporaire et donc changeant souvent (RFC 8981), ou d'une valeur stable dérivée de certaines caractéristiques du réseau d'accueil (RFC 7217). Et ce n'était que les méthodes normalisées, mais il y en a d'autres, par exemple chez Microsoft.
  • Via DHCP (RFC 8415). Notez que le serveur DHCP peut avoir de nombreux moyens de choisir une adresse pour chaque client : cela peut être statique ou dynamique.
  • Enfin, il y a les méthodes d'allocation des techniques de coexistence IPv4-IPv6. L'adresse v6 peut être dérivée de l'adresse v4 (RFC 6052), dérivée de l'adresse et du port (RFC 4380, dérivée de l'adresse et d'un identifiant d'un ensemble de ports (RFC 7596 et suivants)...

Parmi ces nombreuses méthodes, la méthode « SLAAC et IID dérivé de l'adresse MAC » est celle qui pose le plus de problèmes, côté vie privée. Pourquoi ? Parce que l'adresse MAC d'une machine est en général stable (sauf si on utilise un logiciel comme macchanger) même lorsque la machine se déplace. Si on se connecte à un pair sur l'Internet, depuis un certain réseau, le pair verra l'adresse IP source et, si on change de réseau, l'adresse MAC, donc l'IID, dans les 64 derniers bits de l'adresse IP, seront les mêmes et le pair verra donc qu'il s'agit de la même machine.

La section 3 de notre RFC décrit plus précisement les vulnérabilités de cette méthode. La première vulnérabilité est le risque de corrélation. Un pair avec qui on communique, ou bien un observateur du trafic réseau, peuvent se rendre compte que deux machines d'adresses IPv6 différentes sont en fait la même machine, en raison de l'égalité des deux IID. Comme on ne change pas de carte Ethernet tous les mois, la corrélation, dans le cas d'un IID fondé sur l'adresse MAC peut durer des années (cf. RFC 8981 pour l'analyse).

Bien sûr, on peut faire de la corrélation avec autre chose que les adresses MAC, comme l'illustre très bien le Panopticlick (voir aussi la section 5.2.1 du RFC 6973) et une bonne partie des critiques contre ce risque de corrélation avec les IID liés aux adresses MAC étaient juste du FUD anti-IPv6 (des gens qui critiquent le manque de vie privée avec IPv6 mais qui ne filtrent pas les cookies...) Mais cela n'interdit pas d'essayer de résoudre le problème.

Un autre risque est celui de la localisation. Si une machine garde le même IID en changeant de réseau, on peut la suivre à la trace. « Tiens, c'est encore elle, et, cette fois, elle est en Allemagne. Tiens, elle est maintenant à l'université de Berlin. » Cette attaque n'aurait pas marché en IPv4 où l'adresse attribuée est complètement différente à chaque fois.

Les adresses IPv6 dérivées de l'adresse MAC présentent un autre risque : on peut balayer le réseau à la recherche de machines à attaquer. Normalement, la taille de l'espace d'adresssage IPv6 rend le balayage complet irréaliste. Mais, si on sait que le réseau visé n'utilise, par exemple, que des Apple, on peut réduire le nombre de paquets à envoyer en disant au logiciel de balayage de n'utiliser que des adresses IPv6 dérivées d'adresses MAC ayant le préfixe Apple. Et cette possibilité est mise en œuvre dans les outils réels, par exemple avec l'option --tgt-ieee-oui de scan6. (Voir le RFC 7707 pour plus de détail sur le balayage en IPv6.)

Enfin, le fait que les adresses MAC aient un préfixe qui indique le fabricant (sauf si on a pensé à utiliser macchanger ou un logiciel équivalent) fournit une information qui peut être utile à un attaquant, en lui dévoilant le type de machines qu'on utilise.

Bien sûr, ces adresses IPv6 dérivées de l'adresse MAC sont minoritaires, et sont de moins en moins utilisées. Mais les alternatives ne sont pas toujours parfaites. La section 4 de notre RFC fait le point sur les solutions, et leurs propriétés. Les adresses temporaires du RFC 8981 sont la première solution à laquelle on pense. Elles sont typiquement utilisées pour les connexions sortantes, une adresse stable, dérivée de l'adresse MAC, restant en place pour les connexions entrantes. À noter qu'au début, les problèmes de vie privée étant supposés moins importants que les considérations opérationnelles de gestion des réseaux, les RFC demandaient que les adresses temporaires ne soient pas utilisées par défaut. Plusieurs systèmes, comme Windows, ont décidé à juste titre d'ignorer cette demande, et c'est ce qui explique que les adresses dérivées d'une adresse MAC soient aujourd'hui minoritaires dans les journaux des serveurs Internet (voir les mesures à la fin de cet article). L'ancienne recommandation a été abandonné et le RFC 6724 dit clairement qu'il faut utiliser les adresses temporaires par défaut.

D'autre part, comme l'adresse stable fondée sur l'adresse MAC demeure, en plus de l'adresse temporaire, les inconvénients liés au balayage « optimisé » du réseau demeurent.

Il faut aussi noter qu'il n'y a pas que l'IID (la partie droite de l'adresse IP) qui est révélatrice. Le préfixe (la partie gauche) peut l'être également. Par exemple, si on suivait le RFC 3314, qui recommande un préfixe unique par téléphone en GPRS, ce préfixe, s'il était attribué de manière stable, serait caractéristique d'un téléphone donné.

Un tableau au début de la section 4 résume la vulnérabilité des différents choix d'allocation d'adresses IPv6 aux différents risques indiqués en section 3 (corrélation, localisation, balayage et indication du vendeur). Par exemple, une adresse attribuée manuellement permet la corrélation, tant que cette adresse dure (ces attributions manuelles concernent en général les serveurs, pour lesquels les problèmes de vie privée sont nettement moins graves) et une adresse dérivée de l'adresse MAC permet la corrélation tant qu'on ne change pas la carte Ethernet ou Wifi (ou son adresse MAC, ce que les gens oublient souvent, mais qui est possible avec la plupart des cartes).

En revanche, les adresses temporaires ne permettent la corrélation que pendant la durée de vie de ces adresses (une journée, par défaut), et les adresses stables et opaques du RFC 7217 permettent la corrélation tant que la machine ne change pas de réseau mais la bloquent dès qu'on bouge.

Le tableau est explicité dans les sections suivantes :

  • Les adresses dérivées de l'adresse MAC sont sensibles aux quatre risques.
  • Les adresses configurées manuellement sont sensibles aux deux premiers risques (corrélation et localisation).
  • Des adresses générées cryptographiquement (par exemple en suivant le RFC 3972) sont en théorie vulnérables à la corrélation (puisqu'on garde la clé publique, et donc l'IID, très longtemps) mais cela peut être limité en suivant la section 7.3 du RFC 3972.
  • Les adresses stables et opaques du RFC 7217 sont vulnérables à la corrélation tant qu'on reste sur le même réseau. Si une machine utilisant ces adresses change de réseau, il n'y a plus de corrélation possible mais, si elle revient sur le réseau d'origine, ses correspondants la reconnaitront à nouveau.
  • Les adresses temporaires du RFC 8981 sont à l'abri des quatre vulnérabilités citées (ce qui est assez normal : elles sont conçues spécialement pour la vie privée). Il reste le cas du balayage : si l'adresse stable, utilisée pour les connexions entrantes, se fonde sur l'adresse MAC, certaines techniques de balayage peuvent encore s'utiliser. Il est donc recommandé d'utiliser le RFC 7217 ou équivalent pour générer l'adresse stable.

Enfin, la section 5 de notre RFC traite de divers problèmes liés à ce souci de vie privée. Par exemple, il rappelle que des adresses qui changent (telles les adresses temporaires du RFC 8981) peuvent être une plaie pour l'administration de réseaux et que certaines organisations vont donc les désactiver sur les postes de travail, et tant pis pour la vie privée.

Autre cas embêtant, il existe apparemment des suites de test IPv6 qui vérifient que l'adresse IPv6 est bien dérivée de l'adresse MAC. C'est évidemment une mauvaise idée et notre RFC demande que ces suites soient mises à jour.

À noter qu'il existe un outil pratique, addr6, qui fait partie du SI6 toolkit. Utilisant divers techniques (et heuristiques : il se trompe parfois), il vous dit à quelle catégorie appartient une adresse :

[L'adresse de base d'une machine]
% addr6 -a 2a01:ff41:916b:3bb0:ba27:ebff:feaa:78b9
unicast=global=global=ieee-derived=b8-27-eb

[Une des adresses temporaires de la même machine (c'est un FreeBSD avec
ipv6_privacy="YES" dans rc.conf]
% addr6 -a 2a01:ff41:916b:3bb0:810e:9c6d:341:e7a 
unicast=global=global=randomized=unspecified

[Un serveur public, d.nic.fr]
% addr6 -a 2001:678:c::1
unicast=global=global=low-byte=unspecified
    

Quelle est la situation aujourd'hui ? Quels types d'adresses sont utilisés par les machines IPv6 ? J'ai fait un petit test avec les visiteurs de mon blog (qui ne sont pas forcément représentatifs : vus les sujets traités sur ce blog, les visiteurs sont sans doute techniquement plus avancés que la moyenne)  :

% zgrep -h -E  '^[0-9]+:' /var/log/apache2/access.log* | awk '{print $1}' | \
         sort | uniq | addr6 -i -s   

** IPv6 General Address Analysis **

Total IPv6 addresses: 1997
Unicast:    1997 (100.00%)              Multicast:       0 (0.00%)
Unspec.:       0 (0.00%)

** IPv6 Unicast Addresses **

Loopback:           0 (0.00%)           IPv4-mapped:        0 (0.00%)
IPv4-compat.:       0 (0.00%)           Link-local:         0 (0.00%)
Site-local:         0 (0.00%)           Unique-local:       0 (0.00%)
6to4:               9 (0.45%)           Teredo:             0 (0.00%)
Global:          1988 (99.55%)

** IPv6 Interface IDs **

Total IIDs analyzed: 1997
IEEE-based:     230 (11.52%)            Low-byte:            323 (16.17%)
Embed-IPv4:       0 (0.00%)             Embed-IPv4 (64):     122 (6.11%)
Embed-port:       7 (0.35%)             Embed-port (r):        1 (0.05%)
ISATAP:           1 (0.05%)             Byte-pattern:         23 (1.15%)
Randomized:    1190 (59.59%)
      

On voit que la majorité utilise des adresses temporaires (Randomized) ce qui est bon signe (et tord le cou à la légende comme quoi les adresses IPv6 permettraient de suivre un utilisateur à la trace). Le second type, en nombre d'adresses distinctes (je n'ai pas cherché à pondérer par le nombre de visites faites par chaque adresse), est celui des adresses manuelles avec un octet de faible valeur (Low-byte). Il peut s'agir de serveurs, par exemple des crawlers. Les adresses IPv6 fondées sur l'adresse MAC sont le troisième type, avec plus de 11 %, et des efforts seront sans doute nécessaires pour sensibiliser ces utilisateurs.


Téléchargez le RFC 7721


L'article seul

RFC 7707: Network Reconnaissance in IPv6 Networks

Date de publication du RFC : Mars 2016
Auteur(s) du RFC : F. Gont (Huawei Technologies), T. Chown (University of Southampton)
Pour information
Réalisé dans le cadre du groupe de travail IETF opsec
Première rédaction de cet article le 11 mars 2016


Soit un pauvre petit réseau innocent, et un méchant attaquant qui va essayer de faire subir les derniers outrages au réseau en question. L'attaquant commence souvent par une phase de reconnaissance, où il cherche à améliorer sa connaissance du réseau visé. Un outil souvent utilisé dans cette phase est le balayage (scanning) systématique du réseau, à la recherche d'adresses IP de machines à attaquer. En IPv6, contrairement à IPv4, la tâche semble colossale, vu le nombre d'adresses IP possibles. Mais, comme l'avait déjà noté le RFC 5157, cette tâche n'est pas impossible. Ce nouveau RFC fait le point sur le balayage IPv6 et détaille les techniques utilisables.

Comme exemple de la différence de situation entre IPv4 et IPv6, prenons un réseau local typique. La densité de machines (nombre de machines réellement présentes par rapport au nombre d'adresses possibles) est bien inférieure en IPv6. Sur un /26 IPv4, on a 62 adresses théoriquement possibles et la plupart correspondront sans doute effectivement à une machine. Balayer ce /26 est à la fois très rapide et très avantageux. En IPv6, un simple /64 permet d'avoir plus de 10^19 adresses (c'est bien la principale motivation pour déployer IPv6 : avoir davantage d'adresses). Même si on a bien plus de machines, la densité sera infime. Si les adresses étaient attribuées au hasard et que le balayage se fasse également au hasard, les chances de tomber sur une machine réelle sont quasi-nulles. Heureusement pour l'attaquant, les adresses réelles ne sont pas attribuées au hasard, et le balayage n'est pas forcément fait au hasard. Ce nouveau RFC, deux fois plus long que l'ancien (le RFC 5157) fait le point sur ce que les défenseurs et les attaquants doivent savoir sur le balayage en IPv6.

Avant de tester, installons l'outil de balayage scan6, distribué avec le SI6 toolkit (et déjà utilisé dans mon article sur les attaques en IPv6) :

% wget http://www.si6networks.com/tools/ipv6toolkit/ipv6toolkit-v2.0.tar.gz
% tar xzvf ipv6toolkit-v2.0.tar.gz
% cd ipv6toolkit-v2.0
% make

C'est parti, en commençant par les techniques les plus classiques (section 3 de notre RFC). D'abord, lorsque le réseau visé configure les adresses IP avec le SLAAC du RFC 4862. Le SLAAC fonctionne en concaténant un préfixe appris du routeur avec un suffixe, l'IID (Interface IDentifier). Comment la machine choisit-elle son IID ? Il existe plusieurs techniques, qui ont des conséquences sur la facilité de balayage. Par exemple, une technique courante (mais de moins en moins employée) est de fabriquer l'IID à partir de l'adresse MAC de la machine, en mettant juste le bit 6 à 1 et en ajoutant au milieu 0xfffe. Ainsi, mon adresse MAC 38:59:f9:7d:b6:47 me donne actuellement une adresse IPv6 de 2003:88:6c71:c7f8:3a59:f9ff:fe7d:b647 (préfixe 2003:88:6c71:c7f8 chez Deutsche Telekom et IID 3a59:f9ff:fe7d:b647). A priori, il y a 64 bits possibles pour l'IID. Mais ce n'est pas tout à fait vrai. D'abord, 16 sont fixes (le 0xfffe). Ensuite, les 24 premiers bits identifient le vendeur de la carte via son OUI (sauf si, comme dans l'exemple ci-dessus, on a changé son adresse MAC...) Tous les OUI possibles n'étant pas encore affectés, cela réduit le champ de recherche. Et ceux qui sont affectés le sont souvent pour du matériel qui n'est plus fabriqué, réduisant encore ce champ. Enfin, un attaquant malin observera qu'une organisation donnée a souvent un parc matériel homogène (par exemple uniquement des ordinateurs Dell). Cela permet de réduire encore l'espace de recherche (option --tgt-vendor de scan6). En outre, si les machines ont été achetées en même temps, il est tout à fait possible qu'elles fassent partie du même lot et que leurs adresses MAC soient consécutives. Une fois qu'on en a trouvé une, on peut supposer que les autres sont proches.

Un cas particulier est celui des techniques de virtualisation. Par exemple, VirtualBox utilise l'OUI 08:00:27 et, avec le 0xfffe du milieu, cela fait que l'espace de recherche réel n'est que de 24 bits, bien moins que les 64 théoriques. VMware est encore pire, pour ses adresses MAC automatiques : l'OUI est 00:05:69, 16 bits sont tirés de l'adresse IPv4 de la console, 8 bits sont un condensat du nom du fichier de configuration. Il peut donc n'y avoir que 8 bits à chercher ! (Les adresses MAC manuelles de VMware ont 22 bits variables.)

Et les adresses temporaires du RFC 8981, n'avaient-elles pas été conçues justement pour éviter qu'on suive à la trace une machine ? L'IID est cette fois aléatoire, et change souvent (par exemple une fois par jour). Ces adresses temporaires sont une très bonne chose, mais elles ont quelques limites. D'abord, elles viennent en plus des adresses classiques, auxquelles la machine répond toujours. Les adresses temporaires étant utilisées pour les connexions sortantes, le risque de fuite de l'adresse globale permanente est plus faible mais elles n'empêchent pas le balayage, avec les techniques données plus haut.

C'est en partie pour combler les faiblesses des adresses temporaires que les adresses du RFC 7217 ont été développées. L'IID est un condensat de certaines caractéristiques de la machine et du réseau. Ces adresses sont stables tant que la machine ne change pas de réseau (ce qui permet de n'utiliser que ces adresses et d'oublier les adresses globales classiques). Du point de vue de la vie privée, elles représentent la meilleure solution, et devraient être systématiquement utilisées. Pour l'instant, comme l'indique « IPv6 Address Analysis - Privacy In, Transition Out », la grande majorité des clients IPv6 utilisent les adresses temporaires du RFC 8981 (et 7 % utilisent encore les adresses MAC).

Et DHCP ? La politique d'allocation des adresses dépend du serveur DHCP. Parfois, elle mène à des adresses prévisibles, mais pas toujours. Par exemple, si on configure un serveur DHCP pour allouer des adresses dans la plage 2001:db8:a35:b24::/64, et que le serveur DHCP décide qu'une allocation séquentielle (2001:db8:a35:b24::1 puis 2001:db8:a35:b24::2, puis 2001:db8:a35:b24::3...) est la meilleure solution, alors les adresses seront prévisibles. C'est pour cela que le RFC 5157 conseillait aux serveurs DHCP d'allouer au hasard à partir de la plage d'adresses configurée et ce conseil est répété ici.

Et les adresses attribuées manuellement, par l'administrateur système ? C'est utile pour les routeurs (qui ne peuvent pas utiliser SLAAC) et les serveurs (qui ne cherchent pas à se cacher, et pour qui il est très souhaitable d'avoir une adresse IP stable). En théorie, l'administrateur système peut choisir l'IID librement parmi 2^64 valeurs. En pratique, on observe que ces IID ne sont pas choisis au hasard mais que les ingénieurs suivent un de ces quatre schémas, utilisant :

  • Un nombre de faible valeur (schéma dit low byte) : PREFIX::1, PREFIX::2, etc. L'option --tgt-low-byte de scan6 permet de tester en premier ces valeurs. Dans le cas le plus simple, il suffit de tester les 256 valeurs correspondant aux huits bits finaux (certaines variantes de ce schéma utilisent les deux ou trois derniers octets, ce qui rend le balayage un peu plus long). Ce schéma est de loin le plus fréquent pour les serveurs et les routeurs (voir « IPv6 Network Reconnaissance: Theory & Practice », cité en section 3.1.5).
  • Une adresse IPv4, en profitant de ce que la représentation texte d'une adresse IPv6 peut se terminer par une adresse IPv4, comme dans 2001:db8:88:12a::192.0.2.21. Balayer ces adresses revient à balayer l'espace IPv4 correspondant (option --tgt-ipv4, de scan6).
  • Un numéro de port, le serveur DNS sera PREFIX::53, le serveur IMAP PREFIX::993, etc. Le cas le plus simple (numéro de port dans le dernier octet) est très rapide à balayer (option --tgt-port de scan6, il n'y a que quelques dizaines de ports populaires), certaines variantes sont un peu plus lentes.
  • Un terme amusant en hexspeak comme ::dead:beef ou ::a11. Balayer ces termes se fait à partir d'un dictionnaire.

Bon, armés de ces connaissances, voyons maintenant concrètement comment balayer un réseau. D'abord, un réseau distant (section 3.2). Un balayage par la force brute est impossible en IPv6 : un seul /64 peut avoir dans les 10^20 machines, ce qui, même à un million de paquets par seconde, prendrait trois millions d'années à examiner. Un balayeur IPv6 doit donc être plus astucieux que la force brute et exploiter les propriétés des adresses IPv6, qui font que l'espace réel à explorer est plus réduit que l'espace théorique. Ainsi, en balayant dans l'ordre, de PRÉFIXE:: puis PRÉFIXE::1, PRÉFIXE::2, etc, on tire profit des adressses de faible valeur. De même, on peut deviner le plan d'adresssage et utiliser les adresses IPv4 du réseau, les numéros des bâtiments, etc.

À noter que le balayage peut aussi être utilisé pour faire une attaque par déni de service. Certaines mises en œuvres d'IPv6 gèrent mal leur cache NDP et un grand nombre de requêtes pour des machines inexistantes peut planter certains routeurs IPv6 (RFC 6583).

Revenons au balayage fait dans le but de découvrir des adresses actives. Si on balaye le réseau local, celui où on se trouve, il y a encore d'autres possibilités, notamment les adresses multicast. Par exemple, en envoyant un seul paquet à l'adresse multicast ff02::1, on récupère plein de machines :

% ping6 -I eth0 ff02::1
PING ff02::1(ff02::1) from fe80::e349:a3a5:ad58:a21 eth0: 56 data bytes
64 bytes from fe80::e349:a3a5:ad58:a21: icmp_seq=1 ttl=64 time=0.250 ms
64 bytes from fe80::21e:8cff:fe76:29b6: icmp_seq=1 ttl=64 time=1.17 ms (DUP!)
64 bytes from fe80::f6ca:e5ff:fe4d:1f41: icmp_seq=1 ttl=64 time=4.96 ms (DUP!)
64 bytes from fe80::ce0d:dad3:6bc2:6da4: icmp_seq=1 ttl=64 time=4.96 ms (DUP!)
...
 

Ça ne marche pas avec les machines Windows, qui ne répondent pas à ce ping. Mais il y a d'autres astuces comme d'envoyer à cette adresse multicast un paquet IPv6 ayant une option inconnue et dont le type commence par 10 (qui signifie « si cette option n'est pas connue, jeter le paquet et envoyer une erreur ICMP », cf. RFC 2460, section 4.2). Windows répondra alors par un message ICMP Parameter problem. Voici le résultat de scan6 vu avec tcpdump, montrant cette technique :

19:01:06.204431 IP6 fe80::e349:a3a5:ad58:a21 > ff02::1: DSTOPT ICMP6, echo request, seq 34994, length 64
19:01:06.205469 IP6 fe80::21e:8cff:fe76:29b6 > fe80::e349:a3a5:ad58:a21: ICMP6, parameter problem, option - octet 42, length 120
19:01:06.214792 IP6 fe80::ba27:ebff:feaa:78b9 > fe80::e349:a3a5:ad58:a21: ICMP6, parameter problem, option - octet 42, length 120
...

Ces techniques ne sont pas purement théoriques. Certes, un outil comme nmap sait faire du balayage en IPv4 mais pas en IPv6 à distance, mais d'autres outils existent. Ces techniques sont mises en œuvre dans l'outil scan6 du SI6 toolkit, cité plus haut. Une fois compilé et installé, on peut utiliser cet outil pour découvrir ses voisins (sur le même réseau local) :

 % sudo scan6 -L -i eth0
 ...
2a01:f23:a65:6721:21e:8cff:fe76:29b6
2a01:f23:a65:6721::1
2a01:f23:a65:6721:666:6c7c:9bed:b390
2a01:f23:a65:6721:b5a5:dfd6:4e7b:2584
... 
 

Ou bien tester un réseau distant :

% sudo scan6 -d 2001:7b2:dc0:41::/64
2001:7b2:dc0:41::250
...
 

Le dernier exemple ci-dessus est évidemment complètement irréaliste (balayage d'un /64 en force brute), même si ici on a trouvé tout de suite une machine « low-byte ». Ne soyez pas trop optimiste : scan6, livré à lui-même, est très lent et vous trouverez rarement quelque chose. Un balayage d'un site où on connait le vendeur des cartes Ethernet (et donc l'OUI) :

 %  sudo scan6 --tgt-ieee-oui b8:27:eb -d 2001:db8:8469:a30::/64 -i eth0 -e print-global  
 

prend de très nombreuses heures et risque fortement d'être détecté. En pratique, pour utiliser scan6 avec succès, il faut récolter beaucoup d'informations sur le réseau qui vous intéresse, et guider scan6 en lui mettant beaucoup d'options. Un projet intéressant serait de tenter d'automatiser cette phase heuristique.

Une des conséquences de la difficulté de balayer en IPv6 est que la gestion de réseaux devient plus compliquée. L'administrateur réseaux ne peut pas découvrir facilement tout ce qui a été branché et fonctionne sur son réseau. Il doit donc changer ses pratiques. Une des approches, pour connaitre tout son réseau, est l'écoute passive, avec ndpmon, qui permet de se constituer automatiquement une base des machines et de leur adresse MAC.

Et l'administrateur réseaux qui veut défendre son réseau et limiter le balayage, que peut-il faire (section 3.5 du RFC) ? Il existe plusieurs techniques qui aident, en rendant les adresses moins prévisibles :

  • Utiliser les adresses stables mais opaques du RFC 7217. (Au passage, je ne connais pas encore de système d'exploitation où ce soit facile ou même possible.)
  • Utiliser un IDS pour détecter (ou un IPS pour bloquer) : les balayages IPv6 ne peuvent pas être faits discrètement, ils allument les systèmes d'alarme comme un arbre de Noël.
  • Peut-être filtrer certains types de paquets (avec prudence : voir le RFC 4890).
  • Configurer manuellement les adresses MAC (par exemple avec macchanger). Ainsi, même si les adresses IPv6 son dérivées de l'adresse MAC, elles ne seront plus prévisibles.
  • Si on utilise DHCP, configurer le serveur DHCP pour allouer dans un ordre aléatoire, et pas bêtement en partant de 1. (Je n'ai pas regardé les possibilités des serveurs DHCP actuels.)

Ces solutions ne sont pas parfaites. Consolez-vous avec l'idée que la sécurité de vos machines ne doit de toute façon pas dépendre uniquement de la résistance de votre réseau au balayage. Tôt ou tard, l'attaquant découvrira vos adresses IP, et les machines doivent donc être préparées à tout.

Le balayeur n'utilisera pas que des techniques de couche 3 comme décrit dans la précédente section, la section 3 du RFC. Il peut aussi se servir, par exemple, du DNS (section 4). Par exemple, s'il est possible de récupérer la zone DNS, le balayeur obtient beaucoup d'adresses IPv6. Mais il peut aussi tester des noms communs dans le DNS et obtenir ainsi des adresses (et, si votre algorithme d'allocation est prévisible, un petit nombre d'adresses lui permettra d'en déduire d'autres). Un tel balayage est facile à automatiser.

Mieux (du point de vue de l'attaquant), on peut énumérer les enregistrements PTR dans votre sous-arbre de ip6.arpa. (C'est automatisable, avec l'outil dnsrevenum6, qui fait partie de la boîte à outils THC.)

Outre le DNS classique, mDNS (RFC 6762) peut également aider (section 5) : des requêtes envoyées à la cantonade peuvent découvrir des machines qui se signaleraient imprudemment.

L'attaquant en mission de reconnaissance peut aussi utiliser des archives publiques (section 6). Par exemple, une liste de diffusion dont les messages seraient stockées intégralement, y compris les en-têtes Received:, qui contiennent souvent des adresses IP. Difficile d'être discret sur l'Internet !

Certaines applications peuvent également aider l'attaquant à récolter des adresses IP (section 7). Par exemple, BitTorrent ne fait aucun effort pour dissimuler l'adresse du pair avec qui on échange des fichiers. Même chose avec NTP, si les machines de votre réseau local se synchronisent directement à l'extérieur, ce qui les rend visibles à Shodan.)

On trouve également des adresses IP dans les caches NDP (section 8) - et ces caches peuvent parfois être examinés à distance avec SNMP (section 13), dans les journaux (gérer un serveur Web populaire permet d'en récolter beaucoup, cf. section 9), via les protocoles de routage (section 10), via traceroute (section 12)... Au passage, il est recommandé de lire l'excellent article de Bellovin, S., Cheswick, B., et A. Keromytis, « Worm propagation strategies in an IPv6 Internet » dans login: en 2006.

L'annexe A du RFC décrit une mise en œuvre des principales idées expliquées dans ce document. Si vous voulez tous les détails techniques sur le balayage en IPv6, c'est le texte à lire. Il faut par exemple être prudent : un balayage exhaustif en IPv6 peut nécessiter un nombre colossal de paquets et, si on les envoie trop vite, l'augmentation du trafic vous fera repérer (variante : vous surchargerez le réseau, des paquets seront perdsu et vous raterez ainsi des réponses). Cette annexe couvre également les méthodes de dissimulation, pour éviter d'être détecté (avec la plupart des IDS IPv6, il suffit d'ajouter des en-têtes d'extension au paquet). Le tout est évidemment très inspiré de l'expérience de l'un des auteurs du RFC avec l'outil scan6, déjà cité.

Je ne fais pas ici un résumé des différences avec son prédécesseur, le RFC 5157, car il y en a beaucoup trop (notre nouveau RFC est bien plus détaillé).


Téléchargez le RFC 7707


L'article seul

RFC 7754: Technical Considerations for Internet Service Blocking and Filtering

Date de publication du RFC : Mars 2016
Auteur(s) du RFC : R. Barnes (Mozilla), A. Cooper (Cisco), O. Kolkman (ISOC), D. Thaler (Microsoft), E. Nordmark (Arista)
Pour information
Première rédaction de cet article le 10 mars 2016


Normalement, l'Internet est ouvert. C'est même une de ses principales caractéristiques : un outil de communication ouvert, où tout le monde peut s'exprimer. C'est cette ouverture qui est à la base de son succès. Mais une de ses conséquences est que certaines communications vont être indésirables pour certains. Il y a donc une demande pour du « blocage » ou du « filtrage », afin d'empêcher ces communications. Ce nouveau RFC, dû à l'IAB, examine les techniques de blocage et de filtrage et cherche lesquelles sont le plus compatibles avec une architecture saine et robuste de l'Internet. Évidemment, les techniques qui menacent le moins la robustesse de l'Internet sont celles qui se déroulent entièrement aux extrémités. Si je ne veux pas voir les publicités, j'installe un logiciel qui télécharge sur ma machine une liste noire de serveurs distribuant ces publicités, et je peux ainsi bloquer et filtrer sans risques pour l'utilisation de l'Internet par les autres. Mais, hélas, pas mal de gens puissants se moquent de fragiliser l'Internet (ou la démocratie) et bien d'autres méthodes de blocage ou de filtrage existent.

On voit tout de suite que ce RFC est très politique. Les filtrages dont il parle sont évidemment ceux de gens ayant du pouvoir (entreprises, États) et qui vont essayer d'empêcher M. Michu de voir ce qu'il veut. Mais l'IAB essaie de ne pas faire trop de politique, et se limite à analyser le problème technique. Ce RFC est un excellent document, analysant très finement les systèmes de filtrage et blocage, et restant sous l'angle technique, à la fois par désir de ne pas prendre position trop clairement et aussi parce que, pour l'Internet, une censure légale/légitime et une attaque ne sont pas différentes.

Le problème des « communications non souhaitées » est vaste. Il ne se limite pas aux pages Web qui déplaisent aux ministres et que ceux-ci souhaitent censurer. Il y a aussi le logiciel malveillant (qui remonte à loin), les attaques, le spam, etc. C'est donc depuis longtemps qu'il existe des techniques de blocage et de filtrage, et depuis aussi longtemps qu'elles sont vigoureusement contestées.

Le RFC 4084 notait déjà que certains FAI bloquaient l'accès à certains services. Parfois, cela se fait avec le consentement de l'utilisateur, consentement parfois très contestable : si, pour avoir un accès Internet à l'hôtel, vous devez cliquer « J'accepte » après un texte de vingt pages, y a-t-il réellement eu consentement ? Mais, souvent, il n'y a même pas de semblant de consentement : certains voudraient bloquer sans que l'utilisateur soit d'accord, et parfois sans même qu'il soit informé. Si ces « certains » ne contrôlent pas le réseau, ils cherchent à atteindre leurs fins en agissant sur des intermédiaires (comme les résolveurs DNS), et tant pis pour les dommages collatéraux.

J'ai parlé de « blocage » et de « filtrage », quelle est la différence ? On dit en général « blocage » quand on interdit complètement l'accès à un agrégat de ressources et « filtrage » quand il s'agit de sélectivement empêcher l'accès à certaines ressources seulement, dans cet agrégat. Si on empêche l'accès à tout YouTube, c'est du blocage. Si on empêche seulement l'accès à certaines vidéos, c'est du filtrage. Pour l'analyse dans ce RFC, cela ne change pas grand'chose, et on parlera indifféremment de filtrage ou de blocage.

Selon le pays, l'époque, les opinions politiques de la personne à qui on parle, ce filtrage peut être vu comme légal, illégal, éthique, acceptable, dégueulasse, souhaitable, stupide, scandaleux et contraire aux droits de l'homme, indispensable, etc. Mais, pour l'analyse technique qui est faite par l'IAB, cela ne fait pas de différence. Notamment, la distinction légale/illégale est non seulement très complexe (le gouvernement turc a-t-il le droit de détourner l'adresse IP d'un serveur états-unien ?) mais également sans conséquences pour la technique. (Un logiciel ne sait pas ce qui est légal ou illégal et il travaille de la même façon dans les deux cas.)

C'est encore plus vrai pour la distinction éthique/pas éthique, que notre RFC considère comme hors sujet, et sur laquelle il ne prend donc pas position.

La section 2 du RFC donne plusieurs exemples de filtrage ou blocage. Historiquement, les premiers systèmes qui se mettaient sur le trajet entre Alice et Bob étaient les pare-feux (RFC 2979). Ils peuvent être déployés sur les machines terminales (c'est aujourd'hui le cas du Netfilter de Linux) ou bien sur le réseau (souvenir personnel lointain : les débuts avaient été difficiles car certains systèmes supportaient mal qu'une machine soit joignable via certains ports et pas d'autres : c'est ainsi qu'au début des années 1990, Ultrix coupait toute communication avec une machine dès qu'il recevait un ICMP indiquant qu'un port était bloqué).

Il y a bien des sortes de pare-feux, le RFC 4949 contient des définitions, et le RFC 4948 décrit les différents types de trafic non souhaités, ceux qu'on veut typiquement bloquer avec le pare-feu. Notamment, on distingue traditionnellement (ces termes sont absents du RFC 4949, qui est assez ancien) :

  • Les pare-feux sans état, où chaque paquet est traité indépendemment des autres. Ce sont les plus simples à réaliser et les premiers apparus. Ils permettent, par exemple, de bloquer toute connexion sortant vers le port 25 (celui de SMTP), pour empêcher les zombies d'envoyer du spam.
  • Les pare-feux avec état, qui ont une mémoire des précédents paquets, ce qui permet des politiques plus subtiles comme de bloquer tout paquet entrant qui ne correspond pas à un flot de données déjà établi (une connexion TCP, par exemple). Ils sont plus complexe à réaliser (et donc plus fragiles) et l'état nécessite de la mémoire, les rendant très vulnérables en cas d'attaque par déni de service (le pare-feu à état plante souvent avant le serveur qu'il était censé protéger).
  • Les pare-feux capables de DPI. Le terme est assez flou mais il désigne en général, de façon assez arbitraire, les pare-feux qui examinent au-delà de la couche 4, par exemple en regardant le contenu applicatif.

Autre exemple de filtrage, celui du Web. Comme les dirigeants, en général, ne connaissent de l'Internet que le Web, c'est souvent sur celui-ci que portent les efforts de censure. Il est donc fréquent que le filtrage soit spécifique à certains URI, soit en détournant tout le trafic HTTP vers un proxy qui examine les URI, soit par DPI. Évidemment, HTTPS rend bien plus compliqué ce filtrage. Mais ne l'empêche pas complètement, en raison des failles du modèle de sécurité de X.509 : par exemple, le filtreur peut obtenir un faux certificat d'une autorité existante, ou bien faire installer sur les ordinateurs une autorité de certification qui validera les faux certificats générés par le système de filtrage.

Le filtrage n'est pas forcément fait par des méchants dictateurs voulant empêcher les citoyens d'accéder à des informations honnêtes. Un bon exemple d'un filtrage que la majorité des utilisateurs apprécie, et même réclame, est le filtrage du spam. C'est même sans doute dans la lutte contre le spam que le filtrage a trouvé une de ses premières applications. Une des armes utilisées, les listes noires, est, techniquement, tout à fait comparable aux outils de la censure (RFC 5782).

Un autre exemple cité dans le RFC d'un filtrage volontaire par les utilisateurs est le safe browsing, quand le navigateur Web connait une liste de sites Web méchants ou dangereux, et refuse de s'y connecter.

Et le filtrage des noms de domaine ? Cela peut se faire en supprimant ledit nom, par exemple par la procédure de justice privée UDRP (cf. Moore, T. et R. Clayton, « The Impact of Incentives on Notice and Take-down », Workshop on the Economics of Information Security 2008, et Chachra, N., McCoy, D., Savage, S., et G. Voelker « Empirically Characterizing Domain Abuse and the Revenue Impact of Blacklisting », Workshop on the Economics of Information Security 2014. Cette approche nécessite de disposer d'un moyen politique d'action contre le registre qui gère le nom (notez que c'est la loi du pays du registre qui compte, pas la loi du titulaire, comme l'avait illustré l'affaire RojaDirecta).

Mais la censure d'un nom de domaine peut aussi se faire dans le DNS. (Au passage, arrêtez de lire ici et allez, si ce n'est pas encore fait, allez voir l'excellent rapport du conseil scientifique de l'AFNIC « Conséquences du filtrage Internet par le DNS ».) Dans ce cas, un résolveur menteur va donner, pour ce nom de domaine, un autre résultat que celui prévu par le titulaire du nom (c'est ainsi que fonctionne la censure administrative française). Cette technique est utilisée dans de nombreux pays, même si elle fragilise l'Internet, par exemple en perturbant le déploiement de DNSSEC.

Une autre technologie d'infrastructure qui risque d'être utilisée pour le filtrage est le routage. En manipulant le routage de l'Internet, on peut empêcher l'utilisateur d'accéder où il veut. Un exemple typique a été l'action aux Pays-Bas contre le RIPE-NCC dans l'affaire DNSChanger.

Après ce tour des exemples de filtrage (le RFC en cite plusieurs autres que je n'ai pas repris ici), passons maintenant à la théorie et essayons de classer ces systèmes de blocage. Il y a quatre critères de classement importants :

  • Qui bloque ?
  • Pourquoi bloque-t-il ?
  • Quelle est la cible technique du blocage ?
  • Quoi, quel composant de l'Internet est utilisé pour le blocage ?

La liste des cas présentés à la section 2 était délibérement très variée, utilisant des cas qui se classent très différemment selon ces critères.

Commençons, par le premier critère, qui bloque. On a vu des blocages par la police, par des tribunaux, par des entreprises, par des opérateurs réseau et par des utilisateurs individuels. Souvent, la décision est prise par une entité et ensuite appliquée par une autre. Par exemple, le ministère de l'Intérieur décide de bloquer un site Web « djihadiste » mais c'est un FAI qui, via son résolveur DNS menteur, effectue le blocage. (Le RFC n'en parle pas mais un autre exemple est celui où une entreprise choisit d'utiliser un résolveur menteur, par exemple OpenDNS, comme résolveur. OpenDNS affirme toujours que leurs clients ont choisi le blocage. Mais, dans ce cas, l'employé de base a-t-il réellement choisi ?)

Second critère, pourquoi on bloque. On peut bloquer « pour des raisons de sécurité » (c'est souvent une excuse pipeau mais il y a aussi des vraies raisons de sécurité). Par exemple, on va bloquer les sites Web qui distribuent du logiciel malveillant. Ou bien on va bloquer les communications avec tel préfixe IP, d'où partent souvent des attaques.

On peut aussi bloquer un contenu dont on ne veut pas. Le RFC ne cite pas cet exemple mais on pense évidemment aux bloqueurs de pub. Il y a aussi bien sûr les cas de censure étatique, où l'État ne veut pas que les citoyens accèdent à tel site Web. Les raisons sont nombreuses, de la pédopornographie au jeu en ligne en passant par la vente de drogues, la propagande raciste ou la violation des droits sacrés des ayant-droits.

Le blocage peut aussi se faire pour des raisons économiques, par exemple un service d'accès à l'Internet gratuit mais qui bloquerait la plupart des sites, nécessitant une option payante pour y accéder.

Le blocage peut se faire par liste noire (on laisse passer par défaut, et on a une liste des choses interdites, c'est typiquement le cas avec la censure) ou carrément par liste blanche (on bloque par défaut et on a une liste des choses autorisées, c'est typiquement le cas des offres limitées). Une entreprise qui ne veut pas que ses employés passent du temps sur autre chose que les tâches qui leur sont affectées pourrait utiliser une liste noire (interdire ce qui leur ferait « perdre » du temps) ou la liste blanche (limiter les employés à quelques destinations connues).

Troisième critère de classification, quelle est la cible exacte ? Veut-on bloquer un service entier (par exemple la voix sur IP, pour protéger la vache à lait des opérateurs téléphoniques) ? Ou un contenu très spécifique (une seule vidéo sur YouTube) ? Certaines techniques bloquent facilement plus que la cible visé. Par exemple, supprimer un nom de domaine parce que le site Web sert un contenu à problèmes va aussi couper tous les services associés à ce nom de domaine (le courrier par exemple). Les demandes de take down (« le site Web en http://example.com/ vend de la contrefaçon, supprimez immédiatement ce nom ») prennent rarement en compte ce problème. Si on les écoutait, chaque fois que le WordPress d'une mairie est piraté et sert à du hameçonnage, on supprimerait le nom de domaine, coupant ainsi l'accès des citoyens à leur ville.

Enfin, quatrième cas, le comment, quels composants de l'Internet vont être utilisés pour le blocage. Cela peut être :

  • La machine terminale, client ou serveur (ou pair, dans le cas du pair à pair),
  • Le réseau, par exemple les routeurs,
  • Et un composant auquel on ne pense pas toujours, les services de rendez-vous, comme le DNS ou comme une DHT, qui ne sont pas dans le chemin direct entre les machines terminales, mais qui sont en général indispensables à l'établissement d'une communication.

Par exemple, lorsque M. Michu veut accéder à http://example.com/comment-partir-en-syrie avec son navigateur Web, les machines terminales sont son PC et le serveur HTTP, le réseau, ce sont tous les routeurs et autres équipements actifs sur le trajet, le service de rendez-vous, c'est le DNS (par exemple le registre de .com). Autre exemple, Alice appelle Bob en SIP, les machines terminales sont le smartphone d'Alice et le PC de Bob, le réseau, ce sont tous les routeurs et autres équipements actifs sur le trajet, le service de rendez-vous, c'est le proxy SIP.

Dans l'exemple HTTP ci-dessus, on peut empêcher M. Michu de regarder la page Web à de très nombreux endroits. Le RFC donne la liste complète mais voici quelques extraits, aux trois endroits possibles :

  • On peut empêcher le navigateur de faire des requêtes vers cet URL (c'est ce que font les bloqueurs de pub),
  • On peut configurer le réseau pour envoyer tout le trafic vers le serveur dans un trou noir,
  • On peut supprimer le nom de domaine example.com.

Le choix dépendra souvent de qui bloque. Si c'est l'utilisateur (cas des bloqueurs de pub), il fera en général le blocage sur sa machine terminale. Si c'est l'État, il utilisera plus souvent le réseau ou bien le système de rendez-vous (s'il est sur son territoire, ainsi, un .com peut être saisi par les autorités états-uniennes).

Le gros du RFC est représenté par la section 4, qui évalue les différentes techniques. Les critères d'évaluation sont la portée, la granularité, l'efficacité et la sécurité. Commençons par la portée (qui est affecté).

Si je configure Shorewall sur ma machine Linux pour bloquer le trafic vers 2001:db8:bad:1:ef5:34:aba1:96, je n'affecte qu'une toute petite partie de l'Internet. Si le gouvernement des États-Unis décidait de supprimer .ir de la racine du DNS, il affecterait bien plus de monde (« About 35,400,000 results » me dit Google). D'une manière générale, le blocage fait aux bords de l'Internet affecte peu de gens, celui fait dans le réseau affecte beaucoup de monde, sans doute bien plus que ce qui était nécessaire. Les exemples de « bavures » (le blocage « bave » au delà de sa portée normale) sont nombreux, de l'Inde censurant Oman, au célèbre cas de Pakistan Telecom bloquant YouTube, en passant par la censure chinoise débordant en Allemagne. Le « bon » blocage devrait avoir la portée la plus petite possible.

Et la granularité ? Est-ce qu'on pourra bloquer un service sans bloquer les autres ? Par exemple, si une machine héberge un serveur SMTP qui envoie du spam, peut-on la bloquer sans empêcher l'accès aux autres ressources qu'elle héberge, comme un serveur HTTP ? Idéalement, là encore, on souhaite que le blocage puisse être fait avec la granularité la plus fine possible.

Et l'efficacité ? Si on bloque, on veut qu'il ne soit pas facile de « débloquer », c'est-à-dire d'accéder aux ressources bloquées. Évidemment, si le blocage est fait par l'utilisateur (comme dans le cas des bloqueurs de publicité), pas de problème : il ne va évidemment pas chercher à contourner ce blocage. Mais si le blocage est imposé, l'expérience de l'Internet montre que les utilisateurs vont chercher à le contourner (voir par exemple les articles « Failures in a Hybrid Content Blocking System » et « Empirically Characterizing Domain Abuse and the Revenue Impact of Blacklisting »). Un service bloqué se déplace facilement, comme le montre les fréquents changements de TLD de The Pirate Bay. Du côté client, les solutions de contournement sont également nombreuses, du passage par Tor, à l'utilisation de son propre résolveur DNS pour contourner les résolveurs menteurs. Ces contournements mènent parfois à une escalade puis à une course aux armements comme dans le cas turc où le DNS menteur était contourné par l'utilisation de Google Public DNS, ce qui avait mené au piratage du routage de Google. Un autre exemple de course aux armements est le blocage des services par leur numéro de port, poussant les applications à toujours utiliser le port 80, celui de HTTP, poussant les bloqueurs à faire du DPI, poussant les applications à chiffrer, poussant les bloqueurs à faire de l'analyse de trafic pour essayer de détecter, sous le chiffrement, certains type de trafic, etc. Une telle course ne peut pas avoir de fin.

Certains de ces contournements ont d'ailleurs des conséquences pas forcément positives pour l'architecture de l'Internet. C'est ainsi que beaucoup d'applications se pressent sur le port 443, celui de HTTPS, car il est rarement filtré. Ou bien que des victimes d'un blocage de SIP passent à des solutions fermées comme Skype. Le RFC note au passage que le chiffrement rend évidemment plus difficile tout filtrage sélectif, et que cela va donc jouer dans la diabolisation du chiffrement.

Dernier exemple de technique de contournement du blocage, citée par le RFC mais jamais vue en pratique (mais elle amusera les nerds), l'ajout d'en-têtes d'extension dans les paquets IPv6 (par exemple une option Destination) suffit souvent aujourd'hui à rendre aveugles les filtres (ces en-têtes sont parfois difficiles à analyser).

Dans l'évaluation du blocage, reste la question de la sécurité : les techniques de sécurité sur l'Internet cherchent à empêcher toute interférence d'un tiers. Le blocage ne va-t-il pas entrer en conflit avec ce souhait ? Techniquement, rien ne distingue une attaque légale d'une attaque illégale : les mêmes techniques de sécurité vont réagir contre les deux. C'est le cas des protocoles qui visent (entre autres) à assurer l'intégrité des communications (TLSRFC 5246 ou IPsecRFC 4301). Lorsqu'on accède au site de sa banque en TLS, c'est précisement pour empêcher un tiers de modifier les données, justement ce que la censure aimerait bien faire.

La sécurité sur l'Internet repose en général sur des techniques de bout en bout, les seules sûres (RFC 4924). Certains blocages (comme le détournement des sessions TLS) nécessitent d'insérer dans le trafic un intermédiaire non prévu à l'origine, ce qui casse cette sécurité.

La section 4 du RFC se penche ensuite sur les trois lieux où on peut faire le blocage, le réseau, puis le rendez-vous, puis la machine terminale. D'abord, le réseau, par exemple via un pare-feu. Est-ce un bon endroit pour bloquer ? Si on bloque dans un réseau périphérique, proche d'une des machines terminales qui communiquent, la portée reste faible. Si, par contre, on bloque dans l'épine dorsale d'un grand réseau, la portée sera bien plus étendue (dans le cas d'une censure volontaire, une portée importante n'est pas un défaut...) Notez que le blocage dans le réseau nécessite que le réseau ait accès à suffisamment d'informations pour prendre sa décision. Cela peut mener à des pratiques comme le DPI.

Notez qu'un filtrage dans le réseau peut être complexe car rien ne dit qu'un point du réseau verra passer tout le trafic entre Alice et Bob. Pour des blocages sommaires (« couper toute communication avec 192.0.2.0/24 »), ce n'est pas un problème. Mais cela interdit des choses plus subtiles, par exemple de bloquer certains URI sur un site Web mais pas tous. Le routage dans l'Internet étant ce qu'il est, un point donné peut ne voir qu'une partie des paquets d'une même communication. C'est d'ailleurs pour cela que les censeurs essaient toujours d'obtenir que les réseaux soient architecturés de manière à faciliter le blocage, notamment en limitant le nombre de points de sortie vers l'extérieur et en empêchant l'asymétrie du routage (en se moquant des conséquences que cela peut avoir pour les performances et la fiabilité).

Quant à l'efficacité et la sécurité du blocage dans le réseau... Le chiffrement suffit à gêner une grande partie de ces blocages. Il ne laisse que quelques métadonnées comme les adresses IP, qui peuvent être trop grossières pour le système de filtrage.

Et les techniques de contournement sont nombreuses, comme cela a pu être vu dans la lutte des ayant-droits contre The Pirate Bay. Le site visé peut changer d'adresse IP, ou de nom, ses clients peuvent passer par Tor ou par un VPN, etc. Évidemment, plus le blocage reste en place longtemps, plus les techniques de contournement se développeront et seront déployées. Si on bloque dans le réseau, c'est en général parce que les deux parties qui communiquent ne sont pas d'accord avec ce blocage. Elles ont donc des bonnes motivations pour le contourner et la lutte de l'épée et de la cuirasse va donc durer longtemps.

Le bloqueur peut essayer de bloquer l'accès aux services qui permettent un contournement. Par exemple, il peut interdire TLS vers certains sites. Comme l'a montré le projet Telex, même cela n'est pas forcément suffisant : on peut toujours, avec la participation d'un pair accessible, faire des tunnels peu repérables. Plus radical, le censeur peut interdire tout le chiffrement (en France, des tas de politiciens ne demanderaient pas mieux). Cela serait évidemment catastrophique pour la sécurité de l'Internet.

Le RFC conclut donc que le blocage dans le réseau est en général une mauvaise idée.

Bon, mais alors, se dit le censeur qui lit les RFC (cela doit être rare...), pourquoi ne pas bloquer via les systèmes de rendez-vous à la place ? En effet, on a beau parler de pair à pair, presque toutes les communications réelles sur l'Internet nécessitent un mécanisme mettant en rapport les machines de Bob et d'Alice. C'est souvent le DNS mais cela peut être un moteur de recherches (Pirate Bay joue ce rôle, mettant en rapport un utilisateur de BitTorrent et le contenu convoité) ou bien d'autres mécanismes (comme les DHT ou une blockchain).

Le blocage sur le service de rendez-vous est surtout utile pour un État si ledit service est sous sa juridiction. Si vous utilisez un .ly, vous dépendez logiquement des lois libyennes. Si le service est global (c'est le cas d'un registre de noms de domaine), la portée du blocage est également globale. C'est ce qui fait qu'un service légal dans son pays a pu perdre son .com et donc tous ses clients. Si par contre le service est local (un résolveur DNS), la portée est limitée aux utilisateurs de ce service.

Lorsque le système de rendez-vous est le DNS, la granularité du blocage est mauvaise : supprimer le nom de domaine supprime tous les services associés. Quant à l'efficacité, elle n'est jamais parfaite (voir mon article pour une étude sur le cas du DNS ou bien le rapport de l'ISOC) : les utilisateurs peuvent souvent changer de point de rendez-vous (passer à un autre résolveur DNS, par exemple), d'autant plus que la plupart des systèmes de rendez-vous n'ont aucune sécurité (des techniques d'authentification comme DNSSEC pour le DNS changeront peut-être partiellement les choses).

Un autre système de rendez-vous est souvent oublié : les IRR et, d'une manière plus générale, le mécanisme d'allocation d'adresses IP. Dans au moins un cas (déjà cité plus haut), un État a essayé de l'utiliser pour bloquer un service illégal.

En résumé, le blocage par action sur un service de rendez-vous est simple (et donc tentant pour les autorités) car on n'agit que sur un seul point, ou un petit nombre de points, mais n'est pas très efficace et, comme il consiste à bricoler l'infrastructure de l'Internet, il est dangereux pour le bon fonctionnement de celui-ci.

Reste un dernier endroit, dans l'une des machines terminales. Quelles sont les propriétés d'un blocage fait à cet endroit ? À chaque instant, le logiciel installé sur ces machines ou bien leur utilisateur prend des décisions sur le fait de communiquer ou pas. Les utilisateurs choisissent (ou pas) de cliquer sur un lien hypertexte. Le logiciel de messagerie décide si un message doit être montré ou classé dans le dossier Spam. Netfilter jette les paquets ou pas. L'utilisateur installe un nouveau logiciel de communication (ou pas). Les choix du logiciel sont guidés par l'utiisateur (cas d'un filtre bayésien à qui l'utilisateur dit « ce message est un spam ») mais le contraire arrive aussi (SafeBrowsing).

La portée d'un tel blocage est strictement locale. Si j'installe Ghostery pour bloquer les mouchards, cela n'affecte (en bien ou en mal) que moi.

La granularité est très fine : la machine terminale maitrise tous les aspects de la connexion contrairement à, par exemple, le serveur DNS, qui n'a aucune idée de pourquoi on demande ce nom de domaine. Elle peut donc ne bloquer qu'un seul service. Encore mieux si le blocage est fait dans l'application (le cas, là encore, des bloqueurs de publicité) car ils ont la totalité de l'information sur la connexion, sous une forme qui permet des traitements sans ambiguité (cf. RFC 7288).

L'efficacité est bonne. D'abord, puisque le blocage est décidé par l'utilisateur, il ne va évidemment pas chercher à le contourner. Ensuite, les services bloqués peuvent, évidemment, essayer de s'adapter (le point de distribution d'un malware va changer souvent de nom de domaine et d'adresse IP, pour disparaitre des listes noires) mais la machine terminale ayant une visibilité complète (y compris de ces changements) est dans une meilleure position que quiconque pour s'y adapter. Comme le blocage se fait aux extrêmités, il ne gêne pas l'architecture de bout en bout (chacun est bien sûr libre d'accepter de communiquer avec qui il veut).

À noter qu'il existe deux extrêmités à la communication : le blocage peut aussi être fait de l'autre côté, par le serveur (dans le cas d'une communication client/serveur). Voici par exemple les compteurs du nombre de paquets rejetés sur le serveur qui porte ce blog. On voit que je n'accepte pas tout :-)

% sudo iptables -n -v -L net-fw
Chain net-fw (2 references)
 pkts bytes target     prot opt in     out     source               destination         
9360K  659M blacklst   all  --  *      *       0.0.0.0/0            0.0.0.0/0           
 679K   49M smurfs     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ctstate INVALID,NEW,UNTRACKED
9041K  625M tcpflags   tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           
74720   11M Drop       all  --  *      *       0.0.0.0/0            0.0.0.0/0           
 8881  631K DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    

On peut faire la même chose de tas de façons. Par exemple, un serveur HTTP comme Apache a plein de techniques permettant toutes sortes de blocages des visiteurs importuns. Et, évidemment, pour bloquer un service entier sur le serveur, c'est très facile, on ne fait tout simplement pas tourner le logiciel correspondant.

Bien sûr, ce blocage nécessite l'accord de la personne qui utilise ladite machine terminale et les censeurs ne seront donc pas enthousiastes à l'idée de lui demander.

Bref, le blocage sur une des machines terminales est de loin celui qui a le moins de chances de causer des dommages collatéraux sur l'Internet.

Comme tous les RFC, notre RFC 7754 contient une section dédiée à la sécurité, la section 5. Son point essentiel est que le blocage dans le réseau ou dans les services de rendez-vous est un danger pour la sécurité de l'Internet : il s'oppose frontalement aux mesures de sécurité. Par exemple, pour bloquer, on va essayer de casser le chiffrement, avec une attaque de l'homme du milieu, comme le font beaucoup d'entreprises, avec les produits de société comme Blue Coat, en fabriquant de faux certificats pour que les logiciels ne détectent pas cette attaque.

En outre, le système qui effectue cette attaque devient lui-même une cible tentante pour un attaquant extérieur puisqu'il donne accès à tout le trafic en clair. On a donc mis en péril toutes les machines de l'entreprise en introduisant cette « machine du milieu ». (En tant qu'ancien ingénieur système, je suis également sensible à la remarque du RFC comme quoi l'administrateur de cette machine court un gros risque juridique personnel, puisqu'il va avoir accès à des tas de données sensibles.)

La conclusion du RFC (section 6) est que, si on tient à faire du blocage, il faut le faire sur les machines terminales et laisser le réseau tranquille, afin qu'il puisse faire son travail avec rapidité et sécurité. Gageons que cet avis ne sera pas suivi. Parmi toutes les discussions sur le blocage, le filtrage et la censure, beaucoup de temps a été passé sur la légitimité ou non de ces blocages (« si vous vous opposez à la Main Rouge, c'est que vous sympathisez avec les terroristes ») et nettement moins sur les conséquences techniques de ces blocages. En gros, si on veut faire de la censure efficace, il faut ré-architecturer l'Internet pour la censure et non pas pour la communication. (Cf. mon exposé à l'Assemblée Générale de France-IX, et les supports.)

Un des auteurs du RFC, Olaf Kolkman, a écrit ses réflexions personnelles.


Téléchargez le RFC 7754


L'article seul

Pourquoi le certificat de la CNIL n'est pas reconnu et autres belles histoires au coin du feu en hiver

Première rédaction de cet article le 4 mars 2016


Tout le monde, surtout les gens qui ne savent pas distinguer ROT13 de SHA-256, l'a constaté et largement commenté sur les rézosocios : le site de la CNIL a un problème de certificat. Que s'est-il donc passé ? C'est de leur faute ? Ce sont des gros nuls, doublés de feignants ? Les certificats servent-ils à quelque chose ?

Pour commencer, essayez ces deux liens : https://cnil.fr/ et https://www.cnil.fr/. Avec le certificat installé aujourd'hui, le premier lien devrait déclencher une erreur de sécurité (genre « The certificate is only valid for the following names: www.cnil.fr [...] »), le second lien va marcher avec certaines machines, mais, avec d'autres, vous aurez un avertissement de sécurité (comme « The certificate is not trusted because the issuer certificate is unknown »).

Avant de répondre aux questions que je posais plus haut, revenons au rôle des certificats (si vous lisez le X.509 en codé en DER sans l'aide d'un ordinateur, et en faisant les calculs RSA de tête, vous pouvez sauter ce paragraphe). La communication avec le site de la CNIL utilise le protocole HTTPS, qui est HTTP avec en prime la sécurité qu'apporte la cryptographie. Celle-ci, fournie par un mécanisme nommé TLS (et que certains conservateurs s'obstinent à nommer de son nom du siècle précédent, SSL), permet d'éviter l'écoute de votre conversation par un tiers indiscret. Elle fournit également une certaine authentification du site distant, vous garantissant (en théorie) que vous allez bien sur le site de la CNIL. (Les deux fonctions, confidentialité et authentification, sont en fait liées : sans l'authentification, vous pourriez parler à l'Homme du Milieu, qui pourrait alors lire vos communications.) Le certificat est une clé cryptographique, celle qu'utilise le serveur distant pour chiffrer ses communications avec vous, agrémenté d'une série de noms (la norme technique des certificats, X.509, les appelle « sujets »), de quelques métadonnées et signé par une Autorité de Certification. Cette signature par une AC vous garantit que le certificat est bien celui de la CNIL et pas un certificat qu'un plaisantin a généré lui-même, en y mettant comme nom celui de la CNIL.

Deux points sont particulièrement à retenir dans ce résumé très simplifié : le certificat indique les noms possibles pour le site Web, et il ne sera accepté que s'il est signé par une AC elle-même « acceptée ». Or, le nouveau site de la CNIL a deux problèmes, portant sur ces deux points.

Premier problème, dans la liste des noms (les « sujets ») du certificat, on ne trouve pas cnil.fr. Si on se connecte à https://cnil.fr/, on aura donc systématiquement une erreur du genre : cnil-https.png (Dans la version française du navigateur, « Le certificat n'est valide que pour les noms suivants : www.cnil.fr […])

Comment trouver cette liste ? Le navigateur Web peut vous la donner. Sur Firefox, cliquer sur le cadenas, demander More information puis View certificat et, dans la liste des attributs du certificat, sélectionner subject et Subject Alt Name : cnil-subjects.png

Une méthode plus geek est d'utiliser OpenSSL en ligne de commande :

    
% openssl s_client -connect cnil.fr:443  | openssl x509 -text
...   
Subject: C=FR, O=COMMISSION NAT INFORMATIQUE ET LIBERTE, OU=0002 11000012200025, L=PARIS, CN=www.cnil.fr/serialNumber=1-3291
...
X509v3 Subject Alternative Name: 
   DNS:www.cnil.fr, DNS:piwik.cnil.fr, DNS:backoffice.cnil.fr, DNS:www.jeunes.cnil.fr, DNS:www.educnum.fr

On voit bien que cnil.fr ne figure pas dans les noms. Cette erreur là (car, oui, à mon avis, c'est une erreur de la part de la CNIL, qui permet les connexions à https://cnil.fr/ mais ne présente pas de quoi l'authentifier) explique le premier problème.

Le second problème, maintenant. Il ne se produit qu'avec certains systèmes. Par exemple, le Firefox sur ma Debian affiche :

www.cnil.fr uses an invalid security certificate.

The certificate is not trusted because the issuer certificate is unknown.

(Error code: sec_error_unknown_issuer)

Ici, le problème est tout différent. Rappelez-vous que le certificat doit être signé par une Autorité de Certification (le issuer du message ci-dessus). Chaque logiciel qui se connecte avec le protocole TLS a un magasin stockant les AC (Autorités de Certification) qu'il reconnait. (Parfois, le magasin est global au système d'exploitation, ou bien à une bibliothèque logicielle particulière, et le navigateur Web ne fait qu'utiliser ce magasin qu'on lui a fourni.) Qui décide de ce qu'on met dans le magasin ? Eh bien, c'est ça qui est drôle, personne. Il n'existe pas d'autorité qui décide de ce qu'on met ou pas dans ce magasin. Chaque gestionnaire d'un magasin d'AC (donc, chaque navigateur Web, ou système d'exploitation) a ses propres critères (parfois documentés - ici, la politique de Mozilla, parfois opaques, parfois arbitraires) pour décider. Résultat, deux magasins n'ont jamais le même contenu. On peut donc avoir un certificat qui est accepté par une machine et refusé par une autre, ou même accepté par un navigateur Web et refusé par un autre sur la même machine.

C'est ce qui est arrivé à la CNIL. Leur certificat est signé par l'AC Certinomis et certains n'ont pas le certificat de l'AC dans leur magasin (ou, peut-être, n'ont qu'un autre certificat de cette AC). C'est un problème fréquent, et qui n'est pas réellement de la faute de la CNIL. (À noter que la version HTTPS de mon blog a souvent le même problème, en raison de son utilisation de l'AC CAcert.)

Ce petit incident est donc l'occasion de rappeler quelques règles de fonctionnement du système X.509, qui est derrière l'authentification des sessions TLS :

  • La notion d'AC « officielle » ou d'AC « reconnue » n'a aucun sens. Chacun choisit les AC de son magasin.
  • Qu'une AC soit absente d'un magasin ne signifie pas (contrairement à ce que prétendent des ignorants) que les gérants du site Web soient incompétents ou négligents. Ils ne contrôlent pas les AC utilisées par les clients.

L'article seul

RFC 7766: DNS Transport over TCP - Implementation Requirements

Date de publication du RFC : Mars 2016
Auteur(s) du RFC : J. Dickinson, S. Dickinson (Sinodun), R. Bellis (ISC), A. Mankin (Verisign Labs), D. Wessels (Verisign Labs)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 4 mars 2016


Ce nouveau RFC décrit des exigences bien plus importantes pour l'utilisation du DNS au-dessus de TCP : non seulement les serveurs DNS doivent gérer TCP (ce qui a toujours été le cas), mais ils doivent le faire sur un pied d'égalité avec UDP. TCP n'est pas une solution de secours pour des cas rares, c'est désormais une alternative complète à UDP pour le service DNS. La règle est donc désormais plus radicale qu'avec le RFC précédent, le RFC 5966, maintenant retiré.

Traditionnellement, surtout avant la sortie du RFC 5966, le DNS utilisait surtout UDP. Beaucoup de gens croyaient même, bien à tort, que TCP ne servait que pour des cas très particuliers comme le transfert de zones ou comme la récupération de données plus grosses que 512 octets. Ces croyances étaient déjà fausses lors de la sortie des RFC originels sur le DNS, mais le RFC 5966 leur a tordu le cou complètement. UDP a en effet des limites :

La formulation des sections 3.7 du RFC 1034 et 4.2 du RFC 1035 sur l'usage de TCP étaient assez claires (mais personne ne lit les RFC...) Par contre, la section 6.1.3.2 du RFC 1123 avait semé la confusion en laissant entendre que TCP était facultatif. C'est désormais corrigé, TCP est bien obligatoire pour le DNS.

Mais TCP, utilisé bêtement, souffre de plusieurs défauts : si on ouvre une connexion TCP à chaque requête DNS, la latence va être bien plus élevée qu'en UDP, et, si on fait passer toutes les requêtes séquentiellement sur une seule connexion TCP, et que le serveur les traite dans l'ordre, une requête lente peut faire attendre des requêtes qui auraient été rapides. Voici pourquoi notre RFC impose un certain nombre de comportements intelligents (section 3) :

  • Connexion persistente et réutilisable (ne pas fermer la connexion TCP, mais la réutiliser pour les requêtes suivantes),
  • Pipelining (pour un client DNS, ne pas attendre la réponse avant d'envoyer d'autres questions, mais en envoyer plusieurs dans le tuyau),
  • Traitement non-séquentiel (pour un serveur, le fait de traiter en parallèle les requêtes, pour éviter qu'une requête lente ne retarde celles qui suivent). Cela concerne surtout les résolveurs (car le temps de répondre à une requête peut varier considérablement, en fonction du cache et du temps de réponse des serveurs faisant autorité.)

J'ai parlé plus haut de la taille des réponses DNS (section 4 du RFC). C'était autrefois une des bonnes raisons de passer en TCP, afin d'obtenir des réponses supérieures à 512 octets. Les clients DNS le font typiquement automatiquement. Par exemple, ici, dig tente d'obtenir une réponse de plus de 512 octets, et elle est donc tronquée (flag TC pour TrunCation) :

  
% dig +bufsize=0 +noedns +nodnssec +ignore NS fox.com 
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 38102
;; flags: qr tc rd ra ad; QUERY: 1, ANSWER: 15, AUTHORITY: 0, ADDITIONAL: 0
...
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; MSG SIZE  rcvd: 494

J'ai utilisé l'option +ignore pour voir cette troncation. Si on ne l'utilise pas, dig passe automatiquement en TCP (le message « Truncated, retrying in TCP mode ») :


% dig +bufsize=0 +noedns +nodnssec NS fox.com 
;; Truncated, retrying in TCP mode.
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 24693
;; flags: qr rd ra; QUERY: 1, ANSWER: 16, AUTHORITY: 0, ADDITIONAL: 0
...
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; MSG SIZE  rcvd: 522

Maintenant qu'on a EDNS (RFC 6891), TCP est moins utile pour ce problème de taille (il reste utile pour les autres raisons énumérées au début). Voici un exemple avec EDNS pour une donnée de grande taille (comme le note la section 4, une réponse négative, NXDOMAIN dans une zone signée avec DNSSEC/RSA et utilisant le NSEC3 du RFC 5155 va presque toujours faire plus de 512 octets) :


% dig +bufsize=4096 A nimportequoinexistepas.fr
...
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 27274
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 8, ADDITIONAL: 1
...
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; MSG SIZE  rcvd: 1012

Le +bufsize=4096 active EDNS, avec une taille maximale des réponses de 4 096 octets.

(Notez que la troncation est aussi utilisée pour des raisons de sécurité, lorsqu'un serveur détecte une attaque par amplification. Avec la technique RRL, le serveur répond alors avec des paquets tronqués - paquets nommés SLIP, pour forcer le client à réessayer en TCP, où il n'y aura pas d'usurpation d'adresse IP possible.)

Reste la question de la MTU. La réponse précédente faisait 1 012 octets, inférieure à la MTU typique (en général de 1 500 octets, à cause d'Ethernet). Si elle est plus grande, la réponse va être fragmentée et, là, les ennuis commencent. On ne peut pas compter sur la bonne réception des paquets fragmentés : trop de pare-feux configurés avec les pieds sont sur le trajet, et ils jettent souvent bêtement les fragments. En parlant de middleboxes, il faut aussi noter que certaines perturbent EDNS (RFC 5625). Les réponses supérieures à 1 500 octets, elles, auront peut-être besoin de TCP :

% dig DNSKEY cpsc.gov
...
;; MSG SIZE  rcvd: 1733

La section 5 du RFC est la partie normative. Elle contient la nouvelle règle : un serveur DNS doit parler TCP. Et un client DNS peut s'en servir, il n'est même pas forcé d'attendre la troncation.

Maintenant, les détails pratiques. D'abord (section 6), la gestion des connexions TCP. Compte-tenu de la « triple poignée de mains » qui ouvre les connexions TCP, et de son coût en latence, il est fortement recommandé d'éviter de faire une connexion TCP par requête DNS. L'idée est donc, pour le serveur, de ne pas fermer la connexion dès qu'elle est inactive mais de la garder ouverte (comme le font HTTP 1.1 - RFC 7230 et HTTP 2 - RFC 7540) et, pour les clients, de ne pas fermer après la première requête (ce qu'ils font actuellement, en général). Mais, contrairement à HTTP, le DNS n'a pas encore de mécanisme de fermeture explicite de ces connexions TCP persistentes (certains ont été proposés). Il faut donc utiliser des heuristiques pour savoir quand fermer une connexion.

Au fait, j'ai parlé de « connexion inactive » sans l'expliquer. La section 3 la définit comme « pour un client, lorsqu'il a reçu toutes les réponses à ses questions, pour un serveur, lorsqu'il a répondu à toutes les questions posées ».

Les serveurs actuels laissent en général les connexions assez longtemps (deux minutes par défaut, sur Unbound ou sur NSD), et ont un nombre de connexions TCP maximal assez faible. Cela permet des attaques par déni de service triviales (ouvrir N connexions TCP, attendre) ou même des simples accidents, où un petit nombre de clients, sans le faire exprès, épuisent complètement les maigres ressources allouées à TCP. Avec BIND, vous pouvez par exemple regarder combien de clients TCP sont actuellement actifs par rapport au maximum autorisé. Si le nombre de clients actifs se rapproche trop du maximum, il y a un risque :

% rndc status | grep tcp
tcp clients: 8/100

Notre RFC recommande donc (section 6.2) une série de bonnes pratiques qui vont permettre à TCP d'être utilisé massivement pour le DNS. D'abord, réutiliser les connexions, de façon à amortir le coût, relativement élevé, de l'établissement d'une connexion, sur plusieurs requêtes. Attention, le client DNS ne doit pas réutiliser l'identicateur de requête (Query ID, ou id: dans la sortie de dig) sur la même connexion, tant qu'il reste une question non répondue utilisant cet identificateur (autrement, le client ne saurait pas à quelle question correspond une réponse).

Ensuite, une requête ne devrait pas avoir à attendre la réponse à la requête précédente. Dès que le client a une question, il l'envoie (pipelining).

Au passage, un client DNS gourmand pourrait être tenté d'ouvrir plusieurs connexions TCP avec le serveur. Notre RFC le déconseille (sauf pour des cas ponctuels comme les longs transferts de zone) : cela use des ressources, et c'est inutile, si on a le pipelining et le traitement en parallèle. Un serveur a donc le droit de mettre des limites et, par exemple, de ne pas accepter plus de N connexions TCP par adresse IP (avec N probablement strictement supérieur à 1 car il faut tenir compter des clients différents situés derrière une même adresse IP, par exemple en cas de CGN).

Bon, et le quantitatif ? C'est bien de dire qu'un serveur ne devrait pas laisser les connexions TCP inactives ouvertes trop longtemps, mais combien, exactement ? Le RFC recommande quelques secondes, pas plus, après le traitement de la dernière requête, sauf si on a reçu une demande explicite (voir le RFC 7828). À comparer avec les 120 secondes actuelles de NSD ou Unbound... Cette durée peut évidemment être réglée dynamiquement, par exemple pour répondre à la disponibilité de ressources chez le serveur (nombre maximum de connexions TCP atteint, je coupe des connexions inactives...)

Dans tous les cas, outre la coupure d'une connexion par un client qui a fini son travail, le client doit aussi se rappeler qu'un serveur DNS a le droit de couper les connexions TCP quand ça lui chante, et sans prévenir à l'avance. Le client doit donc gérer ces coupures (détecter et reconnecter). C'est d'autant plus important qu'un serveur peut redémarrer (perdant ses sessions TCP) ou que tout simplement, le routage peut changer, amenant le client DNS vers une autre instance d'un nuage anycast, instance qui n'a pas les sessions TCP en cours.

Et le traitement en parallèle (section 7) ? C'est un des points importants de DNS sur TCP, sans lequel TCP n'aurait guère d'intérêt. Lorsqu'un résolveur minimum (rappel, la terminologie du DNS est dans le RFC 8499) se connecte à un résolveur complet en TCP, le résolveur complet va mettre un temps très variable à répondre aux questions. De quelques dizaines de micro-secondes si la réponse est dans le cache à des centaines de milli-secondes s'il a fallu interroger trois ou quatre serveurs faisant autorité avant d'avoir sa réponse. Si le traitement des requêtes était fait de manière strictement séquentielle, la requête rapide qui aurait la malchance d'être située après une requête lente devrait patienter très longtemps. Il est donc crucial de traiter les requêtes en parallèle.

Conséquence : il est parfaitement normal que, lorsqu'on envoie les questions Q1 puis Q2, la réponse R2 arrive avant R1. Tous les clients DNS doivent être prêts à cela. Le démultiplexage des réponses doit se faire sur le Query ID du DNS (et voilà pourquoi il ne faut pas le dupliquer) et, dans le cas le plus fréquent, également sur le nom demandé (QNAME, pour Query NAME).

L'encodage d'un message DNS en TCP est très légèrement différent de ce qu'il est en UDP. Un champ Longueur, de deux octets, précède en effet le message, pour faciliter la lecture. Cela permet au récepteur de savoir combien d'octets il va lire dans le flux TCP (qui, rappelons-le, n'a pas la notion de messages, c'est juste un flux d'octets sans séparateurs). Par exemple, en Go, on lirait ainsi :

// Lire le champ Longueur
smallbuf := make([]byte, 2)
n, error := connection.Read(smallbuf)
msglength := binary.BigEndian.Uint16(smallbuf) // RFC 1035, section 4.2.2 "TCP usage"

// Allouer un tampon pour le message
message := make([]byte, msglength)

// Lire le message DNS
n, error = connection.Read(message)

Le RFC recommande (section 8) que les émetteurs DNS passent ce champ Longueur et le message ensemble, dans un seul write() sur le réseau, de façon à maximiser les chances qu'ils se trouvent dans le même paquet IP, certaines mises en œuvre réagissant mal dans le cas contraire. Ce n'est pas une garantie absolue (TCP peut découper en paquets IP comme il veut). Les experts en Go noteront que le code ci-dessus ne tient pas compte de ce risque : Read() peut lire moins d'octets que la taille du tampon, il faudrait tester ce cas (ou bien utiliser ReadFull().) Et, naturellement, il faudrait tester les cas d'erreur.

On a vu qu'un des problèmes potentiels dus à l'utilisation de TCP était la latence liée à l'ouverture des connexions. Outre la réutilisation des connexions pour plusieurs requêtes, un autre mécanisme peut aider à limiter ce problème (section 9) : TCP Fast Open (RFC 7413). En permettant aux données d'être transportées dès le paquet initial (le paquet SYN), il fait gagner du temps. Contrairement à d'autres tentatives précédentes de faire de l'« ouverture rapide », TCP Fast Open ne permet pas d'attaques par réflexion, grâce à un cookie. C'est donc une solution à considérer, pour les clients et serveurs DNS utilisant TCP.

C'est un bon prétexte pour discuter de sécurité (section 10). Lors de la mise au point de ce RFC, il y a eu beaucoup de discussions concernant le risque d'attaque par déni de service pour les serveurs DNS. Le traitement d'une requête TCP (y compris l'établissement de la connexion) nécessite, après tout, davantage de ressources que celui d'une requête UDP. Mais on a aussi davantage d'expérience avec les attaques utilisant TCP (c'est le protocole sous HTTP, après tout, et de nombreuses attaques sont faites contre les serveurs Web). Outre la lecture du « Security Assessment of the Transmission Control Protocol (TCP) », notre RFC recommande de permettre de configurer le serveur DNS sur des points comme le nombre total de connexions TCP (tcp-clients pour BIND, tcp-count pour NSD, incoming-num-tcp pour Unbound), le nombre maximal de connexions TCP par adresse IP de client, la durée de vie des connexions inactives (tcp-timeout pour NSD et, attention, il faut redémarrer le serveur si on le change), le nombre maximal de requêtes DNS par connexion (tcp-query-count pour NSD), etc. Sans compter les réglages permis par le système d'exploitation (comme les innombrables paramètres sysctl net.ipv4.tcp_* de Linux et, oui, c'est ipv4 même pour IPv6).

En prime, le RFC rappelle que les résolveurs ne devraient pas accepter des connexions du monde entier (RFC 5358), mais, sauf cas rares, uniquement de certains préfixes IP, leurs clients. Cela contribue à limiter les risques.

Pour les amateurs de choix technologiques complexes, l'annexe A du RFC résume les avantages et les inconvénients de TCP pour le DNS. Avantages :

Inconvénients :

  • Coût par requête plus élevé à cause de l'établissement de la connexion. On peut réduire ce coût en réutilisant les connexions,
  • Davantage d'état à maintenir chez les clients et les serveurs,
  • Risques de plantage des connexions TCP si on se connecte à un serveur anycast et que le routage change,
  • Risque avec des middleboxes boguées (RFC 5625).

Le rapport « Connection-Oriented DNS to Improve Privacy and Security » discute bien plus en détail ces choix.

Enfin, l'annexe B liste les principaux changements depuis le RFC 5966. Ils sont importants puisqu'on passe d'un modèle « TCP dans certains cas » à un modèle « pouvoir faire tout en TCP si on veut ». Par exemple, un client peut désormais utiliser TCP avant d'avoir testé en UDP. Les autres changements sont des conséquences de ce principe : les logiciels DNS doivent désormais permettre la réutilisation des connexions, le pipelining et le traitement en parallèle des requêtes parce que, sans cela, TCP ne serait pas vraiment utilisable pour le DNS.

Allez, pour finir, un example avec dig où on demande explicitement du TCP :


% dig +tcp @d.nic.fr NS gouvernement.fr

; <<>> DiG 9.9.5-9+deb8u3-Debian <<>> +tcp @d.nic.fr NS gouvernement.fr
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 14247
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 7, ADDITIONAL: 1
;; WARNING: recursion requested but not available

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

;; AUTHORITY SECTION:
gouvernement.fr.	172800 IN NS ns2.produhost.net.
gouvernement.fr.	172800 IN NS ns33.produhost.net.
gouvernement.fr.	172800 IN NS ns1-sgg.produhost.net.
98dsof44tab20a3p7gv0cgelh01vlv9j.fr. 5400 IN NSEC3 1 1 1 D0D3AC0C (
				98ECUBNBQN7GCK4GQ1KQURRJTRUF6P83
				NS SOA TXT NAPTR RRSIG DNSKEY NSEC3PARAM )
98dsof44tab20a3p7gv0cgelh01vlv9j.fr. 5400 IN RRSIG NSEC3 8 2 5400 (
				20160213101014 20151215091014 1146 fr.
				MDAHRaeLGVQiK6KEQvFn8PNSl608bd5iMup4cwkqgStB
				uXEFWOpQLeSy37IattIDOt0AhwEirpNe7pzH+KMOdrM0
				mEWGiGa3iSdsF9hc29JDUtVyfalNmJqPIoDplw+Q0lpI
				Jxd8XlI/229PEH64Nua2jgLk5gxyZPCFt7yVvGg= )
ceast34o75e1lj5eprb3j5i82re4g1ug.fr. 5400 IN NSEC3 1 1 1 D0D3AC0C (
				CEB3B4VDS9MG7Q92A7FVCRQ5TTIVJ3LT
				NS DS RRSIG )
ceast34o75e1lj5eprb3j5i82re4g1ug.fr. 5400 IN RRSIG NSEC3 8 2 5400 (
				20160213054416 20151215054416 1146 fr.
				Eusw6LfnNPxmquf8JDHJnWZpBFJj8hrvJi1lx3bounyO
				YW8ceJsrm0AkjMHm5Sh40TDfXcVrLeTK5U9PWJYqpUAG
				7LABfh4nwwnlofvuyKtSx1yl44G6Gv/MSyQUnj0dIgQ5
				6MB+b3tsUx2rHI2D0w9kiV50xJeCYVBiViQP2y8= )

;; Query time: 19 msec
;; SERVER: 2001:678:c::1#53(2001:678:c::1)
;; WHEN: Tue Dec 15 22:07:36 CET 2015
;; MSG SIZE  rcvd: 607

Et le tcpdump correspondant :

% sudo tcpdump -n -vvv host 2001:678:c::1
tcpdump: listening on eth1, link-type EN10MB (Ethernet), capture size 262144 bytes
22:08:08.073682 IP6 (hlim 64, next-header TCP (6) payload length: 40) 2001:db8:cafe:1234:21e:8cff:fe76:29b6.60105 > 2001:678:c::1.53: Flags [S], cksum 0x2782 (correct), seq 2640844175, win 28400, options [mss 1420,sackOK,TS val 2942466 ecr 0,nop,wscale 7], length 0
22:08:08.090127 IP6 (hlim 57, next-header TCP (6) payload length: 40) 2001:678:c::1.53 > 2001:db8:cafe:1234:21e:8cff:fe76:29b6.60105: Flags [S.], cksum 0xcb39 (correct), seq 1288542264, ack 2640844176, win 17856, options [mss 8940,sackOK,TS val 1674059577 ecr 2942466,nop,wscale 7], length 0
22:08:08.090175 IP6 (hlim 64, next-header TCP (6) payload length: 32) 2001:db8:cafe:1234:21e:8cff:fe76:29b6.60105 > 2001:678:c::1.53: Flags [.], cksum 0x5c1c (correct), seq 1, ack 1, win 222, options [nop,nop,TS val 2942470 ecr 1674059577], length 0
22:08:08.090246 IP6 (hlim 64, next-header TCP (6) payload length: 78) 2001:db8:cafe:1234:21e:8cff:fe76:29b6.60105 > 2001:678:c::1.53: Flags [P.], cksum 0x71d1 (correct), seq 1:47, ack 1, win 222, options [nop,nop,TS val 2942470 ecr 1674059577], length 4619356+ [1au] NS? gouvernement.fr. ar: . OPT UDPsize=4096 OK (44)
22:08:08.107559 IP6 (hlim 57, next-header TCP (6) payload length: 32) 2001:678:c::1.53 > 2001:db8:cafe:1234:21e:8cff:fe76:29b6.60105: Flags [.], cksum 0x5c2e (correct), seq 1, ack 47, win 140, options [nop,nop,TS val 1674059595 ecr 2942470], length 0
22:08:08.109126 IP6 (hlim 57, next-header TCP (6) payload length: 641) 2001:678:c::1.53 > 2001:db8:cafe:1234:21e:8cff:fe76:29b6.60105: Flags [P.], cksum 0x6c2e (correct), seq 1:610, ack 47, win 140, options [nop,nop,TS val 1674059595 ecr 2942470], length 60919356- q: NS? gouvernement.fr. 0/7/1 ns: gouvernement.fr. [2d] NS ns2.produhost.net., gouvernement.fr. [2d] NS ns33.produhost.net., gouvernement.fr. [2d] NS ns1-sgg.produhost.net., 98dsof44tab20a3p7gv0cgelh01vlv9j.fr. [1h30m] Type50, 98dsof44tab20a3p7gv0cgelh01vlv9j.fr. [1h30m] RRSIG, ceast34o75e1lj5eprb3j5i82re4g1ug.fr. [1h30m] Type50, ceast34o75e1lj5eprb3j5i82re4g1ug.fr. [1h30m] RRSIG ar: . OPT UDPsize=4096 OK (607)
22:08:08.109137 IP6 (hlim 64, next-header TCP (6) payload length: 32) 2001:db8:cafe:1234:21e:8cff:fe76:29b6.60105 > 2001:678:c::1.53: Flags [.], cksum 0x5961 (correct), seq 47, ack 610, win 244, options [nop,nop,TS val 2942474 ecr 1674059595], length 0
22:08:08.109743 IP6 (hlim 64, next-header TCP (6) payload length: 32) 2001:db8:cafe:1234:21e:8cff:fe76:29b6.60105 > 2001:678:c::1.53: Flags [F.], cksum 0x595f (correct), seq 47, ack 610, win 244, options [nop,nop,TS val 2942475 ecr 1674059595], length 0
22:08:08.130087 IP6 (hlim 57, next-header TCP (6) payload length: 32) 2001:678:c::1.53 > 2001:db8:cafe:1234:21e:8cff:fe76:29b6.60105: Flags [F.], cksum 0x59b3 (correct), seq 610, ack 48, win 140, options [nop,nop,TS val 1674059614 ecr 2942475], length 0
22:08:08.130133 IP6 (hlim 64, next-header TCP (6) payload length: 32) 2001:db8:cafe:1234:21e:8cff:fe76:29b6.60105 > 2001:678:c::1.53: Flags [.], cksum 0x5946 (correct), seq 48, ack 611, win 244, options [nop,nop,TS val 2942480 ecr 1674059614], length 0

Question mise en œuvre, remarquez que les dernières versions de BIND ont un outil nommé mdig qui permet d'envoyer plusieurs requêtes DNS sur une même connexion TCP (en pipeline, sans attendre la réponse à la première).


Téléchargez le RFC 7766


L'article seul

Au secours, j'ai perdu mon nom Namecoin

Première rédaction de cet article le 2 mars 2016
Dernière mise à jour le 3 novembre 2017


J'ai déjà raconté ici comment j'avais enregistré dans la blockchain Namecoin le nom d/bortzmeyer, mon premier nom Namecoin. Eh bien, je l'ai perdu accidentellement et stupidement (puis récupéré après), et cette perte est l'occasion de regarder quelques faiblesses de Namecoin.

Pourquoi Namecoin ? Parce que, disent ses promoteurs, il permet l'enregistrement de noms de manière complètement pair à pair. En prime, depuis quelques mois, « blockchain » est devenu un buzzword et, justement, Namecoin utilise une blockchain, un livre des opérations public, permettant une vérification par tous. Mais les fans de Namecoin oublient de signaler que le prix à payer, pour cette indépendance vis-à-vis de tout organisme, est qu'il faut s'occuper de tout soi-même (par exemple faire sa gestion de clés cryptographiques) et que les erreurs ne pardonnent pas.

C'est une telle erreur que j'ai bêtement fait. Je n'ai pas renouvelé le nom. Il a donc été retiré, puis ré-enregistré mais par quelqu'un d'autre. Voyons les étapes, en utilisant un explorateur public. (Comme je l'ai récupéré par la suite, vous pouvez également chercher cette récupération.)

Le nom a été enregistré le 16 janvier 2014. Il a ensuite été modifié, chaque modification remettant à zéro le compteur. Le dernier renouvellement (qui était juste un renouvellement, sans changement du contenu) a été fait le 22 janvier 2015. Non renouvelé, le nom d/bortzmeyer a expiré et a été ré-enregistré le 29 septembre 2015. Une seule donnée dans ce nom a été mise par le nouveau titulaire, le même jour. Cette donnée était une adresse BitMessage. (Toute l'histoire peut se voir d'un coup en https://namecha.in/name/d/bortzmeyer. À noter qu'un autre explorateur de la blockchain, plus connu mais plus bogué, ne voit pas le ré-enregistrement.)

Pourquoi le nouveau titulaire a-t-il indiqué une adresse BitMessage ? Probablement pour qu'on le contacte afin de payer une rançon pour récupérer le nom maladroitement perdu. Cette pratique semble assez courante dans le monde Namecoin en ce moment. Elle illustre l'absence de toute sécurité autre que technique : si on fait une erreur, ou qu'on est négligent, on est fichu. (J'ai écrit à l'adresse BitMessage en question, sans réponse, ce compte semble hors-ligne, mon client BitMessage ne reçoit pas sa clé publique, ou alors c'est que le réseau BitMessage ne marche plus.) Cette pratique d'enregistrer un nom abandonné est très répandu dans le monde des noms de domaine traditionnels.

Comme Namecoin est très peu utilisé en pratique, je ne m'étais même pas aperçu de la perte. J'étais abonné au système d'alarme Name Alert mais celui-ci semble très bogué. Je n'ai pas reçu les messages prévenant que l'expiration approchait, et je n'ai reçu le message m'avertissant du nouveau contenu du nom que le 2 mars, plusieurs mois plus tard ! Cela donne une idée de l'état de l'écosystème Namecoin.

Par la suite, le détourneur a dû se lasser de ne pas avoir de proposition de rachat, et a laissé tomber le nom, que j'ai alors repris. (Cherchez avec les explorateurs, cela vous fera un bon exercice.) Si vous avez un résolveur DNS qui gère le .bit, vous pouvez à nouveau voir le nom :

      
% dig AAAA bortzmeyer.bit
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 3037
...
;; ANSWER SECTION:
bortzmeyer.bit.		86257 IN AAAA 2605:4500:2:245b::42

;; AUTHORITY SECTION:
bit.			70716 IN NS ns5.opennic.glue.
bit.			70716 IN NS ns6.opennic.glue.
...
;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Fri Nov 03 09:39:55 CET 2017
;; MSG SIZE  rcvd: 264
      
    

Le problème de perte de noms est-il soluble ? Oui, bien sûr, on pourrait imaginer la mise en place d'un système de notariat où des notaires stockent les clés et renouvellent les noms pour le compte de leurs clients. Cela permettrait à des non-experts d'avoir des noms Namecoin, tout en préservant la liberté du choix : chacun serait libre d'utiliser le notaire qu'il veut. En l'absence d'un tel système, il y a peu de chance que Namecoin soit un jour adopté massivement.


L'article seul

Drown, et quelques remarques sur la sécurité

Première rédaction de cet article le 1 mars 2016
Dernière mise à jour le 5 mars 2016


Aujourd'hui a été publiée la faille de sécurité Drown, touchant notamment la bibliothèque cryptographique OpenSSL. C'est l'occasion de se livrer à quelques réflexions sur Drown, TLS et la sécurité.

Le même jour, huit (!) failles de sécurité dans OpenSSL ont été publiées (Drown a été éclaté en deux failles, CVE-2016-0800 et CVE-2016-0703). Cela ne facilite pas le travail de ceux qui essaient de démêler tout cela mais Drown est très bien documenté sur son site officiel (très complet, avec logo et tout). Je recommande également le papier officiel, très clair. Il n'y a normalement donc pas besoin de ré-expliquer ce qu'est Drown.

Pourtant, je suis étonné de constater que certaines choses n'ont pas été comprises. Par exemple bien des gens croient que, puisque leur serveur HTTPS n'accepte pas SSLv2, ils sont en sécurité. Rien n'est plus faux et c'est bien expliqué dans la FAQ de Drown : pour effectuer cette attaque, il suffit que la clé du site visé soit disponible sur un autre site, qui, lui, accepte SSLv2. Et, c'est là un point qui m'a personnellement surpris, ce cas est assez fréquent. Comme le note l'article Drown, le modèle de financement des AC encourage à acheter le moins de certificats possibles, et donc à les utiliser sur plusieurs serveurs, ou bien sur le serveur de production et sur celui de développement.

Prenons un exemple : le serveur du journal quotidien Ouest-France n'est apparemment pas vulnérable, il ne gère pas SSLv2 :

%  openssl s_client -connect www.ouest-france.fr:443 -ssl2
CONNECTED(00000003)
write:errno=104
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 48 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : SSLv2
    Cipher    : 0000
...
    

Mais on trouve, sur un tout autre réseau, une machine 93.17.51.145 qui, elle, acceptait (elle a été réparée depuis) SSLv2 et a un certificat *.ouest-france.fr (les certificats avec joker sont évidemment les plus vulnérables à Drown puisqu'on les achète justement pour les mettre sur plusieurs machines) :

%  openssl s_client -connect 93.17.51.145:443 -ssl2
CONNECTED(00000003)
...
subject=/C=FR/postalCode=35000/ST=Ille-et-Vilaine/L=RENNES/street=10 rue Du Breil/street=ZI Rennes Sud-Est/O=SOCIETE OUEST FRANCE/OU=0002 377714654/CN=*.ouest-france.fr
...
SSL handshake has read 1609 bytes and written 367 bytes
---
New, SSLv2, Cipher is RC2-CBC-MD5
Server public key is 2048 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : SSLv2
    Cipher    : RC2-CBC-MD5
    Session-ID: 6F1500003AE7F4EF421B7C964089D28B

Le journal Ouest-France est hébergé par SDV et cette 93.17.51.145 est apparemment dans les locaux du journal. Machine de développement ? Serveur utilisé pour des applications internes ? En tout cas, contrairement au site Web public, cette machine ne semble pas avoir fait l'objet de tests de sécurité et, à elle seule, elle rendait l'attaque Drown possible. En effet, il s'agit bien de la même clé (pas uniquement du même nom dans le certificat) :

% openssl s_client -connect 93.17.51.145:443 | openssl x509 -pubkey -noout
...
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu83rhWk01bad5z55tfKN
TlqWSdXou/QXTNVsk0J47FFEYCvumcd5TgrLtsRDjz23K1+8T9KXgIzNN4wXwWUc
7O1Hu0ddX4w0OOiSaq2rxPcXdzeF98Mth+MtclUliYZTPa94TXEMSM/xPeELkfmi
sAqJjVFfGqacFcuzI0QryQPkAAU4ts0JtAoaUhHDNc+3Mz2UnHtaYsLEh9cHdkKq
QzpggPPN4emqcEr3fbvTPl0JIYossH/mOI8E4NTyVaZaScimi8efklxF3JEc+/6w
AqzGXt8CL2/ce+E4BojHCfilGrxU4WEeo7e9sMXHuhWCQ/fxT/6o3yktI+sLSv61
RQIDAQAB
-----END PUBLIC KEY-----

% openssl s_client -connect www.ouest-france.fr:443 | openssl x509 -pubkey -noout 
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu83rhWk01bad5z55tfKN
TlqWSdXou/QXTNVsk0J47FFEYCvumcd5TgrLtsRDjz23K1+8T9KXgIzNN4wXwWUc
7O1Hu0ddX4w0OOiSaq2rxPcXdzeF98Mth+MtclUliYZTPa94TXEMSM/xPeELkfmi
sAqJjVFfGqacFcuzI0QryQPkAAU4ts0JtAoaUhHDNc+3Mz2UnHtaYsLEh9cHdkKq
QzpggPPN4emqcEr3fbvTPl0JIYossH/mOI8E4NTyVaZaScimi8efklxF3JEc+/6w
AqzGXt8CL2/ce+E4BojHCfilGrxU4WEeo7e9sMXHuhWCQ/fxT/6o3yktI+sLSv61
RQIDAQAB
-----END PUBLIC KEY-----
    

On trouvait d'ailleurs cette clé sur plein d'autres machines du réseau 93.17.51.128/26, presque toutes acceptant SSLv2 d'une façon ou d'une autre.

En revanche, si on regarde un autre domaine signalé sur le site Web de Drown, blockchain.com, on voit que le site Web public n'a pas du tout la même clé (ce n'est même pas le même algorithme) que la machine vulnérable (alors que le nom dans le certificat de la machine vulnérable est bien *.blockchain.com). Leur situation est donc moins grave (attention toutefois aux attaques actives) :

# Machine vulnérable car acceptant SSLv2 dans certaines conditions
% openssl s_client  -connect  50.87.196.92:443 | openssl x509 -pubkey -noout 
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsXMk8xOJaaqKmz88RicY
Mt4e4VlY0uTVaUS7mbgnUGgd15wQ/tLH91RL5S9c1C1FFrcjBpomODJXBdgTXjWi
x4OVRl0sEe6OjIX1FLqBl15n+Lx++933lQUWinMSInEVLnBBjcr9If5+ozJvscRS
eF/hikjhDYW/rDwF1f7ivTiiok8f12zTa2lhlxOH4KxcFPaFklXDa45DccDjdCIZ
uVLpFSngo5iS3nney+LPK4afYYffEWK9aN2Rj9NE8zRm3hGoGDva2vNmKGbewd3w
1huqr3o7fc3WZyW9HZlM7PjZF6YLhgJnAI09XXDHD3t+G4ijcS6F4Rh9B36whuoo
CQIDAQAB
-----END PUBLIC KEY-----

# Serveur Web public
% openssl s_client  -connect  www.blockchain.com:443 | openssl x509 -pubkey -noout
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8DGz/3DLSflRPxO5uHuiww7EbqEP
/S3VWfdw4PGs4WcuqWTtIGht1rwiuTjrU3Es1uxm3T+JfT1JOOhYut8IjA==
-----END PUBLIC KEY-----
    

Pour résumer ce point essentiel « Même si votre serveur n'accepte pas SSLv2, vous êtes peut-être quand même vulnérable ».

(Au passage, petite note technique : certains systèmes d'exploitation, et à juste titre, compilent OpenSSL sans SSLv2. La commande ci-dessus vous dira alors « unknown option -ssl2 ». Il faut utiliser un système non sécurisé, comme Arch Linux, ou bien prendre un OpenSSL qu'on a compilé soi-même. C'est à cause de ce problème que l'excellent script testssl.sh vient avec son propre OpenSSL.)

On voit d'ailleurs un effet négatif de la gamification popularisée, dans le monde HTTPS, par SSLlabs. Pendant que tout le monde s'amuse à obtenir la meilleure note possible pour s'en vanter sur les rézosocios (« j'ai un A sur SSLlabs alors que la banque Machin a uniquement un B, je suis trop un geek crypto-expert »), des machines comme ce pauvre serveur restent ignorés.

Autre question posée par Drown, pourquoi est-ce qu'il y a autant de machines qui acceptent encore SSLv2 ? Il a été officiellement abandonné en 2011 par le RFC 6176. Et le RFC est sorti bien tard, tous les experts savaient depuis longtemps que SSLv2 était cassé sans espoir de réparation. Mais les mises à jour ne se font, sur l'Internet, qu'à un rythme glacial (voir nul). Le problème n'est pas technique, il vient du fait que les mises à jour ne rapportent rien, n'ont pas de retour sur investissement, et ne sont donc en général jamais faites. Tout le monde s'indigne lorsqu'une faille comme Drown est publiée mais, en temps normal, personne ne s'en préoccupe. La prévention est toujours le parent pauvre de la sécurité. L'opérationnel et la sécurité concrète n'intéressent personne.

Compte-tenu de cela, est-ce que Drown représente un réel danger aujourd'hui, et faut-il patcher d'urgence ? Bien sûr, il faut patcher, c'est le B. A. BA de la sécurité pour une machine connectée à l'Internet. Mais le danger exact de Drown n'est pas facile à évaluer. On est dans le cas classique en sécurité du verre que l'optimiste voit à moitié plein alors que le pessimiste le voit à moitié vide. L'optimiste va faire remarquer que l'exploitation effective de Drown est très difficile, dans les conditions du monde réel (en laboratoire, ça marche toujours mieux). Le pessimiste rétorquera que les attaques ne vont toujours qu'en s'améliorant. Si Drown est difficile à exploiter aujourd'hui, cela ne durera pas éternellement. À noter que, pour la raison expliquée plus haut, cela ne sert à rien de patcher votre serveur principal : il faut patcher toutes les machines qui ont le certificat du serveur principal.

Je suggère d'ailleurs d'en tirer une leçon : ne jamais partager un certificat (et donc une clé privée) entre des machines qui ont des administrateurs différents : le risque est en effet très élevé que l'une d'elles soit moins sécurisée que les autres, permettant une attaque.

Ah, notez aussi que patcher OpenSSL ne servira que pour le futur : si un attaquant a utilisé Drown contre vous, et a réussi à obtenir des informations tels que vos mots de passe, il serait prudent de les changer...

Merci à Léo pour avoir signalé une grosse approximation dans l'article original.


L'article seul

RFC 7790: Mapping characters for PRECIS classes

Date de publication du RFC : Février 2016
Auteur(s) du RFC : Y. YONEYA (JPRS), T. Nemoto (Keio University)
Pour information
Réalisé dans le cadre du groupe de travail IETF precis
Première rédaction de cet article le 1 mars 2016


PRECIS (preparation, enforcement, and comparison of internationalized strings), décrit désormais dans le RFC 8264, est un cadre général pour l'internationalisation d'identificateurs sur l'Internet. Il expose un certain nombre de règles, parmi lesquelles les développeurs de protocoles Internet et d'applications vont pouvoir choisir, au lieu de partir de zéro à chaque fois. Ce nouveau et court RFC donne des indications aux concepteurs de nouveaux profils PRECIS sur les correspondances (mappings) à effectuer (par exemple, mais pas uniquement, entre des caractères majuscules et minuscules). Il n'est pas normatif : l'internationalisation est quelque chose de compliqué et il n'est pas facile d'obtenir un consensus. L'utilisateur indique un identificateur, en quoi peut-on le transformer ?

Au départ de cet identificateur, on trouve une saisie par l'utilisateur (clavier physique ou clavier virtuel), ou bien une sélection par ce même utilisateur (copier/coller depuis du texte, choix d'un signet, choix parmi les résultats d'un moteur de recherche...) À ce stade, l'utilisateur ne tient pas compte de certaines caractéristiques du texte, qu'il considère non pertinentes. C'est ainsi qu'il va ignorer la casse, ou bien la largeur du caractère (pour les caractères qui ont une version étroite et une version large comme le point d'exclamation, qui existe en U+0021, « ! » et U+FF01, « ! ») Il est donc souhaitable d'avoir une phase de correspondance (mapping) entre cette saisie ou cette sélection et le moment où l'identificateur est passé au programme. C'est lors que cette phase qu'on va, par exemple, tout mettre en minuscules, et remplacer les caractères larges par leur version étroite.

Pour le cas des noms de domaine (IDN), cette correspondance est déjà traitée dans le RFC 5895. Pour les autres identificateurs, le cadre PRECIS (PReparation, Enforcement, and Comparison of Internationalized Strings), dans le RFC 8264, s'en charge. Mais il ne traite qu'une partie des correspondances souhaitables (comme la casse) et il était donc souhaitable de l'étendre. C'est ce que fait ce nouveau RFC.

La section 2 de notre court RFC spécifie ces correspondances supplémentaires. Par exemple, les délimiteurs (comme le point). Chaque protocole et format a ses propres délimiteurs (@ pour le courrier électronique, / dans les URL, etc). L'idée est de faire correspondre les caractères qui ressemblent au(x) délimiteur(s) du protocole vers le caractère canonique. Ainsi, si un protocole utilise le point (U+002E) come délimiteur, et que le texte saisi par l'utilisateur contient un point idéographique (U+3002, alias « 。 »), il est logique de remplacer ces points par le point « officiel » du protocole.

Après la correspondance des délimiteurs, les « correspondances spéciales ». Le terme désigne des règles qui sont différentes des règles par défaut de PRECIS. Par exemple, supprimer les caractères de contrôle (pas les transformer en un autre caractère, non, les supprimer franchement) ou bien transformer des espaces différents du caractère espace d'ASCII en espaces ASCII (U+0020). C'est ce que font des protocoles comme EAP (RFC 3748) ou les ACL d'IMAP (RFC 4314).

Autre cas rigolo, celui où le changement de casse dépend de la locale, c'est-à-dire en général de la langue utilisée. L'exemple le plus fameux, toujours mentionné dans les discussions Unicode, vient du turc où la minuscule du I (U+0049) n'est pas i (U+0069) mais ı (U+0131, et encore, la règle exacte est un peu plus compliquée). Comme PRECIS est conçu pour des protocoles Internet, qui ne connaissent pas la langue, les applications (qui, elles, connaissent souvent la langue de leur utilisateur) doivent traiter ce cas, avant de passer l'information sur l'Internet (voir aussi l'annexe B et C, pour des cas spéciaux dans le cas spécial).

L'annexe A de notre RFC résume dans un tableau ces correspondances selon divers protocoles (IDN, iSCSI, EAP, etc).


Téléchargez le RFC 7790


L'article seul

RFC 7725: An HTTP Status Code to Report Legal Obstacles

Date de publication du RFC : Février 2016
Auteur(s) du RFC : T. Bray (Textuality)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF httpbis
Première rédaction de cet article le 1 mars 2016


Voici donc un nouveau code de retour HTTP qui a fait couler énormément d'encre : 451 est désormais l'erreur HTTP à utiliser lorsqu'un serveur HTTP ne peut pas envoyer la ressource demandée par son client pour des raisons légales, en clair lorsqu'il y a censure.

Rappelons que les codes d'erreur HTTP (RFC 7231, section 6) sont composés de trois chiffres, le premier indiquant la catégorie. 4 (RFC 7231, section 6.5) est une erreur due au client (et il ne sert donc à rien de réessayer plus tard).

Ce nouveau code 451 permet de la censure avouée, suivant les principes du RFC 4924 et de la section 4 du RFC 4084. On peut dire clairement à l'utilisateur que sa demande est légalement impossible à satisfaire. Notez que toutes les dictatures ne seront pas ravies de cette transparence. Du temps de Ben Ali, la censure tunisienne générait des faux 404 (Not found) pour faire croire que la ressource demandée n'existait pas.

La section 3 de notre RFC expose les détails techniques. Notez que le serveur qui répond 451 n'est pas forcément le serveur d'origine de la ressource (s'il l'était, il ne souhaiterait probablement pas mettre en œuvre la censure de son propre contenu). 451 sera donc sans doute plutôt renvoyé par des serveurs intermédiaires, genre proxy ou moteurs de recherche.

Vu l'objectif de transparence, le RFC demande que la réponse 451 soit accompagnée d'une explication, indiquant qui bloque, pourquoi, et selon quelle loi. Le RFC fournit un exemple amusant, inspiré du film La vie de Brian :

      
HTTP/1.1 451 Unavailable For Legal Reasons
Link: <https://spqr.example.org/legislatione>; rel="blocked-by"
Content-Type: text/html

<html>
 <head><title>Unavailable For Legal Reasons</title></head>
 <body>
  <h1>Unavailable For Legal Reasons</h1>
  <p>This request may not be serviced in the Roman Province
  of Judea due to the Lex Julia Majestatis, which disallows
  access to resources hosted on servers deemed to be
  operated by the People's Front of Judea.</p>
 </body>
</html>

    

Le RFC note bien que le code 451 n'indique pas si la ressource existe ou pas (par exemple, un proxy peut bloquer toutes les requêtes allant vers un nom de domaine donné).

Notre RFC fournit également des indications sur comment la censure peut être contournée, par exemple avec un VPN vers un pays plus libre, ou bien avec Tor. C'est d'ailleurs un des intérêts pratiques de ce code 451 : un client HTTP pourra agir automatiquement lorsqu'il rencontrera cette erreur. Ce code n'est donc pas purement décoratif (une objection qui lui avait souvent été faite au début du processus à l'IETF.) En prime, ce code pourra être utile à des systèmes de suivi de la censure, comme Lumen. Peut-être cela aidera-t-il à mesurer la censure (du moins dans les pays les plus légalistes, les autres n'utiliseront pas 451). Pour les mêmes raisons, des organisations de défense des droits de l'homme comme le CDT ou comme article 19 ont exprimé leur soutien pour ce code.

L'en-tête Link: dans l'exemple plus haut est là pour identifier formellement l'entité responsable du blocage (section 4 du RFC), en utilisant les liens du RFC 8288. Cela suppose évidemment que celle-ci assume ses décisions, ce qui n'est pas toujours le cas (section 5 du RFC, qui rappelle qu'il y aura toujours une censure hypocrite).

Le code 451 est désormais ajouté au registre IANA des codes de retour HTTP, et la relation blocked-by est dans le registre des relations. (Notez bien que l'exemple ci-dessus, copié du RFC, est erroné.)

« Thanks also to Ray Bradbury », dit l'annexe A du RFC, puisque ce code d'erreur est évidemment une référence geek au roman du célèbre écrivain.

Un exemple de mise en œuvre parmi tant d'autres : la bibliothèque Pylons. Le magasin d'applications de Firefox a 451 parmi ses réponses possibles si l'application est illégale dans le pays du client. Et 451 a une image parmi les fameux HTTP status cats, montrant Bradbury et son chat.

Ce code d'erreur a suscité beaucoup d'intérêt, il a une page Wikipédia, un site Web en Grande-Bretagne et a fait l'objet de nombreux articles dans les médias.

En France, le serveur « La Main Rouge » du Ministère de l'Intérieur n'utilise pas 451 lorsqu'on tente d'accéder à un site Web interdit. Au lieu de cela, leur serveur renvoie 200, ce qui est illogique. (Un point amusant : si on utilise wget - mais pas curl - le serveur renvoie 403.)

À la réunion IETF de Prague en juillet 2017, le hackathon a été l'occasion de travailler sur des utilisations de ce code 451. Voici la présentation qui a été faite et l'Internet-Draft draft-451-imp-report. Le code a été mis sur Github.


Téléchargez le RFC 7725


L'article seul

RFC 7772: Reducing energy consumption of Router Advertisements

Date de publication du RFC : Février 2016
Auteur(s) du RFC : A. Yourtchenko (Cisco), L. Colitti (Google)
Réalisé dans le cadre du groupe de travail IETF v6ops
Première rédaction de cet article le 19 février 2016


Lorsque des machines parlent IPv6, elles reçoivent fréquemment des messages RA (Router Advertisment), que les routeurs émettent souvent avec trop d'enthousiasme. Le traitement de ces messages RA nécessite des ressources et, sur des petites machines alimentées par une pile et souhaitant économiser les ampèreheures, ces RA fréquents, qui les obligent à se réveiller et à travailler, sont une plaie. Ce court RFC suggère quelques moyens d'économiser l'énergie.

À l'époque où IPv6 avait été conçu, on ne pensait pas vraiment à l'Internet des Objets, à ces millions de petits machins connectés. Des messages RA (RFC 4861, section 3) fréquents ne sont pas un problème pour des serveurs alimentés électriquement en permanence. Mais le monde a changé, et il faut maintenant économiser la batterie (section 1 du RFC).

Regardons quelques cas typiques (section 2 du RFC). Un RA (Router Advertisement) peut être sollicité ou pas (RFC 4861). Un RA sollicité est typiquement dû à l'arrivée d'une machine dans le réseau. Elle émet alors un RS (Router Solicitation) et le ou les routeurs, en le recevant, répondent par un RA. Dans certains cas (par exemple si la machine émettrice n'a pas encore d'adresse IPv6 propre), ce RA est envoyé à une adresse multicast, ce qui fait que toutes les machines le recevront et devront le traiter. Si beaucoup de machines quittent et rejoignent le réseau fréquemment (ce qui arrive dans les réseaux sans-fil, lorsque la liaison est mauvaise), ces RA sollicités peuvent représenter un trafic non négligeable (un maximum d'un RA toutes les trois seconde et par routeur est toutefois imposé par les sections 6.2.6 et 10 du RFC 4861).

Même en l'absence de sollicitations, les routeurs IPv6 émettent des RA périodiques, parfois un toutes les cinq ou dix secondes, de manière à éviter que des machines ratent l'information importante.

Conséquences (section 3 du RFC) ? La batterie se vide plus vite, ce qui est très frustrant puisque la plupart de ces RA étaient « inutiles » pour la machine qui les recevait. Certaines machines traitent le problème en ignorant les RA lorsqu'elles sont dans un mode de basse consommation (par exemple Android, avec des conséquences négatives). C'est compréhensible mais cela fait qu'elles risquent, en se réveillant, d'avoir perdu leur connectivité car le réseau a changé ou, tout simplement, parce qu'elles ont « oublié » la route par défaut. Encore plus violent, certaines machines ignorent tous les paquets lorsqu'elles veulent économiser leur batterie. Ces comportements poussent certains administrateurs réseau à augmenter la fréquence des RA, aggravant ainsi encore le problème.

Une autre conséquence (merci à Gabriel Kerneis pour l'exemple), les NAS du constructeur Synology refusent de passer en hibernation profonde s’ils reçoivent des RA (ou des paquets DHCP d’ailleurs). Le seul moyen de faire fonctionner IPv6 sur ces machines tout en préservant l’hibernation est de configurer l’adresse manuellement.

Quelle serait la bonne fréquence d'envoi de RA (section 4) ? Un ordinateur de type portable ne verra pas grand'chose, même pour des RA envoyés toutes les cinq secondes. Sa batterie en a vu d'autres. Les engins plus petits (tablettes, téléphones, montres connectées et autres objets) ont davantage de contraintes. Aujourd'hui, un engin typique va consommer 5 mA quand il dort. Le traitement d'un RA qu'il n'a pas demandé va lui coûter 200 mA pendant un quart de seconde, ce qui fera en tout presque 14 µAh.

Pour limiter la consommation électrique due aux RA à moins de 2 % de la consommation du mode « économique », il faut rester en dessous de 100 µA, ce qui fait moins de 7 RA par heure. Comme des RA se perdent, le routeur ne peut pas être sûr que toutes les machines ont reçu cette information. Le RFC fait un choix conservateur : avec une moyenne de 8-9 minutes entre deux RA (afin de rester en dessous de 7 par heure), le routeur doit compter que l'information devra durer au moins 5 fois ce temps (ce qui fera 40-45 minutes). Pas question donc de changer de configuration IPv6 trop souvent.

Il est possible que certains environnements (réseaux de capteurs industriels) soient encore plus limités en énergie et doivent donc recevoir encore moins de RA.

Pour synthétiser, les recommandations de notre RFC pour les routeurs sont :

  • La possibilité de répondre aux RS par un RA unicast est autorisée par le RFC 4861 mais ce n'est pas obligatoire. Notre RFC demande que cela le devienne et qu'on puisse configurer tous les routeurs pour utiliser cette possibilité. (Si l'adresse source du RS le permet.)
  • Les réseaux ayant beaucoup de machines pauvres en énergie ne devraient pas hurler des RA inutiles en permanence. Ces RA devraient être envoyées rarement (voir les chiffres plus haut) quitte à être plus fréquents immédiatement après un changement de la configuration.

Notez que cela ne change pas le protocole IPv6 : ces recommandations sont déjà des comportements légaux.

Et les recommandations pour les machines terminales sont :

  • Si elles peuvent traiter des paquets IPv6 pendant le mode « économie d'énergie », elles doivent aussi traiter les RA (autrement, elles risquent de rater des changements importants dans la configuration du réseau), quitte à en limiter le traitement s'ils sont trop fréquents (par exemple un RA par minute maximum).
  • Si les machines préfèrent être vraiment silencieuses et inactives pendant cette phase d'économie d'énergie, elles peuvent ignorer les RA mais elles devraient alors se retirer explicitement du réseau lorsqu'elles s'endorment, et refaire la procédure d'arrivée dans un nouveau réseau (par exemple en suivant le RFC 6059) quand elles se réveillent avec du travail à faire (car le réseau aura pu changer pendant leur sommeil).

Enfin, la section 8 du RFC, portant sur la sécurité, rappelle qu'un routeur méchant peut ignorer ces conseils et envoyer beaucoup de RA exprès pour vider les batteries. Il faut donc prendre des mesures contre de tels routeurs (par exemple celle du RFC 6105).

Merci beaucoup à Benjamin Cama pour ses corrections, son analyse détaillée et ses excellentes références (reprises ici).


Téléchargez le RFC 7772


L'article seul

Cours « Internet derrière l'écran » au CELSA

Première rédaction de cet article le 10 février 2016


En janvier et février 2016, j'ai eu le plaisir de faire une série de quatre cours au CELSA (master Médias Informatisés et Stratégies de Communication) sur le thème « Internet derrière l'écran ». Que se passe-t-il derrière les jolies images de chatons ?

Ce cours était décliné en quatre parties et voici les supports de cours correspondants :

Merci à Étienne Candel pour avoir insisté :-) à Alexis Tamas, mon prédécesseur, et à Céline Leclaire pour l'organisation et donc pour avoir supporté mes retards et cafouillages.


L'article seul

RFC 7749: The 'XML2RFC' version 2 Vocabulary

Date de publication du RFC : Février 2016
Auteur(s) du RFC : J. Reschke (greenbytes)
Pour information
Première rédaction de cet article le 7 février 2016


Contrairement à beaucoup de SDO, l'IETF n'a pas de format standard pour l'écriture de ses documents. XML est toutefois le plus répandu, avec le vocabulaire qui avait été autrefois décrit dans le RFC 2629, et qui est maintenant spécifié dans ce RFC. (Il a depuis été remplacé par le RFC 7991.)

Vous voulez écrire un RFC ? Un des choix possibles est un format XML, fondé sur un vocabulaire spécifique aux RFC, et mis en œuvre dans l'outil xml2rfc. Ce vocabulaire n'avait pas été mis à jour depuis seize ans (alors que l'outil évoluait) et c'est seulement maintenant, après un processus long et douloureux, que les auteurs d'Internet-Drafts et de RFC disposent enfin d'une description officielle et à jour du format dans lequel ils travaillent. Voici donc le vocabulaire « XML2RFC version 2 ».

Le format principal de publication des RFC est du texte brut, pour des raisons de portabilité, d'indépendance vis-à-vis de tout éditeur de logiciels spécifique, et de facilité de traitement automatique. Mais aucun auteur n'écrit les RFC directement dans ce format (rien que pour la numérotation des pages, cela serait infernal). Ils écrivent en des formats divers, et le convertissent ensuite en texte brut. À noter que certains éléments XML décrits ici ne produisent rien de particulier dans le texte final, mais sont utiles pour d'autres usages, comme l'indexation.

Voici le squelette d'un Internet-Draft écrit avec ce XML :

    
<?xml version="1.0" encoding="utf-8"?>
<rfc docName="draft-ietf-dnsop-qname-minimisation-09"
     category="exp" ipr="trust200902">
<front>
<title abbrev="Qname minimisation">DNS query name minimisation to improve privacy</title>
...
<middle>
<section anchor="intro" title="Introduction and background">
<t>The problem statement is described in <xref
target="RFC7626"/>. [...]
...
</back>
</rfc>

    

(Un squelette plus détaillé est disponible en https://www.rfc-editor.org/materials/template-bare-06.txt.) Sur ce squelette simple, on voit l'élément racine (<rfc>), l'utilisation des attributs (comme category qui indique le statut du futur RFC, ici « expérimental »), la séparation en trois parties, <front>, qui regroupe les métadonnées, <middle>, qui est le texte principal, et <back>, où se trouvent la bibliographie, les annexes, etc.

Parmi les attributs de cet élément racine <rfc>, notez ipr, qui indique les conditions légales d'utilisation de ce RFC. Dans cet example, la valeur est la plus couramment utilisée : trust200902 (cf. l'annexe A.2) indique les règles de l'IETF Trust datant de 2009 (qui disent en gros que le texte du RFC peut être librement copié, reproduit, distribué et mis en œuvre dans des programmes). L'annexe A de notre RFC détaille ce qu'on appelle le boilerplate, ces textes juridiques obligatoires qui sont ajoutés automatiquement par le logiciel xml2rfc. Ainsi, si on met ipr="trust200902" dans l'élément <rfc>, xml2rfc va automatiquement ajouter « Copyright (c) 2015 IETF Trust and the persons identified as the document authors. All rights reserved. \ This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents [...] »...

Le gros morceau du RFC est la section 2, qui donne la liste des éléments XML acceptés. Je ne vais pas reproduire ici cette liste, juste parler de quelques éléments qui me semblent rigolos.

<section> contient une partie du RFC. Cet élément est hiérarchique : on crée des sous-sections en les mettant sous les sections existantes, et ainsi de suite, récursivement. (Contrairement à ce qui se passe avec HTML, où on indique explicitement le niveau de la section, <h1>, <h2>, etc.)

<t> contient un paragraphe et est donc l'équivalent du <p> de HTML.

<artwork> est le seul élément qui permet de spécifier du texte qui sera représenté comme tel, sans aucune justification, mise à la ligne, etc. Il a gagné plusieurs attributs par rapport au RFC 2629, pour bien contrôler le résultat. <artwork> permet d'include du code source ou bien de mettre de l'art ASCII dans un RFC (pour l'instant, il n'y a pas encore d'autre mécanisme simple pour des images, mais c'est quand même possible, cf. le RFC 5598 avec ses différentes versions). Notez que l'attribut src permet de spécifier un fichier externe, l'art ASCII ne servant alors que de solution de secours, pour le format en texte seul. Voici un exemple :


      <figure title="A network">
	<artwork>
 +--------------+				     +----------------+
 |  Alice       |------------------------------------|      Bob	      |
 | 2001:db8::1  |                                    |   2001:db8::2  |
 +--------------+				     +----------------+
	</artwork>
      </figure>

    

<eref> permet de faire un lien hypertexte vers l'extérieur :


      <t>More text and a <eref
      target="http://www.rfc-editor.org/">lien vers le site du RFC Editor</eref>.</t>
    
    

<list> permet de représenter les traditionnelles listes à puces :


<t>There are three sorts of DNS requests being issued:
<list>
<t>Primary request: [...]</t>
<t>Secondary requests: [...]</t>
<t>Tertiary requests: [...]</t>
</list>
</t>
    
    

<references> permet d'indiquer une bibliographie. Il y en a typiquement deux dans un RFC (cf. la section 4.8.6 du RFC 7322), la bibliographie normative (ce qu'il faut absolument avoir lu et compris car le RFC en dépend) et l'informative (ce qu'on peut sauter si on est pressé). Pour aider, le RFC Editor distribue des fichiers XML contenant les références aux RFC publiés, comme http://www.rfc-editor.org/refs/bibxml/reference.RFC.7626.xml.

Si vous voulez un exemple plus complet, regardez ce fichier. Vous pouvez le traiter avec xml2rfc :

% xml2rfc test-xml2rfc-v2.xml
[...]
Created file test-xml2rfc-v2.txt
    

Et vous obtenez un joli RFC.

Ce format de RFC s'appuie sur XML et il faut donc suivre les règles de XML, notamment sur les caractères spéciaux. Ainsi, le chevron ouvrant doit être remplacé par une séquence d'échappement (&lt; au lieu de <). Si cette contrainte est trop forte, on peut aussi enclore les parties à « échapper » dans une section CDATA.

Le format des RFC ne permet pas d'autres caractères que ceux du jeu ASCII. Néanmoins, certains caractères Unicode peuvent être utiles dans le source XML (section 4), pour contrôler certains aspects de la présentation :

  • Espace insécable U+00A0,
  • Tiret insécable U+2011,
  • Gluon de mots (empêche la césure entre deux lettres) U+2060.

La restriction actuelle à ASCII (elle était dans le RFC 2223, section 3a, mais n'a pas été formellement reprise dans son successeur, le RFC 7322) sera peut-être levée dans le futur, et ce RFC devra alors être mis à jour (section 6).

Le format actuel ne permet pas l'inclusion d'autres documents, donc un RFC doit être en une seule pièce, un seul fichier XML (section 5). On peut toutefois utiliser les mécanismes génériques d'inclusion de XML, et c'est souvent utilisé pour la bibliographie :


   <!DOCTYPE rfc [
     <!ENTITY rfc7830 PUBLIC
     "http://xml.resource.org/public/rfc/bibxml/reference.RFC.7830.xml">
   ]>

[...]
     <references>
       &rfc7830;
     </references>
	     
    

À noter qu'il existe désormais un type MIME pour les sources XML de RFC, application/rfc+xml (section 8 de notre RFC).

Si vous voulez voir le schéma XML complet, il est en annexe C (j'en ai exporté une version utilisable telle quelle, sans les sauts de page des RFC, en rfc-schema.rnc). Comme il est écrit en Relax NG, il permet l'utilisation de tous les outils Relax NG, comme le mode emacs nxml-mode et comme rnv. Ainsi, une fois le fichier rfc-schema.rnc chargé dans emacs (menus XML puis Set schema puis File), on dispose de fonctions d'édition bien pratiques (par exemple, on tape un < puis une tabulation et emacs propose de compléter uniquement avec les éléments autorisés à cet endroit). Cela évite bien des erreurs.

À noter que ce RFC ne décrit que les éléments et attributs XML, pas les processing instructions (PI) <?rfc ... ?> qui servent, par exemple, à contrôler si une table des matières est affichée. Pour connaitre celles acceptées par xml2rfc, il faut regarder la documentation de l'outil et la FAQ.

Avec un logiciel comme rnv, on peut tester la syntaxe (uniquement la syntaxe : certaines contraintes dans le RFC ne sont pas exprimables dans le schéma, il a fallu les formuler en langue naturelle dans le texte du RFC) :

% rnv rfc.rnc test-xml2rfc-v2.xml
test-xml2rfc-v2.xml
    

Parfait, ici, tout est bon. S'il y avait eu une erreur :

% rnv rfc.rnc test-xml2rfc-v2.xml
test-xml2rfc-v2.xml
test-xml2rfc-v2.xml:9:4: error: element ^t not allowed
required:
	element ^section
    

Si le RFC contient des références externes (que rnv ne sait pas traiter), on peut utiliser xmllint pour les remplacer :

%  xmllint --dropdtd --noent draft-ietf-dnsop-nxdomain-cut.xml | rnv rfc.rnc 
    

À noter que le RFC n'utilise pas rnv mais Jing (annexe C.1). Mode d'emploi très court, on télécharge :

%  https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/jing-trang/jing-20091111.zip
% unzip jing-20091111.zip
% java -jar ./jing-20091111/bin/jing.jar  -c rfc.rnc draft-ietf-dnsop-nxdomain-cut.xml
%
     

Les changements depuis le texte précédent, le RFC 2629, seize ans auparavant, sont résumés dans l'annexe B. L'élément <appendix>, qui servait pour les annexes des RFC (annexes assez fréquentes, de nos jours), a été supprimé. Pour faire une annexe, désormais, on met une <section> dans le <back>. En revanche, sept nouveaux éléments ont été ajoutés dont les plus importants, à mon avis, sont <texttable>, <ttcol> et <c>, qui permettent enfin de faire des tableaux proprement dans les RFC.


Téléchargez le RFC 7749


L'article seul

RFC 7739: Security Implications of Predictable Fragment Identification Values

Date de publication du RFC : Février 2016
Auteur(s) du RFC : F. Gont (SI6 Networks / UTN-FRH)
Pour information
Réalisé dans le cadre du groupe de travail IETF 6man
Première rédaction de cet article le 7 février 2016


Le protocole IPv6 a un mécanisme de fragmentation des paquets. L'en-tête d'un fragment contient un champ « Identification » (RFC 2460, section 4.5) qui, avec les deux adresses Source et Destination, identifie de manière unique un paquet fragmenté (tous les fragments de ce paquet ont le même identificateur), et permet donc le réassemblage à la destination. La façon la plus simple d'affecter ces identificateurs est d'avoir, dans chaque machine, un compteur global incrémenté à chaque paquet qu'on fragmente (section 1 du RFC). Une telle façon de faire mène à des identificateurs prévisibles : un observateur qui se connecte à cette machine peut prévoir quel sera l'identificateur du paquet suivant. Cela a de sérieuses conséquences en terme de sécurité. Ce RFC explore ces conséquences, et propose des solutions.

Petit rappel au passage sur la fragmentation IPv6 : contrairement à la fragmentation IPv4, elle ne peut se faire que dans la machine émettrice, pas dans les routeurs intermédiaires. Voici un exemple de paquet fragmenté, vu par tcpdump, la réponse DNS, trop grosse, a été fragmentée en deux :

10:45:24.818912 IP6 (hlim 56, next-header Fragment (44) payload length: 432) 2001:4b98:dc2:45:216:3eff:fe4b:8c5b > 2001:67c:1348:7::86:133: frag (0x000079cc:0|424) 53 > 37407: 25110*- q: ANY? . 24/0/1 . [1d] DNSKEY, . [1d] DNSKEY, . [1d] DNSKEY[|domain]
10:45:24.819008 IP6 (hlim 56, next-header Fragment (44) payload length: 1458) 2001:4b98:dc2:45:216:3eff:fe4b:8c5b > 2001:67c:1348:7::86:133: frag (0x000079cc:424|1450)
    

Le paquet a l'identificateur 0x000079cc, seul le premier fragment (de l'octet 0 à l'octet 423) a pu être analysé (il avait le début de la réponse DNS). Et voici les deux fragments, analysés par tshark :

    Type: IPv6 (0x86dd)
      Internet Protocol Version 6, Src: 2001:4b98:dc2:45:216:3eff:fe4b:8c5b, Dst: 2001:67c:1348:7::86:133
    Next header: Fragment Header for IPv6 (44)
    Fragment Header
        Next header: UDP (17)
        Reserved octet: 0x0000
        0000 0000 0000 0... = Offset: 0 (0 bytes)
        .... .... .... .00. = Reserved bits: 0
        .... .... .... ...1 = More Fragments: Yes
        Identification: 0x000079cc

    Type: IPv6 (0x86dd)
	Internet Protocol Version 6, Src: 2001:4b98:dc2:45:216:3eff:fe4b:8c5b, Dst: 2001:67c:1348:7::86:133
    Next header: Fragment Header for IPv6 (44)
    Fragment Header
        Next header: UDP (17)
        Reserved octet: 0x0000
        0000 0001 1010 1... = Offset: 53 (424 bytes)
        .... .... .... .00. = Reserved bits: 0
        .... .... .... ...0 = More Fragments: No
        Identification: 0x000079cc

  [2 IPv6 Fragments (1874 bytes): #2(424), #3(1450)]
        [Frame: 2, payload: 0-423 (424 bytes)]
        [Frame: 3, payload: 424-1873 (1450 bytes)]
        [Fragment count: 2]
        [Reassembled IPv6 length: 1874]
        [Reassembled IPv6 data: 0035921f0752901c6216850000010018000000010000ff00...]
    

Le RFC 2460, section 4.5, indique une seule obligation à la machine fragmenteuse : l'identificateur de paquet doit être unique parmi tous les paquets émis récemment par cette machine, pour éviter toute collision. Ce RFC 2460 donne même le conseil malheureux d'utiliser un compteur global, incrémenté à chaque paquet, pour cela.

Pourquoi, « malheureux » ? Parce que cela rend l'identificateur de paquet prévisible pour un observateur extérieur, faisant ainsi fuir de l'information qui peut être utilisée pour certaines attaques (section 3) :

  • L'observateur peut découvrir le débit de la machine émettrice,
  • Il peut procéder à des balayages de ports très discrets, en utilisant la machine aux identificateurs prévisibles (détails plus loin),
  • Il peut compter le nombre de machines situées derrière un routeur NAT,
  • Et surtout, il peut faire des attaques par déni de service (en empêchant le réassemblage, par exemple en envoyant des faux fragments recouvrant en partie des fragments légitimes) ou, encore pire, injecter du contenu dans un paquet (comme dans l'attaque Shulman contre le DNS).

Ces attaques n'ont rien de spécifique à IPv6 : des identificateurs de paquet prévisibles ont les mêmes conséquences en IPv4 (voir les articles pionniers de Sanfilippo ici ou , puis de nombreux autres papiers cités dans la bibliographie de notre RFC, en section 9). Le RFC 6274 décrit en détail ces attaques pour IPv4.

En IPv4, le champ Identification fait partie de chaque paquet (RFC 791, section 3.1) puisque tout routeur pourra fragmenter ce paquet. En IPv6, ce champ n'est présent que dans les paquets fragmentés, dans un « en-tête d'extension » optionnel. Cela rend les attaques un peu plus compliquées en IPv6 : l'attaquant doit d'abord forcer une fragmentation. Une des possibilités pour cela est d'envoyer un paquet ICMP Packet Too Big. Si, en plus, le paquet ICMP contient une MTU inférieure à 1 280 octets, les paquets ne seront pas fragmentés mais porteront quand même l'en-tête d'extension Fragment Header (c'est ce qu'on appellait des « fragments atomiques », cf. RFC 6946, fragments atomiques dont l'usage est désormais abandonné, voir le RFC 8021).

En théorie, rien de plus simple que d'envoyer un faux paquet ICMP Packet Too Big. En pratique, il y a quelques limitations pour l'attaquant :

  • Les mises en œuvre d'IPv6 mémorisent une PMTU par destination. Il faudra donc envoyer un paquet ICMP contenant l'adresse IP vers laquelle on veut que des fragments soient générés.
  • Comme les paquets ICMP ne sont pas signés, les mises en œuvre d'IP savent bien qu'elles doivent s'en méfier, et déploient souvent les précautions du RFC 5927.

Pour éviter ces attaques, que faudrait-il faire ? On souhaite des identificateurs de paquets imprévisibles, mais en même temps ils ne doivent pas être réutilisés, du moins tant qu'on n'est pas sûr que les paquets portant précédemment cet identificateur n'ont pas terminé leur voyage dans le réseau. Des identificateurs complètement aléatoires, par exemple, ne sont pas si idéaux qu'ils le paraissent : il y a un risque de réutilisation accidentelle. Autre contrainte sur les algorithmes de génération de ces identificateurs : ils doivent être très rapides, puisqu'il faut les faire tourner pour chaque paquet fragmenté.

La section 5 de notre RFC décrit les algorithmes possibles. On a vu que l'algorithme « compteur global » était exclu, car il produit des identificateurs prévisibles. Que reste-t-il ?

Le premier algorithme possible (section 5.1) est « un compteur par destination ». On maintient un compteur par adresse IP de destination utilisée, qu'on initialise avec une valeur aléatoire. Simple à mettre en œuvre (il faut juste un générateur de nombres aléatoires), sans réutilisation (pour qu'il y ait collision, il faudrait qu'on émette tellement de paquets vers une destination donnée que le compteur, de 32 bits, déborde), et très rapide (une fois la valeur initiale choisie). Par contre, le prochain identificateur de fragment reste prévisible, mais uniquement pour la machine de destination. Cela peut être utilisé dans certaines attaques. Et il consomme pas mal de mémoire (une entrée par destination), mémoire qu'on ne peut pas libérer, sauf à risquer des collisions d'identificateurs.

Deuxième algorithme envisageable, « identificateur aléatoire » (section 5.2). Idéal pour la sécurité, mais il fait courir des risques de réutilisation des identificateurs, et il est plus coûteux en temps de calcul.

Enfin, un troisième algorithme possible est « condensation de variables » (section 5.3). On prend des variables comme les adresses source et destination, un compteur (pas forcément global), une valeur secrète et on condense le tout. Non, je simplifie trop. En fait, pour être le plus rapide possible tout en étant imprévisible, on a un tableau de compteurs (pas un par destination, mais pas non plus un seul), la condensation des adresses et d'un secret donne l'index dans ce tableau, et on concatène ce compteur avec un autre condensat, fait avec un autre secret. Le résultat est imprévisible de l'extérieur (mais prévisible par le destinataire) et la réutilisation est plus lente qu'avec un compteur global, et cet algorithme peut être mis en œuvre de façon à être très rapide.

L'annexe B de notre RFC est le résultat d'une étude de la prédictabilité par système d'exploitation, en utilisant l'outil frag6, qui vient du toolkit SI6. On peut refaire la même étude chez soi :

% sudo frag6  --frag-id-policy -d www.example
Identifying the 'Fragment ID' generation policy of the target node....
Fragment ID policy: Per-destination IDs with increments of 2 (sdev: 1.112134)
      

La destination est un FreeBSD, qui utilise des identificateurs aléatoires depuis sa version 9 :

%  sudo frag6   --frag-id-policy -d www.freebsd.org
Identifying the 'Fragment ID' generation policy of the target node....
Fragment ID policy: Randomized IDs (Avg. inc.: 2101165500, sdev: 1531579889.681898)
      

Ici, un Linux récent, avec des compteurs par destination :

	%  sudo frag6   --frag-id-policy -d 2001:db8:9321:8bb0:9da8:f055:5381:d54c
Identifying the 'Fragment ID' generation policy of the target node....
Fragment ID policy: Per-destination IDs with increments of 1 (sdev: 1.504380)
      

On voit, après cet essai sur trois machines différentes, que les différents algorithmes sont toujours utilisés.


Téléchargez le RFC 7739


L'article seul

RFC 7680: A One-Way Loss Metric for IPPM

Date de publication du RFC : Janvier 2015
Auteur(s) du RFC : G. Almes (Texas A&M), S. Kalidindi (Ixia), M. Zekauskas (Internet2), A. Morton (AT&T Labs)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF ippm
Première rédaction de cet article le 1 février 2016


Une des tristes réalités de l'Internet d'aujourd'hui est que les paquets se perdent. Ils quittent la machine émettrice et ne sont jamais reçus par la machine réceptrice. Il y a de nombreuses causes à cela (abandon du paquet par un routeur surchargé, par exemple), mais ce RFC 7680, comme les autres documents du groupe de travail IPPM se focalise sur la mesure du phénomène, pas sur ses causes. Il définit donc une métrique « perte de paquet » permettant de comparer des mesures entre elles en sachant qu'on parle bien de la même chose. (Ce RFC remplace la première définition, qui était dans le RFC 2680.)

Comme les autres RFC décrivant des métriques, des grandeurs rigoureusement définies et qu'on va mesurer, il s'appuie sur les définitions et le vocabulaire des RFC 2330 et RFC 7312. Par ailleurs, il suit de très près le plan du RFC 2679, qui spécifiait la mesure du délai d'acheminement d'un paquet. Cette fois, ce qui est défini est une mesure binaire (un paquet est perdu ou bien ne l'est pas), Type-P-One-way-Loss, puis une statistique pour le cas où il y a plusieurs paquets, le taux de perte moyen. (Petit rappel : Type-P signifie que le rapport de mesure doit indiquer le type du paquet - protocole de transport, port, etc - car le résultat peut en dépendre. Cf. section 2.8.1.)

Pourquoi cette métrique est-elle utile ? La section 1.1 rappelle l'intérêt de connaître les pertes :

  • Certaines applications, notamment interactives, se comportent mal (ou pas du tout) si le taux de pertes dépasse un certain seuil.
  • Les applications plus ou moins temps-réel aiment encore moins les pertes de paquets que les autres applications.
  • Les protocoles de transport comme TCP compensent les pertes en réémettant les paquets mais un taux de pertes trop élevé les empêchera d'atteindre leur débit maximum.

Mais pourquoi mesurer les pertes sur un chemin aller-simple (one-way) plutôt que aller-retour (two-way) ? La célébrissime commande ping affiche en effet des pertes après un aller-retour (ici 57 %) :

% ping -c 19 198.51.100.80 
PING 198.51.100.80 (198.51.100.80) 1450(1478) bytes of data.
1458 bytes from 198.51.100.80: icmp_seq=1 ttl=46 time=168 ms
1458 bytes from 198.51.100.80: icmp_seq=5 ttl=46 time=167 ms
1458 bytes from 198.51.100.80: icmp_seq=6 ttl=46 time=167 ms
1458 bytes from 198.51.100.80: icmp_seq=9 ttl=46 time=169 ms
1458 bytes from 198.51.100.80: icmp_seq=10 ttl=46 time=167 ms
1458 bytes from 198.51.100.80: icmp_seq=13 ttl=46 time=168 ms
1458 bytes from 198.51.100.80: icmp_seq=15 ttl=46 time=168 ms
1458 bytes from 198.51.100.80: icmp_seq=18 ttl=46 time=167 ms
--- 198.51.100.80 ping statistics ---
19 packets transmitted, 8 received, 57% packet loss, time 18013ms
rtt min/avg/max/mdev = 167.407/168.034/169.066/0.639 ms

Mais les mesures aller-retour ont bien des limites :

  • Si le chemin est asymétrique, on mesure en fait les performances de deux chemins, l'aller et le retour, qui n'ont pas forcément les mêmes caractéristiques. Même si le chemin est symétrique (passage par les mêmes routeurs à l'aller et au retour), rien ne dit que les résultats soient les mêmes dans les deux sens : files d'attente différentes, QoS peut-être réglée différemment, etc.
  • Beaucoup d'applications, par exemple les transferts de fichiers, voient leurs performances dépendre essentiellement d'un seul chemin (pour un transfert de fichiers, celui que suivent les données, pas le chemin inverse par lequel ne transitent que les petits accusés de réception).

Mais les mesures aller-simple sont plus difficiles à effectuer entre autres parce qu'elles ont souvent besoin d'horloges synchronisées (section 1.2). Le principe de la mesure de notre métrique est en effet d'émettre un paquet depuis la machine source à un temps T et de l'attendre à la machine destination jusqu'au temps T + t (où t est le délai qu'on accepte d'attendre). Si les horloges des deux machines ne sont pas synchronisées, leurs mesures de T vont différer, faussant ainsi les résultats. La section 1.2 rappelle donc le vocabulaire à utiliser pour évaluer la synchronisation. Les gourous de l'horlogerie verront qu'il est différent de celui des documents UIT comme le G.810, « Definitions and terminology for synchronization networks ».

  • Synchronisation (synchronization) signifie que deux horloges sont d'accord entre elles sur l'heure qu'il est (time error pour l'UIT).
  • Correction (accuracy) désigne le degré d'accord entre une horloge et la vraie heure UTC (time error from UTC pour l'UIT). Deux horloges peuvent donc être synchronisées et néanmoins incorrectes (ce qui n'est pas un grave problème pour nos métriques aller-simple).
  • Résolution (resolution) est la précision de l'horloge. Certains vieux Unix n'avancent ainsi l'horloge que toutes les dix ms et sa résolution est donc de 10 ms (cela se voyait bien avec la commande ping, qui n'affichait que des RTT multiples de 10). L'UIT dit sampling period.
  • Décalage (skew) est le changement dans la synchronisation ou la correction. Il se produit lorsque l'horloge va plus ou moins vite qu'elle ne le devrait. L'UIT appelle cela time drift.

Une fois ces préliminaires achevés, la section 2 décrit la métrique principale de notre RFC, Type-P-One-way-Packet-Loss. Sa valeur est simplement 0 lorsque le paquet est arrivé et 1 autrement.

Il y a bien sûr davantage de choses à dire sur cette métrique. Par exemple (section 2.5), faut-il distinguer le cas où un paquet a vraiment été perdu et le cas où il est simplement arrivé en retard, après l'expiration du délai ? En théorie, on devrait attendre 255 secondes, la durée de vie maximale d'un paquet IPv4 (RFC 791, section 3.2, notez qu'IPv6 n'a aucune limite, cf. RFC 2460, section 8.2). En pratique, on attendra moins longtemps : après tout, pour beaucoup d'applications, un paquet en retard n'a aucun intérêt, on peut aussi bien le considérer comme perdu. C'est l'approche retenue ici. (Par exemple, l'outil de test DNS dig attend, par défaut, cinq secondes avant de considérer la réponse comme perdue.)

Et si le paquet arrive corrompu, le considère-t-on comme perdu ? Là encore, oui, pas de distinction. En effet, si le paquet est corrompu, on ne peut même pas être sûr qu'il était bien le paquet attendu, puisque les bits qui permettent de le reconnaître sont peut-être ceux qui ont été changés.

Même chose si le paquet est fragmenté et que certains des fragments n'arrivent pas du tout. On ne peut pas reconstituer le paquet, on le considère comme perdu. En revanche, la duplication, elle, n'est pas considérée comme une perte.

Notre RFC 7680 décrit une métrique (une grandeur définie rigoureusement), pas une méthodologie de mesure, encore moins un protocole. Toutefois, la section 2.6 donne des indications sur ce que pourrait être une telle méthodologie. Le mécanisme recommandé est de mettre une estampille temporelle dans le paquet émis, et de regarder à l'arrivée si on détecte le paquet au bout d'un temps « raisonnable ». À noter que cette méthode n'implique pas une stricte synchronisation des horloges entre les deux machines. On est loin d'un protocole complet (je n'ai pas l'impression qu'il ait jamais été mis au point) et, par exemple, on n'indique pas comment la destination sait qu'elle doit s'attendre à voir arriver un paquet.

Toute mesure implique des erreurs et des incertitudes et la section 2.7 les analyse. D'abord, si les horloges ne sont pas synchronisées du tout, un paquet peut être déclaré comme perdu à tort (si l'émetteur a une horloge qui retarde, le paquet arrivera tard et le destinataire aura pu s'impatienter et le considéré perdu). Même problème si le délai d'attente n'est pas raisonnable, si le destinataire renonce trop vite. Ces deux problèmes peuvent être évités en synchronisant à peu près les horloges (il suffit que leur écart soit petit par rapport au délai d'attente) et en choisissant bien le délai (par exemple, sur une liaison utilisant un satellite géostationnaire, la finitude de la vitesse de la lumière impose un délai d'attente minimum de 240 ms - 2 * 35 786 / 300 000).

Une troisième source d'erreur est plus subtile : le paquet peut arriver jusqu'à la machine de destination (donc le réseau fonctionne bien) mais celle-ci le rejeter car ses ressources (par exemple les tampons d'entrée/sortie) sont pleines. Pour éviter de compter à tort des paquets comme perdus, il faut s'assurer que la machine de mesure a des ressources suffisantes pour traiter tous les paquets.

La section 2.8 se penche sur la publication des résultats (voir aussi l'excellent RFC 6703). Par exemple, elle impose de publier le Type-P (comme vu plus haut, le taux de pertes peut être différent en TCP et en UDP, par exemple), le seuil de patience (« le pourcentage de paquets non arrivés au bout de 1 500 ms est de X % »), et recommande de publier, autant que possible, le chemin parcouru (entre deux machines, si le chemin change par suite de modifications de routage, le taux de perte va probablement changer).

La métrique présentée en section 2 était pour un paquet. La section 3 définit une métrique supplémentaire, Type-P-One-way-Packet-Loss-Poisson-Stream pour le cas où on utilise plusieurs paquets. Elle utilise une distribution de Poisson (ce n'est pas la seule possible mais elle est d'usage très fréquent). Et la section 4 s'en sert pour définir une statistique utile. Type-P-One-way-Packet-Loss-Ratio (section 4.1, attention, elle a changé de nom depuis le RFC 2680) est le taux de pertes moyen. Si on envoie cinq paquets et que quatre arrivent, elle vaut 0,2 (c'est ce qu'affiche ping sous l'intitulé % packet loss mais attention, ping fait une mesure aller-retour et pas aller-simple comme notre RFC).

Cette moyenne n'est pas toujours facile à évaluer. Ainsi, sur un lien Internet typique, le taux de pertes est bas (nettement moins de 1 %). Pour obtenir une valeur statistiquement significative, il faut souvent tester avec des centaines de paquets.

Comme le note la section 5, consacrée à la sécurité, un problème courant des mesures actives est qu'elles peuvent perturber le réseau qu'elle observent. Si ces mesures actives ne posent pas trop de problèmes de vie privée (on ne mesure pas le trafic existant, mais seulement celui qu'on a créé), elles peuvent par contre faire mal au réseau. Il faut donc prendre soin de ne pas injecter « trop » de paquets (cf. l'option -f de ping).

Après « les mesures qui font du mal au réseau », il y a un autre risque de sécurité, « le réseau qui fait du mal aux mesures ». Imaginons qu'on mesure les performances d'un opérateur réseau et qu'un concurrent envoie exprès un trafic intense au même moment, les résultats seront mauvais. La publication des résultats devrait donc être accompagnée d'une description des solutions utilisées qui permettent de limiter le risque de ce genre d'attaques. (Cela peut être aussi simple que de ne pas communiquer à l'avance les moments où se font les mesures.)

Le RFC mentionne aussi le risque d'une « mesure Volkswagen » : un opérateur peut reconnaître les paquets de mesure et leur donner un traitement préférentiel. Là encore, il faut indiquer les solutions choisies pour que les paquets de mesure ne soient pas favorisés (par exemple en faisant en sorte qu'ils ressemblent autant que possible à des paquets « normaux »).

La section 6 de notre RFC présente les (très faibles) différences avec la précédente norme, le RFC 2680. Le but principal du nouveau RFC (projet documenté dans le RFC 6576) était de faire avancer cette métrique sur le « chemin des normes » (cf. RFC 2026), de « proposition de norme » à « norme [tout court] ». Les tests du RFC 7290 (voir aussi le rapport sur le RFC 2680) ont montré que les métriques Internet étaient sérieuses et utilisables, justifiant cet avancement sur le chemin des normes.

Les changements dans le texte sont minimes, comme l'introduction des références au RFC sur la publication de mesures, RFC 6703 et à d'autres RFC publiés depuis (comme le RFC 4737 sur le réordonnancement des paquets), la correction de petites erreurs, l'accent plus important sur la protection de la vie privée, etc.


Téléchargez le RFC 7680


L'article seul

RFC 7679: A One-Way Delay Metric for IPPM

Date de publication du RFC : Janvier 2015
Auteur(s) du RFC : G. Almes (Texas A&M), S. Kalidindi (Ixia), M. Zekauskas (Internet2), A. Morton (AT&T Labs)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF ippm
Première rédaction de cet article le 1 février 2016


Ce RFC définit une métrique, une grandeur à mesurer, en l'occurrence le délai d'acheminement d'un paquet d'un point à un autre du réseau. Cela semble trivial, mais la définition rigoureuse de la métrique, permettant des mesures scientifiques et leur comparaison, prend vingt pages... Elle remplace l'ancienne définition, qui était normalisée dans le RFC 2679.

Comme tous les RFC du groupe de travail ippm, celui-ci s'appuie sur les définitions et le vocabulaire du RFC 2330, notamment la notion de Type-P (paquets IP ayant la même « signature », c'est-à-dire même protocole de couche 4, même numéro de port, etc, car certains équipements réseaux traitent différemment les paquets selon ces variables).

Commençons par le commencement, c'est-à-dire l'introduction, en section 1. Le RFC définit une métrique pour une mesure unique (un singleton) nommé Type-P-One-way-Delay, ainsi qu'un échantillonnage, pour le cas où la mesure est répétée, et enfin diverses statistiques agrégeant les résultats de plusieurs mesures. Pourquoi une telle métrique ? Comme le rappelle la section 1.1, celle-ci est utile dans des cas comme, par exemple :

  • Estimer le débit maximal qu'on obtiendra (avec certains protocoles comme TCP, il est limité par le RTT, cf. le RFC 7323).
  • La valeur minimale de ce délai d'acheminement nous donne une idée du délai dû uniquement à la propagation (qui est limitée par la vitesse de la lumière) et à la transmission. (Voir aussi la section 4.3.)
  • Par contre, son augmentation nous permet de détecter la présence de congestion.

Mais pourquoi un délai d'acheminement « aller-simple » et pas « aller-retour », comme le fait ping, ou bien comme le normalise le RFC 2681 ? Après tout, le délai aller-retour est bien plus simple à mesurer. Mais il a aussi des défauts :

  • Une bonne partie des routes sur l'Internet sont asymétriques. Le délai aller-retour dépend donc de deux délais aller-simple, qui peuvent être très différents.
  • Même si le chemin est symétrique, les politiques de gestion de la file d'attente par les routeurs peuvent être très différentes dans les deux sens.
  • Certains protocoles s'intéressent surtout aux performances dans une direction. C'est le cas du transfert d'un gros fichier, où la direction des données est plus importante que celle des accusés de réception.

Le RFC ne le mentionne apparemment pas, mais on peut aussi dire que la mesure d'un délai aller-retour dépend aussi du temps de réflexion par la machine distante (avec ping, si la machine visée est très chargée, la génération du paquet ICMP de réponse peut prendre un temps non négligeable ; c'est encore pire avec des protocoles applicatifs, où la réflexion n'est pas faite dans le noyau, et est donc sensible à par exemple, le swapping).

Comme avec tout système de mesure, les horloges et leurs imperfections jouent un rôle crucial. La section 2 rappelle des concepts (voir le RFC 2330) comme la synchronisation (le fait que deux horloges indiquent la même valeur) ou le décalage (le fait qu'une horloge aille plus ou moins vite qu'une autre).

Enfin, après tous ces préliminaires, le RFC en arrive à la définition de la métrique, en section 3. Type-P-One-way-Delay est définie comme une fonction de divers paramètres comme les adresses IP des deux parties et l'instant de la mesure. La mesure dépend aussi du Type-P (par exemple parce que certains ports sont favorisés par la QoS ; notez que si la QoS dépend d'une DPI, la définition du Type-P ne suffira pas). Elle est en secondes. Et sa définition (section 3.4) est « Le temps entre l'envoi du premier bit du paquet sur le câble et la réception du dernier bit du paquet depuis le câble ». Si le paquet n'arrive pas, le délai est dit « indéfini » et, en pratique, pris comme étant infini. Les programmeurs noteront donc qu'il n'est pas possible de mesurer cette valeur avec l'API Posix, qui ne donne pas accès à des détails aussi précis.

Ce n'est pas tout de définir une métrique, il faut aussi la mesurer. Dans le monde réel, cela soulève quelques problèmes, couverts par la section 3.5. Le principal étant évidemment la synchronisation des horloges. Si le paquet part à 1247389451,578306110 (en secondes depuis le 1er janvier 1970) et arrive à 1247389453,018393817, le délai a-t-il réellement été de 1,44 secondes ou bien seulement de 1,32 secondes mais les horloges différaient de 0,12 secondes ? Comme des délais peuvent être aussi bas que 100 µs, une synchronisation précise est nécessaire. Le GPS est une bonne solution pour cela, NTP une moins bonne, car sa résolution est plus faible (de l'ordre de plusieurs ms) et il dépend du réseau qu'on veut mesurer.

Il faut aussi tenir compte de problèmes comme les paquets perdus (si le délai de garde est de cinq secondes, un paquet perdu ne doit pas compter pour un délai d'acheminement de cinq secondes, ou bien des agrégats comme la moyenne seront complètement faussés) ou comme la duplication de paquets (dans ce cas, le RFC précise que c'est la première occurrence qui compte). Le délai de garde (délai d'attente maximal avant de considérer un paquet comme perdu) ne doit pas être trop bas, sinon on risque de sur-estimer les performances du réseau, en éliminant les paquets lentement acheminés.

Enfin, pour celui qui voudrait concevoir un protocole de mesure de cette métrique, le RFC suggère une méthodologie, en section 3.6 :

  • S'assurer de la synchronisation des horloges,
  • Former le paquet et y mettre l'instant de départ sur le câble (sur une machine non temps réel, cela peut être délicat de mettre cet instant exact),
  • À la réception, mesurer l'instant et calculer la différence avec ce qui est indiqué dans le paquet,
  • Évaluer l'erreur (il y en aura forcément) et, éventuellement, corriger.

Cette question de l'analyse d'erreur fait l'objet de la section 3.7. Les deux principales sources d'erreur seront liées aux horloges (qui ne sont jamais parfaites) et à la différence entre le temps de départ ou d'arrivée mesuré et le temps réel. Sur un système d'exploitation multi-tâches et non temps réel comme Unix, le temps entre le moment où le paquet arrive dans la carte Ethernet et celui où l'application peut appeler gettimeofday() est souvent significatif (section 3.7.2) et, pire, variable et imprévisible (car on dépend de l'ordonnanceur). Parmi les mécanismes pour déterminer l'erreur, de façon à pouvoir effectuer les corrections, le RFC suggère la calibration (section 3.7.3), en répétant de nombreuses fois la mesure. Cette partie sur l'analyse des erreurs est détaillée et explique en partie la longueur du RFC : la métrologie n'est pas une science simple !

À noter que les deux horloges, à l'arrivée et au départ, ont besoin d'être synchronisées mais n'ont pas forcément besoin d'être correctes. La correction reste quand même utile, car les délais peuvent dépendre de l'heure de la journée et il faut donc indiquer celle-ci dans le rapport final.

Une fois qu'on a bien travaillé et soigneusement fait ses mesures, il est temps de les communiquer à l'utilisateur. C'est l'objet de la section 3.8. Elle insiste sur l'importance d'indiquer le Type-P, les paramètres, la méthode de calibration, etc. Si possible, le chemin suivi par les paquets dans le réseau devrait également être indiqué.

Maintenant, la métrique pour une mesure isolée, un singleton, est définie. On peut donc bâtir sur elle. C'est ce que fait la section 4, qui définit une mesure répétée, effectuée selon une distribution de Poisson, Type-P-One-way-Delay-Poisson-Stream.

Une fois cette métrique définie, on peut créer des fonctions d'agrégation des données, comme en section 5. Par exemple, la section 5.1 définit Type-P-One-way-Delay-Percentile qui définit le délai d'acheminement sous lequel se trouvent X % des mesures (les mesures indéfinies étant comptées comme de délai infini). Ainsi, le 95e percentile indique le délai pour lequel 95 % des délais seront plus courts (donc une sorte de « délai maximum en écartant les cas pathologiques »). La section 5.2 définit Type-P-One-way-Delay-Median qui est la médiane (équivalente au 50e percentile, si le nombre de mesures est impair). La moyenne, moins utile, n'apparait pas dans ce RFC.

Au moins un protocole a été défini sur la base de cette métrique, OWAMP, normalisé dans le RFC 4656 et mis en œuvre notamment dans le programme de même nom.

Le but principal du nouveau RFC (projet documenté dans le RFC 6576) était de faire avancer cette métrique sur le « chemin des normes » (cf. RFC 2026), de « proposition de norme » à « norme [tout court] ». Les tests du RFC 6808 (voir aussi le rapport sur le RFC 2679) ont montré que les métriques Internet étaient sérieuses et utilisables, justifiant cet avancement sur le chemin des normes.

La section 7 décrit les (rares) changements depuis le RFC 2679. Le RFC 6808 notait plusieurs problèmes avec le RFC 2679, problèmes qui ont été traités par ce nouveau RFC 7679. Par exemple, la métrique Type-P-One-way-Delay-Inverse-Percentile, définie dans le RFC 2679 mais jamais mise en œuvre, est abandonnée. D'autre part, une bogue a été corrigée. Les autres changements sont l'introduction des références au RFC sur la publication de mesures, RFC 6703 et à d'autres RFC publiés depuis, ainsi que l'accent plus important sur la protection de la vie privée. Notre nouveau RFC note aussi que le groupe de travail a étudié les conséquences du RFC 6921 (dont vous noterez la date de parution) et conclut que, même avec des délais de propagation négatifs, les métriques décrites ici ne nécessitaient pas de mise à jour.


Téléchargez le RFC 7679


L'article seul

RFC 7748: Elliptic Curves for Security

Date de publication du RFC : Janvier 2016
Auteur(s) du RFC : A. Langley (Google), M. Hamburg (Rambus Cryptography Research), S. Turner (IECA)
Pour information
Réalisé dans le cadre du groupe de recherche IRTF cfrg
Première rédaction de cet article le 24 janvier 2016
Dernière mise à jour le 29 janvier 2016


Ce nouveau RFC est la description de deux courbes elliptiques largement utilisées mais qui n'avaient pas fait l'objet d'une description formelle complète : curve25519 et curve448. Maintenant que c'est fait, elles pourront être utilisées dans des normes Internet utilisant la cryptographie comme TLS ou DNSSEC.

La cryptographie sur les courbes elliptiques est une alternative aux algorithmes traditionnels fondés sur la décomposition en facteurs premiers, comme le classique RSA. Il est toujours bon de ne pas mettre tous ses œufs dans le même panier, car on ne sait jamais quelle sera la prochaine victime de la cryptanalyse (d'où le RFC 7696, sur l'importance de ne pas être prisonnier d'un seul algorithme). Grâce aux courbes elliptiques, si RSA est cassé complètement, on aura une solution de rechange. En outre, la cryptographie sur les courbes elliptiques a des propriétés intéressantes, comme des clés de taille plus petite. Dans les deux cas, RSA ou courbes elliptiques, je n'y connais pas grand'chose donc n'espérez pas des explications plus pointues.

Le schéma général de la cryptographie sur courbes elliptiques est décrit dans le RFC 6090 (voir aussi le cours « SEC 1: Elliptic Curve Cryptography »). Ce schéma permet l'utilisation d'une infinité de courbes elliptiques mais attention, toutes n'ont pas les propriétés requises. La plus connue est la courbe P-256 normalisée par le NIST. Comme il y a de très bonnes raisons de se méfier du NIST (leur rôle dans l'affaiblissement délibéré de Dual EC DRBG, cf. l'article de Schneier et celui de Greenemeier), et comme les raisons des choix des paramètres de P-256 n'ont jamais été rendues publiques, beaucoup de gens se méfient de P-256 (voir une bonne discussion sur StackExchange). Il est donc important, là encore, d'avoir plusieurs fers au feu, et de disposer d'autres courbes.

Les deux courbes décrites dans ce RFC sont curve25519 et curve448. Elles sont de la famille des courbes de Montgomery (et donc ont une équivalence avec une courbe d'Edwards).

Il n'est pas facile de faire des maths dans un RFC, avec leur format actuel. La section 3 décrit la notation utilisée dans le RFC, mais je ne vais pas reproduire les équations ici (je suis complètement ignorant de MathML et ce blog ne le gère pas). Des formules comme (section 4.1) :

     (u, v) = ((1+y)/(1-y), sqrt(-486664)*u/x)
     (x, y) = (sqrt(-486664)*u/v, (u-1)/(u+1))
    

sont nettement moins jolies dans le texte brut des RFC.

La section 4 du RFC décrit les deux courbes. Curve25519 doit son nom au fait qu'un des nombres premiers utilisés pour la génération des paramètres de la courbe est 2^255-19. Sa description originale est dans l'article de Bernstein « Curve25519 -- new Diffie-Hellman speed records », et son équivalent en courbe d'Edwards, ed25519 dans « High-speed high-security signatures ».

L'autre courbe, curve448, utilise le nombre premier 2^448-2^224-1. La courbe d'Edwards équivalente est nommée Goldilocks et est décrite dans « Ed448-Goldilocks, a new elliptic curve ».

La section 5 du RFC présente les fonctions X25519 et X448, utilisées pour faire du Diffie-Hellman avec ces courbes. Des vecteurs de test sont également fournis, si vous voulez vérifier votre implémentation (rappel au passage : il y a plein de pièges quand on programme de la crypto.)

En parlant de Diffie-Hellman, la section 6 est la description de l'utilisation de ces deux courbes pour un échange de clés ECDH, utilisant les deux fonctions de la section précédente.

Quelle est la sécurité de ces deux courbes (section 7) ? Le niveau de sécurité de curve25519 lors d'une attaque par force brute est d'un peu moins de 128 bits. Une attaque par force brute est normalement l'essai de toutes les clés possibles. Toutefois, le terme est souvent utilisé en cryptographie (avec un abus de langage) pour désigner des méthodes où on fait beaucoup d'essais, sans forcément tester toutes les clés (comme l'algorithme rho). D'autre part, le RFC rappelle qu'il n'est pas facile de comparer des algorithmes de cryptographie, surtout entre algorithmes symétriques et asymétriques, cf. l'article de Bernstein « Understanding brute force ».)

curve448 est normalement « meilleure », avec 224 bits de sécurité (mais plus lente : on n'a rien sans rien). Le RFC note que, pour des ordinateurs quantiques (si on en a un jour...), les deux courbes seront aussi faciles à casser l'une que l'autre. En attendant, curve25519 est parfaitement suffisant.

Notez que, si vous aimez la cryptographie quantique et les discussions sans fin, la NSA a publié en août 2015 un texte qui a stupéfié beaucoup de monde car il affirmait que, vu l'arrivée supposée proche des calculateurs quantiques, il n'était pas recommandé de faire des efforts pour migrer depuis RSA vers les courbes elliptiques. Certains en ont déduit que la NSA avait déjà des calculateurs quantiques et savaient donc que les courbes elliptiques étaient cassées ou proches de l'être, d'autres ont supposé que, si la NSA essayait de décourager les utilisateurs de se servir des courbes elliptiques, c'était au contraire une raison supplémentaire pour migrer vers ces courbes au plus vite. La polémique et l'état des informations disponibles sont très bien expliqués dans l'article « A riddle wrapped in an enigma ».

L'annexe A du RFC décrit comment les paramètres de ces deux courbes ont été générés. Des courbes comme la P-256 du NIST ou comme la courbe elliptique souveraine FRP256 de l'ANSSI ont été très critiquées car les différentes constantes utilisées sont juste annoncées, sans explication. Il n'y a pas besoin d'être excessivement paranoïaque, ou d'avoir lu les documents publiés par Snowden, pour se demander « Pourquoi ces valeurs plutôt que d'autres ? Ne serait-ce pas parce que ces constantes ont des propriétés qui facilitent leur décryptage par la NSA ou un organisme similaire ? ». Il y a consensus aujourd'hui pour dire qu'on ne doit utiliser que des courbes pour lesquelles le choix des paramètres a été fait « objectivement », selon une méthodologie expliquée et vérifiable. C'est ce que fait l'annexe A.

Notez que les paramètres des deux courbes de ces RFC n'ont pas été choisis complètement « objectivement ». Ils ont fait l'objet d'« optimisations », notamment pour des raisons de performance. Si on veut une courbe générée entièrement par un algorithme objectif et publiquement vérifiable, il faudra se tourner (elle est très récente) vers des courbes « publiquement vérifiables » comme la « courbe d'un million de dollars », qui proclame être « a procedure, more than a curve ».

Maintenant que ces courbes font l'objet d'une documentation complète, il sera plus facile de les utiliser depuis un protocole IETF (ceci dit, elles sont déjà dans au moins une norme, voir RFC 7479). Plusieurs travaux sont en cours pour cela ; il y avait un Internet-Draft pour permettre curve25519 dans TLS, draft-ietf-tls-curve25519 mais il a été remplacé par le plus général RFC 8422. Un autre Internet-Draft traite le cas de DNSSEC, draft-sury-dnskey-ed25519.

Notez que les deux courbes de ce RFC sont décrites selon un formalisme qui ne permet pas de les utiliser telles quelles dans un algorithme comme ECDSA (explications sur StackOverflow). Mais on peut avec EdDSA.

OpenSSH dispose de curve25519 depuis la version 6.5. (« Add support for key exchange using elliptic-curve Diffie Hellman in Daniel Bernstein's Curve25519. This key exchange method is the default when both the client and server support it. [...] Add support for Ed25519 as a public key type. Ed25519 is a elliptic curve signature scheme that offers better security than ECDSA and DSA and good performance. It may be used for both user and host keys. »). Dans les sources d'OpenSSH, ce sont les fichiers ayant 25519 dans leur nom :

/tmp/openssh-7.1p2 %   ls *25519*
ed25519.c  fe25519.c  fe25519.h  ge25519_base.data  ge25519.c  ge25519.h  kexc25519.c  kexc25519c.c  kexc25519s.c  sc25519.c  sc25519.h  smult_curve25519_ref.c  ssh-ed25519.c

Pour générer des clés utilisant cette courbe, on utilise le classique ssh-keygen :

% ssh-keygen -t ed25519
Generating public/private ed25519 key pair.
...
Your identification has been saved in /home/stephane/.ssh/id_ed25519.
Your public key has been saved in /home/stephane/.ssh/id_ed25519.pub.
...      
    

Par contre, ces courbes ne sont pas encore dans OpenSSL (voir la discussion #309). Autrement, on trouve des mises en œuvre de curve25519 à plein d'endroits : https://github.com/msotoodeh/curve25519, https://code.google.com/p/curve25519-donna/ et bien sûr http://cr.yp.to/ecdh.html et https://nacl.cr.yp.to/.

Merci à Patrick Mevzek pour son exploration d'OpenSSH et OpenSSL, à Émilien Gaspar pour les discussions et à Manuel Pégourié-Gonnard pour des corrections, notamment sur la force brute.


Téléchargez le RFC 7748


L'article seul

RFC 7723: Port Control Protocol (PCP) Anycast Addresses

Date de publication du RFC : Janvier 2016
Auteur(s) du RFC : S. Kiesel (University of Stuttgart), R. Penno (Cisco Systems), S. Cheshire (Apple)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF pcp
Première rédaction de cet article le 23 janvier 2016


Le protocole PCP, normalisé dans le RFC 6887, permet à une machine de signaler à la box, au routeur CPE, au pare-feu, ses désirs en terme d'ouverture de ports, d'obtention d'information sur l'adresse IP externe, etc. Mais comment l'ordinateur de M. Michu trouve t-il l'adresse du serveur PCP ? Une des solutions est celle introduite par ce RFC : une adresse anycast « bien connue », 192.0.0.9 en IPv4 et 2001:1::1 en IPv6.

Souvent, l'adresse IP du serveur PCP est évidente : c'est l'adresse du routeur par défaut. Mais il y a des cas plus compliqués, par exemple en cas de CGN (section 1 du RFC). Avant notre RFC 7723, les seules autres solutions étaient la configuration manuelle, ou une option DHCP (RFC 7291).

Ce nouveau RFC ajoute une possibilité : le client PCP écrit tout simplement à l'adresse bien connue, 192.0.0.9 ou 2001:1::1, et le serveur PCP approprié répondra. L'anycast s'occupera de router le message du client au bon serveur. Une simple diffusion n'aurait pas suffi : le serveur PCP n'est pas forcément sur le réseau local (notamment en cas de CGN). Avec l'anycast, il n'y a pas besoin d'installer quoi que ce soit de particulier dans le réseau local ou les équipements CPE. Et l'adresse bien connue étant immuable, on peut la mettre en dur dans les applications PCP, sans avoir besoin de l'obtenir du système d'exploitation. (Personnellement, je trouve cela un peu optimiste : comme cette option anycast est nouvelle, et qu'elle ne sera pas forcément déployée partout, l'application aura toujours besoin d'un « plan B » en demandant au système d'exploitation « une idée de l'adresse IP du serveur PCP ? »)

Le comportement du client et du serveur PCP est décrit dans la section 2 du RFC. La liste des serveurs PCP possibles pour le client (section 8.1, étape 2 du RFC 6887) s'enrichit des adresses anycast bien connues. Le traitement de cette liste continue à suivre la norme PCP du RFC 7488. Le serveur, lui, a juste à écouter sur les adresses anycast bien connues, en plus de ses adresses habituelles. Le RFC ne le mentionne apparemment pas, mais l'administrateur réseaux doit aussi évidemment configurer le routage pour que la route vers le serveur PCP soit annoncée partout, et appliquée.

L'anycast peut être déroutant au début pour les administrateurs réseaux et la section 3 du RFC rappelle donc quelques règles de déploiement (en plus des documents existants sur l'anycast, RFC 4786 et RFC 7094). Par exemple, si le réseau a deux connexions vers l'extérieur, chacune avec son propre serveur PCP, l'anycast ne va pas forcément aider car le message PCP du client ne sera reçu que par un seul des deux serveurs (même si tous les serveurs ont été configurés pour écouter sur l'adresse anycast).

Si le routage est toujours symétrique, ce n'est pas un problème, car le serveur PCP qui recevra le message envoyé à l'adresse anycast est également celui qui verra passer tout le trafic, et pourra donc faire ce qui lui a été demandé par le client PCP. Même si le routage change, et qu'on passe subitement par un autre lien, avec un autre serveur PCP, ce n'est pas grave (c'est l'équivalent du redémarrage d'un serveur PCP, cas qui est géré par les clients PCP).

Mais, si le routage est asymétrique... Eh bien, dans ce cas, c'est fichu, c'est une limite de PCP plus que de ces adresses anycast. La seule solution est de développer un mécanisme (qui n'existe pas encore) pour synchroniser deux serveurs PCP.

La section 4 de notre RFC rappelle les enregistrements des deux adresses à l'IANA, dans les registres d'adresses spéciales IPv4 et IPv6.

(Les fanas de sécurité peuvent lire la section 5 mais il n'y a pas grand'chose à dire d'original : les messages PCP, anycast ou pas, peuvent être attaqués comme tous les autres paquets IP, ni plus, ni moins.)

Pour l'instant (PCP est, de toute façon, très peu déployé), je ne crois pas que quiconque utilise déjà ces adresses anycast.


Téléchargez le RFC 7723


L'article seul

RFC 7745: XML Schemas for Reverse DNS Management

Date de publication du RFC : Janvier 2016
Auteur(s) du RFC : T. Manderson (ICANN)
Pour information
Première rédaction de cet article le 21 janvier 2016


Ce court RFC décrit un schéma XML qu'utilise l'ICANN pour gérer les zones DNS dans les domaines ip6.arpa et in-addr.arpa. Rien de standard, juste la documentation d'une pratique locale.

Depuis 2011, l'ICANN utilise ce système pour gérer et produire les zones DNS dont elle a la responsabilité sous .arpa (in-addr.arpa est documenté dans le RFC 1034 et ip6.arpa dans le RFC 3152). L'ICANN délègue des zones aux RIR et ceux-ci souhaitent un système le plus fiable, simple et prévisible possible.

La gestion de ces zones se faisait, il y a fort longtemps, à la main, avec un éditeur ordinaire, mais cela n'est évidemment plus possible depuis le déploiement de DNSSEC : les clés changent, les enregistrements DS (Delegation Signer) doivent être mis à jour, etc. Et la plus petite erreur casse la validation cryptographique. Bref, pour ce service comme pour d'autres, DNSSEC pousse fortement à automatiser sérieusement les processus.

Le principe de base (section 3, le gros du RFC) est que le RIR prépare sa demande sous forme d'un fichier XML conforme au schéma décrit dans ce RFC, et l'envoie à l'ICANN par une requête REST. Elle est évidemment en HTTPS et authentifiée par un certificat client (et un pour le serveur, également). L'AC est l'ICANN elle-même. Recevant le XML, l'ICANN met à jour automatiquement les zones sous .arpa.

En bonne logique REST, les requêtes HTTP sont GET, PUT et DELETE. GET sert à interroger l'état actuel de la base (et le RIR n'utilise donc que l'URI, il n'envoie pas de XML).

Voici un exemple d'une requête en XML qui pourrait être envoyée (requête PUT) pour mettre à jour la zone 10.in-addr.arpa, avec deux enregistrements DS (pour la même clé, la 33682) :


<zone xmlns="http://download.research.icann.org/rdns/1.1"
     name="10.in-addr.arpa" cust="IANA" ipversion="ipv4"
     version="1.1" modified="2012-01-18T01:00:06"
     state="active" href="https://host.example.org/ipv4/10">
     <nserver>
       <fqdn>BLACKHOLE-1.IANA.ORG.</fqdn>
     </nserver>
     <nserver>
       <fqdn>BLACKHOLE-2.IANA.ORG.</fqdn>
     </nserver>
     <ds>
       <rdata>33682 5 1 ea8afb5fce7caf381ab101039</rdata>
     </ds>
     <ds>
       <rdata>33682 5 2 7d44874f1d93aaceb793a88001739a</rdata>
     </ds>
   </zone>	       

    

Notez que la modification n'est pas forcément instantanée : il peut y avoir un système de vérification manuelle et d'approbation explicite.

Les URL utilisés par le client sont variables. Par exemple, pour mettre à jour le domaine 10.in-addr.arpa cité plus haut, l'URL serait http://icann.example/4/10.in-addr.arpa (en remplaçant icann.example par le vrai nom du serveur REST à l'ICANN). Pour avoir une liste des demandes en attente (rappelez-vous que le système n'est pas synchrone), le client ferait un GET sur http://icann.example/queuelist, etc.

Les annexes A et B du RFC donnent le schéma Relax NG complet des éléments XML possibles. Par exemple, une zone DNS se définit ainsi :

      
   # A single zone record
   zone = element zone {
     # The zone record's name, eg 10.in-addr.arpa
     attribute name { text },
     ...
     # The administrative state of the zone (optional)
     attribute state { "active" | "pending" | "error" }?,
     # The last modified timestamp in UTC (optional)
     attribute modified  { xsd:dateTime }?,
     ...
     # A zone NS RRset MUST have at least two NS records
     nserver,
     nserver+,
     # It MAY contain some DS records
     ds*
   }

    

À noter que ce schéma ne permet pas d'indiquer de la colle (adresses IP de serveurs de noms situés dans la zone elle-même) puisqu'il ne sert que pour les zones sous .arpa (on ne voit jamais de serveurs de noms nommés ainsi).

Pourquoi développer un tel système plutôt que d'utiliser la norme EPP ? Le RFC ne le dit pas mais on peut supposer que c'est parce qu'EPP est bien plus complexe.


Téléchargez le RFC 7745


L'article seul

Deux flux de syndication, avec et sans TLS

Première rédaction de cet article le 17 janvier 2016
Dernière mise à jour le 23 janvier 2016


Il y a un vieux problème sur ce blog, qui se pose depuis que j'ai activé l'accès en HTTPS : les flux de syndication ne fonctionnaient pas avec un grand nombre d'agrégateurs. J'ai contourné le problème en ayant désormais deux flux, un en HTTPS et un sans.

Quel est le problème ? Comme j'utilise une AC gratuite et automatique, CAcert, qui n'est pas dans tous les magasins de certificats, loin de là, je ne peux pas forcer l'usage de HTTPS, cela perturberait trop de lecteurs. (Pourtant, j'ai publié des enregistrements DANE mais, malheureusement, il y a encore bien des navigateurs qui, bêtement, ne les utilisent pas. Demandez aux auteurs de votre navigateur et dites-leur bien que DANE est la bonne solution à ce problème.)

Pour les flux de syndication Atom, j'avais pensé résoudre le problème en utilisant des liens « presque absolus ». Ces liens commencent par deux barres obliques, par exemple //www.bortzmeyer.org/toot.html et le logiciel client est supposé, pour le plan (http: ou https:) utiliser le même plan que celui utilisé pour récupérer le fichier où il y avait ces liens.

Avec tous les navigateurs Web, ça marche, le navigateur ajoute http: ou https: selon l'URL utilisé pour récupérer la ressource originale. J'ai malheuresement constaté que ce n'était pas le cas avec les agrégateurs de syndication. De nombreux agrégateurs ne comprennent pas ces liens, et font, par exemple, des requêtes pour une ressource //www.bortzmeyer.org/toot.html, ce qui produit une erreur 404. Le problème semble affecter, entre autres, Liferea ou spaRSS. Certains agrégateurs ont corrigé (Netvibes) mais d'autres trainent la patte.

Qui a raison ? Ce n'est pas évident. La syntaxe des URI est normalisé par le RFC 3986, qui semble autoriser ces URI relatifs commençant par deux barres obliques (section 4.2 du RFC, « A relative reference that begins with two slash characters is termed a network-path reference », et l'exemple //g en 5.4.1). Ces URI « double slash » sont également appelés « protocol-relative URIs » ou « protocol-less URIs », termes tout à fait erronés puisque le plan n'est pas forcément un protocole, « scheme-relative URIs » serait un meilleur terme. De toute façon, personnellement, je trouve le RFC peu clair sur ce point : ces URI sont légaux mais leur sémantique est mal expliquée. En attendant, le RFC sur Atom (RFC 4287) semble décourager l'usage de liens non-absolus (sections 4.2.7.1 et 4.2.6). (Pour RSS, les liens non-absolus sont clairement interdits car RSS n'a pas de notion d'« URL de base », contrairement à Atom.)

Un autre inconvénient de ces liens presques absolus étaient qu'ils ne donnent pas le résultat attendu si le flux Atom a été récupéré par un autre moyen que HTTP ou HTTPS (par exemple un fichier sur le disque local).

Plutôt que d'essayer de faire corriger tous les agrégateurs, j'ai préféré offrir le choix au lecteur, qui va donc devoir manuellement sélectionner le flux qu'il préfère.

Voici donc les quatre flux Atom. Il y a en effet le choix entre TLS ou pas (pour la sécurité et la vie privée) et article complet ou pas :

Merci à tous les signaleurs de bogue et notamment à Styx.


L'article seul

Un OS souverain, c'est quoi, et ça mène à quoi ?

Première rédaction de cet article le 16 janvier 2016
Dernière mise à jour le 22 janvier 2016


La commission des lois de l'Assemblée Nationale a voté le 13 janvier le principe de la création d'un « OS souverain », et cet amendement a été confirmé par le vote de l'Assemblée les 20 et 21 janvier (voir l'actuel texte consolidé). Si cette initiative ni réfléchie, ni étudiée, a, à juste titre, déclenché l'hilarité de Twitter, c'est l'occasion d'expliquer ce que cela veut dire et où ça mène.

L'idée est en effet ancienne, dans tous les endroits où se promènent des Excellences et des gourous à ministres, on entend ce projet, en général jamais explicité et jamais détaillé. Comme les zombies dans les jeux vidéo, cette idée est très difficile à tuer et renait tout le temps. C'est en bonne partie parce qu'il n'y a aucun cahier des charges digne de ce nom : juste un slogan creux.

Mais imaginons qu'on cherche un peu. Qu'est-ce que pourrait être un OS souverain et pourquoi est-ce que ce serait une mauvaise idée ?

D'abord, questionnons un peu ce qu'on entend par « OS ». Le terme de « système d'exploitation » (OS = Operating System dans la langue d'Edgar Hoover) peut désigner deux choses en français :

  • Le logiciel qui parle directement au matériel et présente ensuite aux applications une vue abstraite de ce matériel. C'est ce sens qui est utilisé quand on dit « Linux est un système d'exploitation ».
  • L'ensemble des logiciels livrés ensemble, avec le noyau, les bibliothèques, un certain nombre d'applications de base, etc. C'est le sens de « système d'exploitation » dans la phrase « Windows est un système d'exploitation ».

Rappelez-vous, l'Assemblée a voté un projet sans définir ce qu'elle entendait par là. On va donc supposer que c'est le deuxième sens, celui d'un ensemble complet, permettant à des gens ordinaires de commencer à travailler.

Si c'est bien le cas, c'est une tâche colossale et, franchement, déraisonnable. Cela représente une quantité de logiciels astronomique, que ne peuvent réaliser que de très grosses entreprises comme Microsoft, ou bien les myriades de développeurs du logiciel libre. Le futur « Commissariat à la Souveraineté Numérique » n'aura certainement pas les moyens de financer un tel développement. Clamer « on va écrire un système d'exploitation » est donc une vantardise ridicule.

Peut-être qu'il y aura simplement adaptation d'un système d'exploitation existant ? Prendre un système qui existe, par exemple en logiciel libre, modifier deux ou trois choses et lui coller un drapeau tricolore sur l'écran de démarrage ? Techniquement, c'est plus raisonnable. C'est ce qu'ont fait des États soucieux de souveraineté comme la Corée du Nord avec Red Star OS, ou bien l'administration française avec CLIP (non cité à l'Assemblée : la main droite de l'État ignore ce que fait sa main gauche). Il existe plein de systèmes existants qui pourraient servir de base pour éviter de réinventer la roue (réinvention qu'adorent les députés, ainsi bien sûr que les gagneurs de marchés publics habituels). On peut citer, entre autres :

On ne peut plus alors dire « on va développer un OS souverain » mais, est-ce que, sur le fond, le résultat ne serait pas le même ?

Dans l'hypothèse où ce soit la stratégie suivie, quelles modifications pourraient être apportées au système existant ? C'est là que commencent les problèmes politiques : soucieux d'unanimité, les députés n'ont pas expliqué ce point. Pas la moindre plus petite ébauche de liste des fonctions souhaitées, dans l'amendement voté à l'Assemblée. Essayons de faire le travail des députés. Un tel système pourrait permettre :

  • De ne pas envoyer toutes les données personnelles à Google, contrairement à ce que fait Android,
  • De fournir des outils de chiffrement solides et faciles à utiliser, immédiatement disponibles,
  • D'avoir des portes dérobées permettant à l'État de lire nos communications,
  • De mettre en œuvre dans le code les lois et règlements français, par exemple en incorporant le filtrage imposé par les ayant-trop-de-droits,
  • De gérer proprement Unicode partout, afin de pouvoir écrire correctement le français et les langues de France (chose qui est difficile avec Windows).

Ce n'est qu'une liste partielle. Mes lecteurs ont certainement plein d'autres idées intéressantes. Mais le point important de cette liste est que, toute partielle qu'elle soit, elle est déjà très contradictoire. C'est en effet le problème de fond avec la souveraineté : il s'agit de la souveraineté de qui ? Du citoyen qui veut se protéger ? De l'État qui veut tout voir et tout entendre ? Le futur système d'exploitation souverain offrira-t-il du chiffrement solide de bout en bout ou bien facilitera-t-il la surveillance des utilisateurs ? Ça, c'est une vraie question politique, et c'est normalement le travail des députés. Qu'ils ne l'aient pas discuté dans leur amendement illustre bien leur manque de sérieux.

D'autant plus qu'écrire un tel « OS souverain » n'est pas tout. Encore faut-il que les gens l'utilisent. En Corée du Nord, citée plus haut, pas de problème, il suffit qu'on leur demande gentiment et tous les citoyens le font. Mais en France ? Il faudrait convaincre les citoyens et cela sera difficile si on leur dit juste « c'est un fantasme de Pierre Bellanger, installez-le, ça lui fera plaisir. » Après tout, il n'y a aucune demande des utilisateurs.

Les députés eux-mêmes seront sans doute les plus réticents : ils crient bien fort à la tribune qu'ils veulent de la souveraineté numérique, mais les rares parmi eux qui répondent aux courriers électroniques le font depuis une adresse Yahoo ou Gmail. Jamais ils ne se dégooglisent, mais ils voudraient dégoogliser les autres.

Une administration particulièrement difficile à convaincre sera l'Éducation Nationale : comme elle a signé un accord scandaleux avec Microsoft, elle n'utilisera sans doute pas l'« OS souverain » (sur lequel il y a peu de chances que Microsoft porte ses applications...).

Enfin, il faut noter que l'expérience ne sert à rien : après les sommes faramineuses englouties dans l'escroquerie nommée « cloud souverain » (alors qu'il existait déjà plusieurs acteurs français du cloud), on pourrait s'attendre à davantage de précautions de la part de l'État, et à une analyse du passé, avant de prétendre influencer l'avenir... Sans compter l'expérience récente de Louvois, qui laisse des doutes sur la capacité de l'État français à gérer des grands projets informatiques.

Que va donner le projet actuel ? Verrons-nous naître le « Commissariat à la Souveraineté Numérique » ? Réalisera-t-il le fameux « OS souverain » ? Je vois cinq scénarios possibles :

  • Tout cela sera oublié dans un mois. C'est juste un de ces votes habituels des politiques, pour faire un peu de buzz, sans suite dans les idées.
  • Il y aura bien un début de réalisation mais cela n'ira pas très loin, peut-être juste la production d'une image Fedora avec un logo différent (genre coq).
  • Selon un mécanisme plus proche de celui du projet « cloud souverain », beaucoup d'argent public sera dépensé, les habituelles sociétés gagnantes des marchés publics seront sélectionnées, elles remueront beaucoup d'air et, dans dix ans, il faudra constater l'échec du projet. (Mais on continuera à faire des discours, comme si rien n'était arrivé.)
  • Un « OS souverain » sera bien développé, il intégrera portes dérobées, marquage des fichiers, DRM, et son utilisation sera rendue obligatoire par la loi, en utilisant l'émotion créée par le dernier attentat terroriste en date.
  • Le Commissariat à la Souveraineté Numérique, convaincu par l'April et Framasoft, dégage de l'argent et des ressources humaines pour aider au développement de projets existants entièrement libres, comme Debian ou Replicant, systèmes qui permettent la souveraineté de l'utilisateur.

Le scénario 5 semble le moins probable, le 4 serait le pire, il en ferait même souhaiter que ce soit le scénario 3 qui soit réalisé : mieux vaut le gaspillage que la dictature.

Quelques lectures en plus :


L'article seul

RFC 7735: Tracking Reviews of Documents

Date de publication du RFC : Janvier 2016
Auteur(s) du RFC : R. Sparks (Oracle), T. Kivinen (INSIDE Secure)
Pour information
Première rédaction de cet article le 14 janvier 2016


Le processus de production des normes par l'IETF suit de nombreuses étapes, toutes se déroulant en public. Il est en effet essentiel que de nombreux yeux puissent regarder les documents en voie de devenir des RFC. Et que de nombreux examens (reviews) aient lieu. Pour suivre ces examens, il est préférable de disposer d'outils et ce sont les futurs outils à développer que décrit ce RFC.

Parmi les équipes qui effectuent des examens des Internet-Drafts en cours d'avancement figurent Gen-ART et SecDir. Mais il en existe plusieurs autres, parfois très spécialisées, et qui n'examinent que les documents relevant de leur spécialité (par exemple les MIB par les MIB doctors ou bien les schémas YANG par les YANG doctors).

Les équipes en question doivent se tenir au courant des documents en cours, leur affecter un examinateur parmi ceux qui sont enregistrés pour cette tâche, fixer une date limite et relancer l'examinateur s'il est en retard, etc. Cela serait évidemment très pénible à faire à la main et ces équipes utilisent actuellement un outil, développé il y a longtemps. Du fait de son âge, il n'est pas bien intégré avec le principal outil de travail en groupe de l'IETF, le Datatracker. Par exemple, pour obtenir certaines informations, l'outil analyse des pages HTML du Datatracker :-) .

[Au passage, notez que le Datatracker est vraiment un excellent outil, qui facilite beaucoup la vie du participant à l'IETF. On voudrait tous avoir des outils de travail en groupe équivalents au bureau.]

Une meilleure intégration avec le Datatracker permettrait de simplifier l'accès à ces informations, et à d'autres qui ne sont pas utilisées actuellement, car trop pénibles à extraire. Ce nouveau RFC est le cahier des charges du futur outil (voir aussi le système de gestion de tickets de l'outil actuel).

Pour comprendre ce cahier des charges, il est utile de revenir sur l'utilisation actuelle de l'outil des examens (section 2 du RFC). Typiquement, l'équipe a un secrétariat qui, une fois par semaine environ, dresse une liste des documents qui sont prêts à subir un examen, par exemple parce qu'ils sont en IETF Last Call (dernier appel avant approbation) ou parce qu'ils sont sur l'agenda des réunions (virtuelles) de l'IESG.

Le secrétariat prend ensuite un examinateur parmi la liste des examinateurs possibles, en tenant compte de paramètres comme le fait qu'un auteur ne doit évidemment pas être examinateur de son propre Internet-Draft. L'idée est en général de prendre un examinateur qui a un regard neuf et n'a pas été impliqué dans le développement du document.

Les différentes équipes d'examen n'ont pas toutes le même fonctionnement. Certaines, comme indiqué plus haut, s'« auto-saisissent » alors que d'autres sont plutôt en mode « on examine si on nous le demande » (c'est le cas de l'équipe du routage, par exemple).

Les examinateurs eux-même n'utilisent pas en général l'outil directement : ils communiquent par courrier avec le secrétariat. Et c'est par courrier qu'ils envoient le résultat de leur examen, après avoir rempli un « courrier-type ». Voici par exemple l'examen fait par Gen-ART pour le futur RFC sur la QNAME minimisation ou bien celui de RTG-Dir pour un futur protocole d'HomeNet.

Voici donc le fonctionnement actuel. Pour le futur outil, les exigences sont dans la section 3 de notre RFC. D'abord, ce qui intéresse le secrétariat de l'IETF (section 3.1) :

  • Le secrétariat doit pouvoir configurer une équipe,
  • Et doit pouvoir effectuer toute action à la place du secrétariat de l'équipe (en cas de défaillance de celui-ci).

Plus importantes, les exigences pour le secrétariat de l'équipe d'examen (section 3.2), entre autres :

  • Pouvoir voir quels documents sont dans un état donné (par exemple IETF Last Call),
  • Possibilité de sélectionner les documents à examiner, soit automatiquement (« tous ceux qui sont sur l'agenda de l'IESG »), soit manuellement (ajouter explicitement un document intéressant),
  • Permettre les accès concurrents à l'outil (une équipe peut avoir plusieurs secrétaires),
  • Faciliter l'envoi des courriers, par exemple en remplissant automatiquement un gabarit, puis en permettant au secrétaire de faire des modifications, avant envoi,
  • Pouvoir voir les examinateurs libres,
  • Capacité à gérer les disponibilités des examinateurs (par exemple, on doit pouvoir indiquer « Machin ne sera pas libre avant le 2 février » et il ne doit alors pas être présenté dans la liste des examinateurs potentiels),
  • Gérer automatiquement l'exclusion des examinateurs de certains documents. L'outil actuel utilise une expression rationnelle. M. Michu, examinateur qui est très investi dans le groupe de travail DPRIVE, aura une expression d'exclusion pour les documents nommés ^draft-(michu|ietf-dprive).*, l'excluant de ses drafts et de ceux de DPRIVE,
  • Permettre le suivi des examens (certains examinateurs sont très occupés, peuvent « oublier » leur tâche, etc),
  • Par la même occasion, l'outil doit permettre de suivre les « performances » des examinateurs (afficher le retard moyen...) de manière à détecter les « maillons faibles »,
  • Autoriser le changement d'examinateur, l'ajout d'un examinateur...

Et pour l'examinateur lui-même, que doit savoir faire l'outil (section 3.3) ? Par exemple :

  • Il doit permettre à l'examinateur d'indiquer ses disponibilités, à la fois en dates (« en vacances tout le mois d'août ») et en fréquence (« pas plus d'un examen de document par trimestre »), avec notification du secrétariat par courrier,
  • L'examinateur doit avoir accès aux documents qui lui sont affectés, avec leur état, pour suivre son propre travail,
  • Possibilité de rejeter une affectation, avec explication optionnelle (et, là aussi, notification du secrétariat),
  • De même, l'examinateur doit pouvoir indiquer explicitement qu'il accepte une affectation,
  • Rappels automatiques (« il te reste 24 h pour ton examen du draft draft-ietf-cuterabbit-security-analysis-09.txt »),
  • Et bien sûr, puisque c'est le but de l'examen, l'examinateur doit pouvoir soumettre facilement le texte final, par un formulaire Web ou en téléversant un fichier, le texte étant alors automatiquement envoyé aux auteurs et au groupe de travail concerné,
  • Et cette soumission doit aussi être possible par courrier, pour les examinateurs qui sont allergiques au Web (c'est possible avec les bons outils de gestion de tâche, comme RT).

Comme tout le monde aime les statistiques, et qu'il est bon de pouvoir évaluer si une équipe d'examen marche bien ou pas, l'outil devra également fournir des chiffres (section 3.5) :

  • Pour une période donnée, indiquer combien d'examens ont été faits, combien sont en cours, combien ont été en retard et de combien, le temps moyen d'examen,
  • Mêmes résultats, mais pour un examinateur donné,
  • Ces chiffres doivent pouvoir être pondérés par des caractéristiques du document (notamment sa taille, mesurée en nombre de signes),
  • Et, autant que possible, ces statistiques, par exemple le nombre d'examens faits par un examinateur par an devraient pouvoir tenir compte des périodes d'indisponibilité,
  • Et si l'outil pouvait faire des jolis graphes avec les séries temporelles, ce serait encore mieux,
  • L'accès à ces chiffres doit être limité : le secrétariat d'une équipe peut tout voir pour son équipe, un examinateur peut voir ses résultats, ou bien les résultats globaux de son équipe,

Les outils actuels de l'IETF sont écrits en Django. Pour rendre ce cahier des charges plus concret, l'annexe A fournit un modèle Django tout prêt. Par exemple, l'état d'un examen peut être :

 class ReviewRequestStateName(NameModel):
     """ Requested, Accepted, Rejected, Withdrawn, Overtaken By Events,
         No Response , Completed  """
      

Un examinateur est ainsi modélisé :

class Reviewer(models.Model):
     """
     These records associate reviewers with review team, and keeps track
     of admin data associated with the reviewer in the particular team.
     There will be one record for each combination of reviewer and team.
     """
     role        = models.ForeignKey(Role)
     frequency   = models.IntegerField(help_text=
                                   "Can review every N days")
     available   = models.DateTimeField(blank=True,null=True, help_text=
                         "When will this reviewer be available again")
     filter_re   = models.CharField(blank=True)
     skip_next   = models.IntegerField(help_text=
                          "Skip the next N review assignments")
      

Et une demande d'examen est :

 class ReviewRequest(models.Model):
     """
     There should be one ReviewRequest entered for each combination of
     document, rev, and reviewer.
     """
     # Fields filled in on the initial record creation:
     time          = models.DateTimeField(auto_now_add=True)
     type          = models.ReviewTypeName()
     doc           = models.ForeignKey(Document,
                            related_name='review_request_set')
     team          = models.ForeignKey(Group)
     deadline      = models.DateTimeField()
     requested_rev = models.CharField(verbose_name="requested_revision",
                             max_length=16, blank=True)
     state         = models.ForeignKey(ReviewRequestStateName)
     # Fields filled in as reviewer is assigned, and as the review
     # is uploaded
     reviewer      = models.ForeignKey(Reviewer, null=True, blank=True)
     review        = models.OneToOneField(Document, null=True,
                                                    blank=True)
     reviewed_rev  = models.CharField(verbose_name="reviewed_revision",
                                      max_length=16, blank=True)
     result        = models.ForeignKey(ReviewResultName)
      

Vous avez envie de réaliser cet outil ? L'annonce a été publiée le 28 décembre 2015 et vous avez jusqu'au 18 janvier 2016 pour proposer vos services.


Téléchargez le RFC 7735


L'article seul

RFC 7713: Congestion Exposure (ConEx) Concepts, Abstract Mechanism and Requirements

Date de publication du RFC : Janvier 2016
Auteur(s) du RFC : M. Mathis (Google), B. Briscoe (BT)
Pour information
Réalisé dans le cadre du groupe de travail IETF conex
Première rédaction de cet article le 6 janvier 2016


Le projet ConEx de l'IETF vise à développer des mécanismes permettant à l'émetteur de paquets IP de prévenir le réseau situé en aval que ce flot de données rencontre de la congestion. Les routeurs pourront alors éventuellement prendre des décisions concernant ce flot. Ce nouveau RFC expose le mécanisme abstrait de signalisation (le mécanisme concret, dans des protocoles comme TCP, a été normalisé plus tard).

La spécification se fait donc en trois temps, décrire le problème et les scénarios d'utilisation (RFC 6789), décrire un mécanisme de signalisation de la congestion abstrait, sans se soucier des détails techniques (ce RFC 7713), puis enfin normaliser le protocole concret (RFC 7786 et RFC 7837), avec les inévitables compromis que cela implique.

Aujourd'hui, les équipements réseau comme les routeurs signalent la congestion vers l'aval, en utilisant ECN (RFC 3168), en retardant les paquets (car les files d'attente mettent du temps à se vider) ou, tout simplement, en laissant tomber des paquets. Ce signalement arrive au récepteur qui peut alors informer l'émetteur, par exemple en réduisant la fenêtre, dans TCP. Cette boucle de rétroaction préserve l'Internet de la congestion (RFC 5681). (De ces trois signaux, le temps d'acheminement est le moins utilisé, car il n'est pas un indicateur univoque de la congestion.)

Mais ce signalement n'est pas visible de tous les équipements réseau traversés par ce flot de paquets. Ceux situés en amont du premier routeur qui détecte la congestion ne sont pas prévenus, alors qu'ils auraient pu jouer un rôle. Le rôle de ConEx est justement que tout le monde soit informé. Le principe de base est que l'émetteur, une fois prévenu de la congestion, mette dans les paquets qu'il envoie un indicateur que ce flot rencontre de la congestion quelque part sur le trajet.

Pour que ConEx soit déployé, il faudra que les gens y trouvent un avantage, surtout au début où le déploiement sera limité. Ce problème est commun à tous les nouveaux protocoles mais il sera encore plus crucial pour un protocole qui permettra de signaler les gros consommateurs... Ceux-ci pourraient se retrouver pénalisés (« vos flots signalent tous de la congestion, vous devriez ne les lancer qu'aux heures creuses ») ou poussés à utiliser des protocoles moins gourmands comme LEDBAT (RFC 6817).

ConEx semblait moins nécessaire autrefois car les protocoles comme TCP étaient conçus pour limiter la congestion, en se calmant dès qu'ils la détectaient. Un problème jamais résolu était celui de machines qui ignorent délibérement cet objectif et, par exemple, utilisent des protocoles de transport qui maximisent le débit individuel et tant pis pour le reste de l'Internet. Difficile de lutter contre cet égoïsme. Il pourrait être contagieux puisque les bons citoyens se trouveraient alors défavorisés, et seraient donc tentés de suivre la voie égoïste à leur tour, poussant les gros consommateurs à faire des protocoles encore plus agressifs, etc. L'IETF a toujours découragé ces pratiques (comme celle d'ouvrir plusieurs connexions TCP simultanées pour avoir une plus grosse part du gâteau) avec un succès variable.

ConEx est une approche complémentaire : les gens peuvent consommer de la capacité réseau mais ils doivent le signaler.

Comme une des conséquences de ce signalement pourrait être un traitement différencié du flot en question (« il encombre le réseau, je le limite »), une partie importante du projet ConEx est de s'assurer qu'il n'y aura pas de triche (par exemple d'émetteur « négligeant » d'informer le réseau des problèmes qu'il pose). Les signaux ConEx doivent donc être auditables, pour détecter les tricheurs. (Voir Briscoe, « Re-feedback: Freedom with Accountability for Causing Congestion in a Connectionless Internetwork »).

Une dernière chose avant d'attaquer le cahier des charges exact de ConEx, le vocabulaire :

  • Transport qui ne peut pas faire du ConEx (Not-ConEx) : un mécanisme de transport des données qui ne connait pas du tout ConEx, ce qui est le cas de la totalité des mécanismes actuels.
  • Transport qui peut faire du ConEx (ConEx-capable) : les futurs mécanismes de transport qui sauront faire du ConEx.
  • Signal ConEx : quelque chose dans un paquet (transporté par un mécanisme capable de faire du ConEx) qui indique soit une perte de paquets (signal Re-Echo-Loss), soit une marque ECN (signal Re-Echo-ECN), soit que l'émetteur s'attend à déclencher de la congestion bientôt, par exemple parce qu'il démarre et teste la capacité du réseau (signal Credit), soit qu'il n'a rien à signaler, à part qu'il sait faire du ConEx (signal ConEx-Not-Marked).

La section 3 de notre RFC décrit les exigences précises de ConEx. D'abord, pour les signaux :

  • Le signal ConEx doit être visible par les éléments intermédiaires du réseau comme les routeurs. Il doit donc être mis dans l'en-tête IP, pas enfoui au fin fond du paquet. Il ne doit pas être modifié par ces éléments intermédiaires, l'émetteur met le signal, le reste du réseau ne fait que regarder.
  • Comme le déploiement ne sera pas instantané (et qu'il est très probable, quand on voit le déploiement très limité d'ECN, qu'il ne sera jamais complet), il est important que ConEx soit utilisable, et ait des bénéfices, même en cas de déploiement partiel.
  • Le signal doit être rapidement émis, pour bien rendre compte de la situation actuelle. Le RFC reconnait qu'il faudra évidemment au moins un RTT avant l'émission du signal (et davantage avec RTP, cf. RFC 3550 et RFC 6679).
  • Le signal doit être exact (évidemment...) et auditable, ce qui veut dire qu'un observateur extérieur doit pouvoir le vérifier, afin de détecter d'éventuels tricheurs.

Ces exigences sont parfois contradictoires et le RFC note qu'il faudra sans doute, en passant de ces abstractions à un protocole concret, accepter quelques compromis.

J'ai parlé de l'importance d'auditer les signaux ConEx. La fonction d'audition n'est pas normalisée dans ce RFC mais il pose des exigences qu'elle doit suivre, notamment :

  • Le moins de faux positifs possibles (flots honnêtes notés à tort comme tricheurs).
  • Le moins de faux négatifs possibles (tricheurs non détectés). Je note personnellement que ces deux premières exigences sont souvent en conflit...
  • Des sanctions suffisantes pour être dissuasives mais proportionnelle à la triche : en raison des faux positifs, des sanctions excessives n'encourageront pas à déployer le protocole (et pourraient représenter un vecteur d'attaque par déni de service).

Ce RFC décrit des mécanismes abstraits. Le futur travail du groupe de travail ConEx devra en faire un ensemble de mécanismes concrets, traitant entre autres de ces points :

  • L'encodage des signaux.
  • Les mécanismes d'authentification et d'intégrité.
  • Les techniques de coexistence entre des machines ConEx et non-ConEx.
  • L'extensibilité du protocole.

Là encore, il ne sera sans doute pas possible de tout satisfaire. Les futurs RFC ConEx devront donc noter quelles exigences ont été délibérement affaiblies, voire abandonnées.(Cf. les RFC 7837 et RFC 7786.)

Place à l'encodage, maintenant, pour satisfaire mes lecteurs qui préfèrent savoir à quoi vont ressembler les bits sur le câble. Je rappelle que le protocole précis n'est pas encore normalisé, cette section 4 du RFC ne fait que pointer les problèmes liés à l'encodage des signaux. Prenons en effet un encodage naïf : on décide d'un bit dans l'en-tête IP qu'on met à 1 dès qu'il y a eu une retransmission TCP (des données sans accusé de réception, qu'il a fallu réémettre), ou dès qu'on a réduit la fenêtre TCP en réponse à ECN. Cet encodage semble satisfaire les premières exigences de ConEx : il est trivial à réaliser (sans doute une seule ligne de code dans la plupart des mises en œuvre de TCP/IP), il est compatible avec les matériels et logiciels existants (les non-ConEx ignoreront tout simplement ce bit), tout routeur ConEx sur le trajet peut lire ce bit et agir en fonction de sa valeur.

Mais cet encodage trop simple a des défauts : comme dans le cas du RFC 3514, il ne permet pas un audit. On n'a aucun moyen de vérifier si l'émetteur triche ou pas. Bon, ne soyons pas trop critique : un tel encodage est utile pour aider à comprendre ConEx et à se représenter à quoi cela peut bien ressembler. Dans des environnements fermés où tout le monde est honnête, il peut suffire.

D'autres encodages sont imaginables. Par exemple, on pourrait ne rien encoder du tout et dire aux routeurs ConEx de regarder les flots TCP et d'en déduire s'il y a eu rencontre avec la congestion en aval ; en effet, si on voit des retransmissions, ou la fenêtre TCP se réduire, on peut en déduire que l'émetteur a vu de la congestion et a réagi. Cela implique que les routeurs analysent TCP (ce qu'ils ne font normalement pas) et gardent un état (au moins un RTT de données), ce qui serait coûteux. Mais cela dispenserait de toute modification des émetteurs. Et cela ne permet pas de triche.

Dans un routeur implémenté en logiciel, en bordure du réseau, cela pourrait être réaliste (dans un routeur de cœur traitant des milliards de paquets à la seconde, cela le serait moins). À noter que des protocoles de sécurité comme TLS ou SSH ne masquent pas TCP et ne seraient donc pas un problème pour une analyse ConEx (contrairement à IPsec avec ESP, mais qui est beaucoup moins répandu). Mais si ConEx était ainsi déployé, cela pourrait motiver certains pour tout faire passer dans un VPN qui empêcherait cette observation.

Et encoder avec ECN ? Il existe une proposition (Internet-Drafts draft-briscoe-conex-re-ecn-tcp et draft-briscoe-conex-re-ecn-motiv) d'intégration d'ECN avec ConEx, qui a l'avantage d'empêcher la triche.

L'inconvénient de l'approche précédente est de nécessiter ECN, que n'ont pas tous les récepteurs. Une approche purement ConEx à l'encodage serait d'avoir des bits dédiés à ConEx dans l'en-tête IP (ou dans un en-tête d'extension en IPv6). On peut utiliser un bit par signal ConEx (ConEx, Re-Echo-Loss, Re-Echo-ECN et Credit), ou bien essayer de profiter du fait que certains sont mutuellement exclusifs pour condenser un peu.

Un sous-problème intéressant est celui de savoir si on compte la congestion en bits ou bien en paquets ? Est-ce que la perte d'un paquet de 1 500 octets vaut celle d'un paquet de 64 octets ? La perte d'un gros paquet est-elle due à sa taille ou bien un petit paquet aurait-il été également jeté ? Certaines parties du réseau sont limitées en nombre de bits (c'est typiquement le cas des tuyaux), d'autres en nombre de paquets (c'est partiellement le cas des équipements actifs). Le RFC 7141 recommande d'utiliser plutôt les bits, le RFC 6789 suggère la même chose, au moins dans l'Internet actuel.

La section 5 du RFC décrit les composants du réseau qui auront un rôle à jouer dans ConEx (voir aussi la section 6). Les équipements intermédiaires (notamment les routeurs) d'aujourd'hui ignorent les signaux ConEx et passent les paquets tels quels (espérons qu'aucun pare-feu trop zélé ne se permettra de les bloquer). Ceux qui seront modifiés ConEx, soit des routeurs, soit des engins spécialisés (congestion policer ?) liront les signaux ConEx, les vérifieront (cf. la partie sur l'audit) et pourront agir, par exemple en shapant les émetteurs qui déclenchent de la congestion.

Les émetteurs, typiquement des machines terminales, devront voir leur code TCP/IP modifié pour émettre des signaux ConEx. A priori, ceux qui n'ont même pas encore ECN n'utiliseront pas ConEx non plus, mais ceux qui ont ECN trouveront peut-être l'ajout de ConEx intéressant.

Les récepteurs, typiquement des machines terminales, n'ont pas à être modifiés.

L'audit des signaux ConEx, pour détecter les tricheurs (pensez au RFC 3514) est évidemment essentiel (section 5.5). Si des équipements réseaux limitent le trafic des émetteurs qui déclenchent de la congestion, afin d'épargner le réseau aval, ces émetteurs auront évidemment un bon mobile pour tricher. Ils risquent de ne pas mettre les signaux ConEx. (Voir aussi la section 8, sur la sécurité.)

Comment détecter les tricheurs ? Une solution possible est de détecter les pertes de paquets et de voir si l'émetteur envoie bien des Re-Echo-Loss. Mais attention : rien ne dit que l'auditeur voit tous les paquets d'un flot. Si le trafic passe par deux liens différents, l'auditeur situé sur un des liens risque de ne pas voir certains paquets et croire à tort qu'ils sont perdus.

Les signaux ECN peuvent aussi servir à l'audit. Pour être sûr de les voir, il faut être en aval des points où il y a congestion.

Une autre solution est d'utiliser les retransmissions de TCP. Si l'émetteur réémet, c'est que que paquets ont été perdus. Là, il vaut mieux être proche de l'émetteur (donc le plus en amont possible), pour être sûr de voir tous ses paquets, même en cas de chemins multiples dans le réseau.

Le routeur qui doit jeter des paquets (ou les marquer avec ECN) car il n'arrive plus à tout transmettre est aussi un bon endroit pour faire de l'audit : il peut directement comparer ce qu'il fait (jeter les paquets d'un flot donné) avec l'apparition, un RTT plus tard, des signaux ConEx.

La thèse de B. Briscoe (un des auteurs du RFC), « Re-feedback: Freedom with Accountability for Causing Congestion in a Connectionless Internetwork » contient une analyse détaillée de toutes les techniques de triche, et d'audit, connues.


Téléchargez le RFC 7713


L'article seul

FreeBSD sur un Raspberry Pi

Première rédaction de cet article le 3 janvier 2016


Je viens d'installer FreeBSD sur un Raspberry Pi. Rien d'extraordinaire, je voulais juste expliquer pourquoi je ne garderai pas ce système en production.

Il y a désormais des images officielles pour le Raspberry Pi chez FreeBSD : ftp://ftp.freebsd.org/pub/FreeBSD/releases/ISO-IMAGES/10.2/ (« ...arm-armv6-RPI-B... »). On télécharge, on décomprime, on copie sur un carte SD avec dd et on démarre le Pi dessus :

wget ftp://ftp.freebsd.org/pub/FreeBSD/releases/arm/armv6/ISO-IMAGES/10.2/FreeBSD-10.2-RELEASE-arm-armv6-RPI-B.img.xz
unxz FreeBSD-10.2-RELEASE-arm-armv6-RPI-B.img.xz
sudo dd if=FreeBSD-10.2-RELEASE-arm-armv6-RPI-B.img of=/dev/sdb bs=1M conv=sync
[Démarrage du Pi ; il faut être patient la première fois, cela prend
plusieurs minutes pour générer les clés SSH.]
    

Ensuite, on peut se connecter au Pi en SSH (login/mot de passe freebsd/freebsd). On crée des comptes, on change les mot de passe, tout va bien :

amour% uname -a
FreeBSD amour 10.2-RELEASE FreeBSD 10.2-RELEASE #0 r286666: Thu Aug 13 03:16:22 UTC 2015     root@releng1.nyi.freebsd.org:/usr/obj/arm.armv6/usr/src/sys/RPI-B  arm
amour% uptime
 1:59PM  up 39 mins, 2 users, load averages: 1.67, 1.83, 1.66

(Les messages de démarrage du noyau sont disponibles ici.)

C'est ensuite que les ennuis commencent. Le programme bsdinstall censé permettre de configurer la machine facilement ne marche pas, la liste des miroirs n'étant pas adapté au processeur ARM : la plupart des miroirs n'ont pas ARM et on n'a aucun moyen de le savoir à l'avance. bsdinstall quitte donc rapidement. Il faut donc faire les réglages à la main. Par exemple, pour la date et le fuseau horaire :

ln -s  /usr/share/zoneinfo/Europe/Paris /etc/localtime
ntpdate  ntp.nic.fr

Et pour le clavier :

% kbdmap
kbdcontrol: getting keymap: Inappropriate ioctl for device
You are not on a virtual console - expect certain strange side-effects
lang_default = en
dialect = en
lang_abk = en
keymap="fr.kbd"

Mais le plus gênant concerne les paquetages. Dans la terminologie FreeBSD, le port est le source et le paquetage le binaire (pré-compilé, donc). Quand on a démarré sur l'image officielle, on n'a que le système de base. Pour des raisons historiques (enfin, plutôt, pré-historiques), FreeBSD maintient une division des anciens Unix, entre un système de base et les applications. La distinction est assez arbitraire (le système « de base » contient un compilateur, par exemple, alors que l'écrasante majorité des machines n'en ont pas besoin). Pour installer des applications utiles, il existe plusieurs mécanismes (et qui changent tout le temps, donc les vieux articles récupérés sur le Web ne vous aideront pas). Un peu au hasard, j'ai testé avec pkg :

# pkg update
The package management tool is not yet installed on your system.
Do you want to fetch and install it now? [y/N]: y
Bootstrapping pkg from pkg+http://pkg.FreeBSD.org/FreeBSD:10:armv6/quarterly, please wait...
pkg: Error fetching http://pkg.FreeBSD.org/FreeBSD:10:armv6/quarterly/Latest/pkg.txz: No address record
A pre-built version of pkg could not be found for your system.
Consider changing PACKAGESITE or installing it from ports: 'ports-mgmt/pkg'.
    

Le message « No address record » est erroné. Le site existe bien, mais n'a rien pour les processeurs ARM. En fait, le fond du problème est qu'il n'y a pas de paquetages (donc de binaires) pour le Raspberry Pi ; il parait qu'ils apparaitront dans la prochaine version de FreeBSD (je rappelle que les mises à jour du système sont très complexes avec FreeBSD, rien à voir avec ce que permet un système comme Debian, donc je n'envisage pas de passer dans les systèmes ultérieurs).

Il faut donc tout compiler soi-même ce qui, sur le Raspberry Pi, prend des siècles (et use la carte SD). J'ai utilisé portsnap pour extraire les ports (les sources, ou plutôt les références aux sources) comme suggéré par Johnson D :

portsnap fetch
portsnap extract
   

puis, cd /usr/ports/CATEGORY/SOFTWARE et make install. C'est horriblement lent et je ne rêve même pas d'arriver à installer emacs ainsi. Donc, pas utilisable « en vrai ».

Autre problème, j'ai eu du mal à activer IPv6 (qui ne l'est pas par défaut, ce qui est incroyable en 2016). Il existe d'innombrables variables IPv6 pour le /etc/rc.conf et les explications sur leur interaction sont confuses. Mon réseau utilise SLAAC pour la configuration IPv6. Un peu au hasard, j'ai mis :

ipv6_enable="YES"
ipv6_activate_all_interfaces="YES"
ipv6_privacy="YES"
ifconfig_ue0_ipv6="inet6 accept_rtadv"

ue0 est le nom de l'interface Ethernet du Pi. Avec un peu de patience ensuite, cela marche.

Quelques documentations et articles :

Des alternatives possibles :


L'article seul

Le journal d'Anne Frank monte dans le domaine public

Première rédaction de cet article le 1 janvier 2016


À l'heure où le fanatisme religieux est à l'offensive dans le monde, il faut lire et relire le journal d'Anne Frank. C'est plus facile désormais qu'il est monté dans le domaine public, ce premier janvier.

La famille d'Anne Frank, jeune juive allemande, réfugiée, déchue de sa nationalité, s'est installée à Amsterdam en 1934. C'est à Amsterdam qu'elle a écrit son journal intime, notamment pendant la période où sa famille était cachée, pendant l'occupation allemande. Elle a été arrêtée et assassinée par les nazis.

Ce journal monte dans le domaine public aujourd'hui. Malheureusement, un groupe de professionnels de l'appropriation intellectuelle prétend que le journal d'Anne Frank lui appartient, et menace ceux qui le publieraient. Il est donc crucial que le plus d'internautes possibles relayent cette publication, à l'image de Olivier Ertzscheid et d'Isabelle Attard, que je félicite chaleureusement au passage.

Voici donc le texte original, en néerlandais. Point juridique : la montée dans le domaine public se fait en général 70 ans après la mort de l'auteur (une durée incroyablement et anormalement longue). Mais cela ne vaut que pour le texte original, toute traduction (en français, par exemple), remet le compteur à zéro. Voici pourquoi il n'y a « que » le texte original.


L'article seul

Articles des différentes années : 2024  2023  2022  2021  2020  2019  2018  Précédentes années

Syndication : Flux Atom avec seulement les résumés et Flux Atom avec tout le contenu.

Un article de ce blog au hasard.