Je suis Charlie

Autres trucs

Accueil

Seulement les RFC

Seulement les fiches de lecture

Ève

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

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

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

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


RFC 8093: Deprecation of BGP Path Attribute Values 30, 31, 129, 241, 242, and 243

Date de publication du RFC : Février 2017
Auteur(s) du RFC : J. Snijders (NTT)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF idr
Première rédaction de cet article le 17 février 2017


Ce très court RFC ne fait pas grand'chose : il marque juste comme « à ne pas utiliser » (deprecated) un certain nombre d'attributs BGP.

BGP est le protocole de routage de l'Internet. En permanence, les routeurs s'envoient des annonces de routes, annonces portant certains attributs (RFC 4271, section 5) qui précisent des caractéristiques de la route. La liste de ces attributs figure dans un registre IANA. Les attributs cités dans ce RFC sont marqués comme officiellement abandonnés. Ce n'est pas qu'ils ne servaient pas : au contraire, ils étaient « squattés » en étant annoncés bien qu'ils n'aient jamais fait l'objet d'un enregistrement formel. Mieux valait donc les marquer dans le registre.

Mais pourquoi est-ce que des gens peuvent utiliser des attributs non enregistrés ? Parce qu'il n'y a pas de police de l'Internet (en dépit de raccourcis franchements abusifs, par exemple de certains journalistes qui écrivent que « l'ICANN est le régulateur de l'Internet »). Personne ne peut donner des ordres à tous les routeurs, et les faire appliquer.

Bref, il y a des mises en œuvre de BGP qui fabriquent des annonces avec des attributs non enregistrés. C'est la vie. Mais c'est ennuyeux car cela peut entrainer des collisions avec de nouveaux attributs qui, eux, suivent les règles. C'est ainsi que l'attribut LARGE_COMMUNITY du RFC 8092 avait d'abord reçu la valeur numérique 30 avant qu'on s'aperçoive que cette valeur était squattée par un autre attribut (merci, Huawei)... Résultat, les routeurs squatteurs, quand ils recevaient des annonces avec un attribut LARGE_COMMUNITY ne lui trouvaient pas la syntaxe attendue et retiraient donc la route de leur table de routage (conformément au RFC 7606). LARGE_COMMUNITY a donc dû aller chercher un autre numéro (32), et 30 a été ajouté au registre, pour indiquer « territoire dangereux, squatteurs ici ». Le même traitement a été appliqué aux attributs 31, 129, 241, 242 et 243, qui étaient également squattés.

Le groupe de travail à l'IETF s'est demandé s'il n'aurait pas mieux valu « punir » les squatteurs en allouant délibérement le numéro officiel pour un autre attribut que le leur mais cela aurait davantage gêné les utilisateurs de l'attribut légitime que les squatteurs, qui avaient déjà une base installée.


Téléchargez le RFC 8093


L'article seul

RFC 8092: BGP Large Communities Attribute

Date de publication du RFC : Février 2017
Auteur(s) du RFC : J. Heitz (Cisco), J. Snijders (NTT), K. Patel (Arrcus), I. Bagdonas (Equinix), N. Hilliard (INEX)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF idr
Première rédaction de cet article le 19 février 2017


Ce RFC normalise un nouvel attribut des annonces BGP, « Large Communities ». Les « communautés » BGP sont des courtes données collées aux annonces BGP et qui permettent d'indiquer certaines caractéristiques des routes. Les décisions des routeurs peuvent utiliser ces caractéristiques. Mais les communautés originales étaient trop courtes (seulement quatre octets) : le nouvel attribut permet des communautés de douze octets.

Les « communautés » sont définies dans le RFC 1997. On les apprend via les documentations des opérateurs ou des points d'échange. Par exemple, celle du point d'échange irlandais (section « Community based prefix filtering »). Un attribut COMMUNITY dans une annonce BGP peut comporter plusieurs communautés. Traditionnellement, les quatre octets des communautés initiales sont utilisées pour représenter le numéro d'AS dans les deux premiers octets (ainsi, une communauté est mondialement unique, par ce système d'allocation à deux niveaux), et des données spécifiques à l'AS dans les deux suivants. Évidemment, avec les numéros d'AS de quatre octets du RFC 6793, ça ne marchait plus. D'où cet attribut LARGE_COMMUNITY, désormais stocké dans le registre IANA sous le numéro (type code) 32. (Il y a bien eu une autre tentative d'augmenter la taille des communautés, dans le RFC 4360, mais pas suffisamment pour que les AS à quatre octets puissent être utilisés partout.) Comme pour les « petites » communautés, ces grandes communautés dans une annonce forment un ensemble (donc, non ordonné) : plusieurs routeurs auront pu ajouter une communauté à cet ensemble.

Les communautés sont importantes car elles sont utilisées dans la politique de routage. BGP ne cherche pas à trouver le meilleur chemin : il fait du routage politique, où les décisions sont prises en fonction de choix faits par les opérateurs (privilégier tel ou tel lien pour le trafic entrant, par exemple). Les informations contenues dans une annonce BGP (section 4.3 du RFC 4271) habituelle ne sont pas toujours suffisantes, et c'est pour cela que les communautés ont été introduites par le RFC 1997, pour ajouter des informations utiles, comme l'endroit où telle route a été apprise. L'attribut COMMUNITY (numéro 8) est transitif (section 5 du RFC 4271), ce qui veut dire qu'après réception d'une annonce, il est transmis aux autres routeurs (d'où l'importance de marquer la communauté avec un numéro d'AS, pour que les communautés soient uniques au niveau mondial, sans qu'il existe un registre central des communautés).

Le nouvel attribut LARGE_COMMUNITY (numéro 32) est également optionnel et transitif (section 2 de notre RFC). Il se compose d'un ensemble de grandes communautés, chacune étant stockée sur douze octets. L'idée est qu'on utilise les quatre premiers octets pour identifier l'AS (ce qui va bien avec les grands AS du du RFC 6793), ce qui va garantir l'unicité des communautés. Le nombre de communautés dans un attribut LARGE_COMMUNITY est donné par le champ Longueur de l'attribut, les attributs BGP étant encodés en TLV (cf. RFC 4271, section 4.3).

En cas d'agrégation de routes (section 3 du RFC), il est recommandé d'utiliser comme communautés l'union des ensembles de communautés des différentes annonces.

Et comment on va représenter ces grandes communautés sous forme texte ? (Sur le câble, entre les deux routeurs, c'est du binaire, en gros boutien, cf. RFC 4271, section 4.) On note trois groupes de quatre octets, séparés par un deux-points, par exemple 2914:65400:38016 (section 4 de notre RFC), où le premier champ est presque toujours l'AS.

Comme toutes les grandes communautés font exactement douze octets, si le champ Longueur de l'attribut n'est pas un multiple de douze, l'attribut est invalide, et le routeur qui reçoit cette annonce doit la gérer comme étant un retrait de la route (RFC 7606).

Un point de sécurité important en section 6 du RFC ; en gros, les grandes communautés ont quasiment les mêmes propriétés de sécurité que les anciennes petites communautés. Notamment, elles ne sont pas protégées contre une manipulation en transit : tout AS dans le chemin peut ajouter des communautés (même « mensongères », c'est-à-dire indiquant un autre AS que le sien) ou retirer des communautés existantes. La section 11 du RFC 7454 donne quelques détails à ce sujet. Ce problème n'est pas spécifique aux communautés, c'est un problème général de BGP. L'Internet n'a pas de chef et il est donc difficile de concevoir un mécanisme permettant de garantir l'authenticité des annonces.

Il existe déjà de nombreuses mises en œuvre de BGP qui gèrent ces grandes communautés. Par exemple IOS XR, ExaBGP, BIRD, OpenBGPD, GoBGP, Quagga, bgpdump depuis la version 1.5, pmacct... Une liste plus complète figure sur le Wiki. Mais il y a aussi le site Web du projet, où vous trouverez plein de choses. Si vous avez accès à un routeur BGP, ou à un looking glass qui affiche les grandes communautés (c'est le cas de celui du Ring de NLnog), les deux préfixes 2001:67c:208c::/48 et 192.147.168.0/24 ont une grande communauté (15562:1:1). Si vous essayez sur un routeur qui a un vieux logiciel, ne comprenant pas ces grandes communautés, vous verrez sans doute quelque chose du genre « unknown attribute ». Ici sur IOS à Route Views :

% telnet route-views.oregon-ix.net
...
Username: rviews
route-views>  show ip bgp 192.147.168.0
BGP routing table entry for 192.147.168.0/24, version 37389686
Paths: (41 available, best #21, table default)
  Not advertised to any peer
  Refresh Epoch 1
  3333 1273 2914 15562
    193.0.0.56 from 193.0.0.56 (193.0.0.56)
      Origin IGP, localpref 100, valid, external
      Community: 1273:22000 2914:410 2914:1206 2914:2203 2914:3200
      unknown transitive attribute: flag 0xE0 type 0x20 length 0xC
        value 0000 3CCA 0000 0001 0000 0001 
...
  

Ici sur un vieux IOS-XR (le test a été fait à l'époque où l'attribut avait le numéro 30 et pas 32, d'où le 0x1e) :

			   
RP/0/RSP0/CPU0:Router#  show bgp  ipv6 unicast 2001:67c:208c::/48 unknown-attributes 
        BGP routing table entry for 2001:67c:208c::/48
        Community: 2914:370 2914:1206 2914:2203 2914:3200
        Unknown attributes have size 15
        Raw value:
        e0 1e 0c 00 00 3c ca 00 00 00 01 00 00 00 01 

Et ici sur JunOS :

user at JunOS-re6> show route 2001:67c:208c::/48 detail 
        2001:67c:208c::/48 (1 entry, 1 announced)
            AS path: 15562 I
            Unrecognized Attributes: 15 bytes
            Attr flags e0 code 1e: 00 00 3c ca 00 00 00 01 00 00 00 01

Notez que certaines configurations (parfois activées par défaut) du routeur peuvent supprimer l'attribut « grandes communautés ». Pour empêcher cela, il faut, sur JunOS :

[edit protocols bgp]
user at junos# delete drop-path-attributes 32
    

Et sur IOS-XR :

    
    configure
    router bgp YourASN
        attribute-filter group ReallyBadIdea ! avoid creating bogons
        no attribute 32
      !
    !

Deux lectures pour finir :


Téléchargez le RFC 8092


L'article seul

RFC 8089: The "file" URI Scheme

Date de publication du RFC : Février 2017
Auteur(s) du RFC : M. Kerwin (QUT)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF appsawg
Première rédaction de cet article le 20 février 2017


Vous connaissez le plan d'URI file:, qui indique que la ressource se trouve sur le système de fichiers local ? (Par exemple, ce fichier que je suis en train d'éditer est file:///home/stephane/Blog/RFC/8089.xml.) Ce plan avait été défini très brièvement dans le RFC 1738 (section 3.10). Tellement brièvement qu'il y manquait pas mal de choses. Ce nouveau RFC remplace cette partie du RFC 1738 et fournit cette fois une description complète du plan file:. Ce n'était pas une tâche facile car les différents systèmes de fichiers ont des syntaxes et des comportements très différents. Le RFC lui-même est très court, mais il comporte plusieurs annexes plus longues, discutant de points spécifiques parfois assez tordus.

Donc, d'abord, la définition (section 1 de notre RFC) : un fichier est un objet qui se trouve rangé dans un environnement structuré, qui fournit notamment un système de nommage, environnement qu'on nomme le système de fichiers. (Et le fichier contient des données mais ce point n'est pas crucial pour les URI et n'est donc pas mentionné.) Ensuite, les URI : ce sont les identificateurs standard du Web. Leur syntaxe générique est définie dans le RFC 3986 et ce nouveau RFC ne fait donc que spécialiser le RFC 3986. Normalement, ce RFC est parfaitement compatible avec l'ancienne syntaxe, celle du RFC 1738 mais, en pratique, comme l'ancienne définition était vraiment trop vague, il y aura forcément quelques différences. (L'annexe E donne quelques exemples de pratiques utilisées dans la nature et qui ne sont pas strictement alignées sur les nouvelles règles. Elle cite par exemple l'ajout d'un nom d'utilisateur dans l'URI. Un exemple des problèmes que ces différences posent aux navigateurs est bien expliqué dans cet article de Microsoft.)

Les URI file: ne supposent pas l'utilisation d'un protocole particulier, ni d'un type de média particulier.

Ce plan d'URI désigne des « fichiers locaux ». Un fichier local est accessible juste à partir de son nom, sans autre information (par exemple sans utiliser une adresse réseau explicite). Mais, en pratique (section 1.1), il peut être physiquement sur une autre machine, grâce à des techniques comme NFS ou SMB.

La syntaxe de ces URI figure en section 2 de notre RFC, formalisée en ABNF (RFC 5234). S'appuyant sur la syntaxe générique du RFC 3986, elle diffère légèrement de celle du RFC 1738 (l'annexe A liste les différences). Le plan file: est référencé dans le registre des plans d'URI. Je vous laisse découvrir sa grammaire dans le RFC, je donne juste des exemples qui illustrent certains points de la syntaxe :

  • Commençons par un URI banal : file:///tmp/toto.txt. Il désigne le fichier local /tmp/toto.txt de l'ordinateur sur lequel on travaille. La syntaxe du nom de fichier est celle d'Unix, même si ledit ordinateur n'utilise pas Unix. Ainsi, le fichier c:\machin\truc sur une machine Windows sera quand même file:///c:/machin/truc (il existe plein de variantes non-standard, voir l'annexe E, et l'article cité plus haut, sur les problèmes que cela pose). Sur VMS, DISK1:[CS.JANE]PAPER.PS deviendra file:///disk1/cs/jane/paper.ps (cf. annexe D).
  • Le composant après les trois barres obliques doit être un chemin absolu dans le système de fichiers de la machine. Cela a l'air simple mais la notion de « chemin absolu » ne l'est pas, et l'annexe D cite quelques surprises possibles (comme le tilde de certains shells Unix).
  • Après les deux premières barres obliques, il y a normalement un champ nommé « Autorité » (en pratique un nom de domaine), qui est optionnel. Pour les URI file:, on peut mettre dans ce champ localhost, voire n'importe quel nom qui désigne la machine locale (je ne suis pas sûr de l'intérêt que cela présente, mais c'est la norme qui, il est vrai, déconseille cet usage). Donc, l'URI cité au début aurait pu (mais ce n'est pas recommandé) être file://localhost/tmp/toto.txt. (Voir aussi la section 3 du RFC.)
  • Si on ne met pas le nom de domaine, les deux premières barres obliques sont facultatives (c'est une nouveauté de notre RFC, par rapport au RFC 1738) et file:/tmp/toto.txt est donc légal.
  • Certains systèmes de fichiers sont sensibles à la casse et il faut donc faire attention, en manipulant les URI, à ne pas changer la casse. file:///c:/machin/truc et file:///c:/Machin/TRUC sont deux URI différents même si on sait bien que, sur une machine Windows, ils désigneront le même fichier.

Que peut-on faire avec un fichier ? Plein de choses (l'ouvrir, lire les données, le détruire… La norme POSIX peut donner des idées à ce sujet.) Le plan d'URI file: ne limite pas les opérations possibles.

Évidemment, l'encodage des caractères utilisé va faire des histoires, puisqu'il varie d'une machine à l'autre. C'est parfois UTF-8, parfois un autre encodage et, parfois, le système de fichiers ne définit rien, le nom est juste une suite d'octets, qui devra être interprétée par les applications utilisées (c'est le cas d'Unix). Notre RFC (section 4) recommande bien sûr d'utiliser UTF-8, avant l'optionelle transformation pour cent (RFC 3986, section 2.5). Ainsi, le fichier /home/stéphane/café.txt aura l'URI file:/home/st%C3%A9phane/caf%C3%A9.txt, quel qu'ait été son encodage sur la machine. Au passage, j'ai essayé avec curl et file:///tmp/café.txt, file:/tmp/café.txt, file:/tmp/caf%C3%A9.txt, file://localhost/tmp/caf%C3%A9.txt et même file://mon.adresse.ip.publique/tmp/caf%C3%A9.txt marchent tous.

Et la sécurité ? Toucher aux fichiers peut évidemment avoir des tas de conséquences néfastes. Par exemple, si l'utilisateur charge le fichier file:///home/michu/foobar.html, aura-t-il la même origine (au sens de la sécurité du Web) que file:///tmp/youpi.html ? Après tout, ils viennent du même domaine (le domaine vide, donc la machine locale). Le RFC note qu'au contraire l'option la plus sûre est de considérer que chaque fichier est sa propre origine (RFC 6454).

Autre question de sécurité rigolote, les systèmes de fichiers ont en général des caractères spéciaux (comme la barre oblique ou un couple de points pour Unix). Accéder bêtement à un fichier en passant juste le nom au système de fichiers peut soulever des problèmes de sécurité (c'est évidemment encore pire si on passe ces noms à des interpréteurs comme le shell, qui rajoutent leur propre liste de caractères spéciaux). Le RFC ne spécifie pas de liste de caractères « dangereux » car tout nouveau système de fichiers peut l'agrandir. C'est aux programmeurs qui font les logiciels de faire attention, pour le système d'exploitation pour lequel ils travaillent. (Un problème du même ordre existe pour les noms de fichiers spéciaux, comme /dev/zero sur Unix ou aux et lpt sur Windows.)

Une mauvaise gestion de la sensibilité à la casse ou de l'encodage des caractères peut aussi poser des problèmes de sécurité (voir par exemple le rapport technique UAX #15 d'Unicode.)

Notons qu'il existe d'autres définitions possibles d'un URI file: (annexe C de notre RFC). Par exemple, le WhatWG maintient une liste des plans d'URI, non synchronisée avec celle « officielle », et dont l'existence a fait pas mal de remous à l'IETF, certains se demandant s'il fallait quand même publier ce RFC, au risque d'avoir des définitions contradictoires (cela a sérieusement retardé la sortie du RFC). En gros, l'IETF se concentre plutôt sur la syntaxe, et le WhatWG sur le comportement des navigateurs (rappelez-vous que les URI ne sont pas utilisés que par des navigateurs…). Il y a aussi les définitions Microsoft comme UNC ou leurs règles sur les noms de fichier.

Et, pour finir, je vous recommande cet autre article de Microsoft sur l'évolution du traitement des URI dans IE.


Téléchargez le RFC 8089


L'article seul

RFC 8080: Edwards-Curve Digital Security Algorithm (EdDSA) for DNSSEC

Date de publication du RFC : Février 2017
Auteur(s) du RFC : O. Sury (CZ.NIC), R. Edmonds (Fastly)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF curdle
Première rédaction de cet article le 15 février 2017


Ce RFC (premier RFC du groupe CURDLE) spécifie comment utiliser les algorithmes de cryptographie à courbe elliptique Ed25519 et Ed448 dans DNSSEC.

Contrairement à ce qu'on a pu parfois lire sous la plume de trolls ignorants, DNSSEC, mécanisme d'authentification des enregistrements DNS, n'est en rien lié à RSA. Au contraire, comme tous les protocoles cryptographiques de l'IETF, il dispose d'une propriété nommée agilité cryptographique. Ce nom désigne un système utilisant la cryptographie qui n'est pas lié à un algorithme cryptographique particulier. Il peut donc en changer, notamment pour suivre les progrès de la cryptanalyse, qui rend l'abandon de certains algorithmes nécessaire. Aujourd'hui, par exemple, RSA semble bien démodé, et les courbes elliptiques ont le vent en poupe. Aucun problème pour DNSSEC : aussi bien les clés que les signatures disposent d'un champ numérique qui indique l'algorithme cryptographique utilisé. Les valeurs possibles de ce champ figurent dans un registre IANA, registre auquel viennent d'être ajoutés (cf. sections 5 et 7) 15 pour Ed25519 et 16 pour Ed448.

Notez que ces algorithmes ne sont pas les premiers algorithmes à courbes elliptiques normalisés pour DNSSEC : le premier avait été GOST R 34.10-2001 (RFC 5933), il y a six ans, et le second ECDSA (RFC 6605).

Les algorithmes cryptographiques Ed25519 et Ed448, instances de EdDSA, sont spécifiés dans le RFC 8032. Ils peuvent d'ailleurs servir à d'autres systèmes que DNSSEC (par exemple SSH, cf. RFC 7479).

Les détails pratiques pour DNSSEC, maintenant (section 3 du RFC). Notre nouveau RFC est court car l'essentiel était déjà fait dans le RFC 8032, il ne restait plus qu'à décrire les spécificités DNSSEC. Une clé publique Ed25519 fait 32 octets (section 5.1.5 du RFC 8032) et est encodée sous forme d'une simple chaîne de bits. Une clé publique Ed448 fait, elle, 57 octets (section 5.2.5 du RFC 8032).

Les signatures (cf. section 4 de notre RFC) font 64 octets pour Ed25519 et 114 octets pour Ed448. La façon de les générer et de les vérifier est également dans le RFC 8032, section 5.

Voici un exemple de clé publique Ed25519, et des signatures faites avec cette clé, extrait de la section 6 du RFC (attention, il y a deux erreurs, les RFC ne sont pas parfaits) :


example.com. 3600 IN DNSKEY 257 3 15 (
             l02Woi0iS8Aa25FQkUd9RMzZHJpBoRQwAQEX1SxZJA4= )

example.com. 3600 IN DS 3613 15 2 (
             3aa5ab37efce57f737fc1627013fee07bdf241bd10f3b1964ab55c78e79
             a304b )

example.com. 3600 IN MX 10 mail.example.com.

example.com. 3600 IN RRSIG MX 3 3600 (
             1440021600 1438207200 3613 example.com. (
             Edk+IB9KNNWg0HAjm7FazXyrd5m3Rk8zNZbvNpAcM+eysqcUOMIjWoevFkj
             H5GaMWeG96GUVZu6ECKOQmemHDg== )      
    

Et, pour une vraie clé dans un vrai domaine, cette fois sans erreur :


% dig DNSKEY ed25519.monshouwer.eu

; <<>> DiG 9.9.5-9+deb8u9-Debian <<>> DNSKEY ed25519.monshouwer.eu
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 46166
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;ed25519.monshouwer.eu.	IN DNSKEY

;; ANSWER SECTION:
ed25519.monshouwer.eu.	3537 IN	DNSKEY 257 3 15 (
				2wUHg68jW7/o4CkbYue3fYvGxdrd83Ikhaw38bI9dRI=
				) ; KSK; alg = 15; key id = 42116
ed25519.monshouwer.eu.	3537 IN	RRSIG DNSKEY 15 3 3600 (
				20170223000000 20170202000000 42116 ed25519.monshouwer.eu.
				Gq9WUlr01WvoXEihtwQ6r7t9AfkQfyETKTfm84WtcZkd
				M04KEe+4xu9jqhnG9THDAmV3FKASyWQ1LtCaOFr5Dw== )

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Wed Feb 15 13:13:27 CET 2017
;; MSG SIZE  rcvd: 215

Quelques questions de sécurité pour conclure ce RFC (section 8). Les clés Ed25519 font l'équivalent de 128 bits de sécurité (et 224 pour Ed448). Du fait de l'existence d'algorithmes efficaces pour les casser sur un ordinateur quantique, cela ne sera pas suffisant le jour où on disposera d'un tel ordinateur. Ce jour est probablement très lointain (bien que la NSA, organisme de confiance, dise le contraire).

Enfin, la même section 8 rappelle l'existence des attaques trans-protocoles : il ne faut pas utiliser une clé dans DNSSEC et dans un autre protocole.

À noter que ce RFC est un pas de plus vers une cryptographie 100 % Bernstein, avec cette adaptation des algorithmes utilisant Curve25519 à DNSSEC. Bientôt, l'ancien monopole de RSA aura été remplacé par un monopole de Curve25519.

Apparemment, le RFC est un peu en avance sur le logiciel, les systèmes DNSSEC existants ne gèrent pas encore Ed25519 ou Ed448 (à part, semble-t-il, PowerDNS et, bientôt, DNS Go.)


Téléchargez le RFC 8080


L'article seul

RFC 8067: Updating When Standards Track Documents May Refer Normatively to Documents at a Lower Level

Date de publication du RFC : Janvier 2017
Auteur(s) du RFC : B. Leiba (Huawei)
Première rédaction de cet article le 29 janvier 2017


Un très (vraiment très court) RFC purement bureaucratique, pour un très léger (vraiment très léger) changement des règles concernant les références d'un RFC à un autre RFC.

Le problème était simple : un RFC situé sur le Chemin des Normes est dans une étape donnée. Au nombre de trois au début (RFC 2026), ces étapes sont désormais deux (RFC 6410) : Proposition de norme et Norme. D'autre part, un RFC a des références à d'autres RFC, dans sa bibliographie, et ces références peuvent être normatives (il faut avoir lu et compris les RFC cités) ou informatives (elles sont juste là pour compléter et éclairer). Une règle de l'IETF est qu'un RFC ne peut pas avoir de référence normative à un RFC situé à une étape inférieure. Le but était d'éviter qu'une norme ne dépende d'un texte de maturité et d'adoption inférieurs.

Le RFC 3967 introduisait une exception à cette règle, mais en imposant un processus jugé désormais trop rigide. On pouvait donc, quand c'était nécessaire, déroger à la règle « pas de références vers le bas [du chemin des normes, downward reference en anglais] » mais il fallait le documenter dans le Last Call (dernier appel avant adoption). Si quelque chose changeait dans les références d'un RFC, il pouvait donc y avoir à refaire le Last Call.

C'était d'autant plus gênant que la question se pose plus souvent maintenant. En effet, les groupes de travail de l'IETF qui bossent sur un sujet compliqué font souvent un document « de base », définissant les concepts, la terminologie, etc, et ces documents ne sont pas sur le chemin des normes (ils sont juste « pour information »). Impossible donc de mettre une référence « vers le bas ».

La nouvelle règle figure en section 2 du RFC : le RFC 3967 est légèrement mis à jour. Désormais, il n'est plus nécessaire de mentionner l'existence d'une référence « vers le bas » au moment du dernier appel. En cas de changement des références, il ne sera donc plus obligatoire de répéter le dernier appel. C'est donc entièrement à l'IESG de déterminer si une référence à un RFC « inférieur » est acceptable ou non.


Téléchargez le RFC 8067


L'article seul

RFC 8065: Privacy Considerations for IPv6 Adaptation-Layer Mechanisms

Date de publication du RFC : Février 2017
Auteur(s) du RFC : D. Thaler (Microsoft)
Pour information
Réalisé dans le cadre du groupe de travail IETF 6lo
Première rédaction de cet article le 24 février 2017


Entre la couche 3 (du modèle en couches) et la couche 2 (par exemple Ethernet) se trouve une adaptation, qui définit comment on va mettre les paquets IPv6 sur la couche sous-jacente. Certaines de ces adaptations posent des problèmes de protection de la vie privée. Ce RFC résume les problèmes existants. Chaque adaptation devra ensuite travailler à s'améliorer sur ce plan (le RFC donne des idées). L'idée est d'améliorer les normes actuelles et futures, pour mieux prendre en compte ce problème de vie privée.

Ce problème de la vie privée pour IPv6 a déjà été beaucoup discuté, notamment en raison d'un choix initial de privilégier une adaptation à Ethernet qui gardait une partie de l'adresse IPv6 constante, même quand la machine changeait de réseau. Ce problème est résolu depuis longtemps (RFC 4941) mais d'autres peuvent demeurer, surtout si la couche 2 a des contraintes qui empêchent de déployer certaines protections de la vie privée.

Les documents de référence à lire d'abord sont le RFC général sur la vie privée, RFC 6973 (sa section 5.2 est particulièrement utile ici), et, plus spécifique à IPv6, le RFC 7721. Le risque qui concerne l'adaptation est lié au mécanisme de génération des IID (identificateurs d'interface, cf. RFC 4291), puisque cet IID fait partie de l'adresse IPv6 (typiquement les 64 derniers bits) et va donc être potentiellement visible publiquement. Si l'IID est trop prévisible ou trop stable, il permettra notamment :

  • De corréler des activités du même utilisateur au cours du temps,
  • De suivre l'utilisateur à la trace s'il se déplace en gardant le même IID,
  • De balayer plus facilement un réseau à la recherche de machines à attaquer (alors que, normalement, la taille élevée de l'espace d'adressage IPv6 rend ces balayages lents et pénibles).

Un concept important est celui d'entropie, c'est-à-dire du nombre de bits dans l'IID qui sont réellement imprévisibles. Idéalement, l'entropie devrait être de 64 bits (le préfixe IPv6 ayant typiquement une longueur de 64 bits pour un réseau, cf. RFC 7421).

Voilà pourquoi le RFC 8064 déconseille de créer un IID à partir d'une adresse « couche 2 » fixe, comme l'est souvent l'adresse MAC. Il recommande au contraire la technique du RFC 7217 si on veut des adresses stables tant qu'on ne se déplace pas, et celle du RFC 4941 si on veut être vraiment difficile à tracer (au prix d'une administration réseaux plus difficile). Le RFC sur la sélection des adresses source, RFC 6724 privilégie déjà par défaut les adresses temporaires du RFC 4941.

Revenons maintenant à cette histoire d'entropie (section 2 du RFC). Combien de bits sont-ils nécessaires ? Prenons le cas le plus difficile, celui d'un balayage du réseau local, avec des paquets ICMP Echo Request ou bien avec des TCP SYN. L'entropie minimum est celle qui minimise les chances d'un attaquant de trouver une adresse qui réponde. Quel temps faudra-t-il pour avoir une chance sur deux de trouver une adresse ? (Notez que la capacité de l'attaquant à trouver des machines dépend aussi du fait qu'elles répondent ou pas. Si une machine ne répond pas aux ICMP Echo Request, et n'envoie pas de RST aux paquets TCP SYN, la tâche de l'attaquant sera plus compliquée. Cf. RFC 7288, notamment sa section 5. Même si la machine répond, un limiteur de trafic peut rendre la tâche de l'attaquant pénible. Avec la valeur par défaut d'IOS de deux réponses ICMP par seconde, il faut une année pour balayer un espace de seulement 26 bits.)

Les formules mathématiques détaillées sont dans cette section 2 du RFC. L'entropie nécessaire dépend de la taille de l'espace d'adressage mais aussi de la durée de vie du réseau. Avec 2^16 machines sur le réseau (c'est un grand réseau !) et un réseau qui fonctionne pendant 8 ans, il faudra 46 bits d'entropie pour que l'attaquant n'ait qu'une chance sur deux de trouver une machine qui réponde (avec la même limite de 2 requêtes par seconde ; sinon, il faudra davantage d'entropie).

Et combien de bits d'entropie a-t-on avec les techniques actuelles ? La section 3 donne quelques exemples : seulement 48 bits en Bluetooth (RFC 7668), 8 (oui, uniquement 256 adresses possibles, mais c'est nécessaire pour permettre la compression des en-têtes) en G.9959 (RFC 7428) et le pire, 5 bits pour NFC (RFC pas encore paru).

Ces adaptations d'IPv6 à diverses couches 2 utilisent comme identificants d'interface des adresses IEEE (comme les adresses MAC) ou bien des « adresses courtes ». Commençons par les adresses reposant sur des adresses IEEE. Dans certains cas, la carte ou la puce qui gère le réseau dispose d'une adresse EUI-48 ou EUI-64 (comme l'adresse MAC des cartes Ethernet). On peut facilement construire une adresse IPv6 avec ces adresses, en concaténant le préfixe avec cette adresse IEEE utilisée comme identificateur d'interface (IID). L'entropie dépend du caractère imprévisible de l'adresse IEEE. L'IEEE a d'ailleurs des mécanismes (pas forcément déployés dans le vrai monde) pour rendre ces adresses imprévisibles. Même dans ce cas, la corrélation temporelle reste possible, sauf si on change les adresses de temps en temps (par exemple avec macchanger).

Un argument souvent donné en faveur des adresses MAC est leur unicité, qui garantit que les adresses IPv6 seront « automatiquement » distinctes, rendant ainsi inutile la détection d'adresses dupliquées (DAD, RFC 4862, section 5.4, et RFC 4429, annexe A). Sauf que ce n'est pas vrai, les adresses MAC ne sont pas forcément uniques, en pratique et les identificateurs d'interface aléatoires sont donc préférables, pour éviter les collisions d'adresses.

En dehors des adresses allouées par un mécanismes de l'IEEE, il y a les « adresses courtes » (16 bits, utilisées par IEEE 802.15.4, cf. RFC 4944), allouées localement, et uniques seulement à l'intérieur du réseau local. Vu leur taille, elles n'offrent évidemment pas assez d'entropie. Il faut donc les étendre avant de s'en servir comme identificateur d'interface. Le RFC cite par exemple un condensat de la concaténation de l'adresse courte avec un secret partagé par toutes les machines du réseau.

On peut aussi utiliser dans le condensat le numéro de version spécifié dans la section 4.3 du RFC 6775. Ainsi, un changement de numéro de version permettra une rénumérotation automatique.

Bien, après cette analyse, les recommandations (section 4) :

  • La section Sécurité (Security Considerations) des RFC qui normalisent une adaptation à une couche 2 donnée devrait dire clairement comment on limite le balayage. Cela nécessite de préciser clairement la durée de vie des adresses, et le nombre de bits d'entropie.
  • Il faut évidemment essayer de maximiser cette entropie. Avoir des identificateurs d'adresses aléatoires est une bonne façon de le faire.
  • En tout cas, pas question de juste utiliser une adresse courte et stable avec quelques bits supplémentaires de valeur fixe et bien connue.
  • Les adresses ne devraient pas être éternelles, pour limiter la durée des corrélations temporelles.
  • Si une machine peut se déplacer d'un réseau à l'autre (ce qui est courant aujourd'hui), il faudrait que l'identifiant d'interface change, pour limiter les corrélations spatiales.

Téléchargez le RFC 8065


L'article seul

RFC 8064: Recommendation on Stable IPv6 Interface Identifiers

Date de publication du RFC : Février 2017
Auteur(s) du RFC : F. Gont (SI6 Networks / UTN-FRH), A. Cooper (Cisco), D. Thaler (Microsoft), W. Liu (Huawei Technologies)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF 6man
Première rédaction de cet article le 24 février 2017


Ce RFC parle de vie privée mais il est très court, car il se contente de changer une règle, la nouvelle étant déjà largement acceptée. Désormais, si une machine IPv6 configure son adresse par le système SLAAC, et que cette adresse doit être stable dans le temps, désormais, donc, la méthode recommandée est celle du RFC 7217 et non plus celle, mauvaise pour la vie privée, d'utiliser l'adresse MAC. (Si l'adresse n'a pas besoin d'être stable, aucun changement, la méthode recommandée reste celle du RFC 4941, les adresses temporaires.)

Que veut dire SLAAC, au fait ? Ce mécanisme de configuration d'une adresse IPv6 est normalisé dans le RFC 4862. L'idée est que la machine écoute sur le réseau les annonces faites par les routeurs, apprenant ainsi le·s préfixe·s IP du réseau. Elle ajoute ensuite à ce préfixe un terme, l'identificateur d'interface (IID, cf. RFC 4291), formant ainsi une adresse IPv6 mondiale, et unique (si l'IID est bien choisi). La méthode originelle était de dériver l'IID de l'adresse MAC. Celle-ci est en effet unique et, en prime, son utilisation présente certains avantages (compression des en-têtes du RFC 6775, par exemple). Mais s'en servir soulève plein de problèmes de sécurité et notamment de vie privée : traçabilité des utilisateurs dans le temps, et dans l'espace (si la machine se déplace, elle change de préfixe mais garde le même identificateur d'interface), facilitation du balayage des adresses dans le réseau, etc (cf. RFC 7721). D'une manière générale, réutiliser des identificateurs d'un autre « monde » est une fausse bonne idée, souvent dangereuse en matière de vie privée. Voilà pourquoi ce RFC dit clairement que, désormais, il est fortement déconseillé d'utiliser les adresses MAC. (Plusieurs mises en œuvre d'IPv6, comme celles de Microsoft, avaient déjà cessé, avant même que ce RFC ne soit publié.)

Et ce RFC 7217 qu'il faut désormais suivre, il dit quoi ? Il propose de fabriquer l'identificateur d'interface en condensat une concaténation du préfixe et de diverses valeurs stables. Si on change de réseau, on a une nouvelle adresse (on ne peut donc pas suivre à la trace une machine mobile). Mais, si on reste sur le même réseau, l'adresse est stable.

La section 1 de notre RFC rappelle aussi la différence entre les adresses stables et les autres. Toutes les adresses IP n'ont pas besoin d'être stables. La solution la meilleure pour la vie privée est certainement celle du RFC 4941, des adresses temporaires, non stables (pour de telles adresses, on peut aussi utiliser le système des adresses MAC si elles changent souvent par exemple avec macchanger). Toutefois, dans certains cas, les adresses stables sont souhaitables : l'administration réseaux est plus simple, les journaux sont plus faciles à lire, on peut mettre des ACL, on peut avoir des connexions TCP de longue durée, etc. Et, bien sûr, si la machine est un serveur, ses adresses doivent être stables. Il y a donc une place pour une solution différente de celle du RFC 4941, afin de fournir des adresses stables. C'est seulement pour ces adresses stables que notre RFC recommande désormais la solution du RFC 7217.

La nouvelle règle figure donc en section 3 de notre RFC : lorsqu'une machine veut utiliser SLAAC et avoir des adresses stables, qui ne changent pas dans le temps, tant que la machine reste sur le même réseau, alors, dans ce cas et seulement dans ce cas, la méthode à utiliser est celle du RFC 7217. L'ancienne méthode (qu'on trouve par exemple dans le RFC 2464) d'ajouter le préfixe à l'adresse MAC ne doit plus être utilisée.

Notez donc bien que ce RFC ne s'adresse pas à toutes les machines IPv6. Ainsi, si vous configurez vos serveurs (qui ont clairement besoin d'une adresse stable) à la main, avec des adresses en leet comme 2001:db8::bad:dcaf, ce RFC 8064 ne vous concerne pas (puisqu'il n'y a pas de SLAAC).

Les RFC comme le RFC 4944, RFC 6282, RFC 6775 ou RFC 7428 devront donc être remplacés par des documents tenant compte de la nouvelle règles. (Cf. RFC 8065.)

Aujourd'hui, il semble que les dernières versions de Windows, MacOS, iOS et Android mettent déjà en œuvre la nouvelle règle.


Téléchargez le RFC 8064


L'article seul

RFC 8063: Key Relay Mapping for the Extensible Provisioning Protocol

Date de publication du RFC : Février 2017
Auteur(s) du RFC : H.W. Ribbers, M.W. Groeneweg (SIDN), R. Gieben, A.L.J Verschuren
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF eppext
Première rédaction de cet article le 15 février 2017


Un des problèmes pratiques que pose DNSSEC est le changement d'hébergeur DNS. Si on sous-traite sa gestion des clés cryptographiques, et ses signatures à un tiers, que faire lors du changement de prestataire, pour ne pas casser la chaîne de confiance DNSSEC ? On ne peut évidemment pas demander à l'ancien hébergeur de transmettre la clé privée au nouveau ! Même pour les données non confidentielles, comme la clé publique, la transmission est difficile car les deux hébergeurs n'ont pas de canal de transmission sécurisé commun. Ce nouveau RFC propose d'utiliser comme canal sécurisé le registre de la zone parente et, plus concrètement, de définir une extension au protocole EPP, qui permet un mécanisme de « messagerie » électronique sécurisée, afin de l'utiliser entre deux clients du même registre.

Pour bien comprendre le problème et sa solution, il faut faire un peu de terminologie :

  • Bureau d'enregistrement (BE) : l'entité par laquelle il faut passer pour toute opération sur le registre. À noter que tous les registres n'ont pas ce concept et c'est pour cela que notre RFC, comme les autres RFC sur EPP, ne parle pas de BE mais de client EPP.
  • Hébergeur DNS (DNS operator dans le RFC) : l'entité qui gère les serveurs de nom du domaine. C'est souvent le BE mais ce n'est pas du tout obligatoire. Les serveurs DNS peuvent être gérés par une entreprise spécialisée, qui n'est pas BE, ou bien directement par l'utilisateur.
  • EPP : protocole d'avitaillement (notamment de noms de domaine), normalisé dans le RFC 5730, entre un serveur (le registre) et un client (le BE, lorsque ce registre utilise des BE).
  • DNSSEC : système d'authentification des informations récupérées via le DNS. Il repose sur la cryptographie asymétrique et il y a donc une clé publique (mise dans le DNS) et une clé privée (qui n'est... pas publique). DNSSEC utilise le DNS et doit donc faire attention au temps qui s'écoule ; par exemple, lorsqu'on publie une nouvelle clé (on l'ajoute à l'ensemble DNSKEY), elle ne va pas être visible tout de suite par tous les clients DNS, certains ont en effet mémorisé l'ancien ensemble de clés.

Dans le cas le plus fréquent, l'hébergeur DNS assure la gestion des clés (création, suppression, etc) et connait donc la clé privée, qu'il utilise pour signer les enregistrements. Si le titulaire du domaine veut changer d'hébergeur, pas question bien sûr de transmettre la clé privée. Le nouvel hébergeur (le « gagnant ») va donc créer des nouvelles clés et les utiliser pour signer. Le problème est qu'un résolveur DNS peut avoir des signatures de l'ancien hébergeur (le « perdant ») et des clés du nouveau (ou bien le contraire). Dans ces deux cas, la validation échouera, le domaine sera vu comme invalide.

Une solution à ce problème serait que l'ancien hébergeur mette à l'avance (rappelez-vous, le temps est crucial dès qu'on fait du DNS...) dans les clés qu'il publie la nouvelle clé du nouvel hébergeur. Mais cela suppose qu'il connaisse cette clé. Le titulaire du nom peut servir de relais mais il n'est pas forcément compétent pour cela (« M. Michu, votre nouvel hébergeur a dû vous remettre une clé cryptographique. C'est une série de lettres et de chiffres incompréhensiblles. Pouvez-nous nous la transmettre sans la moindre altération ? »). L'ancien hébergeur ne peut pas non plus utiliser le DNS puisque les serveurs du nouveau ne sont pas encore configurés et, même s'ils le sont, l'ancien hébergeur ne peut pas valider leur contenu avec DNSSEC. L'idée de notre RFC est donc d'utiliser le registre comme intermédiaire de confiance. Si les deux hébergeurs sont également BE, ils ont déjà un canal sécurisé avec le registre (la session EPP). Sinon, on peut espérer que le BE acceptera de servir de relais entre l'hébergeur et le registre.

Avec la solution de ce RFC, le nouvel hébergeur (on va suppose qu'il est également BE, ce sera plus simple) va créer ses clés, les transmettre (la clé publique seulement, bien sûr) au registre via l'extension EPP de notre nouveau RFC, l'ancien hébergeur va les lire (le registre ne sert que de boîte aux lettres sécurisée), les mettre dans la zone DNS. Au bout d'un temps déterminé par le TTL des enregistrements, tous les résolveurs auront l'ancienne et la nouvelle clé publique dans leur mémoire, et pourront valider aussi bien les anciennes que les nouvelles signatures.

Une autre façon de résoudre ce problème serait évidemment que chacun gère sa zone DNS lui-même, et donc ne change jamais d'« hébergeur » mais ce n'est évidemment pas souhaitable pour la plupart des titulaires.

Ce RFC ne spécifie qu'un mécanisme de messagerie, pas une politique, ni une procédure détaillée. La politique est du ressort du registre et de ses BE (via le contrat qui les lie, qui spécifie typiquement des obligations comme « le BE perdant doit coopérer au transfert du domaine, et mettre les nouvelles clés dans la zone qu'il gère encore »). La procédure n'est pas décrite dans un RFC. (Il y a eu une tentative via le document draft-koch-dnsop-dnssec-operator-change, mais qui n'a pas abouti. La lecture de ce document est quand même très recommandée.) Le mécanisme de messagerie décrit dans notre RFC est donc « neutre » : il ne suppose pas une politique particulière. Une fois la clé transmise, sa bonne utilisation va dépendre des règles en plus et de si elles sont obéies ou pas. Comme le dit le RFC, « The registry SHOULD have certain policies in place that require the losing DNS operator to cooperate with this transaction, however this is beyond this document. »

Les détails EPP figurent en section 2. Les clés publiques sont dans un élément XML <keyRelayData>. Il contient deux éléments, <keyData>, avec la clé elle-même (encodée en suivant la section 4 du RFC 5910), et <expiry> (optionnel) qui indique combien de temps (en absolu ou bien en relatif) garder cette clé dans la zone. La syntaxe formelle complète figure en section 4, en XML Schema.

Les commandes EPP liées à cette extension figurent en section 3. Certaines commandes EPP ne sont pas modifiées par cette extension, comme check, info, etc. La commande create, elle, est étendue pour permettre d'indiquer la nouvelle clé (un exemple figure dans notre RFC, section 3.2.1). Si le serveur EPP accepte cette demande, il met la clé dans la file d'attente de messages du client EPP qui gère le nom de domaine en question (typiquement le BE « perdant »). Sinon, il répond pas le code de retour 2308.

La nouvelle clé apparaitra dans le système de « messagerie » d'EPP (poll queue, RFC 5730, section 2.9.2.3. Un exemple de réponse figure dans notre RFC, section 3.1.2.

Quelques points de sécurité pour finir (section 6). Un client EPP méchant pourrait envoyer des clés à plein de gens juste pour faire une attaque par déni de service. C'est au serveur EPP de détecter ces abus et d'y mettre fin. Le serveur EPP peut exiger un authinfo correct dans le message de création, pour vérifier que l'action a bien été autorisée par le titulaire. Enfin, cette technique d'envoi des clés ne garantit pas, à elle seule, que tout aura bien été fait de bout en bout. Par exemple, le nouvel hébergeur a tout intérêt à vérifier, par une requête DNS epxlicite, que l'ancien a bien mis la nouvelle clé dans la zone.

Ce RFC a eu une histoire longue et compliquée, malgré une forte demande des utilisateurs. Il y a notamment eu un gros problème avec un brevet futile (comme la plupart des brevets logiciels) de Verisign, qui a fait perdre beaucoup de temps (la déclaration de Verisign est la n° 2393, le brevet lui-même est le US.201113078643.A, la décision de l'IETF de continuer malgré ce brevet, et malgré l'absence de promesses de licence, est enregistrée ici).

Question mise en œuvre, la bibliothèque Net::DRI gère déjà ce RFC. Combien de registres et de BE déploieront ce RFC ? Le coût pour le registre est probablement assez faible, puisqu'il a juste à relayer la demande, utilisant un mécanisme de « messagerie » qui existe déjà dans EPP. Mais, pour les BE, il y a certainement un problème de motivation. Ce RFC aidera le BE « gagnant », et le titulaire du domaine, mais pas le BE « perdant ». Il n'a donc pas de raison de faire des efforts, sauf contrainte explicite imposée par le registre (et l'expérience indique que ce genre de contraintes n'est pas toujours strictement respecté).

Comme bonne explication de ce RFC, vous pouvez aussi lire l'excellent explication de SIDN (avec une jolie image). En parlant de SIDN, vous pouvez noter que leur première mention d'un déploiement d'une version préliminaire de cette solution a eu lieu en 2013 (cf. leur rapport d'activité). Le même SIDN vient de publier un article de premier bilan sur ce projet.

Merci à Patrick Mevzek pour les explications, le code et les opinions.


Téléchargez le RFC 8063


L'article seul

RFC 8060: LISP Canonical Address Format (LCAF)

Date de publication du RFC : Février 2017
Auteur(s) du RFC : D. Farinacci (lispers.net), D. Meyer (Brocade), J. Snijders (NTT)
Expérimental
Réalisé dans le cadre du groupe de travail IETF lisp
Première rédaction de cet article le 3 février 2017


Le protocole LISP permet d'utiliser comme identificateur ou comme localisateur aussi bien des adresses IPv4 qu'IPv6. Pour rendre les mécanismes de résolution d'identificateur en localisateur aussi génériques que possibles, ce nouveau RFC décrit un format d'adresses qui permet de gérer les deux familles d'adresses (et davantage).

Il existait des méthodes partielles pour représenter ces deux familles. Par exemple, on peut décider de tout mettre en IPv6 et de représenter les adresses IPv4 sous la forme « IPv4-mapped » (RFC 4291, section 2.5.5.2, par exemple ::ffff:192.0.2.151). Ou on pourrait, comme c'est le cas dans les URL, représenter les adresses sous forme texte en utilisant les crochets pour distinguer IPv4 et IPv6 (RFC 3986, section 3.2.2, par exemple https://192.0.2.151/ vs. https://[2001:db8:3f:ae51::78b:ff1]/). Mais le groupe de travail à l'IETF a choisi une solution qui traite les deux familles sur un pied d'égalité, et est parfaitement générique (elle intégre d'autres familles que simplement IPv4 et IPv6). La solution finalement documentée dans ce RFC est très souple et peut servir à bien d'autres que LISP, dès qu'on veut représenter des requêtes ou réponses d'un système d'annuaire.

À propos de familles, un terme important à retenir est celui d'AFI (Address Family Identifier). C'est un nombre identifiant la famille d'adresses utilisée. Il avait été introduit dans le RFC 2453 puis précisé dans le RFC 4760, et peut prendre plusieurs valeurs, stockées dans un registre à l'IANA (1 pour IPv4, 2 pour IPv6, etc). 0 indique une famille non spécifiée.

Le format de ces adresses LCA (LISP Canonical Address) est décrit dans la section 3 de notre RFC. L'adresse LCAF commence par l'AFI de LISP (16387) suivi de divers champs notamment la longueur totale de l'adresse et son type. Une LCA peut en effet contenir plus que des adresses IP (type 1). Elle peut aussi servir à transporter des numéros d'AS (type 3), des coordonnées géographiques (type 5), etc. La liste des types possibles est enregistrée à l'IANA. La section 4 explique les différents types et l'encodage du contenu associé.

Lorsqu'une LCA indique des adresses IP, elle utilise le type 1 : son contenu est une série de couples {AFI, adresse}. Des adresses IPv4 (AFI 1) et IPv6 (AFI 2) peuvent donc apparaitre dans cette liste (mais aussi des adresses MAC, AFI 6, lorsqu'on crée des VPN de couche 2, ou bien des noms de domaine, AFI 16). Ce seront ces LCA qui seront sans doute les plus utilisées dans les systèmes de correspondance LISP comme le futur DDT (RFC pas encore publié) ou ALT (RFC 6836).

Pour les numéros d'AS (type 3), la LCA contient un numéro d'AS, puis un préfixe (IPv4 ou IPv6) affecté à cet AS. Quant aux coordonnées géographiques (type 5), elles sont indiquées sous forme de latitude, longitude et altitude dans le système WGS-84. Cela permet, dans une réponse du système de correspondance LISP, d'indiquer la position physique du réseau du préfixe encodé dans la LCA. (Attention, le RFC note bien que cela a des conséquences pour la vie privée.) On peut aussi stocker des clés cryptographiques (type 11) dans une LCA (voir le futur RFC sur DDT et RFC 8061).

Les mises en œuvre existantes de LISP utilisent déjà les LCA (mais ne gèrent pas forcément tous les types officiels).


Téléchargez le RFC 8060


L'article seul

RFC 8058: Signaling One-Click Functionality for List Email Headers

Date de publication du RFC : Janvier 2017
Auteur(s) du RFC : J. Levine (Taughannock Networks), T. Herkula (optivo)
Chemin des normes
Première rédaction de cet article le 31 janvier 2017


Le RFC 2369 décrit des en-têtes du courrier électronique qui indiquent, entre autres, comment se désabonner d'une liste de diffusion (en-tête List-Unsubscribe:, qui indique des URI à activer pour se désabonner). Cela peut permettre des désabonnements sans interaction explicite avec l'utilisateur : le MUA voit cette en-tête, propose un bouton « Désabonnement » à l'utilisateur, et le MUA effectue la requête (par exemple HTTP) tout seul. L'inconvénient est que certains logiciels (par exemple des anti-spam) visitent automatiquement tous les liens hypertexte présents dans les messages, et risquent alors de désabonner l'abonné accidentellement. Pour éviter cela, la page pointée par l'URI présent dans List-Unsubscribe: n'est en général pas « one-click » : il faut une action explicite une fois cette page affichée. Ce nouveau RFC propose des ajouts à List-Unsubscribe: pour indiquer qu'un désabonnement one-click est possible.

Voici un exemple de cet en-tête traditionnel List-Unsubscribe: dans une liste de diffusion IETF :


List-Unsubscribe: <https://www.ietf.org/mailman/options/ietf>,
        <mailto:ietf-request@ietf.org?subject=unsubscribe>
      
    

La page indiquée dans l'URI HTTPS est une landing page : elle ne désabonne pas directement, il faut indiquer son adresse et sélectionner le bouton Unsubscribe. C'est acceptable quand l'utilisateur est un humain, mais pas dans les cas où il n'y a pas d'interaction possible. Imaginons un logiciel qui traite automatiquement les messages après le départ ou le décès d'un utilisateur, et qui veut donc le désabonner proprement de toutes les listes où il était abonné avec cette adresse désormais invalide. Ce logiciel doit pouvoir fonctionner sans intervention humaine, donc sans analyser une page HTML compliquée.

À noter que l'en-tête List-Unsubscribe: ci-dessus, comme dans la plupart des cas, propose également un URI de plan mailto:, déclenchant l'envoi d'un message par courrier électronique. La plupart des services qui envoient de grosses quantités de message (les hébergeurs de listes de diffusion à grand volume) ont du mal à gérer le flot de messages de désinscription (ils sont optimisés pour envoyer beaucoup, pas pour recevoir beaucoup), et ce RFC ne prend donc en compte que les URI de plan https:.

La section 1 résume le cahier des charges de la solution présentée ici :

  • Permettre aux émetteurs de courrier de signaler de manière standard et non-ambigue qu'on peut se désabonner en un seul clic (« one-click »),
  • Permettre aux auteurs de MUA de fournir une interface simple (par exemple un bouton « Désabonnement immédiat », lorsque le message lu est signalé comme le permettant),
  • Permettre aux utilisateurs de se désabonner sans quitter leur MUA, sans avoir à basculer vers une page Web avec des instructions spécifiques (et, notre RFC oublie de le dire, page Web qui est souvent conçue pour décourager le désabonnement de la newsletter à la con).

La section 3 du RFC spécifie la solution retenue. Elle consiste dans l'ajout d'un nouvel en-tête, List-Unsubscribe-Post:, dont le contenu est un couple clé=valeur, List-Unsubscribe=One-Click. (Ce nouvel en-tête a été ajouté dans le registre IANA.) Par exemple, l'en-tête montré plus haut deviendrait :


List-Unsubscribe: <https://www.ietf.org/mailman/options/ietf?id=66fd1aF64>,
        <mailto:ietf-request@ietf.org?subject=unsubscribe>
List-Unsubscribe-Post: List-Unsubscribe=One-Click
      
    

Cela indiquerait clairement que le désabonnement en un clic est possible. Le MUA, s'il désire effectuer le désabonnement, va alors faire une requête HTTPS de méthode POST, en mettant dans le corps de la requête le contenu de l'en-tête List-Unsubscribe-Post:. Le serveur HTTPS, s'il voit ce List-Unsubscribe=One-Click dans la requête, doit exécuter la requête sans poser de questions supplémentaires (le but étant de faire un désabonnement en un seul clic).

Notez qu'il faut indiquer quelque part l'adresse à désabonner, le serveur HTTP ne peut pas la deviner autrement. Pour rendre plus difficile la création de fausses instructions de désabonnement, cela se fait indirectement, via une donnée opaque, comprise seulement du serveur (le id dans l'exemple hypothétique ci-dessus).

Les données contenues dans le List-Unsubscribe-Post: doivent idéalement être envoyées avec le type MIME multipart/form-data (RFC 7578), et, sinon, en application/x-www-form-urlencoded, comme le ferait un navigateur Web. Bien sûr, le MUA doit avoir la permission de l'utilisateur pour effectuer ce désabonnement (on est en « un seul clic », pas en « zéro clic »).

Au fait, pourquoi la méthode POST ? GET ne peut pas modifier l'état du serveur et PUT ou DELETE sont rarement accessibles.

Le courrier électronique n'étant pas vraiment sécurisé, il y a un risque de recevoir des messages avec un List-Unsubscribe-Post: mensonger. C'est pourquoi le RFC demande (section 4) qu'il y ait un minimum d'authentification du message. La seule méthode d'authentification décrite est DKIM (RFC 6376), avec une étiquette d= identifiant le domaine. La signature DKIM doit évidemment inclure dans les en-têtes signés les List-Unsubscribe: et List-Unsubscribe-Post: dans l'étiquette DKIM h=.

Avec l'exemple plus haut, la requête HTTP POST ressemblerait à :

POST /mailman/options/ietf?id=66fd1aF64 HTTP/1.1
Host: www.ietf.org
Content-Type: multipart/form-data; boundary=---FormBoundaryjWmhtjORrn
Content-Length: 124

---FormBoundaryjWmhtjORrn
Content-Disposition: form-data; name="List-Unsubscribe"

One-Click
---FormBoundaryjWmhtjORrn--
    

La section 6 de notre RFC décrit les éventuels problèmes de sécurité. En gros, il en existe plusieurs, mais tous sont en fait des problèmes génériques du courrier électronique, et ne sont pas spécifiques à cette nouvelle solution. Par exemple, un spammeur pourrait envoyer plein de messages ayant l'en-tête List-Unsubscribe-Post:, pour faire générer plein de requêtes POST vers le pauvre serveur. Mais c'est déjà possible aujourd'hui en mettant des URI dans un message, avec les logiciels qui vont faire des GET automatiquement.

Je n'ai pas encore vu cet en-tête List-Unsubscribe-Post: apparaitre dans de vrais messages.

Un des auteurs du RFC a écrit un bon résumé de son utilité, article qui explique bien comment fonctionne le courrier aujourd'hui.


Téléchargez le RFC 8058


L'article seul

RFC 8056: Extensible Provisioning Protocol (EPP) and Registration Data Access Protocol (RDAP) Status Mapping

Date de publication du RFC : Janvier 2017
Auteur(s) du RFC : J. Gould (Verisign)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF regext
Première rédaction de cet article le 18 janvier 2017


Deux protocoles utilisés dans l'industrie des noms de domaine, EPP et RDAP, ont la notion d'état d'un nom de domaine, indiquant, par exemple, que ce nom est verrouillé et ne doit pas être modifié. Mais les états de EPP et de RDAP sont différents, et pas toujours évidents à rapprocher. Ce nouveau RFC précise la correspondance entre les états EPP et les états RDAP, établissant la liste comparée.

EPP (protocole d'avitaillement d'objets dans un registre, par exemple un registre de noms de domaine) est normalisé dans divers RFC (STD 69), ceux qui décrivent les états sont les RFC 5731 (section 2.3), RFC 5732 (section 2.3), RFC 5733 (section 2.2) et RFC 3915 (section 3.1). Les états RDAP (protocole d'information sur les objets d'un registre, qui vise à remplacer whois) sont normalisés dans le RFC 7483 (section 10.2) qui crée un registre IANA des états possibles. Pourquoi des états différents dans ces deux protocoles ? Disons qu'ils ont été conçus pour des buts différents, et que la nécessité de faire correspondre les états de l'un avec ceux de l'autre n'est devenue évidente qu'après. Le but de ce nouveau RFC est justement d'établir une correspondance univoque entre les états d'EPP et de RDAP.

La section 2 de notre RFC commence par une liste des états EPP, avec leur équivalent RDAP (quand il existe). Par exemple, il est assez évident que le pendingDelete d'EPP (RFC 5731) correspond au pending delete de RDAP. De même, le ok d'EPP est clairement l'équivalent du active de RDAP. Mais les addPeriod (RFC 3915, durée après l'enregistrement d'un nom de domaine pendant laquelle on peut annuler l'enregistrement gratuitement) ou clientHold (RFC 5731, le client a demandé que ce nom de domaine ne soit pas publié dans le DNS) d'EPP n'ont pas d'équivalent RDAP. L'inverse existe aussi, le delete prohibited de RDAP n'a pas un équivalent simple en EPP, qui a deux états pour cela, selon que l'interdiction a été posée par le client EPP ou par le serveur.

La section 2 du RFC se continue donc avec ce qui est désormais la liste officielle des correspondances, en tenant compte des nouveaux états ajoutés, par exemple dans le registre RDAP. C'est ainsi qu'un add period et un client hold ont été ajoutés (section 3 du RFC), ainsi qu'un client delete prohibited et un server delete prohibited, pour préciser le delete prohibited.

Pour les TLD gérés par l'ICANN, il va sans doute être obligatoire d'utiliser ces nouveaux états.


Téléchargez le RFC 8056


L'article seul

RFC 8054: Network News Transfer Protocol (NNTP) Extension for Compression

Date de publication du RFC : Janvier 2017
Auteur(s) du RFC : K. Murchison (Carnegie Mellon University), J. Élie
Chemin des normes
Première rédaction de cet article le 26 janvier 2017


Ce nouveau RFC définit un mécanisme standard de compression des news échangées en NNTP, sur Usenet.

NNTP, normalisé dans le RFC 3977 est un protocole gourmand en débit. Comprimer les données transmises est donc très souhaitable. C'est aussi un protocole très ancien, ce qui se voit dans certaines références du RFC, comme l'allusion à la compression PPP du RFC 1962 ou bien à la compression par modem comme V42bis :-)

Mais, malgré ce besoin de compression, il n'y avait pas encore de solution standard en NNTP. Un certain nombre de mécanismes non-standards avaient été déployés avec des noms comme XZVER, XZHDR, XFEATURE COMPRESS, ou MODE COMPRESS. Outre l'absence de normalisation, ils souffraient de ne comprimer que les réponses du serveur de news.

Compte-tenu du déploiement de plus en plus fréquent de TLS, pour assurer la confidentialité des échanges, il avait été envisagé à une époque de compter sur le mécanisme de compression de TLS (RFC 4642). Celui-ci présente malheureusement des dangers, qui fait que son usage est déconseillé dans beaucoup de cas (section 3.3 du RFC 7525, et section 2.6 du RFC 7457). En outre, la solution de ce RFC bénéficie de davantage de souplesse : elle peut par exemple n'être activée qu'une fois l'authentification faite, pour éviter les attaques comme CRIME (voir aussi les sections 2.2.2 et 7 de notre RFC, pour tous les détails de sécurité).

Pour assurer l'interopérabilité maximale, un seul algorithme de compression est défini, et il est, logiquement, obligatoire. Cela garantit qu'un client et un serveur NNTP auront toujours cet algorithme en commun. Il s'agit de Deflate, normalisé dans le RFC 1951.

(Un petit point qui n'a rien à voir avec NNTP et la compression : comme le demandait l'Internet-Draft qui a donné naissance à notre RFC, j'ai mis un accent à la première lettre du nom d'un des auteurs, ce qui n'est pas possible dans le RFC original, cela ne le sera que lorsque le RFC 7997 sera mis en œuvre.)

Maintenant, les détails techniques (section 2 du RFC). Le serveur doit annoncer sa capacité à comprimer en réponse à la commande CAPABILITIES. Par exemple (C = client, S = serveur) :

[C] CAPABILITIES
[S] 101 Capability list:
[S] VERSION 2
[S] READER
[S] IHAVE
[S] COMPRESS DEFLATE SHRINK
[S] LIST ACTIVE NEWSGROUPS
[S] .
    

L'annonce de la capacité est suivie de la liste des algorithmes gérés. On trouve évidemment l'algorithme obligatoire DEFLATE mais aussi un algorithme non-standard (imaginaire, ce n'est qu'un exemple) SHRINK.

Le client peut alors utiliser la commande COMPRESS, suivie du nom d'un algorithme (cette commande a été ajoutée au registre IANA des commandes NNTP). Voici un exemple où le serveur accepte la compression :

[C] COMPRESS DEFLATE
[S] 206 Compression active    
(À partir de là, le trafic est comprimé)
    

Attention à ne pas confondre la réponse du serveur à une demande de ses capacités, et la commande envoyée par le client (dans les deux cas, ce sera une ligne COMPRESS DEFLATE).

Et voici un exemple où le serveur refuse, par exemple parce que la compression a déjà été activée :

[C] COMPRESS DEFLATE
[S] 502 Command unavailable
    

Si on utilise TLS, ce qui est évidemment recommandé pour des raisons de confidentialité et d'authentification, l'envoyeur doit d'abord comprimer, puis (si SASL est activé) appliquer SASL (RFC 4422), puis seulement à la fin chiffrer avec TLS. À la réception, c'est bien sûr le contraire, on déchiffre le TLS, on analyse SASL, puis on décomprime.

Voici un exemple d'un dialogue plus détaillé, avec TLS et compression :

    
[C] CAPABILITIES
[S] 101 Capability list:
[S] VERSION 2
[S] READER
[S] STARTTLS
[S] AUTHINFO
[S] COMPRESS DEFLATE
[S] LIST ACTIVE NEWSGROUPS
[S] .
[C] STARTTLS
[S] 382 Continue with TLS negotiation
(Négociation TLS)
(Désormais, tout est chiffré)
[C] CAPABILITIES
[S] 101 Capability list:
[S] VERSION 2
[S] READER
[S] AUTHINFO USER
[S] COMPRESS DEFLATE
[S] LIST ACTIVE NEWSGROUPS
[S] .
[C] AUTHINFO USER michu
[S] 381 Enter passphrase
[C] AUTHINFO PASS monsieur
[S] 281 Authentication accepted
[C] CAPABILITIES
[S] 101 Capability list:
[S] VERSION 2
[S] READER
[S] POST
[S] COMPRESS DEFLATE
[S] LIST ACTIVE NEWSGROUPS
[S] .
[C] COMPRESS DEFLATE
[S] 206 Compression active
(Désormais, toutes les données envoyées sont comprimées, puis chiffrées)
[C] CAPABILITIES
[S] 101 Capability list:
[S] VERSION 2
[S] READER
[S] POST
[S] LIST ACTIVE NEWSGROUPS
[S] .

Et voici deux exemples où le serveur refuse la compression. D'abord parce qu'il ne peut pas (manque de mémoire, par exemple) :

[C] COMPRESS DEFLATE
[S] 403 Unable to activate compression

Et ici parce que le client essaie d'utiliser un algorithme que le serveur ne connait pas :

[C] COMPRESS SHRINK
[S] 503 Compression algorithm not supported

La liste des algorithmes standards (pour l'instant réduite à un seul) est dans un registre IANA.

NNTP est un protocole dont les spécificités posent des problèmes amusants lorsqu'on veut comprimer son trafic (section 3 du RFC). Les messages sont très divers, ce qui peut être contrariant pour une compression fondée sur un dictionnaire. Les réponses à certaines commandes (DATE, GROUP, NEXT, et le CHECK du RFC 4644) sont peu comprimables. Par contre, les réponses à LIST, LISTGROUP ou NEWNEWS sont facilement réduites à 25 à 40 % de la taille originale avec zlib.

En outre, les news envoyées sont dans des formats différents. Un article sera parfois du texte seul, relativement court (et souvent uniquement en ASCII) et se comprimera bien. Les textes plus longs sont souvent envoyés sous un format déjà comprimé et, là, le compresseur NNTP va s'essouffler pour rien. Mais il y a aussi souvent des données binaires (images, par exemple), encodées en Base64 ou uuencode. On peut souvent les réduire à 75 % de l'original. (Deflate marche bien sur des données en 8 bits mais l'encodage lui dissimule la nature 8-bitesque de ces données.) Si les données sont encodées en yEnc, elles seront moins compressibles.

Il y a apparemment au moins un logiciel serveur (INN) et un client (flnews) qui gèrent cette compression.

Merci à Julien Élie pour sa relecture attentive (et pour avoir trouvé au moins une grosse faute.)


Téléchargez le RFC 8054


L'article seul

RFC 8040: RESTCONF Protocol

Date de publication du RFC : Janvier 2017
Auteur(s) du RFC : A. Bierman (YumaWorks), M. Bjorklund (Tail-f Systems), K. Watsen (Juniper)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF netconf
Première rédaction de cet article le 1 février 2017


Pour configurer à distance un équipement réseau (par exemple un routeur ou bien un commutateur), il existait déjà le protocole NETCONF (RFC 6241). Fondé sur un échange de données en XML, il n'a pas convaincu tout le monde, qui aurait préféré un protocole REST. C'est désormais fait avec RESTCONF, décrit dans ce RFC.

RESTCONF est donc bâti sur HTTP (RFC 7230) et les opérations CRUD. Comme NETCONF, RESTCONF utilise des modèles de données décrits en YANG (RFC 7950). Il devrait donc permettre de configurer plus simplement les équipements réseau. (Les historiens noteront que l'ancêtre SNMP avait été prévu, non seulement pour lire des informations, mais également pour écrire, par exemple pour modifier la configuration d'un routeur. Cette possibilité n'a eu aucun succès. Cet échec est une des raisons pour lesquelles NETCONF a été développé.)

Les opérations CRUD sont donc faites avec les méthodes classiques de HTTP (RFC 7231). Lire l'état de l'engin se fait évidemment avec la méthode GET. Le modifier se fait avec une des méthodes parmi PUT, DELETE, POST ou PATCH (cf. section 4 du RFC). Les données envoyées, ou bien lues, sont encodées, au choix, en XML ou en JSON. À noter que RESTCONF, conçu pour les cas relativement simples, est plus limité que NETCONF (il n'a pas de fonction de verrou, par exemple). Il ne peut donc pas complètement remplacer NETCONF (ainsi, si un client NETCONF a mis un verrou sur une ressource, le client RESTCONF ne peut pas y accéder, voir la section 1.4 du RFC). Mais le RFC fait quand même plus de 130 pages, avec plein d'options.

La syntaxe des URL utilisés comme paramètres de ces méthodes est spécifiée dans ce RFC en utilisant le langage de gabarit du RFC 6570. Ainsi, dans ce langage, les URL de Wikipédia sont décrits par http://fr.wikipedia.org/wiki/{topic} ce qui signifie « le préfixe http://fr.wikipedia.org/wiki/ suivi d'une variable (qui est le sujet de la page) ».

En connaissant le modèle de données YANG du serveur, le client peut ainsi générer les requêtes REST nécessaires.

Les exemples du RFC utilisent presque tous la configuration d'un... juke-box (le module YANG est décrit dans l'annexe A). Cet engin a une fonction « jouer un morceau » et voici un exemple de requête et réponse REST encodée en JSON où le client demande au serveur ce qu'il sait faire :

GET /top/restconf/operations HTTP/1.1
Host: example.com
Accept: application/yang-data+json

HTTP/1.1 200 OK
Date: Mon, 23 Apr 2016 17:01:00 GMT
Server: example-server
Cache-Control: no-cache
Last-Modified: Sun, 22 Apr 2016 01:00:14 GMT
Content-Type: application/yang-data+json

{ "operations" : { "example-jukebox:play" : [null] } }
    

L'opération play, elle, est décrite dans l'annexe A, le modèle de données du juke-box :

rpc play {
        description "Control function for the jukebox player";
        input {
          leaf playlist {
            type string;
            mandatory true;
            description "playlist name";
            }
	  leaf song-number {
            type uint32;
            mandatory true;
	  ...
    

Autre exemple, où on essaie de redémarrer le juke-box (et, cette fois, on encode en XML pour montrer la différence avec JSON - notez les différents types MIME, comme application/yang-data+xml ou application/yang-data+json, et le fait que la racine est /restconf et plus /top/restconf) :


POST /restconf/operations/example-ops:reboot HTTP/1.1
Host: example.com
Content-Type: application/yang-data+xml

<input xmlns="https://example.com/ns/example-ops">
    <delay>600</delay>
    <message>Going down for system maintenance</message>
    <language>en-US</language>
</input>

HTTP/1.1 204 No Content
Date: Mon, 25 Apr 2016 11:01:00 GMT
Server: example-server

    

(Le serveur a accepté - le code de retour commence par 2 - mais n'a rien à dire, d'où le corps de la réponse vide, et le code 204 au lieu de 200.)

Et voici un exemple de récupération d'informations avec GET :

      
GET /restconf/data/example-jukebox:jukebox/library/artist=Foo%20Fighters/album=Wasting%20Light HTTP/1.1
Host: example.com
Accept: application/yang-data+xml

HTTP/1.1 200 OK
Date: Mon, 23 Apr 2016 17:02:40 GMT
Server: example-server
Content-Type: application/yang-data+xml
Cache-Control: no-cache
ETag: "a74eefc993a2b"
Last-Modified: Mon, 23 Apr 2016 11:02:14 GMT

<album xmlns="http://example.com/ns/example-jukebox"
             xmlns:jbox="http://example.com/ns/example-jukebox">
        <name>Wasting Light</name>
        <genre>jbox:alternative</genre>
        <year>2011</year>
</album>

    

Pour éviter les collisions d'édition (Alice lit une variable, tente de l'incrémenter, Bob tente de la multiplier par deux, qui va gagner ?), RESTCONF utilise les mécanismes classiques de HTTP, If-Unmodified-Since:, If-Match:, etc.

Allez, encore un exemple, je trouve qu'on comprend mieux avec des exemples, celui-ci est pour modifier une variable :

PUT /restconf/data/example-jukebox:jukebox/library/artist=Foo%20Fighters/album=Wasting%20Light HTTP/1.1
Host: example.com
Content-Type: application/yang-data+json

{
        "example-jukebox:album" : [
          {
            "name" : "Wasting Light",
            "genre" : "example-jukebox:alternative",
            "year" : 2011
          }
        ]
}

HTTP/1.1 204 No Content
Date: Mon, 23 Apr 2016 17:04:00 GMT
Server: example-server
Last-Modified: Mon, 23 Apr 2016 17:04:00 GMT
ETag: "b27480aeda4c"     
    

Et voici un exemple utilisant la méthode PATCH, qui avait été introduite dans le RFC 5789, pour changer l'année de l'album :


PATCH /restconf/data/example-jukebox:jukebox/library/artist=Foo%20Fighters/album=Wasting%20Light HTTP/1.1
Host: example.com
If-Match: "b8389233a4c"
Content-Type: application/yang-data+xml

<album xmlns="http://example.com/ns/example-jukebox">
       <year>2011</year>
</album>

HTTP/1.1 204 No Content
Date: Mon, 23 Apr 2016 17:49:30 GMT
Server: example-server
Last-Modified: Mon, 23 Apr 2016 17:49:30 GMT
ETag: "b2788923da4c"

    

Et on peut naturellement détruire une ressource :

DELETE /restconf/data/example-jukebox:jukebox/library/artist=Foo%20Fighters/album=Wasting%20Light HTTP/1.1
Host: example.com

HTTP/1.1 204 No Content
Date: Mon, 23 Apr 2016 17:49:40 GMT
Server: example-server
    

L'URL utilisé dans la requête comprend les différentes parties habituelles d'un URL (RFC 3986) : le chemin, la requête, l'identificateur, etc. (Dans les exemples précédents, je n'ai pas mis de requête ou d'identificateur.)

Notre RFC impose HTTPS, puisque modifier la configuration d'un équipement réseau est évidemment une opération sensible. Pour la même raison, le serveur RESTCONF doit évidemment authentifier le client. La méthode recommandée est le certificat client (section 7.4.6 du RFC 5246) mais on peut aussi utiliser une autre méthode d'authentification HTTP.


Téléchargez le RFC 8040


L'article seul

RFC 8032: Edwards-curve Digital Signature Algorithm (EdDSA)

Date de publication du RFC : Janvier 2017
Auteur(s) du RFC : S. Josefsson (SJD AB), I. Liusvaara (Independent)
Pour information
Réalisé dans le cadre du groupe de recherche IRTF cfrg
Première rédaction de cet article le 25 janvier 2017


Ce RFC est la description IETF de l'algorithme de signature cryptographique EdDSA. EdDSA est en fait une famille, il prend un certain nombre de paramètres, comme la courbe elliptique Edwards utilisée et ce RFC décrit son utilisation avec les courbes Edwards25519 et Edwards448.

EdDSA n'avait apparemment été décrit auparavant que dans des publications scientifiques, ce RFC sert à la fois à avoir une référence IETF, et également à décrire EdDSA dans des termes plus familiers aux programmeurs. Pourquoi faire de l'EdDSA, d'ailleurs ? Parce que cet algorithme (ou plutôt cette famille d'algorithmes) a plusieurs avantages, notamment :

  • Rapide,
  • Ne nécessite pas un nombre aléatoire différent par signature (un problème qui a souvent frappé les mises en œuvres de DSA, par exemple avec la Sony Playstation),
  • Clés et signatures de taille réduite.

Un site Web sur EdDSA a été créé par ses auteurs. La référence officielle d'EdDSA est l'article « High-speed high-security signatures » de D. Bernstein, N. Duif, T. Lange, P. Schwabe, P., et B. Yang. Une extension à d'autres courbes est décrite dans « EdDSA for more curves ». Sur les courbes elles-mêmes, on peut consulter le RFC 7748.

La section 3 du RFC décrit l'algorithme générique d'EdDSA. Comme il laisse ouvert pas moins de onze paramètres, on voit qu'on peut créer une vaste famille d'algorithmes se réclamant d'EdDSA. Mais, évidemment, toutes les combinaisons possibles pour ces onze paramètres ne sont pas sérieuses du point de vue de la sécurité cryptographique, et notre RFC ne décrira que cinq algorithmes spécifiques, dont ed25519 et ed448. L'algorithme générique est surtout utile pour la culture générale.

C'est parce que EdDSA est un algorithme générique (au contraire de ECDSA) que les programmes qui l'utilisent ne donnent pas son nom mais celui de l'algorithme spécifique. Ainsi, OpenSSH vous permet de générer des clés Ed25519 (ssh-keygen -t ed25519) mais pas de clés EdDSA (ce qui ne voudrait rien dire).

La section 4 du RFC décrit en détail un des paramètres importants de EdDSA : le choix de la fonction prehash. Celle-ci peut être l'identité (on parle alors de Pure EdDSA) ou bien une fonction de condensation cryptographique (on parle alors de Hash EdDSA).

La section 5, elle, spécifie EdDSA avec les autres paramètres, décrivant notamment Ed25519 et Ed448. Ainsi, Ed25519 est EdDSA avec la courbe Edwards25519, et une fonction prehash qui est l'identité. (Pour les autres paramètres, voir le RFC.) L'algorithme Ed25519ph est presque identique sauf que sa fonction prehash est SHA-512.

Comme tout algorithme de cryptographie, il faut évidemment beaucoup de soin quand on le programme. La section 8 du RFC contient de nombreux avertissements indispensables pour le programmeur. Un exemple typique est la qualité du générateur aléatoire. EdDSA n'utilise pas un nombre aléatoire par signature (la plaie de DSA), et est déterministe. La sécurité de la signature ne dépend donc pas d'un bon ou d'un mauvais générateur aléatoire. (Rappelons qu'il est très difficile de faire un bon générateur aléatoire, et que beaucoup de programmes de cryptographie ont eu des failles de sécurité sérieuses à cause d'un mauvais générateur.) Par contre, la génération des clés, elle, dépend de la qualité du générateur aléatoire (RFC 4086).

Il existe désormais pas mal de mises en œuvre d'EdDSA, par exemple dans OpenSSH cité plus haut. Sinon, les annexes A et B du RFC contiennent une mise en œuvre en Python d'EdDSA. Attention, elle est conçue pour illustrer l'algorithme, pas forcément pour être utilisée en production. Par exemple, elle n'offre aucune protection contre les attaques exploitant la différence de temps de calcul selon les valeurs de la clé privée (cf. la section 8.1). J'ai extrait ces deux fichiers, la bibliothèque eddsalib.py et le programme de test eddsa-test.py (ils nécessitent Python 3). Le programme de test prend comme entrée un fichier composé de plusieurs vecteurs de test, chacun comprenant quatre champs, séparés par des deux-points, clé secrète, clé publique, message et signature. La section 7 du RFC contient des vecteurs de test pour de nombreux cas. Par exemple, le test 2 de la section 7.1 du RFC s'écrit 4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb:3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c:72:92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00 et l'exécution du programme de test affiche juste le numéro de ligne quand tout va bien :

% python3 eddsa-test.py < vector2.txt      
1
    

On peut aussi utiliser des tests plus détaillés comme ce fichier de vecteurs de test :

    
% python3 eddsa-test.py < sign.input
1
2
3
...
1024

Si on change le message, la signature ne correspond évidemment plus et le programme de test indique une assertion erronée :


% python3 eddsa-test.py < vector2-modified.txt
1
Traceback (most recent call last):
  File "eddsa-test.py", line 30, in <module>
    assert signature == Ed25519.sign(privkey, pubkey, msg)
AssertionError

    

Téléchargez le RFC 8032


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 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 8021: Generation of IPv6 Atomic Fragments Considered Harmful

Date de publication du RFC : Janvier 2017
Auteur(s) du RFC : F. Gont (SI6 Networks / UTN-FRH), W. Liu (Huawei Technologies), T. Anderson (Redpill Linpro)
Pour information
Première rédaction de cet article le 7 janvier 2017


C'est quoi, un « fragment atomique » ? Décrits dans le RFC 6946, ces charmants objets sont des datagrammes IPv6 qui sont des fragments... sans en être. Ils ont un en-tête de fragmentation sans être fragmentés du tout. Ce RFC estime qu'ils ne servent à rien, et sont dangereux, et devraient donc ne plus être générés.

Le mécanisme de fragmentation d'IPv6 (assez différent de celui d'IPv4) est décrit dans le RFC 2460, sections 4.5 et 5. Que se passe-t-il si un routeur génère un message ICMP Packet Too Big (RFC 4443, section 3.2) en indiquant une MTU inférieure à 1 280 octets, qui est normalement la MTU minimale d'IPv6 ? (Le plus beau, c'est que ce routeur n'est pas forcément en tort, cf. RFC 6145, qui décrivait leur utilisation pour être sûr d'avoir un identificateur de datagramme.) Eh bien, dans ce cas, l'émetteur du datagramme trop gros doit mettre un en-tête « Fragmentation » dans les datagrammes suivants, même s'il ne réduit pas sa MTU en dessous de 1 280 octets. Ce sont ces datagrammes portant un en-tête « Fragmentation » mais pas réellement fragmentés (leur bit M est à 0), qui sont les fragments atomiques du RFC 6946.

Malheureusement, ces fragments atomiques permettent des attaques contre les machines IPv6 (section 2 du RFC). Il existe des attaques liées à la fragmentation (RFC 6274 et RFC 7739). Certaines nécessitent que les datagrammes soient réellement fragmentés mais ce n'est pas le cas de toutes : il y en a qui marchent aussi bien avec des fragments atomiques. Un exemple d'une telle attaque exploite une énorme erreur de certaines middleboxes, jeter les datagrammes IPv6 ayant un en-tête d'extension, quel qu'il soit (y compris, donc, l'en-tête Fragmentation). Ce comportement est stupide mais hélas répandu (cf. RFC 7872). Un attaquant peut exploiter cette violation de la neutralité du réseau pour faire une attaque par déni de service : il émet des faux messages ICMP Packet Too Big avec une MTU inférieur à 1 280 octets, la source se met à générer des fragments atomiques, et ceux-ci sont jetés par ces imbéciles de middleboxes.

Le RFC décrit aussi une variante de cette attaque, où deux pairs BGP jettent les fragments reçus (méthode qui évite certaines attaques contre le plan de contrôle du routeur) mais reçoivent les ICMP Packet Too Big et fabriquent alors des fragments atomiques. Il serait alors facile de couper la session entre ces deux pairs. (Personnellement, le cas me parait assez tiré par les cheveux...)

Ces attaques sont plus faciles à faire qu'on ne pourrait le croire car :

  • Un paquet ICMP peut être légitimement émis par un routeur intermédiaire et l'attaquant n'a donc pas besoin d'usurper l'adresse IP de la destination (donc, BCP 38 ne sert à rien).
  • Certes, l'attaquant doit usurper les adresses IP contenues dans le message ICMP lui-même mais c'est trivial : même si on peut en théorie envisager des contrôles du style BCP 38 de ce contenu, en pratique, personne ne le fait aujourd'hui.
  • De toute façon, pas mal de mises en œuvres d'IP ne font aucune validation du contenu du message ICMP (malgré les recommandations du RFC 5927).
  • Un seul message ICMP suffit, y compris pour plusieurs connexions TCP, car la MTU réduite est typiquement mémorisée dans le cache de l'émetteur.
  • Comme la seule utilisation légitime connue des fragments atomiques était celle du RFC 6145 (qui a depuis été remplacé par le RFC 7915), on pourrait se dire qu'il suffit de limiter leur génération aux cas où on écrit à un traducteur utilisant le RFC 6145. Mais cela ne marche pas, car il n'y a pas de moyen fiable de détecter ces traducteurs.

Outre ces problèmes de sécurité, le RFC note (section 3) que les fragments atomiques ne sont de toute façon pas quelque chose sur lequel on puisse compter. Il faut que la machine émettrice les génère (elle devrait, mais la section 6 du RFC 6145 note que beaucoup ne le font pas), et, malheureusement, aussi bien les messages ICMP Packet Too Big que les fragments sont souvent jetés par des machines intermédiaires.

D'ailleurs, il n'est même pas certain que la méthode du RFC 6145 (faire générer des fragments atomiques afin d'obtenir un identificateur par datagramme) marche vraiment, l'API ne donnant pas toujours accès à cet identificateur de fragment. (Au passage, pour avoir une idée de la complexité de la mise en œuvre des fragments IP, voir cet excellent article sur le noyau Linux.)

En conclusion (section 4), notre RFC demande qu'on abandonne les fragments atomiques :

  • Les traducteurs du RFC 7915 (la seule utilisation légitime connue) devraient arrêter d'en faire générer.
  • Les machines IPv6 devraient désormais ignorer les messages ICMP Packet Too Big lorsqu'ils indiquent une MTU inférieure à 1 280 octets.

Téléchargez le RFC 8021


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 7816, 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 :

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

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 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 des différentes séries : 0  1000  2000  3000  4000  5000  6000  7000  8000