Je suis Charlie

Autres trucs

Accueil

Seulement les RFC

Seulement les fiches de lecture

echoping

Ève

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


Le protocole RDAP, remplaçant de whois ?

Première rédaction de cet article le 26 mars 2015


Traditionnellement, pour trouver de l'information sur un objet enregistré dans une base de données publique de l'Internet (nom de domaine, adresse IP, etc), on utilisait le protocole whois (qui avait été normalisé, longtemps après sa création, dans le RFC 3912). Ce protocole a de grosses limitations (décrites au paragraphe suivant) et plusieurs tentatives ont déjà été faites pour le remplacer. Le nouveau venu, RDAP (Registration Data Access Protocol), va t-il mieux réussir que les précédents ?

Attention, comme le note le document SAC-051 « SSAC Report on Domain Name WHOIS Terminology and Structure », le terme « whois » est souvent employé incorrectement. Il désigne normalement un protocole (celui normalisé dans le RFC 3912) mais est également utilisé pour désigner un service (celui d'accès aux données d'enregistrement) voire pour désigner les données elle-mêmes (« informations WHOIS », terme erroné mais fréquent). Voici un exemple d'utilisation de whois sur Unix, avec le logiciel client GNU whois, pour avoir de l'information sur le domaine reflets.info :

% whois reflets.info
Domain Name:REFLETS.INFO
Creation Date: 2010-12-23T13:46:11Z
Updated Date: 2014-12-12T17:24:31Z
Sponsoring Registrar:Gandi SAS (R191-LRMS)
...
Registrant Name:Antoine Champagne
Registrant Organization:
Registrant Street: Whois Protege / Obfuscated whois
Registrant Street: Gandi, 63-65 boulevard Massena
Registrant City:Paris
Registrant State/Province:
Registrant Postal Code:75013
Registrant Country:FR
Registrant Phone:+33.170377666
Registrant Email:ea208c9533d64ffbaa6ff82bdbf084d4-3087564@contact.gandi.net

Parmi les principales limites de whois :

  • Aucun mécanisme d'authentification, donc pas de possibilité de restreindre les données selon le client (certains registres utilisent l'adresse IP du client pour donner des privilèges à certains clients),
  • Aucun mécanisme de confidentialité (ce point est lié au précédent : comme tout est public actuellement, la confidentialité ne servirait à rien),
  • Aucun mécanisme standard pour fournir des options spécifiques à la recherche,
  • Aucune structuration des données : le client doit analyser des dizaines de formats différents pour trouver ce qu'il cherche (certains logiciels le font pour lui, comme Net::DRI mais ils sont rarement complets, il y a toujours un serveur whois quelque part qui suit des règles différentes et non reconnues) ; même chose pour les messages d'erreur (comme « entitée non trouvée »),
  • Aucune internationalisation : peut-on envoyer de l'Unicode en réponse à un client et, si oui, avec quel encodage ?
  • Aucune façon normalisée d'adapter le résultat au lecteur (par exemple envoyer une adresse en caractères chinois ou bien en caractères latins selon le client),
  • Aucun mécanisme standard pour trouver le serveur pertinent pour un objet donné : chaque client whois utilise un truc particulier (par exemple, GNU whois a une liste de serveurs, qu'on peut modifier en éditant un fichier de configuration /etc/whois.conf).

Cette liste est connue depuis longtemps. C'est ainsi que le RFC 3707 dressait déjà un cahier des charges d'un bon successeur de whois.

En mai 2012, après pas mal de discussions, l'IETF a créé le groupe de travail WEIRDS pour produire un remplaçant à whois. Ce groupe WEIRDS publie aujourd'hui RDAP (Registration Data Access Protocol), le nouveau protocole. Ses principes ? Modularité (on peut utiliser plusieurs protocoles de transport, le langage d'expression des requêtes est séparé de la définition du format des réponses), et le respect des modes actuelles. Le premier transport normalisé utilise REST et le premier format de réponses est bâti sur JSON (RFC 7159). La requête RDAP avec REST+JSON équivalente à la requête whois citée plus haut serait (cf. la documentation du service RDAP expérimental de .info) :

%  curl   http://rdg.afilias.info/rdap/domain/reflets.info 
{
   "entities": [
      {
         "links": [
            {
               "href": "http://rdg.afilias.info/rdap/entity/AC12196-GANDI", 
               "rel": "self", 
               "type": "application/rdap+json", 
               "value": "http://rdg.afilias.info/rdap/entity/AC12196-GANDI"
            }
         ], 
         "objectClassName": "entity", 
         "roles": [
            "technical", 
            "billing", 
            "administrative", 
            "registrant"
         ], 
         "vcardArray": [
            "vcard", 
            [
               [
                  "version", 
                  {}, 
                  "text", 
                  "4.0"
               ], 
               [
                  "fn", 
                  {}, 
                  "text", 
                  "Antoine Champagne"
               ], 
               [
                  "adr", 
                  {}, 
                  "text", 
                  [
                     "", 
                     "", 
                     "Whois Protege / Obfuscated whois", 
                     "Paris", 
                     "", 
                     "75013", 
                     "FR"
                  ]
               ], 
               [
                  "email", 
                  {}, 
                  "text", 
                  "ea208c9533d64ffbaa6ff82bdbf084d4-3087564@contact.gandi.net"
               ], 
               [
                  "tel", 
                  {
                     "type": "work"
                  }, 
                  "uri", 
                  "tel:+33.170377666"
               ], 
               [
                  "tel", 
                  {
                     "type": "fax"
                  }, 
                  "uri", 
                  "tel:+33.143730576"
               ]
            ]
         ]
...

Les RFC qui forment la définition de RDAP sont :

  • RFC 7482, « Registration Data Access Protocol Query Format », explique comment former des requêtes RDAP, sous forme d'URL.
  • RFC 7483, « JSON Responses for the Registration Data Access Protocol (RDAP) », décrit le format des réponses du serveur RDAP, format qui utilise JSON.
  • RFC 7480, « HTTP usage in the Registration Data Access Protocol (RDAP) », normalise l'utilisation de HTTP pour transporter les requêtes et réponses RDAP.
  • RFC 7484, « Finding the Authoritative Registration Data (RDAP) Service », explique comment trouver le bon serveur RDAP.
  • RFC 7481, « Security Services for the Registration Data Access Protocol », détaille les services de sécurité de RDAP (en général fournis par HTTP).
  • RFC 7485, « Inventory and Analysis of WHOIS Registration Objects », qui n'est pas à proprement parler une partie de la définition de RDAP mais qui a servi à spécifier RDAP.

RDAP remplacera-t-il whois ? C'est que whois en a eu, des concurrents malheureux, et que tous sont bien oubliés aujourd'hui. Dans l'ordre rétro-chronologique :

En tout cas, RDAP est déjà largement mis en œuvre (dix implémentations dont l'interopérabilité a été testée au cours de réunions IETF) même s'il n'y a guère de déploiement en production pour l'instant.

L'exemple plus haut était pour trouver de l'information sur un nom de domaine. Mais RDAP marche aussi pour les adresses IP :

%  curl http://rdap.apnic.net/ip/2001:dc7:dd01:0:218:241:97:42
{
  "handle" : "2001:0DC7::/32",
  "startAddress" : "2001:dc7::",
  "endAddress" : "2001:dc7:ffff:ffff:ffff:ffff:ffff:ffff",
  "name" : "CNNIC-CN-20040913",
  "type" : "ALLOCATED PORTABLE",
  "country" : "CN",
  "parentHandle" : "2001:0C00::/23",
  "entities" : [ {
    "handle" : "IPAS1-AP",
    "vcardArray" : [ "vcard", [ [ "version", { }, "text", "4.0" ], [ "fn", { }, "text", "CNNIC IPAS CONFEDERATION" ], [ "kind", { }, "text", "group" ], [ "adr", {
      "label" : "No.4, Zhongguancun No.4 South Street,\\nHaidian District, Beijing"
    }, "text", [ "", "", "", "", "", "", "" ] ], [ "tel", {
      "type" : "voice"
    }, "text", "+86-010-58813000" ], [ "tel", {
      "type" : "fax"
    }, "text", "+86-010-58813075" ], [ "email", { }, "text", "ipas@cnnic.cn" ] ] ],
...

C'est bien compliqué, tout ce JSON. Et si on veut juste extraire certaines informations ? On peut utiliser un client RDAP spécialisé, ou écrire soi-même un traitement, ou encore se servir des processeurs JSON tout faits comme jq :

%  curl -s http://rdap.apnic.net/ip/2001:dc7:dd01:0:218:241:97:42 | jq .country 
"CN"

Questions mises en œuvre, on peut citer :

De bonnes lectures sur RDAP et le travail du groupe WEIRDS :

Et merci au dit Marc Blanchet pour sa relecture attentive de mon article.


L'article seul

RFC 7493: The I-JSON Message Format

Date de publication du RFC : Mars 2015
Auteur(s) du RFC : T. Bray (Textuality Services)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF json
Première rédaction de cet article le 1 avril 2015


Le format JSON, normalisé dans le RFC 7159, est aujourd'hui très répandu dans l'Internet et largement utilisé. Il a pourtant des faiblesses, notamment une définition un peu floue sur certains points, qui laisse planer un doute sur l'interopérabilité : si j'envoie dans le fichier un objet JSON où deux membres portent le même nom, le destinataire pourra-t-il le traiter ? Ce nouveau RFC résoud le problème en créant un profil, une restriction de JSON, nommée I-JSON, qui n'a pas ces flous et garantit donc normalement l'interopérabilité.

On peut penser qu'il aurait mieux valu préciser la norme JSON (aujourd'hui dans le RFC 7159) pour éliminer les ambiguités. Mais cela n'est pas possible sans casser la compatibilité. Si, par exemple, on interdisait dans la norme les objets dont deux membres ont le même nom, on rendrait illégaux des textes JSON existants, qui profitaient du flou de la norme. Cela a été jugé inacceptable, d'où ce choix d'un profil de JSON. Ceux qui veulent continuer à profiter du vague de la norme restent au JSON traditionnel, ceux qui veulent le maximum d'interopérabilité envoient désormais uniquement du I-JSON (ce qui veut dire « Internet JSON » et qui, curieusement, n'a pas de type MIME à lui, on continue à utiliser application/json). Ne pas casser l'existant était d'autant plus nécessaire que bien des analyseurs JSON mettent directement en correspondance les objets JSON avec des structures de données équivalentes dans leur langage de programmation, et qu'il ne fallait donc pas leur imposer une vérification préalable.

Donc, définition du format (section 2). Un texte I-JSON est un texte JSON, puisque I-JSON est un profil, un sous-ensemble de JSON. Il est forcément encodé en UTF-8 et ne doit pas utiliser les surrogates (seizets d'indirection) d'Unicode, ni des points de code qui sont des non-caractères.

Il y a deux grands problèmes d'interopérabilité avec JSON : la représentation des nombres (voir la section 6 du RFC 7159), et les noms de membres dupliqués dans les objets (cf. la section 4 du RFC 7159). La section 2.2 traite les nombres : un texte I-JSON ne devrait pas (sauf raison vitale) utiliser des nombres flottants qui ne sont pas représentables en IEEE 754-2008 binary64, soit en raison de leur taille (1E400...), soit à cause de leur précision (3.141592653589793238462643383279). Pour les entiers, il ne faut pas espérer que les nombres en dehors de l'intervalle [ -(2**53)+1 , (2**53)-1 ] soient acceptés.

Pour les noms de membres, la section 2.3 est claire : les noms dupliqués sont interdits. Donc, cet objet est du JSON légal, quoique dangereux, alors qu'il n'est pas du I-JSON, en raison du Title dupliqué :

"Image": {
            "Width":  800,
            "Height": 600,
            "Title": "View from 15th Floor",
            "Title": "Nice view"
}

D'autre part, I-JSON dit clairement que l'ordre des membres d'un objet ne compte pas. Ces deux objets sont identiques :

"Image": {
            "Width":  800,
            "Height": 600}

"Image": {
            "Height": 600, "Width":  800}

La section 3 de notre RFC précise bien qu'une mise en œuvre de I-JSON est tout à fait autorisée à rejeter ou ignorer un texte JSON qui n'est pas du bel I-JSON bien propre. Les protocoles Internet qui utilisent I-JSON sont invités à prévoir un moyen de signaler ce genre d'erreurs à l'envoyeur.

La section 4 du RFC couvre quelques choix supplémentaires. D'abord, comme dans l'ancien RFC 4627, et de manière différente de ce que permet le RFC 7159, un texte I-JSON doit avoir un objet ou un tableau au niveau supérieur. Ce texte est du JSON valable (depuis le RFC 7159) mais pas du I-JSON :

"Ma belle chaîne n'est pas acceptée car elle n'est pas objet ou tableau"

Il est recommandé que les protocoles qui utilisent I-JSON précisent que le type de plus haut niveau d'un texte soit un objet et que les membres inconnus de cet objet soient ignorés. Il existe en effet deux politiques dans les protocoles pour traiter les éléments inconnus : Must-Ignore et Must-Understand. La première indique que le receveur d'un message doit en ignorer les membres qu'il ne connait pas et continuer comme s'ils étaient absents. La deuxième indique qu'il faut connaitre tous les membres présents, et donc rejeter un message comportant des membres inconnus. La politique Must-Ignore permet l'extensibilité du protocole : une nouvelle version permet d'ajouter des membres à un objet, sans craindre que les anciens récepteurs ne plantent.

I-JSON ajoute aussi des contraintes aux types de données de base. Ainsi, il impose que les dates et heures soient au format du RFC 3339, avec en outre uniquement des letres en majuscules et des secondes indiquées explicitement :

"creation": "2015-03-23T09:13:00Z"

Et une dernière contrainte sur les données, le binaire devra être encodé en base64url (section 5 du RFC 4648). Ce point fut l'un des plus chaudement disputés dans le groupe de travail.

Je n'ai pas trouvé d'outil qui testerait qu'un texte JSON est conforme à cette nouvelle norme I-JSON. Si quelqu'un connait...

I-JSON est expliqué par l'auteur du RFC sur son blog.


Téléchargez le RFC 7493


L'article seul

RFC 7484: Finding the Authoritative Registration Data (RDAP) Service

Date de publication du RFC : Mars 2015
Auteur(s) du RFC : M. Blanchet (Viagenie)
Chemin des normes
Première rédaction de cet article le 1 avril 2015


Le nouveau protocole RDAP d'accès à l'information sur les objets (noms de domaines, adresses IP, etc) stockés dans un registre fonctionne en interrogeant le serveur en HTTP. Encore faut-il trouver le serveur. Comment le client RDAP qui veut des informations sur 2001:67c:288::2 sait-il à quel serveur demander ? Ce fut une des plus chaudes discussions au sein du groupe de travail IETF qui a mis au point RDAP. Ce RFC décrit le mécanisme choisi. En gros, l'IANA gère des « méta-services » qui donnent la liste de serveurs RDAP, mais il peut aussi y avoir redirection d'un serveur RDAP vers un autre.

Le protocole RDAP est décrit entre autres dans le RFC 7480 qui précise comment utiliser HTTP pour transporter les requêtes et réponses RDAP. Comme indiqué plus haut, il ne précise pas comment trouver le serveur RDAP responsable d'un objet donné. Avant d'exposer la solution utilisée, la section 1 de notre RFC rappelle comment ces objets (noms de domaine, adresses IP, numéros d'AS, etc) sont alloués et délégués. L'IANA délégue les TLD aux registres de noms de domaines, des grands préfixes IP et les blocs de numéros d'AS aux RIR. Il est donc logique que RDAP suive le même chemin : pour trouver le serveur responsable, on commence par demander à l'IANA, qui a déjà les processus pour cela, et maintient les registres correspondants (adresses IPv4, adresses IPv6, numéros d'AS et domaines).

Pour permettre à RDAP de fonctionner, ce RFC demande donc à l'IANA quelques fichiers supplémentaires, au format JSON (RFC 7159), dont le contenu dérive des registres cités plus haut. (À noter que c'est le premier registre IANA au format JSON.) Et l'IANA doit aussi prévoir des serveurs adaptés à servir ces fichiers, nommés RDAP Bootstrap Service, à de nombreux clients RDAP.

Le format de ces fichiers JSON est décrit dans la section 3 de notre RFC. Chaque bootstrap service contient des métadonnées comme un numéro de version et une date de publication, et il contient un membre nommé services qui indique les URL où aller chercher l'information (la syntaxe formelle figure en section 10). Actuellement, ces services sont encore vides :

 
% curl http://data.iana.org/rdap/ipv4.json
{
  "description": "RDAP bootstrap file for IPv4 address allocations",
  "publication": "2015-03-20T20:39:57Z",
  "services": [],
  "version": "1.0"
}

Mais dans le futur, ce sera un tableau donnant, pour des objets donnés, les URL des serveurs RDAP à contacter pour ces objets indiqués, par exemple :

 {
       "version": "1.0",
       "publication": "2024-01-07T10:11:12Z",
       "description": "RDAP Bootstrap file for example registries.",
       "services": [
         [
           ["1.0.0.0/8", "192.0.0.0/8"],
           [
             "https://rir1.example.com/myrdap/"
           ]
         ],
...

Le membre publication indique la date de parution au format du RFC 3339. Les URL indiqués se terminent par une barre oblique, le client RDAP a juste à leur ajouter une requête formulée selon la syntaxe du RFC 7482. Ainsi, cherchant des informations sur 192.0.2.24, on ajoutera ip/192.0.2.24 à l'URL de base ce qui, avec le bootstrap service précédent, donnerait https://rir1.example.com/myrdap/ip/192.0.2.24.

Pour les adresses IP (section 5), les entrées sont des préfixes, comme dans le premier exemple montré plus haut et la correspondance se fait avec le préfixe le plus spécifique (comme pour le routage IP). Les préfixes IPv4 suivent la syntaxe du RFC 4632 et les IPv6 celle du RFC 4291. Voici un exemple IPv6 :

       "services": [
         [
           ["2001:200::/23", "2001:db8::/32"],
           [
             "https://rir2.example.com/myrdap/"
           ]
         ],
         [
           ["2600::/16", "2100:ffff::/32"],
           [
             "http://example.org/"
           ]
         ],
         [
           ["2001:200:1000::/36"],
           [
             "https://example.net/rdaprir2/",
             "http://example.net/rdaprir2/"
           ]
          ]
       ]

Si on cherche de l'information sur le préfixe 2001:200:1000::/48, il correspond à deux entrées dans le tableau des services (2001:200::/23 et 2001:200:1000::/36) mais la règle du préfixe le plus long (le plus spécifique) fait qu'on va utiliser 2001:200:1000::/36, et la requête finale sera donc https://example.net/rdaprir2/ip/2001:200:1000::/48. (Si elle échoue, on peut passer au deuxième URL du tableau, celui sans HTTPS.)

Pour les domaines (section 4), les entrées des services sont des noms de domaine :

...
       "services": [
         [
           ["net", "com", "org"],
           [
             "https://registry.example.com/myrdap/"
           ]
         ],
         [
           ["foobar.org", "mytld"],
           [
             "http://example.org/"
           ]
         ],
...

L'entrée sélectionnée est la plus longue (en nombre de composants du nom, pas en nombre de caractères) qui correspond. Dans l'exemple ci-dessus, si on cherche des informations sur foobar.org, on ira voir le serveur RDAP en http://example.org/, si on en cherche sur toto.org, on ira en https://registry.example.com/myrdap/.

Pour les numéros d'AS (section 5.3), on se sert d'intervalles de numéros :

"services": [
         [
           ["2045-2045"],
           [
             "https://rir3.example.com/myrdap/"
           ]
         ],
         [
           ["10000-12000", "300000-400000"],
           [
             "http://example.org/"
           ]
         ],
...

Les entités (section 6 de notre RFC) posent un problème particulier, elles ne se situent pas dans un espace arborescent, contrairement aux autres objets utilisable avec RDAP. (Rappel : les entités sont les contacts, les titulaires, les BE...) Il n'existe donc pas de bootstrap service pour les entités (ni, d'ailleurs, pour les serveurs de noms, cf. section 9). En pratique, si une requête RDAP renvoie une réponse incluant un handle pour une entité, il n'est pas idiot d'envoyer les requêtes d'information sur cette entité au même serveur RDAP.

Notez (section 7) que le tableau services ne sera pas forcément complet et que certains objets peuvent ne pas s'y trouver. Par exemple, dans un tableau pour les TLD, les registres n'ayant pas encore de serveur RDAP ne seront logiquement pas cités. On peut toujours tenter un autre serveur, en espérant qu'il utilisera les redirections HTTP. Par exemple, ici, on demande au serveur RDAP de l'APNIC pour une adresse RIPE. On est bien redirigé avec un code 301 (RFC 7231, section 6.4.2) :


%  curl -v http://rdap.apnic.net/ip/2001:67c:288::2
...
> GET /ip/2001:67c:288::2 HTTP/1.1
> User-Agent: curl/7.38.0
> Host: rdap.apnic.net
> Accept: */*
> 
< HTTP/1.1 301 Moved Permanently
< Date: Wed, 01 Apr 2015 13:07:00 GMT
< Location: http://rdap.db.ripe.net/ip/2001:67c:288::2
< Content-Type: application/rdap+json
...

La section 8 couvre quelques détails liés au déploiement de ce service, qui a pris du temps et n'a été effectif que le 25 mars 2015, en pleine réunion IETF à Dallas. C'est que le Bootstrap Service est différent des autres registres IANA. Ces autres registres ne sont consultés que rarement (par exemple, lors de l'écriture d'un logiciel) et jamais en temps réel. Si le serveur HTTP de l'IANA plante, ce n'est donc pas trop grave. Au contraire, le Bootstrap Service doit marcher en permanence, car un client RDAP en a besoin. Pour limiter la pression sur les serveurs de l'IANA, notre RFC recommande que les clients RDAP ne consultent pas ce service à chaque requête RDAP, mais qu'au contraire ils mémorisent le JSON récupéré, en utilisant le champ Expires: de HTTP (RFC 7234) pour déterminer combien de temps doit durer cette mémorisation. (Notez qu'aujourd'hui, l'IANA n'a pas encore ce champ, ticket IANA [IANA #816674].) Néanmoins, l'IANA a dû ajuster ses serveurs HTTP et louer les services d'un CDN pour assurer ce rôle relativement nouveau.

Le client RDAP doit d'autre part être conscient que le registre n'est pas mis à jour instantanément. Par exemple, si un nouveau TLD est ajouté par le gouvernement états-unien, via Verisign, TLD dont le registre a un serveur RDAP, cette information ne sera pas disponible immédiatement pour tous les clients RDAP.

Comme son ancêtre whois, RDAP soulève plein de questions de sécurité intéressantes, détaillées plus précisement dans le RFC 7481.

La section 12 de notre RFC détaille les processus IANA à l'œuvre. En effet, et c'est une autre différence avec les registres IANA habituels, il n'y a pas de mise à jour explicite des registres du bootstrap service, ils sont mis à jour implicitement comme effet de bord des allocations et modifications d'allocation dans les registres d'adresses IPv4, adresses IPv6, numéros d'AS et domaines. Il faudra juste modifier les procédures de gestion de ces registres existants, pour permettre d'indiquer le serveur RDAP (une information qui n'est pas récoltée aujourd'hui, ce qui explique pourquoi le bootstrap service est vide). Ainsi, le formulaire de gestion d'un TLD par son responsable devra être modifié pour ajouter un champ "serveur RDAP" comme il y a aujourd'hui un champ "serveur Whois".

Aujourd'hui, les fichiers de ce service sont :

  • http://data.iana.org/rdap/dns.json
  • http://data.iana.org/rdap/ipv4.json
  • http://data.iana.org/rdap/ipv6.json
  • http://data.iana.org/rdap/asn.json

Voici, par exemple, celui d'IPv6 (encore vide) :


% curl -v http://data.iana.org/rdap/ipv6.json
...
> GET /rdap/ipv6.json HTTP/1.1
> User-Agent: curl/7.38.0
> Host: data.iana.org
> Accept: */*
> 
< HTTP/1.1 200 OK
< Accept-Ranges: bytes
< Content-Type: text/plain; charset=UTF-8
< Date: Wed, 01 Apr 2015 13:47:28 GMT
< Etag: "63ea7-96-511be51c6e140"
< Last-Modified: Fri, 20 Mar 2015 20:39:57 GMT
< Server: ECAcc (ewr/14C3)
< X-Cache: HIT
< Content-Length: 150
< 
{
  "description": "RDAP bootstrap file for IPv6 address allocations",
  "publication": "2015-03-20T20:39:57Z",
  "services": [],
  "version": "1.0"
}

Question lecture, John Levine, dans son article sur RDAP, parlait de ce problème de bootstrap : « The biggest delay in getting RDAP done turned out to be the bootstrap, figuring out where the server is for each top level domain, IP range, or ASN range. A lot of proposals that seemed reasonable, like a fixed name (http://rdap.domain) or a DNS approach like SRV records turned out either to have administrative issues, or to be hard to implement (you can't do SRV lookups from Javascript.) There were also issues that were arguably technical or political (depending which side you're on) about specifying the URL syntax of the queries. » Notez qu'on parle parfois de bootstrap service pour désigner, non pas un ensemble de fichiers dirigeant vers le bon serveur RDAP, comme décrit dans ce RFC, mais un serveur qui ne fait que des redirections, comme celui (expérimental) en rdap.org qui, ici, redirige à juste titre vers Afilias :

  
% curl -v http://rdap.org/domain/rmll.info
...
> GET /domain/rmll.info HTTP/1.1
> User-Agent: curl/7.35.0
> Host: rdap.org
> Accept: */*
> 
< HTTP/1.0 301 Moved Permanently
< Date: Thu, 26 Mar 2015 13:57:20 GMT
< Server: Apache
< X-Powered-By: PHP/5.3.3
< Content-Language: en
< Status: 301
< Location: http://rdg.afilias.info/.well-known/rdap/domain/rmll.info
< Content-Length: 0
< Content-Type: application/rdap+json; charset=UTF-8

D'ailleurs, si vous cherchez une mise en œuvre d'un tel redirecteur, il y a rdapbootstrap (en Java).


Téléchargez le RFC 7484


L'article seul

Faut-il refaire l'Internet en partant de zéro ?

Première rédaction de cet article le 30 mars 2015


Hier, aux Journées du Logiciel Libre à Lyon, j'ai fait un exposé sur la question de la « refondation » de l'Internet.

Les supports de l'exposé :

Quelques autres supports d'exposés :


L'article seul

RFC 7478: Web Real-Time Communication Use-cases and Requirements

Date de publication du RFC : Mars 2015
Auteur(s) du RFC : C. Holmberg, S. Hakansson, G. Eriksson (Ericsson)
Pour information
Réalisé dans le cadre du groupe de travail IETF rtcweb
Première rédaction de cet article le 30 mars 2015


Le système WebRTC permet une communication interactive et multimédia entre deux applications tournant dans un navigateur Web (d'où le nom de WebRTC). La vision est qu'Alice et Bob lanceront leur navigateur, iront sur une page qui chargera le code du logiciel (typiquement du JavaScript) et qu'ils communiqueront ensuite. Contrairement à Skype, WebRTC ne nécessitera pas l'installation d'un logiciel, et, surtout, il s'agira d'un protocole ouvert. Ce RFC, le premier du groupe de travail rtcweb, décrit certains scénarios d'usage de WebRTC, pour aider à comprendre quel rôle il joue exactement. Il ne prétend pas être un cahier des charges pour WebRTC et, bien que publié tardivement, il représente plutôt l'état d'esprit au début du projet.

WebRTC peut permettre la communication avec des systèmes extérieurs et au moins un des scénarios décrits envisage une communication avec un téléphone SIP. Les demandes mises par ce document sur le (à cette époque) futur protocole WebRTC sont marquées Fn (où n est un entier) mais, on l'a vu, ce document ne prétend pas être un cahier des charges et WebRTC ne suivra pas forcément rigoureusement ces demandes. Les demandes marquées An concernent uniquement l'API de WebRTC (le protocole est développé par l'IETF, l'API par le W3C, oui, c'est un peu compliqué). L'annexe A contient ces exigences concernant l'API mais il faut voir le W3C pour avoir l'information fiable.

Les clients WebRTC peuvent être connectés en IPv4, en IPv6, les deux, avoir des capacités réseau très différentes, être sur des réseaux dont la capacité effective varie (liens radio, liens congestionnés), être derrière des pare-feux fascistes, et, bien sûr, être coincés derrière des NAT, des NAT de toutes les sortes (RFC 4787).

Attaquons maintenant les scénarios en commençant par le plus simple : ces chers Alice et Bob veulent discuter par vidéo. Ils ont le même opérateur WebRTC, sont informés en temps réel de la disponibilité de l'autre par une notification au navigateur, et, en cliquant sur le nom du correspondant, peuvent lui parler, l'écouter, le voir et se montrer. On a bien sûr les fonctions classiques, une petite vignette avec un retour de sa propre caméra, la capacité de couper le son pour crier une remarque à son conjoint sans que le correspondant l'entende, etc. Chaque partie peut raccrocher quand elle le veut. Évidemment, Bob et Alice ont des navigateurs de modèles différents, tournant sur des systèmes d'exploitation différents. Bien sûr, on veut de la sécurité, tout le trafic audio et vidéo doit évidemment être chiffré, authentifié et protégé contre toute modification.

De ce premier scénario d'usage, le cas le plus simple et le plus courant, on en déduit les exigences de base. Je ne vais pas toutes les citer mais en voici un échantillon, avec leur identificateur Fn :

  • F1 : le navigateur doit avoir accès au micro et à la caméra,
  • F2 : le navigateur doit pouvoir envoyer des données, même en présence de NAT,
  • Diverses exigences sur la qualité des flux multimédia (F3, réagir à la congestion, F6, détecter que le pair ne reçoit plus rien, F8, pouvoir synchroniser audio et vidéo),
  • F11 : Protection contre les écoutes et autres « interceptions de sécurité » (RFC 2804 et RFC 7258),
  • F13 : authentification et intégrité,
  • F14 : vie privée, il doit exister un mode où Alice communique avec Bob sans lui révéler son adresse IP (possibilité de passer par un serveur pour se protéger).

Les autres exigences apparaissent au fur et à mesure des autres scénarios, qui présentent des cas de plus en plus complexes. Par exemple, Alice ou Bob est derrière un réseau fasciste ou mal configuré qui bloque complètement UDP. On en déduit l'exigence F18, pouvoir passer même quand UDP est bloqué. Variante : un réseau encore plus fasciste ou mal conçu qui n'autorise que HTTP, et via un relais. L'exigence F21 traite cas cas.

Réussir à faire passer une communication malgré les middleboxes, les pare-feux et le NAT est le grand défi des applications réseau modernes. Les solutions nécessitent en général d'utiliser STUN (RFC 5389) et TURN (RFC 5766, le tout avec ICE (RFC 5245). L'exigence F19 impose de pouvoir utiliser ces services, y compris dans le cas où il y a plusieurs serveurs STUN et TURN disponibles. F20 impose de permettre l'utilisation de serveurs STUN et TURN qui ne sont pas ceux du fournisseur WebRTC (par exemple, au sein d'une organisation qui a son propre serveur STUN).

Lorsqu'on utilise des équipements mobiles, le problème peut se compliquer par un changement de réseau en cours de communication, menant presque toujours à un changement d'adresse IP (un smartphone qui était connecté en 4G et qui rentre au bercail où il bascule vers la WiFi). F17 demande que WebRTC puisse continuer à fonctionner dans ce cas, pour éviter le « Allo, Alice, je vais passer en WiFi, je te rappelle ».

Satisfaits de ces services, Alice et Bob multiplient leur exigence. Voilà tout à coup qu'apparait dans le RFC leur désir de partager l'écran, pendant la communication, avec un tiers, que ce dernier puisse suivre ce qu'il se passe (exigence F36).

Laissons maintenant Alice et Bob tranquilles, ils ont peut-être enfin réussi à communiquer. Le RFC passe ensuite à des scénarios plus collectifs, autour du hockey. Un chercheur de talents est à un match avec son téléphone portable (qui a deux caméras, une devant et une derrière), il filme les joueurs qui lui semblent les plus prometteurs et il veut en discuter en télé-conférence avec le patron du club, à distance, et qui regarde le match transmis par le chercheur de talents. WebRTC doit donc pouvoir gérer de nombreux flux multimédias (exigence F25).

Ce genre de demandes s'étend à tout système de conférence à plusieurs, loin du cas simple des seuls Alice et Bob. WebRTC doit jongler avec les flux et de nombreux pairs qui veulent les recevoir (exigences F23 à F29).

C'est bien joli de communiquer avec les autres utilisateurs de WebRTC mais, souvent, on voudrait communiquer avec des gens qui n'ont pas WebRTC, en passant par une passerelle vers leur système, par exemple vers la téléphonie classique. Un premier exemple est celui d'un opérateur qui permet à ses abonnés de passer un appel téléphonique depuis un navigateur Web. L'utilisateur se connecte au site de l'opérateur, s'authentifie, puis appelle qui il veut, comme s'il utilisait un téléphone traditionnel. WebRTC doit donc gérer les codecs traditionnels de la téléphonie (exigence F31).

Si le service qu'on appelle a des commandes comme « pour signaler un problème, appuyez sur la touche 1 », il faut évidemment un moyen de le faire (exigence F32).

Voilà, je n'ai pas tout indiqué mais cela vous donne déjà une bonne idée de ce que WebRTC doit permettre. La section 3 de notre RFC résume toutes ces exigences de manière synthétique, si vous ne voulez pas lire tout le RFC.

Notez que, comme avec tout système qui apporte de nouvelles possibilités, il y a aussi de nouveaux risques. La section 4 liste les risques connus de WebRTC. Notamment, il faut obtenir le consentement éclairé de l'utilisateur avant de permettre l'utilisation du micro et de la caméra (songez aux facilités d'espionnage qu'on aurait si un script WebRTC sur un site Web pouvait allumer la caméra...) et il faut prévenir clairement l'utilisateur que micro et caméras sont allumés.


Téléchargez le RFC 7478


L'article seul

RFC 7476: Information-centric Networking: Baseline Scenarios

Date de publication du RFC : Mars 2015
Auteur(s) du RFC : K. Pentikousis (EICT), B. Ohlman (Ericsson), D. Corujo (Universidade de Aveiro), G. Boggia (Politecnico di Bari), G. Tyson (Queen Mary, University of London), E. Davies (Trinity College Dublin), A. Molinaro (UNIRC), S. Eum (NICT)
Pour information
Réalisé dans le cadre du groupe de recherche IRTF icnrg
Première rédaction de cet article le 27 mars 2015


Le concept d'ICN (Information-Centric Networking) est assez à la mode en ce moment. Il désigne une conception du réseau où le composant essentiel n'est pas une machine mais une information, ayant un identificateur, et dont la récupération par l'utilisateur est le but principal de la connectivité. Ce modèle très minitélien colle bien à certains usages du réseau (comme le Web traditionnel, avant les applications Web, ou comme l'accès aux œuvres culturelles en pair à pair), ce qui explique son succès actuel. Ce RFC est le premier publié qui se penche sur ce paradigme : il décrit un certain nombre de scénarios où l'ICN a un sens.

N'attendez pas la description d'un protocole précis, c'est bien trop tôt. Ce RFC sort de l'IRTF, pas de l'IETF et est donc dans une démarche plus recherche qu'ingéniérie. Il liste des cas, étudie une bibliographie mais ne donne pas encore de solutions.

Donc, d'abord, une introduction à l'ICN (section 1 du RFC). Ses promoteurs aiment expliquer que l'Internet actuel est host-centric, c'est-à-dire construit autour de l'host, l'ordinateur ou le routeur connecté à l'Internet et identifié par une ou plusieurs adresses IP. Ces machines, ordinateurs et routeurs, sont connectées plus ou moins en permanence et, dans le modèle original, ont une connectivité de bout en bout (tout le monde peut parler à tout le monde). Le modèle ICN repose sur un changement important de paradigme : ce qui compte, c'est l'information, c'est elle qui a un identificateur, les machines ne sont pas forcément connectées tout le temps, ce qui compte, c'est qu'on puisse récupérer l'information, et peu importe si elle vient d'un serveur précis, ou d'un cache ou d'autres équipements dans le réseau. Le réseau ne transporte donc pas seulement des bits, il peut aussi servir de mécanisme de distribution. Les partisans de l'ICN utilisent souvent le terme de location independance.

Naturellement, cela change la vision qu'on a de la sécurité. Aujourd'hui, si je télécharge le rapport ANSSI « Comprendre et anticiper les attaques DDoS », ma confiance dans l'intégrité et l'authenticité de ce document vient du serveur où je l'ai récupéré (ici, un serveur de l'ANSSI) et des mécanismes techniques qui empêchent une modification en cours (comme HTTPS). En ICN, le serveur n'a plus d'importance, il faut donc bâtir la confiance sur autre chose, qui doit voyager avec l'information elle-même, comme par exemple des signatures. (Vous noterez que, contrairement à ce que prétendent les promoteurs de l'ICN, qui ne connaissent en général que HTTP, il existe plusieurs protocoles Internet qui fonctionnent ainsi depuis longtemps. Ainsi, pour le DNS, il est rare qu'on récupère l'information depuis le serveur original - qui peut être non-joignable, on passe par une série de caches, et la sécurité demande donc un mécanisme de signature, DNSSEC.)

Il existe plusieurs travaux de recherche autour de cette idée. C'est le cas de NetInf, CCN (sur lequel j'ai déjà écrit), NDN et bien d'autres. Comme le note notre RFC, c'est l'équivalent du bouillonement que connaissait le réseau de la fin des années 70 à la fin des années 80 quand DECnet, IPX et quelques autres concurrençaient sérieusement IP, avant que ce dernier ne s'impose.

Un travail est en cours, au sein du groupe de recherche ICN, pour évaluer les différentes façons de faire de l'ICN qui existent. Les documents correspondants ne sont pas encore publiés.

Donc, en section 2, le cœur du RFC, les scénarios envisagés. Logiquement, on commence par les usages à la mode avec les réseaux sociaux. Un gros réseau social comme Facebook doit distribuer énormément d'informations à beaucoup de gens, situés dans des endroits très divers. Le service est donc une combinaison de multicast et de cache. Le contenu est disséminé sur plein de serveurs différents et le modèle ICN convient donc particulièrement bien puisque le client veut récupérer « les photos de Mère-Grand » et pas se connecter à telle ou telle machine (cf. Mathieu, B. et al., « Information-centric networking: a natural design for social network applications » en 2012). Dans le monde merveilleux de l'ICN, un réseau social comme Twitter pourrait être bâti très simplement : un utilisateur publie son tweet, certains utilisateurs le recevront tout de suite (ceux qui sont connectés), les autres le récupéreront à partir d'un cache dans le réseau dès qu'ils seront connectés. L'article de Kim, J. et al. « Content Centric Network-based Virtual Private Community » de 2011 décrit plus en détail cette vision, que le RFC qualifie, de manière franchement baratineuse, de serverless (il y a bien des serveurs, même s'ils ne sont pas explicitement nommés).

Autre scénario d'usage possible, la communication en temps-réel, avec multimédia, par exemple des services comme Skype. Cela inclut des communications entre deux personnes, des conférences d'un groupe de personnes, des ressources partagées comme un tableau virtuel où tout le monde peut écrire, etc. Le tout est soumis à des contraintes de performance assez strictes. Contrairement au scénario précédent, celui-ci semble aux antipodes de l'ICN, puisqu'il s'agit d'échanger et non plus d'« accéder à du contenu ». Et, pourtant, il y a déjà eu des recherches à ce sujet (j'en ai mentionné une dans mon article sur le CCN).

Le RFC cite également un exemple de MMORPG fait en ICN, par Chen, J. et al., « G-COPSS: A Content Centric Communication Infrastructure for Gaming Applications » en 2012.

Peut-on utiliser l'ICN pour le partage d'infrastructures, comme la capacité disque ou réseau ? Le RFC dit que oui, en se basant sur le fait que l'ICN sécurise des objets et pas des canaux de communication et permet donc le partage de réssources. Par exemple, toute machine avec suffisamment de place disque peut devenir un cache. Nul besoin de lui faire confiance, puisque les objets seront sécurisés (par exemple par le biais d'une signature qui leur sera attachée). Cette possibilité est creusée dans l'article de Jacobson, V. et al, « Custodian-Based Information Sharing » en 2012 mais aussi dans le cas de trafic HTTP classique (Psaras, I. et al., « Modelling and Evaluation of CCN- Caching Trees », 2011) ou de trafic BitTorrent (Tyson, G. et al., « A Trace-Driven Analysis of Caching in Content-Centric Networks », 2012). Les CDN actuels font déjà un travail analogue, mais au prix d'une configuration manuelle plus importante.

Si, arrivé à ce stade, vous pensez qu'il y a beaucoup de promesses et peu de réalisations concrètes, je dirais que vous avez tout à fait raison. L'ICN, c'est beaucoup de marketing, faisant miroiter d'extraordinaires changements positifs et se souciant peu des vulgaires problèmes pratiques. Il y a toutefois des applications plus raisonnables comme la distribution de contenu, certes le scénario le plus réaliste puisque l'ICN voit tout comme du contenu. Il est donc logique que ce soit le domaine où l'ICN ait été le plus étudié, voyez le RFC (section 2.5) pour une bonne bibliographie.

Autre exemple marketing et spectaculaire, les réseaux dans les véhicules en mouvement (les VANET). Aussi bien la communication entre véhicules, que celle entre le véhicule et des stations fixes, posent des problèmes très difficiles, et sont un vrai défi pour les concepteurs de réseaux. La topologie change très vite (à la vitesse du véhicule), et la connectivité n'est pas permanente. On est dans un cas adapté à l'ICN où on se soucie moins de qui a envoyé l'information, que de l'information elle-même. Les caches et la réplication de l'information seront certainement utiles ici.

Vous trouvez ce scénario trop terrestre ? Plus en altitude, il y a les réseaux spatiaux, voire interplanétaires. Le concept de DTN (Delay-Tolerant Networking) était né autour des voyages dans l'espace mais peut s'appliquer à d'autres secteurs (comme les sous-marins ou comme des réseaux très perturbés, par exemple suite à une catastrophe naturelle). Comme son nom l'indique, le DTN est conçu pour des cas où le délai d'acheminement d'un bit d'une machine à une autre est tel que les protocoles de transport traditionnels comme TCP ne fonctionneront jamais. (On ne pourra jamais terminer une « triple poignée de mains » dans les temps, par exemple.) En plus du délai d'acheminement, le monde du DTN se caractérise par le fait que la connectivité est l'exception, plutôt que la règle. Pour travailler dans ces conditions, les systèmes DTN (RFC 4838) retrouvent l'architecture « store and forward » des anciens protocoles comme UUCP. Tout routeur est également un serveur de stockage et un cache, et garde l'information au moins jusqu'à ce qu'il ait pu la transmettre à quelqu'un d'autre. Le stockage se fait donc en partie dans le réseau. Ce paradigme peut même s'étendre au cas où certaines des communications se font par un mécanisme de « mule de données », de transport d'un mécanisme de stockage physique (une clé USB, par exemple). Le DTN et ICN ont en commun qu'il n'imposent pas une connectivité permanente et ils pourraient donc, en théorie, bien s'entendre ensemble (Tyson, G., Bigham, J. et E. Bodanese, « Towards an Information-Centric Delay-Tolerant Network », 2013). De plus, les deux paradigmes reposent sur le traitement de l'information comme étant un objet en soi (que le DTN nomme un bundle), à longue durée de vie.

Une variante de ce scénario où le contenu est distribué entre des machines à la connectivité intermittente est celle du « partage de données selon l'occasion » où des informations sont disponibles et seront récupérées si on passe à côté. L'exemple typique (mais non cité par le RFC...) est celui de la PirateBox, qui attend tranquillement d'éventuels visiteurs. Le RFC préfère un cas où les deux parties sont mobiles, et où on distribue des tweets (Hossmann, T., et al. « Twitter in disaster mode: smart probing for opportunistic peers », 2012).

Seconde variante, celle où on distribue de l'information pendant une crise majeure, ayant mené à une importante perturbation des réseaux, perturbation d'autant plus sérieuse que l'énergie manque elle aussi, stoppant ainsi les équipements réseau qui n'avaient pas été mis hors de service pendant la crise. Les DTN peuvent se montrer très utiles dans ce cas, par exemple pour diistribuer efficacement l'information utile (comme les alertes, ou l'emplacement des camps de réfugiés). Comme avec tous les réseaux pair-à-pair se posera le problème de la motivation à participer : si le tremblement de terre a frappé et que je me retrouve à la rue avec un smartphone qui n'a plus qu'une heure de batterie, sans espoir de recharge proche, pourquoi est-ce que je consacrerai ces précieux watt-heures à router des messages pour les autres ? Peut-être faudra t-il compter uniquement sur les équipements apportés par les premiers secours.

On l'a vu, l'ICN repose sur beaucoup de buzzwords et de promesses aussi floues que mirobolantes. Il était donc inévitable que le super-buzzword Internet des objets soit mentionné dans ce RFC. On sait que les progrès du matériel font que de nombreux objets qui n'étaient pas vus comme des ordinateurs sont désormais connectés à un réseau et même parfois à l'Internet. Prenons les capteurs, par exemple : on peut envisager plein de capteurs dispersés un peu partout, récoltant plein d'informations utiles, auxquelles il faut ensuite accéder. Les idées de l'ICN comme le cache réparti peuvent être utiles ici (cf. l'Internet-Draft de Kutscher, D. et S. Farrell, « Towards an Information-Centric Internet with more Things », présenté à l'atelier Interconnecting Smart Objects with the Internet de l'IAB, en 2011, atelier décrit dans le RFC 6574, ou bien les très nombreuses références citées dans la section 2.8).

Un des points difficiles de tout réseau informatique est le nommage, et le RFC cite ici les possibilités de nommer directement le contenu, ce que permettent par exemple les URI ni: du RFC 6920 (un exemple concret et utile). Par contre, le RFC ne cite pas les magnets mais il est vrai qu'ils n'ont jamais fait l'objet d'une standardisation rigoureuse.

Autre buzzword à ne pas manquer, la smart city. Le RFC tourne ici franchement au discours marketing, avec des envolées sur l'interaction des smart people avec la smart city, le tout sous l'égide d'une bienveillante smart governance.

Assez de scénarios d'usage, la section 3 du RFC passe enuite aux questions transversales, communes à plusieurs scénarios. Cette fois, il y a davantage de concret. Premier problème, évidemment, le fric. La section 3.1 se penche sur l'économie de la connectivité. Par exemple, les engins connectés auront de plus en plus souvent le choix entre plusieurs connexions (pensez aux smartphones actuels, avec leur choix entre WiFi et 3G) et intégreront probablement des considérations financières dans leur choix. L'accès aux données indépendamment d'un serveur précis est ici utile, pour laisser davantage de liberté de choix aux engins connectés. À condition, comme toujours en économie, que les acteurs rationnels et égoïstes d'Adam Smith soient parfaitement informés des conséquences de leur choix. Le RFC note donc qu'il faudra un travail en ce sens, avec des offres simples et claires, et distribuées automatiquement aux engins qui auront à faire des choix de connectivité.

Ces questions de sous dans les réseaux ne concernent évidemment pas que la machine terminale mais également les opérateurs. L'ICN leur offre de nouvelles possibilités (le déploiement de caches dans leur réseau, automatiquement utilisés par les clients, permet de diminuer les coûts liés à la connectivité externe). Là encore, le RFC cite énormément de références vers des travaux existants.

Autre sujet transversal qui a une grande importance (tout à fait justifiée) aujourd'hui, la consommation énergétique. Le problème est bien réel (les factures d'électricité augmentent, la pollution et les autres conséquences pour l'environnment aussi, les petits objets n'ayant qu'une batterie à capacité limitée souhaitent faire des économies d'électricité) mais son traitement dans le RFC est très décevant : ce ne sont que des vagues promesses comme quoi l'ICN permettrait de diminuer la consommation électrique. L'idée est que l'utilisation massive de caches, le traitement des données dans le réseau lui-même et pas dans les extrêmités, et enfin la non-obligation d'être connecté en permanence seraient plus efficace énergétiquement. Le RFC cite plusieurs études dont j'ai l'impression qu'elles sont purement théoriques, sans mesures effectives.

Autre question qui s'applique à plusieurs scénarios d'usage de l'ICN, le cas où des réseaux de différents types, n'utilisant pas tous IP, sont disponibles. Dans le modèle original, dit du sablier, IP formait la ceinture, le point de passage obligé (aujourd'hui, dans la réalité, c'est plutôt HTTP qui joue ce rôle). Dans un monde qui utilise massivement l'ICN, ce pourrait être ICN qui serait la ceinture, l'unificateur de toutes les interactions (Trossen, D. et al., « Arguments for an information centric internetworking architecture », 2010). Les auteurs du RFC sont évidemment conscients du caractère très spéculatif de ce projet, et notent que bien des points restent à résoudre pour avancer dans ce sens, comme la sécurité.


Téléchargez le RFC 7476


L'article seul

RFC 7483: JSON Responses for the Registration Data Access Protocol (RDAP)

Date de publication du RFC : Mars 2015
Auteur(s) du RFC : A. Newton (ARIN), S. Hollenbeck (Verisign Labs)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF weirds
Première rédaction de cet article le 26 mars 2015


Dans l'ensemble des normes sur le protocole RDAP, ce RFC est destiné à décrire le format de sortie, celui des réponses envoyées par le serveur d'information RDAP. Ce format est basé sur JSON et, pour utiliser RDAP en remplacement de whois, il faudra donc se munir de quelques outils pour traiter le JSON.

JSON est normalisé dans le RFC 7159 et représente aujourd'hui le format de choix pour les données structurées c'est-à-dire analysables par un programme. (L'annexe E de notre RFC explique en détail le pourquoi du choix de JSON.) Une des caractéristiques importantes de whois est en effet que son format de sortie n'a aucune structure, c'est du texte libre, ce qui est pénible pour les programmeurs qui essaient de le traiter (mais, d'un autre côté, cela ralentit certains usages déplorables, comme la récolte d'adresses de courrier à des fins de spam, jouant ainsi un rôle de semantic firewall). L'utilisation typique de RDAP est en HTTP (RFC 7480) avec les requêtes exprimées dans la syntaxe des URL du RFC 7482. Voici tout de suite un exemple réel, avec la réponse JSON :

% curl http://rdg.afilias.info/rdap/domain/kornog-computing.info
...
{
   "entities": [
...
         "objectClassName": "entity", 
         "roles": [
            "technical", 
            "billing", 
            "administrative"
         ], 
         "vcardArray": [
            "vcard", 
            [
               [
                  "version", 
                  {}, 
                  "text", 
                  "4.0"
               ], 
               [
                  "fn", 
                  {}, 
                  "text", 
                  "Simon TOSSER"
               ], 
               [
                  "fn", 
                  {}, 
                  "text", 
                  "KORNOG computing"
               ], 
               [
                  "adr", 
                  {}, 
                  "text", 
                  [
                     "", 
                     "", 
                     "26b rue d'Aiguillon", 
                     "MORLAIX", 
                     "", 
                     "29600", 
                     "FR"
                  ]
               ], 
...
   "events": [
      {
         "eventAction": "registration", 
         "eventDate": "2007-08-14T17:02:33Z"
      }, 
      {
         "eventAction": "last changed", 
         "eventDate": "2014-08-14T01:54:07Z"
      }, 
      {
         "eventAction": "expiration", 
         "eventDate": "2015-08-14T17:02:33Z"
      }
   ], 
   "handle": "D19378523-LRMS", 
   "lang": "en", 
   "ldhName": "kornog-computing.info", 
...
   "nameservers": [
      {
         "ldhName": "ns1.kornog-computing.net", 
         "objectClassName": "nameserver", 
         "remarks": [
            {
               "description": [
                  "Summary data only. For complete data, send a specific query for the object."
               ], 
               "title": "Incomplete Data", 
               "type": "object truncated due to unexplainable reasons"
            }
         ]
      }, 
      {
         "ldhName": "ns2.kornog-computing.net", 
         "objectClassName": "nameserver", 
         "remarks": [
            {
               "description": [
                  "Summary data only. For complete data, send a specific query for the object."
               ], 
               "title": "Incomplete Data", 
               "type": "object truncated due to unexplainable reasons"
            }
         ]
      }
   ], 
   "notices": [
      {
         "description": [
            "Access to AFILIAS WHOIS information is provided to assist persons in determining the contents of a domain name registration record in the Afilias registry database. The data in this record is provided by Afilias Limited for informational purposes only, and Afilias does not guarantee its accuracy. [...]"
         ], 
         "title": "TERMS OF USE"
      }
   ], 
   "objectClassName": "domain", 
...
   "rdapConformance": [
      "rdap_level_0"
   ], 
   "secureDNS": {
      "zoneSigned": false
   }, 
   "status": [
      "clientDeleteProhibited -- http://www.icann.org/epp#clientDeleteProhibited", 
      "clientTransferProhibited -- http://www.icann.org/epp#clientTransferProhibited"
   ]
}

La section 1.2 présente le modèle de données de RDAP. Dans les réponses, on trouve des types simples (comme des chaînes de caractères), des tableaux JSON, et des objets JSON qui décrivent les trucs sur lesquels on veut de l'information (noms de domaine, adresses IP, etc). Ces objets peuvent comporter des tableaux ou d'autres objets et, lorsqu'une réponse renvoie plusieurs objets (cas des recherches ouvertes, cf. RFC 7482, section 3.2), peuvent eux-même être regroupés en tableaux. Il existe plusieurs classes de ces objets. D'abord, les classes communes aux registres de noms de domaine et aux RIR :

  • Domaines (oui, même pour les RIR, pensez à in-addr.arpa et ip6.arpa),
  • Serveurs de noms,
  • Entités diverses, comme les handles des contacts.

Deux classes sont spécifiques aux RIR :

On verra peut-être apparaître d'autres classes avec le temps, si l'usage de RDAP se répand.

La section 2 de notre RFC décrit comment JSON est utilisé. Le type MIME renvoyé est application/rdap+json. La section 2 commence par un rappel que le client RDAP doit ignorer les membres inconnus dans les objets JSON, afin de préserver la future extensibilité. (Cette règle ne s'applique pas au jCard - cf. RFC 7095 - embarqué.) Si un serveur veut ajouter des membres qui lui sont spécifiques, il est recommandé qu'il préfixe leur nom avec un identificateur court suivi d'un tiret bas. Ainsi, cet objet RDAP standard :

{
     "handle" : "ABC123",
     "remarks" :
     [
       {
         "description" :
         [
           "She sells sea shells down by the sea shore.",
           "Originally written by Terry Sullivan."
         ]
       }
     ]
   }

S'il est servi par le « registre de la Lune » (registre imaginaire qui fournit les exemples de ce RFC), celui-ci, lorsqu'il voudra ajouter des membres, les précédera de lunarNIC_ :

{
     "handle" : "ABC123",
     "lunarNic_beforeOneSmallStep" : "TRUE THAT!",
     "remarks" :
     [
       {
         "description" :
         [
           "She sells sea shells down by the sea shore.",
           "Originally written by Terry Sullivan."
         ]
       }
     ],
     "lunarNic_harshMistressNotes" :
     [
       "In space,",
       "nobody can hear you scream."
     ]
   }

(Je vous laisse décoder les références geeks dans l'exemple.)

La section 3 s'occupe des types de données de base. On utilise du JSON normal, tel que spécifié dans le RFC 7159, avec ses chaînes de caractères, ses booléens, son null... Un handle (l'identifiant unique - par registre - d'un contact, parfois nommé NIC handle ou registry ID) est une chaîne. Les adresses IP se représentent également par une chaîne de caractères (ne pas oublier le RFC 5952 pour IPv6). Les pays sont identifiés par le code à deux lettres de ISO 3166. Les noms de domaines peuvent être sous une forme ASCII ou bien en Unicode. Les dates et heures suivent le RFC 3339, et les URI le RFC 3986.

Les informations plus complexes (comme les détails sur un contact) utilisent jCard, normalisé dans le RFC 7095.

Que trouve-t-on dans les objets JSON renvoyés par un serveur RDAP ? Une indication de la version de la norme :

"rdapConformance" :
   [
     "rdap_level_0"
   ]

Et des liens vers des ressources situées ailleurs, suivant le cadre du RFC 5988 :

         "links": [
            {
               "href": "http://rdg.afilias.info/rdap/entity/ovh53ec16bekre5", 
               "rel": "self", 
               "type": "application/rdap+json", 
               "value": "http://rdg.afilias.info/rdap/entity/ovh53ec16bekre5"
            }

On peut aussi avoir du texte libre, comme dans l'exemple plus haut avec le membre remarks. Ce membre sert aux textes décrivant la classe, alors que notice est utilisé pour le service RDAP. Un exemple :

   "notices": [
      {
         "description": [
            "Access to AFILIAS WHOIS information is provided to assist persons in determining the contents of a domain name registration record in the Afilias registry database. The data in this record is provided by Afilias Limited for informational purposes only, and Afilias does not guarantee its accuracy. [...]"
         ], 
         "title": "TERMS OF USE"
      }
   ], 

Contrairement à whois, RDAP permet l'internationalisation sous tous ses aspects. Par exemple, on peut indiquer la langue des textes avec une étiquette de langue (RFC 5646) :

   "lang": "en", 

Enfin, la classe (le type) de l'objet renvoyé par RDAP est indiqué par un membre objectClassName :

   "objectClassName": "domain", 

Ces classes, justement. La section 5 les décrit. Il y a d'abord la classe Entity qui correspond aux requêtes /entity du RFC 7482. Elle sert à décrire les personnes et les organisations. Parmi les membres importants pour les objets de cette classe, handle qui est un identificateur de l'instance de la classe, et roles qui indique la relation de cette instance avec l'objet qui la contient (par exemple "roles": ["technical"] indiquera que cette Entity est le contact technique de l'objet). L'information de contact sur une Entity se fait avec le format jCard du RFC 7095, dans un membre vcardArray. Voici un exemple :

% curl http://rdg.afilias.info/rdap/entity/ovh53ec16bekre5
...
         "objectClassName": "entity", 
         "roles": [
            "technical", 
            "billing", 
            "administrative"
         ], 
         "vcardArray": [
            "vcard", 
            [
               [
                  "version", 
                  {}, 
                  "text", 
                  "4.0"
               ], 
               [
                  "fn", 
                  {}, 
                  "text", 
                  "Simon TOSSER"
               ], 
               [
                  "fn", 
                  {}, 
                  "text", 
                  "KORNOG computing"
               ], 
               [
                  "adr", 
                  {}, 
                  "text", 
                  [
                     "", 
                     "", 
                     "26b rue d'Aiguillon", 
                     "MORLAIX", 
                     "", 
                     "29600", 
                     "FR"
                  ]
               ], 
               [
                  "email", 
                  {}, 
                  "text", 
                  "simon.tosser@gmail.com"
               ], 
               [
                  "tel", 
                  {
                     "type": "work"
                  }, 
                  "uri", 
                  "tel:+33.661463099"
               ], 
            ]
         ]

La classe Nameserver correspond aux requêtes /nameserver du RFC 7482. Notez qu'un registre peut gérer les serveurs de noms de deux façons : ils peuvent être vus comme des objets autonomes, enregistrés tels quel dans le registre (par exemple via le RFC 5732), ayant des attributs par exemple des contacts, et interrogeables directement par whois ou RDAP (c'est le modèle de .com, on dit alors que les serveurs de noms sont des « objets de première classe »). Ou bien ils peuvent être simplement des attributs des domaines, accessibles via le domaine (c'est le modèle de .fr : regardez ssi.gouv.fr, bien que les serveurs de noms soient dans la zone, vous ne pouvez pas demander directement des informations sur ces serveurs via whois). Le principal attribut d'un objet Nameserver est son adresse IP, pour pouvoir générer des colles dans le DNS (enregistrement DNS d'une adresse IP, pour le cas où le serveur de noms est lui-même dans la zone qu'il sert). Voici un exemple avec un des serveurs de noms de la zone afilias-nst.info :

% curl http://rdg.afilias.info/rdap/nameserver/b0.dig.afilias-nst.info 
...
   "ipAddresses": {
      "v4": [
         "65.22.7.1"
      ], 
      "v6": [
         "2a01:8840:7::1"
      ]
   }, 
...

Notez que l'adresse IP est un tableau, un serveur pouvant avoir plusieurs adresses.

La classe Domain correspond aux requêtes /domain du RFC 7482. Un objet de cette classe a des membres indiquant les serveurs de noms, si la zone est signée avec DNSSEC ou pas, l'enregistrement DS si elle est signée, le statut (actif ou non, bloqué ou non), les contacts, etc. Voici un exemple :

% curl http://rdg.afilias.info/rdap/domain/afilias-nst.info  
...
   "nameservers": [
      {
         "ldhName": "a0.dig.afilias-nst.info", 
...
   "secureDNS": {
      "zoneSigned": false
   }, 
   "status": [
      "clientTransferProhibited -- http://www.icann.org/epp#clientTransferProhibited", 
      "serverDeleteProhibited -- http://www.icann.org/epp#serverDeleteProhibited"
   ]
...

La classe IP network rassemble les objets qu'on trouve dans les réponses aux requêtes /ip du RFC 7482. Un objet de cette classe ne désigne en général pas une seule adresse IP mais un préfixe, dont on indique la première (startAddress) et la dernière adresse (endAddress). Personnellement, je trouve cela très laid et j'aurai préféré qu'on utilise une notation préfixe/longueur. Voici un exemple :

% curl http://rdap.db.ripe.net/ip/131.111.150.25    
...
{
  "handle" : "131.111.0.0 - 131.111.255.255",
  "startAddress" : "131.111.0.0/32",
  "endAddress" : "131.111.255.255/32",
  "ipVersion" : "v4",
  "name" : "CAM-AC-UK",
  "type" : "LEGACY",
  "country" : "GB",
...

La dernière classe normalisée à ce stade est autnum (les AS), en réponse aux requêtes /autnum du RFC 7482. Elle indique notamment les contacts de l'AS. Pour l'instant, il n'y a pas de format pour indiquer la politique de routage (RFC 4012). Un exemple d'un objet de cette classe :

% curl  http://rdap.db.ripe.net/autnum/20766 
{
  "handle" : "AS20766",
  "name" : "GITOYEN-MAIN-AS",
  "type" : "DIRECT ALLOCATION",
...
    "handle" : "GI1036-RIPE",
    "vcardArray" : [ "vcard", [ [ "version", { }, "text", "4.0" ], [ "fn", { }, "text", "NOC Gitoyen" ], [ "kind", { }, "text", "group" ], [ "adr", {
      "label" : "Gitoyen\n21 ter rue Voltaire\n75011 Paris\nFrance"
    }, "text", null ], [ "email", { }, "text", "noc@gitoyen.net" ] ] ],
...

Comme, dans la vie, il y a parfois des problèmes, une section de notre RFC, la section 6, est dédiée aux formats des erreurs que peuvent indiquer les serveurs RDAP. Le code de retour HTTP fournit déjà des indications (404 = cet objet n'existe pas ici, 403 = vous n'avez pas le droit de le savoir, etc) mais on peut aussi ajouter un objet JSON pour en indiquer d'avantage, objet ayant un membre errorCode (qui reprend le code HTTP), un membre title et un membre description. Voici un exemple sur le serveur RDAP expérimental de l'ARIN :

% curl -v http://rdappilot.arin.net/restfulwhois/rdap/autnum/99999 
< HTTP/1.0 404 Not Found
< Date: Thu, 26 Mar 2015 16:02:07 GMT
< Server: Apache/2.2.3 (CentOS)
...
{
...
  "errorCode" : 404,
  "title" : "AUTNUM NOT FOUND",
  "description" : [ "The autnum you are seeking as '99999' is/are not here." ]

Plus positive, la possibilité de demander de l'aide à un serveur RDAP, en se renseignant sur ses capacités, avec la requête /help. Son résultat est décrit dans la section 7 mais les serveurs RDAP actuels ne semblent pas encore utiliser cette possibilité. L'exemple qui suit est donc purement théorique :

{
     "rdapConformance" :
     [
       "rdap_level_0"
     ],
     "notices" :
     [
       {
         "title" : "Authentication Policy",
         "description" :
         [
           "Access to sensitive data for users with proper credentials."
         ],
         "links" :
         [
           {
             "value" : "http://example.net/help",
             "rel" : "alternate",
             "type" : "text/html",
             "href" : "http://www.example.com/auth_policy.html"
           }
         ]
       }
     ]
   }

Et les résultats des recherches ouvertes (section 3.2 du RFC 7482), qui peuvent renvoyer plusieurs objets ? Ce sont des tableaux JSON, dans des membres dont le nom se termine par Results. Par exemple, en cherchant les noms de domaines commençant par ra :

% curl http://rdg.afilias.info/rdap/domains\?name=ra\*|more           
   "domainSearchResults": [
      {
         "ldhName": "RAINSTRAGE.INFO", 
         ...
         "objectClassName": "domain", 
         "remarks": [
            {
               "description": [
                  "Summary data only. For complete data, send a specific query for the object."
               ], 
               "title": "Incomplete Data", 
               "type": "object truncated due to unexplainable reasons"
            }
...
         "ldhName": "RADONREMOVAL.INFO", 
...
         "ldhName": "RANCONDI.INFO", 
...

Vous avez peut-être noté dans le tout premier exemple le membre events (section 4.5 du RFC). Ces événements comme created ou last-changed donnent accès à l'histoire d'un objet enregistré. Ici, nous apprenons que le domaine kornog-computing.info a été enregistré en 2007.

Certaines valeurs qui apparaissent dans les résultats sont des chaînes de caractères fixes, stockées dans un nouveau registre IANA. Elles sont conçues pour être utilisées dans les notice, remark, status, role et quelques autres. Parmi les remarques, on trouvera le cas où une réponse a été tronquée (section 9 du RFC), comme dans l'exemple ci-dessus avec la mention Incomplete Data. Parmi les statuts, on trouvera, par exemple validated (pour un objet vérifié, par exemple un nom de domaine dont on a vérifié les coordonnées du titulaire), locked (pour un objet verrouillé), obscured (qui n'est pas un statut dans le base du données du registre mais simplement la mention du fait que le serveur RDAP a délibérement modifié certaines informations qu'il affiche, par exemple pour protéger la vie privée), etc. Pour les rôles, on trouvera registrant (titulaire), technical (contact technique), etc.

Pour ceux qu'intéressent les questions d'internationalisation, la section 12 contient d'utiles mentions. L'encodage des données JSON doit être de l'UTF-8. Et, comme indiqué plus haut, les IDN peuvent être sous la forme Punycode ou bien directement en UTF-8.

Et la vie privée, un problème permanent avec whois, où il faut toujours choisir entre la distribution de données utiles pour contacter quelqu'un et les risques pour sa vie privée ? La section 13 revient sur cette question. Un point important : RDAP est un protocole, pas une politique. Il ne définit pas quelles règles suivre (c'est de la responsabilité des divers registres) mais il fournit les outils pour mettre en œuvre ces règles. Notamment, RDAP permet de marquer des parties de la réponse comme étant connues du registre, mais n'ayant délibérement pas été envoyées (avec les codes private et removed) ou bien comme ayant été volontairement rendues peu ou pas lisibles (code obscured).

Vous avez vu dans les exemples précédents que les réponses d'un serveur RDAP sont souvent longues et, a priori, moins lisibles que celles d'un serveur whois. Il faudra souvent les traiter avec un logiciel qui comprend le JSON. Un exemple très simple et que j'apprécie est jq. Il peut servir à présenter le résultat de manière plus jolie :

% curl  https://rdap.centralnic.com/domain/centralnic.pw  | jq "" 
{
  "cnic_recordGenerated": "2015-03-26T16:11:20.0Z",
  "lang": "en",
  "notices": [
    {
      "links": [
        {
          "type": "application/json",
          "media": "screen",
          "rel": "item",
          "href": "https://www.centralnic.com/registry/labs/rdap#service-level",
          "value": "https://www.centralnic.com/registry/labs/rdap#service-level",
          "title": "Service Level"
        }
      ],
      "description": [
        "The RDAP service is currently an alpha quality product. CentralNic makes no warranty of it
s correctness, usefulness or reliability. CentralNic reserves the right to change or remove part or
 all of the service at any time with no prior warning. No service level is offered."
      ],
      "title": "Service Level"
    },
    {
      "links": [
        {
...

(Essayez ce même serveur RDAP sans jq !)

Mais on peut aussi se servir de jq pour extraire un champ particulier, ici le pays :

% curl -s  http://rdap.db.ripe.net/ip/131.111.150.25 | jq ".country"
"GB"

% curl -s  http://rdap.db.ripe.net/ip/192.134.1.1 | jq ".country"
"FR"

Il y a évidemment d'autres logiciels que jq sur ce créneau, comme JSONpath, jpath ou, pour les programmeurs Python, python -m json.tool.

Un dernier mot, sur le choix de JSON pour le format de sortie, alors que le protocole standard d'avitaillement des objets dans les bases Internet, EPP (RFC 5730) est en XML. L'annexe E de notre RFC, qui discute ce choix, donne comme principaux arguments que JSON est désormais plus répandu que XML (cf. l'article « The Stealthy Ascendancy of JSON ») et que c'est surtout vrai chez les utilisateurs (EPP étant utilisé par une population de professionnels bien plus réduite).


Téléchargez le RFC 7483


L'article seul

RFC 7480: HTTP usage in the Registration Data Access Protocol (RDAP)

Date de publication du RFC : Mars 2015
Auteur(s) du RFC : A. Newton (ARIN), B. Ellacott (APNIC), N. Kong (CNNIC)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF weirds
Première rédaction de cet article le 26 mars 2015


Le protocole d'accès aux informations des registres RDAP (Registration Data Access Protocol), qui se veut successeur de whois, peut utiliser plusieurs protocoles de transport différents. Pour l'instant, le seul normalisé est HTTP, dans ce RFC.

HTTP est normalisé dans le RFC 7230. Mais, à part cela, il n'y a évidemment pas besoin de le présenter. Son choix comme protocole de transport va de soi dans l'Internet aujourd'hui, et permet de doter RDAP d'une jolie sémantique REST. Toute la complexité est dans le serveur, un des objectifs de ce RFC est que « on puisse utiliser comme client RDAP des outils généralistes comme bash ou wget ». Le mode d'emploi est à peu près :

  • Trouver le bon serveur, par exemple en utilisant la technique du RFC 7484,
  • Fabriquer une jolie requête HTTP de type GET (RFC 7231), en suivant le RFC 7482, par exemple, pour trouver de l'information sur le réseau 192.0.2.0, ce sera http://example.net/rdap/ip/192.0.2.0,
  • Envoyer la requête et lire la réponse en JSON (RFC 7483),
  • La réponse était peut-être sur un autre serveur et, dans ce cas, on a reçu non pas le code JSON, avec le statut 200, mais une redirection (statut HTTP 3xx) ; dans ce cas, on réessaie avec l'URL indiqué dans la redirection.

D'autres réponses étaient possibles, comme le fameux 404 si on demande des informations sur un objet qui n'existe pas. RDAP utilise HTTP et on a donc toutes les subtilités de HTTP à sa disposition.

La section 3 de notre RFC résume les principes de RDAP-sur-HTTP :

  • Une seule requête HTTP pour avoir l'information,
  • Plusieurs formats de sortie possible en théorie même si, pour l'instant, seul le JSON du RFC 7483 est spécifié,
  • Possibilité d'utiliser tous ce que permet HTTP, afin d'éviter de réinventer la roue. Ainsi, si on veut de la compression, on ne la réinvente pas dans RDAP, on utilise celle de HTTP (RFC 7231, section 3.1.2). Même chose pour les mécanismes d'authentification, où on suivra le RFC 7235 ou bien le cache, selon le RFC 7234. Ainsi, on pourra récupérer tous les logiciels et l'expertise de HTTP.

La section 4 détaille la formation des requêtes RDAP sur HTTP. Ce sont des requêtes GET ou HEAD (puisqu'elles ne modifient pas les données, RDAP étant un protocole en lecture seule), qui fonctionnent sur HTTP ou HTTPS (qui est obligatoire pour les logiciels RDAP). Le client doit penser à mettre un en-tête Accept: qui indique un type de données qui existe pour RDAP, comme le application/rdap+json du RFC 7483 (notez la syntaxe avec un +, issue du RFC 6839). S'il l'oublie, le serveur est libre de faire ce qu'il veut, le RFC suggérant d'envoyer une réponse acceptable par un navigateur Web ordinaire (comme text/html), car c'est sans doute cela qui provoquera le moins de surprise (les serveurs RDAP existants - voir par exemple http://rdg.afilias.info/rdap/domain/reflets.info - ne suivent pas cette recommandation).

La requête peut contenir des paramètres (après le ? dans l'URL).

La section 5 de notre RFC détaille les réponses possibles. Comme on utilise HTTP comme transport, tous les codes de réponse HTTP (RFC 7231, section 6) sont admissibles. Néanmoins, certains seront sans doute plus courants :

  • 200 : réponse positive, tout va bien,
  • 301 (redirection permanente, permettant de changer la méthode HTTP), 302 (redirection temporaire, permettant de changer la méthode), 307 (redirection temporaire, ne permettant pas de changer la méthode), 308 (redirection permanente, ne permettant pas de changer la méthode) : les divers codes de redirection, permettant à un « méta-serveur » d'indiquer le bon serveur RDAP dans l'en-tête Location: de la réponse (par exemple, en théorie, l'IANA pourrait avoir un serveur RDAP qui redirige vers les serveurs RDAP des TLD),
  • 404 : ce truc n'a pas été trouvé, par exemple parce que je cherche un nom de domaine qui n'existe pas,
  • 400 : requête mal formée, parce que le client RDAP est bogué ou bien parce qu'on a fabriqué une requête RDAP à la main, en se trompant,
  • 429 : on envoie trop de requêtes (ce code a été normalisé dans le RFC 6585). Aujourd'hui, les serveurs whois ont souvent ce problème de requêtes répétées, cela peut être une attaque DoS mais aussi un domaineur qui veut récolter de l'information, ou un autre type de malhonnête qui veut se constituer une base de données. Un serveur RDAP aura donc probablement une fonction de limitation du trafic, et répondra 429 si le client exagère. Les clients honnêtes ralentiront alors.

Voici quelques exemples réels avec le serveur RDAP expérimental d'APNIC et le client HTTP curl. D'abord, un cas où tout se passe bien :


% curl -v http://rdap.apnic.net/ip/2001:dc0:2001:11::194 
> GET /ip/2001:dc0:2001:11::194 HTTP/1.1
> User-Agent: curl/7.26.0
> Host: rdap.apnic.net
> Accept: */*
> 
< HTTP/1.1 200 OK
< Date: Thu, 05 Mar 2015 16:08:37 GMT
< Content-Type: application/rdap+json
< Access-Control-Allow-Origin: *
< Transfer-Encoding: chunked
< Server: Jetty(9.2.z-SNAPSHOT)

Un cas où l'objet demandé n'existe pas et où le serveur renvoie le fameux code HTTP 404 :


% curl -v http://rdap.apnic.net/ip/4001:dc0:2001:11::194 
> GET /ip/4001:dc0:2001:11::194 HTTP/1.1
> User-Agent: curl/7.26.0
> Host: rdap.apnic.net
> Accept: */*
> 
< HTTP/1.1 404 Not Found

Et enfin un cas où l'objet existe chez un autre RIR et on est donc renvoyé au RIPE-NCC, avec le code normal de redirection HTTP :


% curl -v http://rdap.apnic.net/ip/2001:4b98:dc0:41:: 
> GET /ip/2001:4b98:dc0:41:: HTTP/1.1
> User-Agent: curl/7.26.0
> Host: rdap.apnic.net
> Accept: */*
> 
< HTTP/1.1 301 Moved Permanently
< Date: Thu, 05 Mar 2015 16:11:16 GMT
< Location: http://rdap.db.ripe.net/ip/2001:4b98:dc0:41::


Téléchargez le RFC 7480


L'article seul

RFC 7482: Registration Data Access Protocol Query Format

Date de publication du RFC : Mars 2015
Auteur(s) du RFC : A. Newton (ARIN), S. Hollenbeck (Verisign Labs)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF weirds
Première rédaction de cet article le 26 mars 2015


Le nouveau protocole d'information RDAP, qui vise à remplacer whois, est décrit dans un ensemble de RFC. Celui présenté ici normalise la façon de former les requêtes RDAP. Celles-ci ont la forme d'une URL, puisque RDAP repose sur l'architecture REST.

Vous pouvez voir les autres RFC sur RDAP dans mon autre article. Je rappelle juste que le seul transport actuellement normalisé pour RDAP (dans le RFC 7480) est HTTP. RDAP peut être utilisé pour beaucoup de sortes d'entités différentes mais ce RFC ne couvre que ce qui correspond aux usages actuels de whois, les préfixes d'adresses IP, les AS, les noms de domaine, etc. Bien sûr, un serveur RDAP donné ne gère pas forcément tous ces types d'entités, et il renvoie le code HTTP 501 (Not implemented) s'il ne sait pas gérer une demande donnée. Ce RFC ne spécifie que l'URL de la requête, le format de la réponse est variable (JSON, XML...) et le seul actuellement normalisé, au dessus de JSON, est décrit dans le RFC 7483. D'autre part, ces RFC RDAP ne décrivent que le protocole entre le client RDAP et le serveur, pas « l'arrière-cuisine », c'est-à-dire l'avitaillement (création, modification et suppression) des entités enregistrées. RDAP est en lecture seule et ne modifie pas le contenu des bases de données qu'il interroge.

Passons aux choses concrètes. Une requête RDAP est un URL RFC 3986. Celui-ci est obtenu en ajoutant un chemin spécifique à une base. La base (par exemple https://rdap.example.net/) va être obtenue par des mécanismes divers, comme celui du RFC 7484. On met ensuite un chemin qui dépend du type d'entité sur laquelle on veut se renseigner, et qui indique l'identificateur de l'entité. Par exemple, avec la base ci-dessus, et une recherche du nom de domaine internautique.fr, on construirait un URL complet https://rdap.example.net/domain/internautique.fr. Il y a cinq types d'entités possibles :

  • ip : les préfixes IP (notez qu'on peut chercher un préfixe en donnant juste une des adresses IP couvertes par ce préfixe),
  • autnum : les numéros de systèmes autonomes,
  • domain : un nom de domaine (notez que cela peut être un domaine dans in-addr.arpa ou ipv6.arpa),
  • nameserver : un serveur de noms,
  • entity : une entité quelconque, comme un bureau d'enregistrement, ou un contact identifié par un handle.

Pour ip, le chemin dans l'URL est /ip/XXXXXX peut être une adresse IPv4 ou IPv6 sous forme texte. Il peut aussi y avoir une longueur de préfixe à la fin donc /ip/2001:db8:1:a::/64 est un chemin valable. Ainsi, sur le service RDAP expérimental du RIPE-NCC, http://rdap.db.ripe.net/ip/2001:4b98:dc0:41:: est un URL possible. Testons-le :

% curl  http://rdap.db.ripe.net/ip/2001:4b98:dc0:41:: 
{
  "handle" : "2001:4b98:dc0::/48",
  "startAddress" : "2001:4b98:dc0::/128",
  "endAddress" : "2001:4b98:dc0:ffff:ffff:ffff:ffff:ffff/128",
  "ipVersion" : "v6",
  "name" : "GANDI-HOSTING-DC0",
  "type" : "ASSIGNED",
  "country" : "FR",
  "rdapConformance" : [ "rdap_level_0" ],
  "entities" : [ {
    "handle" : "GAD42-RIPE",
    "vcardArray" : [ "vcard", [ [ "version", { }, "text", "4.0" ], [ "fn", { }, "text", "Gandi Abuse Department" ], [ "kind", { }, "text", "group" ], [ "adr", {
      "label" : "63-65 Boulevard Massena\n75013 Paris\nFrance"
...

Pour autnum, on met le numéro de l'AS après /autnum/. Toujours dans l'exemple RIPE-NCC, http://rdap.db.ripe.net/autnum/29169 permet de chercher de l'information sur l'AS 29169 :

% curl   http://rdap.db.ripe.net/autnum/29169 
{
  "handle" : "AS29169",
  "name" : "GANDI-AS",
  "type" : "DIRECT ALLOCATION",
  "rdapConformance" : [ "rdap_level_0" ],
  "entities" : [ {
    "handle" : "GANDI-NOC",
    "roles" : [ "registrant" ]
  }, {
...

Pour les noms de domaines, on met le nom après /domain/. Ainsi, sur le serveur RDAP expérimental d'Afilias, http://rdg.afilias.info/rdap/domain/rmll.info nous donnera de l'information sur le domaine rmll.info. On peut mettre un nom en Unicode donc https://rdap.example.net/domain/potamochère.fr est valable, mais il devra être encodé comme l'explique la section 6.1, plus loin. Si on ne veut pas lire cette information sur l'encodage, on peut aussi utiliser la forme Punycode, donc chercher avec https://rdap.example.net/domain/xn--potamochre-66a.fr.

On peut aussi se servir de RDAP pour les noms de domaines qui servent à traduire une adresse IP en nom :

% curl http://rdap.db.ripe.net/domain/1.8.a.4.1.0.0.0.0.d.1.4.1.0.0.2.ip6.arpa
{
  "handle" : "0.d.1.4.1.0.0.2.ip6.arpa",
  "ldhName" : "0.d.1.4.1.0.0.2.ip6.arpa",
  "nameServers" : [ {
    "ldhName" : "dns15.ovh.net"
  }, {
    "ldhName" : "ns15.ovh.net"
  } ],
  "rdapConformance" : [ "rdap_level_0" ],
  "entities" : [ {
    "handle" : "OK217-RIPE",
    "roles" : [ "administrative" ]
  }, {
    "handle" : "OTC2-RIPE",
    "roles" : [ "zone", "technical" ]
  }, {
    "handle" : "OVH-MNT",
    "roles" : [ "registrant" ]
  } ],
  "remarks" : [ {
    "description" : [ "OVH IPv6 reverse delegation" ]
  } ],
...

Pour un serveur de noms, on met son nom après /nameserver donc, chez Afilias :

% curl  http://rdg.afilias.info/rdap/nameserver/rmll1.rmll.info 
{
...
   "ipAddresses": {
      "v4": [
         "80.67.169.65"
      ]
   }, 
   "lang": "en", 
   "ldhName": "rmll1.rmll.info", 
...

Pour entity, on indique juste un identificateur. Voici un exemple :

% curl  http://rdg.afilias.info/rdap/entity/R-R191-LRMS   
{
   "handle": "R-R191-LRMS", 
   "lang": "en", 
...
   "roles": [
      "registrar"
   ], 
   "vcardArray": [
      "vcard", 
      [
         [
            "version", 
            {}, 
            "text", 
            "4.0"
         ], 
         [
            "fn", 
            {}, 
            "text", 
            "Gandi SAS"
         ], 
         [
            "adr", 
            {}, 
            "text", 
            [
               "", 
               "", 
               "63-65 boulevard Massena", 
               "Paris", 
               "", 
               "F-75013", 
               "FR"
            ]
...

Dernière possibilité, un chemin spécial indique qu'on veut récupérer de l'aide sur ce serveur RDAP particulier. En envoyant help (par exemple https://rdap.example.net/help, on obtient un document décrivant les capacités de ce serveur, ses conditions d'utilisation, sa politique vis-à-vis de la vie privée, ses possibilités d'authentification, l'adresse où contacter les responsables, etc. C'est l'équivalent de la fonction d'aide qu'offrent certains serveurs whois, ici celui de l'AFNIC :

% whois -h whois.nic.fr  -- -h
...
%% Option   Function
%% -------  -------------------------------------
%% -r       turn off recursive lookups
%% -n       AFNIC output format
%% -o       old fashioned output format (Default)
%% -7       force 7bits ASCII output format
%% -v       verbose mode for templates and help options
%%          (may be use for reverse query)
%% -T type  return only objects of specified type
%% -P       don't return individual objects in case of contact search
%% -h       informations about server features
%% -l lang  choice of a language for informations (you can specify US|EN|UK for
%%          english or FR for french)
%%
...

Pour RDAP, voyez par exemple http://rdg.afilias.info/rdap/help ou, dans un genre très différent, http://rdap.apnic.net/help.

Toutes les recherches jusque là ont été des recherches exactes (pas complètement pour les adresses IP, où on pouvait chercher un réseau par une seule des adresses contenues dans le réseau). Mais on peut aussi faire des recherches plus ouvertes, sur une partie de l'identificateur. Cela se fait en ajoutant une requête (la partie après le point d'interrogation) dans l'URL et en ajoutant un astérisque (cf. section 4.1). Ainsi, https://rdap.example.net/domains?name=foo* cherchera tous les domaines dont le nom comporte la chaîne de caractères foo. (Vous avez noté que c'est /domains au pluriel et plus /domain ?) Voici un exemple d'utilisation :

% curl  http://rdg.afilias.info/rdap/domains\?name=rm\*|more
   "domainSearchResults": [
      {
         "handle": "D10775367-LRMS", 
         "ldhName": "RMLL.INFO", 
...
         "remarks": [
            {
               "description": [
                  "Summary data only. For complete data, send a specific query for the object."
               ], 
               "title": "Incomplete Data", 
               "type": "object truncated due to unexplainable reasons"
            }
...
         "ldhName": "RMLL2015.INFO", 
...
         "ldhName": "RMLLOCKSMITHS.INFO", 
... 
      {
         "description": [
            "Search results are limited to 50 per query."
         ], 
         "title": "Search Policy", 
         "type": "result set truncated due to unexplainable reasons"
      }

On peut aussi chercher un domaine d'après ses serveurs de noms, par exemple https://rdap.example.net/domains?nsLdhName=ns1.example.com chercherait tous les domaines délégués au serveur DNS ns1.example.com. Une telle fonction peut être jugée très indiscrète et le serveur RDAP est toujours libre de répondre ou pas :

% curl http://rdg.afilias.info/rdap/domains\?nsLdhName=ns0.abul.org
...
{
   "description": [
      "Domain name search by nameserver is not supported."
   ], 
   "errorCode": 501, 
...

Deux autres types permettent ces recherches ouvertes, /nameservers (comme dans https://rdap.example.net/nameservers?ip=2001:db8:42::1:53, mais notez qu'on peut aussi chercher un serveur par son nom) et /entities (comme dans https://rdap.example.net/entities?fn=Jean%20Dupon*) :

% curl  http://rdg.afilias.info/rdap/entities\?fn=go\*     
{
   "entitySearchResults": [
      {
         "fn": "Go China Domains, Inc.", 
...
         "fn": "Gotnames.ca Inc.", 
...

Notez que ce type de recherche peut représenter un sérieux danger pour la vie privée (comme noté dans le RFC, par exemple en section 4.2) puisqu'elle permettrait, par exemple de trouver tous les titulaires prénommés Jean. Il faut donc espérer qu'elle ne sera accessible qu'à des clients authentifiés, et de confiance.

La section 4 détaille le traitement des requêtes. N'oubliez pas qu'on travaille ici sur HTTP et que, par défaut, les codes de retour RDAP suivent la sémantique HTTP (404 pour un objet non trouvé, par exemple). Il y a aussi quelques cas où le code à retourner est moins évident. Ainsi, si un serveur ne veut pas faire une recherche ouverte, il va répondre 422 (Unprocessable Entity).

Vous avez noté plus haut, mais la section 6 le rapelle aux distraits, que le nom de domaine peut être exprimé en Unicode ou en ASCII. Donc, https://rdap.example.net/domain/potamochère.fr et https://rdap.example.net/domain/xn--potamochre-66a sont deux requêtes acceptables.

Enfin, la section 8 rappelle quelques règles de sécurité comme :

  • Les requêtes ouvertes peuvent mener à une forte consommation de ressources sur le serveur. Le serveur qui ne vaut pas se faire DoSer doit donc faire attention avant de les accepter.
  • Les requêtes RDAP, et surtout les requêtes ouvertes, peuvent soulever des questions liées à la vie privée. Les serveurs RDAP doivent donc réfléchir avant de renvoyer de l'information. Rappelez-vous que RDAP, contrairement à whois, peut avoir un mécanisme d'authentification, donc peut envoyer des réponses différentes selon le client.
  • Et, corollaire du précédent point, les gérants de serveurs RDAP doivent définir une politique d'auorisation : qu'est-ce que je renvoie, et à qui ?

Téléchargez le RFC 7482


L'article seul

Censure administrative du Web en France, un premier regard technique

Première rédaction de cet article le 15 mars 2015
Dernière mise à jour le 17 mars 2015


Prenons l'exemple de http://islamic-news.info/ dont, je suppose, d'après son nom de domaine, qu'il s'agit d'un site de propagande intégriste (je n'ai pas pu le consulter, pas à cause de la censure française, facile à contourner, mais parce qu'il semble en panne). Si on essaie de le consulter depuis un FAI français typique, on obtient à la place une page Web avec une main rouge menaçante (une référence historique très malencontreuse, pour une décision étatique, il aurait mieux valu utiliser une main de justice ; la fameuse main rouge a été supprimée vers le 24 mars) et un texte TOUT EN MAJUSCULES « VOUS AVEZ ÉTÉ REDIRIGÉ VERS CE SITE OFFICIEL CAR VOTRE ORDINATEUR ALLAIT SE CONNECTER À UNE PAGE DONT LE CONTENU PROVOQUE À DES ACTES DE TERRORISME OU FAIT PUBLIQUEMENT L'APOLOGIE D'ACTES DE TERRORISME » (ce texte a été légèrement modifié vers le 24 mars). Comment est-ce réalisé ?

Les différents textes officiels sur ces mesures de censure n'imposaient pas aux FAI une technique particulière mais les conditions de mise en œuvre (liste noire de noms de domaine « Les adresses électroniques figurant sur la liste [noire] comportent soit un nom de domaine (DNS), soit un nom d'hôte caractérisé par un nom de domaine précédé d'un nom de serveur », obligation de rediriger vers « CE SITE OFFICIEL » situé au ministère de l'Intérieur), fait que la solution la plus simple est de mettre en place un résolveur DNS menteur. Ce résolveur est la machine qui répond normalement aux requêtes DNS de l'utilisateur, en lui donnant l'adresse IP du serveur à contacter. (Au passage, une explication plus grand public du DNS avait été faite par Andréa Fradin.) Essayons avec dig depuis une machine au Japon, pour voir la vraie adresse IP :

% dig +short A islamic-news.info 
37.59.14.72

Et depuis un FAI français (Free, mais on verra plus loin qu'il n'est pas le seul) :

% dig +short A islamic-news.info 
90.85.16.52

L'adresse obtenue est différente, il y a bien un résolveur DNS menteur. Si on utilise un résolveur DNS public comme Google Public DNS, on a également la vraie adresse IP :

% dig @8.8.4.4 +short A islamic-news.info  
37.59.14.72

Est-ce bien ce trompeur 90.85.16.52 qui est le site officiel servant la « main rouge » ? Testons-le en HTTP. Il y a plusieurs méthodes pour cela mais j'ai utilisé une des plus simples, mettre dans mon fichier local /etc/hosts l'adresse de ce site pour un nom bidon :

% cat /etc/hosts
...
90.85.16.52 front-liberation-potamocheres.example

Et, en visitant http://front-liberation-potamocheres.example/, j'ai bien la page à la main rouge. On peut bien sûr tester directement http://90.85.16.52/ mais des astuces techniques utilisées par le ministère font que cela ne marche pas toujours si le champ Host: indique une adresse IP, et qu'on récupère parfois un 403 Forbidden. Si vous ne voulez pas modifier votre /etc/hosts comme moi, vous pouvez vous servir des noms créés par Pierre Beyssac, http://interieur0.eu.org/, http://interieur1.eu.org/ ou http://interieur2.eu.org/, ou encore les noms dans le domaine de Lauret Penou, gsec.ovh. Commme il y a un joker dans ce nom de domaine, n'importe quel nom convient, comme cazeneuve-a-raison.gsec.ovh.

Si vous voulez tester avec d'autres noms de domaine censurés, vous pouvez essayer jihadmin.com, is0lamnation.blogspot.fr, mujahida89.wordpress.com, ou alhayatmedia.wordpress.com (sans que j'en recommande leur contenu, œuvre des crapules intégristes !).

Notez que cela veut dire que le ministère de l'Intérieur est au courant de mon intérêt pour cet animal : avec ce système, l'utilisateur est redirigé, à son insu, vers un serveur Web du ministère de l'Intérieur, qui aura accès, via le champ HTTP Host: (RFC 7230, section 5.4) au nom originellement demandé. Lourde responsabilité pour le FAI qui, en configurant son résolveur DNS pour rediriger, fait cette redirection, il envoie ses clients vers un site qui saura si on aime les potamochères, le djihad ou les photos pédophiles.

Voici, vue avec tshark, la requête HTTP qu'envoie votre machine au serveur géré par le ministère de l'Intérieur, où on voit bien le champ Host :

Internet Protocol Version 4, Src: 192.168.2.1 (192.168.2.1), Dst: 90.85.16.52 (90.85.16.52)
Transmission Control Protocol, Src Port: 56532 (56532), Dst Port: http (80), Seq: 450, Ack: 311, Len: 468
Hypertext Transfer Protocol
    GET / HTTP/1.0\r\n
    Host: front-liberation-potamocheres.example\r\n
    User-Agent: Mozilla/5.0 (X11; Linux i686; rv:31.0) Gecko/20100101 Firefox/31.0 Iceweasel/31.4.0\r\n
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n
    Accept-Language: en-US,en;q=0.5\r\n
    Accept-Encoding: gzip, deflate\r\n
    Pragma: no-cache\r\n
    Connection: keep-alive\r\n
    \r\n
    [Full request URI: http://front-liberation-potamocheres.example/]

On voit également que votre adresse IP source apparait mais on y voit moins (c'est dans le reste de la connexion) que votre navigateur Web envoie également bien d'autres informations qui peuvent vous identifier, et qui sont peut-être également journalisées. (Voir le Panopticlick pour une impressionnante démonstration.) Donc, ce « SITE OFFICIEL » part d'une bonne intention (rendre la censure explicite, comme à Dubaï) mais a des conséquences très dangereuses. Pour s'amuser un peu, dans ce monde de brutes, on peut d'ailleurs utiliser cette propriété pour envoyer un message bien senti à ceux qui lisent ces journaux, avec curl (attention, cela se fera avec votre adresse IP : le but est de prendre position, pas de se cacher) :

% curl -o /dev/null -H "Host: Halte a la censure administrative du Web" \
      -H "X-Charlie: Je suis Charlie" \
      http://90.85.16.52/\?$RANDOM

Une solution technique pour éviter que vos utilisateurs soient redirigés à leur insu vers un serveur HTTP qui va noter leur adresse et peut-être d'autres informations, est de bloquer les accès à ce serveur. Une requête whois montre que ce serveur est dans la plage 90.85.16.32/27 (notez que rien n'indique de lien avec le ministère de l'Intérieur, on a juste un nom, à Metz). Pour bloquer cette plage, si on utilise Shorewall, ce sera dans /etc/shorewall/blacklist quelque chose comme :

# 2015-03-16: may do logging of visitors (French censorship system)
90.85.16.32/27

Si vous utilisez directement Netfilter, ce sera une commande du genre :

# iptables --insert OUTPUT --destination 90.85.16.32/27  --jump REJECT

Notez que la CNIL avait formulé un avis sur ce point, et noté que « [les textes officiels ne] permet ni la collecte ni l'exploitation, par l'OCLCTIC, des données de connexion des internautes qui seraient redirigés vers la page d'information du ministère de l'intérieur. Elle [la CNIL] rappelle que si des traitements de données à caractère personnel spécifiques étaient alimentés par ces données, ils devraient être soumis à l'examen préalable de la commission. » Bref, la CNIL ne se mouille pas. Pas d'avis concret, du genre « l'adresse IP source et le champ Host: ne devront pas être journalisés", ce qui serait la moindre des choses, et laisserait quand même le ministère de l'Intérieur faire des statistiques sur le nombre de visiteurs des sites censurés. (Note technique au passage, si vous utilisez Apache, la directive pour journaliser l'adresse IP source est %h - ou %a - et celle pour le champ Host: est %v. Ce sont ces deux directives qu'il faudrait retirer du LogFormat du ministère pour ne pas fliquer les utilisateurs. Cf. la documentation d'Apache.)

Le décret cité au début comprend plusieurs motifs de censure, et on note que l'hébergeur a prévu des sites Web différents, avec des messages différents, selon le motif. Comparez les messages en http://90.85.16.52/ (terrorisme), http://90.85.16.51/ (pédophilie) et http://90.85.16.50/ (le reste, non spécifié).

Continuons avec d'autres détails techniques : le « SITE OFFICIEL » est sans doute en place depuis très peu de temps car DNSDB (qui n'est pas temps réel, loin de là), n'a pas encore vu de noms se résolvant en 90.85.16.52 (DNSDB permet de chercher par le contenu de la réponse DNS, pas juste par le nom demandé). Il est vrai que DNSDB a probablement peu ou pas de capteurs en France (je n'ai rien vu non plus sur les bases équivalentes comme PassiveDNS.cn.)

Quant au type de serveur HTTP utilisé, il prétend être un nginx (dans l'en-tête HTTP Server:) mais il ressemble plutôt à un Apache : le message d'erreur en cas d'accès refusé (testez http://90.85.16.51/server-status) et le fait que les Etags ont le format Apache à trois champs, pas le format nginx à deux champs (analyse faite par Kim-Minh Kaplan, merci).

Quelle est l'ampleur du déploiement de ces DNS menteurs ? Pour cela, on va utiliser les sondes Atlas, petits ordinateurs placés un peu partout, et interrogeables via leur API. Avec le programme resolve-name.py, on va interroger les résolveurs DNS des sondes Atlas allemandes, pour commencer :

% python resolve-name.py --country=DE islamic-news.info 
Measurement #1895738 for islamic-news.info/A uses 499 probes
Probe 4407 failed (trailing junk)
[] : 16 occurrences
[37.59.14.72] : 677 occurrences
Test done at 2015-03-15T16:03:37Z

Toutes (sauf quelques-unes qui n'ont pas pu résoudre du tout le nom) trouvent la bonne adresse. (Il y a davantage de résultats que de sondes car chaque sonde fait plusieurs essais.) Essayons en France :

% python resolve-name.py --country=FR islamic-news.info 
Measurement #1895736 for islamic-news.info/A uses 498 probes                                
[] : 22 occurrences
[90.85.16.52] : 346 occurrences
[37.59.14.72] : 403 occurrences
Test done at 2015-03-15T15:39:15Z

À peu près la moitié des sondes Atlas en France voient la censure. Notez que les sondes Atlas ne sont pas du tout représentatives : installées par des volontaires, sans doute dans des réseaux plus geeks que la moyenne, elles ont plus de chances d'avoir un résolveur local non menteur (voir plus loin, pour cette solution anti-censure).

Par défaut, ce programme fait des requêtes de type A (demande d'une adresse IPv4). On peut lui demander ce qu'il en est pour les AAAA (demande d'une adresse IPv6). Normalement, il ne devrait pas y avoir de réponse (le nom n'a pas d'adresse IPv6 associé) mais un FAI a trouvé le moyen de mentir pour IPv6 et quel mensonge :

% python resolve-name.py -t AAAA -c FR islamic-news.info
Measurement #1895755 for islamic-news.info/AAAA uses 498 probes
[] : 586 occurrences
[::1] : 191 occurrences
Test done at 2015-03-15T20:25:57Z

Il renvoie, non pas vers la page du gouvernement, mais vers la machine locale...

Et si on regarde par AS et plus par pays :

% python resolve-name.py --as=3215 islamic-news.info 
Measurement #1895737 for islamic-news.info/A uses 133 probes
[90.85.16.52] : 189 occurrences
[37.59.14.72] : 32 occurrences
Test done at 2015-03-15T15:59:52Z

% python resolve-name.py --as=20766 islamic-news.info   
Measurement #1895739 for islamic-news.info/A uses 4 probes
[37.59.14.72] : 5 occurrences
Test done at 2015-03-15T16:06:34Z

Le premier AS est celui d'Orange, où il semble que la majorité des sondes voient le résolveur légal. Le second est celui de Gitoyen, dont les clients (comme FDN) ont plus de chances d'utiliser un résolveur non-menteur. (Notez toutefois que le faible nombre de sondes doit rendre prudent dans l'analyse.)

Et DNSSEC ? Est-ce qu'il résoudrait ce problème ? Non, car la validation est faite dans le résolveur. S'il est menteur, le fait de valider ne changera rien. Seul avantage, les gens qui valident avec DNSSEC ne verront pas la page d'information du ministère de l’intérieur (et ne seront pas enregistrés par ledit ministère) puisque le mensonge dans le résolveur entraînera une erreur (SERVFAIL : Server Failure) sur les domaines signés (ce qui n'est de toute façon pas le cas de islamic-news.info).

À propos de cryptographie, notez que le site vers lequel on est redirigé n'a pas HTTPS. Cela veut dire que le djihadiste ou le pédophile prudent, qui n'utilise que HTTPS, ne verra jamais la jolie main rouge (juste un timeout).

Quelles solutions sont disponibles si on veut quand même voir la propagande djihadiste ? La seule solution propre techniquement est d'avoir son propre résolveur DNS. En attendant, on peut utiliser un résolveur non-menteur (en supposant qu'il ne soit pas détourné et que le port 53 ne soit pas filtré). Dans tous les cas, il est sûr que la stabilité et la sécurité de l'Internet vont en souffrir. Sinon, on peut aussi s'auto-radicaliser un peu plus et franchement passer à Tor pour naviguer sur le Web.

Quelques bonnes lectures :

Et merci à David Thomson pour avoir apparemment été le premier à repérer cette censure, aujourd'hui, dimanche 15 mars.


L'article seul

RFC 7477: Child To Parent Synchronization in DNS

Date de publication du RFC : Mars 2015
Auteur(s) du RFC : W. Hardaker (Parsons)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 14 mars 2015


Le DNS est un système décentralisé, mais arborescent : toute zone (à part la racine) dépend d'une zone parente, qui doit notamment indiquer les serveurs de noms de ses zones filles. En théorie, l'information dans la zone parente et celle dans la zone fille doivent parfaitement coïncider mais, en pratique, des différences apparaissent souvent, et elles ont parfois des conséquences ennuyeuses, pouvant aller jusqu'à mettre en danger le bon fonctionnement de la zone. La principale raison de cette « désynchronisation » est qu'il n'existait aucun mécanisme standard par lequel le gestionnaire d'une zone fille pouvait transmettre à la zone parente les données à distribuer. C'est ce manque que comble notre tout nouveau RFC, avec l'introduction des enregistrements DNS de type CSYNC (Child SYNChronization).

Les deux types principaux d'enregistrement à copier de la zone fille vers la zone parente sont la liste des serveurs de noms de la zone (enregistrements NS) et les adresses IP de ces serveurs, si et seulement si leur nom est lui-même dans la zone servie, et qu'on ne peut donc pas compter sur la résolution DNS normale pour trouver les adresses. Ces adresses servies par la zone parente sont nommées colles (glue) et sont des enregistrements de type A et de type AAAA.

La résolution DNS dépend de cette information. En effet, le résolveur DNS part de la racine, et descend, de zone parente en zone fille, jusqu'à trouver l'information qu'il veut. S'il cherche www.hacklab-esgi.fr, il passera par les serveurs de la racine (qui connaissent la liste des serveurs de noms de .fr) puis par ceux de .fr (qui connaissent la liste des serveurs de hacklab-esgi.fr). Voici, reproduite avec dig, la requête qui sera envoyée à un serveur de .fr :


% dig +norecurse @d.nic.fr A www.hacklab-esgi.fr
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 30993
;; flags: qr; QUERY: 1, ANSWER: 0, AUTHORITY: 2, ADDITIONAL: 0

;; QUESTION SECTION:
;www.hacklab-esgi.fr.	IN A

;; AUTHORITY SECTION:
hacklab-esgi.fr.	172800 IN NS ns0.online.net.
hacklab-esgi.fr.	172800 IN NS ns1.online.net.

On y voit qu'une réponse correcte nécessite que les serveurs de l'AFNIC (ici d.nic.fr) connaissent les serveurs de hacklab-esgi.fr. Mais la liste de ces serveurs est également dans la zone :


% dig +norecurse @ns0.online.net. NS hacklab-esgi.fr 
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 59586
;; flags: qr aa; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;hacklab-esgi.fr.	IN NS

;; ANSWER SECTION:
hacklab-esgi.fr.	14400 IN NS ns0.online.net.
hacklab-esgi.fr.	14400 IN NS ns1.online.net.

Ce sont ces deux listes qui devraient idéalement rester synchrones. (On note au passage que la liste dans les serveurs de hacklab-esgi.fr fait autorité : on a le bit aaAuthoritative Answer - dans la réponse, alors que la copie dans les serveurs de .fr ne fait pas autorité.)

Le processus typique actuel d'avitaillement, c'est-à-dire d'enregistrement des informations nécessaires à la délégation, se fait de diverses manières. Rappelez-vous qu'il n'y avait pas de standard pour cela. Prenons deux cas dans le TLD imaginaire .example, Jeanne Michu qui gère sa zone jeanne.example sur ses propres serveurs de noms, et utilise la société Foo comme BE, et Paul Michu, moins geek, qui utilise la société Bar à la fois comme BE et comme hébergeur DNS, pour sa zone paul.example. Jeanne utilise emacs pour modifier le fichier de zone et y mettre :

jeanne.example.	IN	NS	ns1.jeanne.example.
        	IN	NS	ns2.hosted-by-a-friend.example.
ns1             IN      AAAA    2001:db8:f54::2:53

On note que Jeanne n'indique pas l'adresse IP de ns2.hosted-by-a-friend.example, qui est dans une autre zone. Elle recharge ensuite son serveur de noms pour prendre en compte les informations (nsd-control reconfig si elle utilise nsd4) et elle lance un programme qu'elle a écrit qui, utilisant l'API que le BE Foo met à la disposition de ses utilisateurs, envoie les données au BE qui les transmettra au registre, typiquement en EPP. Paul, lui, ne fait rien, il a enregistré le domaine auprès de la société Bar et celle-ci se charge de mettre l'information dans ses propres serveurs de noms, et de prévenir le registre (puisque cette société est BE). Le résultat sera le même pour les deux zones, une fois les serveurs de la zone parente mis à jour, tout sera synchrone. (Rappelez-vous que ce ne sont que deux exemples, il peut y avoir beaucoup d'autres configurations possibles.)

Là où il peut y avoir des problèmes, c'est si la communication se passe mal. Par exemple, si Jeanne se plante dans une manipulation compliquée, ou oublie. Elle modifie l'ensemble NS dans sa zone mais ne pense pas ensuite de signaler le changement au parent. Ou bien elle lance le programme qui va modifier les données chez le parent mais les informations sont rejetées par la zone parente, sauf que ce refus n'est pas transmis à la titulaire du nom de domaine. Il existe des tas de raisons qui peuvent entrainer une désynchronisation de la zone fille et de la parente. C'est ce genre de problème que veut traiter notre nouveau RFC.

La solution proposée est de créer un nouveau type d'enregistrement DNS, nommé CSYNC, que le gérant technique de la zone DNS fille mettra dans la zone, et qui indiquera quelles données de la zone doivent être recopiées dans la zone parente. Qui fera cette copie ? Ce rôle reviendra au parental agent (terme récent et pas encore traduit), qui peut être un BE (charge à lui de transmettre au registre, sans doute en EPP) ou directement le registre.

À première vue, on pourrait penser que cette technique conviendrait très bien également pour DNSSEC (et cela avait été sérieusement envisagé dans le groupe de travail), afin de permettre la synchronisation des enregistrements DS de la zone parente avec les clés (enregistrements DNSKEY) de la zone fille. Mais le cas de DNSSEC est différent (notamment parce que la zone parente fait autorité pour les DS, contrairement aux NS et colles). Un mécanisme différent est donc utilisé, normalisé dans le RFC 7344.

Un autre point que ne traite pas notre nouveau RFC est celui de la configuration initiale. La zone fille doit évidemment être sécurisée avec DNSSEC pour que la parente puisse être sûre d'avoir récupéré le bon CSYNC. La configuration initiale de DNSSEC, ainsi que celle du parental agent pour le commencement des opérations, ne font pas l'objet d'une standardisation. Les CSYNC permettent de maintenir la synchronisation, pas de la créer au début.

La section 2 de notre RFC décrit l'enregistrement CSYNC. Il est placé à l'apex (au sommet) de la zone fille. Il doit être unique. Son numéro, enregistré à l'IANA, est le 62. Ses données comportent trois champs :

  • Un numéro de série (identique à celui qu'on trouve dans le SOA de la zone),
  • Des options (décrites plus loin),
  • Une liste de types d'enregistrement à recopier dans la zone parente (en général, NS, A et AAAA). Elle est encodée selon le mécanisme un peu compliqué du RFC 4034, section 4.1.2.

Cette dernière liste est à respecter totalement ou pas du tout. Si elle compte un type que le parental agent ne connait pas, il ne doit faire aucun changement. D'une manière générale, les opérations liées à un CSYNC sont atomiques.

Voici un exemple d'enregistrement CSYNC, avec le format texte standard, pour la zone de Jeanne Michu :

jeanne.example. 3600 IN CSYNC 2015031401 1 NS AAAA

Il se lit ainsi :

  • Le numéro de série est 2015031401,
  • Les options se limitent à celle du premier bit, immediate,
  • Il faut recopier les enregistrements NS et AAAA (il n'y a pas de colle de type A dans la zone). Si vous voyez un TYPEnnn dans un enregistrement CSYNC, c'est que le type était inconnu de votre client DNS (RFC 3597, section 5).

Le numéro de série doit être une copie de celui du SOA de la zone fille, ou bien avoir une valeur supérieure (si on ne change pas les informations de délégation, on n'est pas obligé de mettre à jour le numéro de série dans le CSYNC). Voir le RFC 1982 pour une définition rigoureuse de « avoir une valeur supérieure ».

L'utilisation de ce numéro de série dépend des options (le deuxième champ). Ces options consistent en seize bits dont seulement deux sont définis aujourd'hui (tout cela est stocké dans un registre IANA, tout ajout nécessitant la rédaction d'une norme). Les deux options définies sont immediate et soaminimum.

La section 3 du RFC décrit les détails du traitement d'un enregistrement CSYNC par le parental agent. Cet agent ne doit agir automatiquement que si l'option immediate est mise (c'est le cas dans l'enregistrement d'exemple ci-dessus). Autrement, il doit attendre une validation, par exemple via une action dans une interface Web (« cette modification de vos serveurs de noms attend votre confirmation »). Quant à l'autre option normalisée, soaminimum, elle indique au parental agent qu'il ne doit copier les données indiquées que si le numéro de série de la zone (indiqué dans l'enregistrement SOA) est supérieur au numéro de série de l'enregistrement CSYNC. (Dans l'exemple plus haut, l'option soaminimum n'était pas activé et le numéro de série dans le CSYNC est donc ignoré.)

J'ai dit plus haut que la copie des données de la zone fille vers la parente devait être atomique (tout copier, ou ne rien changer). Cela ne concerne pas les TTL que la zone parente peut modifier lors de la copie.

D'autre part, la zone parente n'est pas obligée de copier les données quelles qu'elles soient. En effet, la zone parente a sa propre politique (des trucs du genre « deux serveurs de noms minimum » ou bien « je ne tiens compte de la colle que si elle concerne des serveurs qui sont dans la zone qu'ils servent », cf. section 4.3) et peut donc décider de ne pas utiliser les données fournies, rejetant ainsi la mise à jour demandée.

Voyons maintenant (en section 4) quelques problèmes concrets liés à l'utilisation de cette technique. Premier point à garder en tête, il n'y a aucun mécanisme pour remonter une erreur ou un refus (comme celui cité dans le paragraphe précédent) depuis la zone parente vers le gestionnaire de la zone fille. L'information doit donc passer par une autre voie (un message envoyé automatiquement, par exemple). Le gestionnaire de la zone fille ne doit donc pas tenir pour acquis que les données de la zone parente seront modifiées : il doit vérifier.

Le mécanisme des CSYNC nécessite une requête DNS depuis le parental agent. Si celui-ci a peu de zones à surveiller, il peut simplement faire de la scrutation répétée. Mais cela ne passe pas forcément à l'échelle. Les parental agents avec beaucoup de zones à surveiller préféreront peut-être attendre un signal explicite de la part du gérant de la zone (un bouton sur une interface Web du BE, par exemple et/ou une fonction dans l'API).

Pour faciliter la vie des gérants de zones DNS, il faudrait de toute façon que le parental agent documente ses capacités : s'il traite les CSYNC, quels types d'enregistrements accepte-t-il (à part les évidents NS, A et AAAA), le mécanisme de scrutation (à quel intervalle ?), la notification des erreurs...

Une fois que la zone parente a été modifiée, la zone fille peut-elle retirer le CSYNC ? Oui, le changement n'est fait qu'une fois, et la zone parente ne va pas l'annuler même si le CSYNC disparait après.

Le parental agent ne doit agir que si les données ont été validées par DNSSEC (section 5, sur la sécurité du mécanisme). Si votre zone n'est pas encore signée (n'avez-vous pas honte de ce retard ?), vous ne pourrez pas bénéficier des nouveaux services comme CSYNC.

Il n'y a pas encore de mise en œuvre de cette technique (mais Wireshark sait décoder ces paquets). Je serais curieux de voir une liste des parental agents potentiels qui la déploient mais, début 2015, c'est encore trop tôt.


Téléchargez le RFC 7477


L'article seul

« Come to the dark side » ou « L'informatique est-elle neutre ? »

Première rédaction de cet article le 13 mars 2015
Dernière mise à jour le 20 mars 2015


Hier, 12 mars 2015, à l'ESGI à Paris, j'ai participé au « Security Day » avec un exposé plutôt orienté éthique et philosophie sur le thème des responsabilités morales de l'informaticien.

Les supports de l'exposé :

Parmi les autres exposés de la journée, j'ai beaucoup apprécié celui d'Alexandra Toussaint et Sébastien Larinier sur la « déobfuscation » de code malveillant JavaScript. Très vivant, plein de techniques rigolotes, et se terminant sur un constat d'échec, ce qu'on ose rarement avouer dans les conférences.

Merci à l'ESGI, merci aux organisateurs, notamment Dylan Dubief, pour tout le travail et merci à Genma pour le soutien moral et la bière.

Je recommence, avec un format plus court, le 17 avril, à Lyon pour Mix-IT.


L'article seul

RFC 7488: PCP Server Selection

Date de publication du RFC : Mars 2015
Auteur(s) du RFC : M. Boucadair (France Telecom), R. Penno, D. Wing, P. Patil, T. Reddy (Cisco)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF pcp
Première rédaction de cet article le 13 mars 2015


Le protocole PCP décrit un mécanisme (ayant vocation à remplacer UPnP) pour configurer automatiquement son routeur/pare-feu, notamment pour autoriser les connexions entrantes. Que doit faire un client PCP s'il reçoit plusieurs adresses IP de serveurs PCP ?

Dans quels cas a-t-on plusieurs serveurs PCP (donc, a priori, plusieurs routeurs à sa disposition) ? Un exemple typique est le multi-homing, si une machine est connectée en filaire et en radio en même temps, par exemple (l'annexe A du RFC décrit en détail un cas de multi-homing). Le RFC 6887, qui normalise PCP, en parlait un peu (dans sa section 8.1, qui explique en outre comment on trouve le ou les serveurs PCP, par exemple en suivant le RFC 7291), mais ne normalisait que le cas à un seul serveur, reportant à plus tard le cas à plusieurs serveurs. C'est donc désormais fait, deux ans après. Que doit donc faire le client qui a à sa disposition les adresses de plusieurs serveurs PCP ? D'autant plus que ceux-ci n'ont pas forcément les mêmes capacités, et ne sont typiquement pas coordonnés entre eux. Notez que les règles données dans ce nouveau RFC exigent que le client puisse déterminer si deux adresses IP pointent vers le même serveur PCP ou bien deux serveurs différents.

La section 3 décrit le cas où il y a plusieurs adresses mais un seul serveur : le client doit alors choisir l'adresse IP source de sa requête PCP, en suivant les règles habituelles (section 4 du RFC 6724) et les contraintes spécifiques à PCP du RFC 6887. Un exemple de ces contraintes est que, si on veut configurer une connexion existante, il faut utiliser comme adresse IP source celle utilisée par ladite connexion. Une fois ce choix fait, le client crée une liste d'adresses IP possibles pour le serveur (section 6 du RFC 6724) et les essaie successivement (rappelez-vous que PCP fonctionne sur UDP). Une fois qu'on en a trouvé une qui marche, on la mémorise pour les futures requêtes.

Si les différentes adresses IP obtenues concernent plusieurs serveurs PCP, c'est plus compliqué (section 4). Il faut alors que le client mémorise plusieurs serveurs et, si nécessaire, les synchronise lui-même (rappelez-vous que les différents serveurs PCP ne se coordonnent pas entre eux). Par exemple, si on veut configurer le pare-feu, c'est de la responsabilité du client d'envoyer la même configuration à tous les serveurs PCP. En revanche, si on veut configurer le NAT, le client ne s'adresse typiquement qu'à un seul serveur PCP, celui correspondant à l'adresse IP externe qu'on veut utiliser. (Il faut donc que le client PCP, lorsqu'il reçoit l'information sur l'existence d'un serveur PCP, se souvienne de l'interface et des adresses IP correspondantes.)

La section 5 fournit plusieurs exemples concrets de ces procédures. Par contre, aucune idée de combien d'implémentations de PCP suivent ce RFC (on ne peut pas dire que PCP soit largement déployé...)


Téléchargez le RFC 7488


L'article seul

RFC 7479: Using ED25519 in SSHFP Resource Records

Date de publication du RFC : Mars 2015
Auteur(s) du RFC : S. Moonesamy
Pour information
Première rédaction de cet article le 12 mars 2015


L'algorithme de signature Ed25519 ayant été mis en œuvre dans OpenSSH, ce nouveau RFC permet d'utiliser cet algorithme dans les enregistrements DNS SSHFP (SSH fingerprint).

Ces enregistrements SSHFP, qui permettent de trouver la clé publique d'un serveur SSH dans le DNS, sont normalisés dans le RFC 4255. Les valeurs possibles sont stockées dans un registre IANA. Ce registre est donc mis à jour pour inclure Ed25519, la valeur étant 4 (RSA était 1 et DSA 2).

Voici un exemple d'un tel enregistrement, pour la clé publique 

ssh-ed25519 
    AAAAC3NzaC1lZDI1NTE5AAAAIGPKSUTyz1HwHReFVvD5obVsALAgJRNarH4TRpNePnAS

Le condensat a été fait en SHA-256 :

ssh.example.com. IN SSHFP 4 2 ( a87f1b687ac0e57d2a081a2f2826723
                                         34d90ed316d2b818ca9580ea384d924
                                         01 )

(L'exemple est tiré du RFC mais celui-ci contient une légère bogue, je vous laisse la trouver.)

Question mises en œuvre, Ed25519 est dans OpenSSH depuis la version 6.5. D'autres logiciels utilisent cet algorithme, comme TeraTerm. Wireshark sait désormais le décoder.


Téléchargez le RFC 7479


L'article seul

RFC 7475: Increasing the Number of Area Directors in an IETF Area

Date de publication du RFC : Mars 2015
Auteur(s) du RFC : S. Dawkins (Huawei)
Première rédaction de cet article le 11 mars 2015


Un court RFC bureaucratique pour faire passer de deux à « plus de deux » le nombre maximum de directeurs de chaque zone d'activité de l'IETF.

L'IETF a en effet ses activités divisées en plusieurs zones (areas), chacune sous la responsabilité de directeurs (Area Directors qui, ensemble, forment l'IESG). Le RFC 2026 fixait (section 14) ce nombre de directeurs à « un ou deux » (même chose en section 1 du RFC 2418). Aujourd'hui, c'est presque toujours deux, mais ce chiffre a varié dans le temps (voir le RFC 1396 pour un passé lointain). Ce nouveau RFC 7475 fait sauter cette limite. Cela ne devrait pas trop changer la taille de l'IESG, l'idée est que cette possibilité ne soit utilisée que rarement.

L'IESG a une grande latitude en ce qui concerne la répartition de l'IETF en zones : le nombre de zones ou leur ampleur n'est pas contrainte par aucun document. On pourrait donc imaginer moins de zones mais de plus grande ampleur, et deux directeurs risqueraient alors de ne pas suffire.

Donc, le texte des RFC 2026 et RFC 2418 est modifié pour remplacer « un ou deux [directeurs] » par « un ou plus ».


Téléchargez le RFC 7475


L'article seul

RFC 7459: Representation of Uncertainty and Confidence in PIDF-LO

Date de publication du RFC : Février 2015
Auteur(s) du RFC : M. Thomson (Mozilla), J. Winterbottom (Unaffiliated)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF geopriv
Première rédaction de cet article le 27 février 2015


Le format PIDF-LO (Presence Information Data Format - Location Object, RFC 4119) permet de représenter la position présente d'un objet mobile. Ce nouveau RFC est consacré à la représentation de l'incertitude sur la position de cet objet, et ajoute un moyen d'indiquer la confiance qu'on a sur la position de cet objet. Ce RFC fournit également des indications sur le comportement à avoir lorsqu'on reçoit de l'information imprécise ou incertaine.

Le cadre général sur le service de localisation est présenté dans le RFC 6280. Idéalement, la localisation de la cible (oui, le RFC utilise le terme de target, ce qui est un peu effrayant) est connue parfaitement. Dans la réalité, on n'a pas une précision infinie, et on a même des doutes sur l'exactitude de la localisation. Il faut donc pouvoir représenter ce manque de précision et ces doutes, à la fois par un vocabulaire commun et par un format standard (une extension du PIDF-LO, Presence Information Data Format - Location Object du RFC 4119). Notez que l'IETF, dans ses RFC, ne normalise pas comment on arrive à déterminer une localisation. Il existe de nombreuses méthodes (triangulation entre les relais de téléphonie mobile, déclaration par la cible elle-même, lorsqu'elle est munie d'un GPS ou équivalent, etc) mais l'IETF ne se préoccupe que du format et de la distribution de cette information, pas de comment elle a été obtenue.

D'abord, revenons sur la notion d'incertitude, si importante en métrologie. La section 2 de notre RFC donne la définition suivante : « l'incertitude exprime de manière quantitative ce que l'on sait à propos d'une grandeur mesurée ». Par exemple, on sait que les instruments de mesure ont une précision limitée et on intègre cette imprécision dans l'incertitude. Ou bien on sait que la grandeur varie très vite et cette variation devient une partie de l'incertitude. Techniquement, l'incertitude est en général représentée par une distribution de probabilité. Celle-ci peut être trop complexe pour être manipulée simplement donc on adopte en général un modèle simple : toute grandeur est accompagnée d'un intervalle et d'un degré de confiance. Par exemple, si je mesure une longueur, je vais l'indiquer « L = 1,00742 +/- 0,0043 m à 95 % de confiance » ce qui veut dire qu'il y a 95 chances sur 100 que L soit entre 1,00312 et 1,01172 mètres. (On note que, si la « vraie » mesure a une dimension - c'est un point, la mesure avec l'incertitude a deux ou trois dimensions, dessinant une région d'incertitude. Les formes de cette région peuvent être variées, cf. RFC 5491.) Si vous voulez en savoir plus sur l'incertitude, vous pouvez lire le « Guide to the expression of uncertainty in measurement (GUM) 98:1995 » de l'ISO ou la Technical Note 1297, « Guidelines for Evaluating and Expressing the Uncertainty of NIST Measurement Result » du NIST.

On a dit plus haut que l'incertitude pouvait être exprimée par une distribution de probabilité. Celle-ci est représentée par une fonction, la PDF (probability density function) qui indique la probabilité, en chaque point, que la « vraie » valeur figure en ce point. Deux PDF sont très répandues, la gaussienne, aussi appelée distribution normale, qui provient en général de la combinaison de beaucoup de petites erreurs aléatoires, et la PDF rectangulaire, qui représente en général une mesure avec une source d'erreurs principale. La PDF est centrée sur la moyenne des mesures, la PDF gaussienne est caractérisée par l'écart-type, la rectangulaire par sa largeur (le RFC utilise la demi-largeur).

L'ancien RFC 3693 utilisait également les termes de précision et de résolution, qui sont désormais abandonnés, l'expérience ayant montré que leur définition ne suffisait pas en pratique. Par contre, comme alternative aux termes quantitatifs comme les caractéristiques de la PDF, notre nouveau RFC 7459 utilise le concept qualitatif d'exactitude (accuracy). L'exactitude d'une mesure indique qualitativement le degré de proximité avec la réalité. On dira ainsi qu'une mesure est « plus exacte » qu'une autre.

Après ces considérations générales sur l'incertitude, les sections 3 et 4 du RFC décrivent précisement comment celle-ci est représentée dans le format PIDF-LO (format fondé sur XML). La section 3 précise le modèle utilisé : la cible qui nous intéresse est considérée comme un point. (Ce n'est pas vrai si la cible est de grande taille, par exemple un aéroport, ou si elle est quantique, mais le modèle adopté par l'IETF est délibérement simplifié.) Le format PIDF-LO du RFC 4119 permet de décrire les incertitudes, et d'indiquer la forme de la région d'incertitude, en utilisant les formes géométriques standard de la norme « GML 3.1.1 PIDF-LO Shape Application Schema for use by the Internet Engineering Task Force (IETF) - Candidate OpenGIS Implementation Specification 06-142r1 ». Par contre, le format PIDF-LO original ne permet pas d'indiquer la confiance, le RFC 5491 se contentant d'une valeur fixe de 95 %. À noter que l'absence d'incertitude dans le fichier PIDF-LO ne signifie pas que la mesure était parfaite : il se peut qu'on n'ait pas cherché à évaluer l'incertitude, ou bien qu'on la connaisse mais qu'on la cache délibérement, par exemple pour des raisons de protection de la vie privée. Notez enfin que le problème de l'incertitude existe aussi pour les localisations civiles (comme « 8, rue de la Pompe, 12345 Villeneuve ») du RFC 5139.

La section 4 de notre RFC étend l'élement <location-info> de PIDF-LO (format normalisé dans le RFC 4119) en ajoutant un élément <confidence>. La confiance est exprimée sous forme d'un pourcentage (comme le « 95 % » indiqué plus haut) ou de la valeur spéciale unknown. Les anciens logiciels ignoreront cet élément (qui n'existait pas au début de PIDF-LO) mais les nouveaux pourront s'en servir pour améliorer les traitements et les messages aux utilisateurs. Un attribut pdf indique l'apparence de la fonction PDF : inconnue, normale (gaussienne) ou rectangulaire. Voici un exemple :


<pidf:presence
         xmlns:pidf="urn:ietf:params:xml:ns:pidf"
         xmlns:con="urn:ietf:params:xml:ns:pidf:geopriv:conf"
         ... >
       <dm:device id="sg89ab">
         <pidf:status>
           <gp:geopriv>
             <gp:location-info>
               <gs:Circle srsName="urn:ogc:def:crs:EPSG::4326">
                 <gml:pos>42.5463 -73.2512</gml:pos>
                 <gs:radius uom="urn:ogc:def:uom:EPSG::9001">
                   850.24
                 </gs:radius>
               </gs:Circle>
<!-- NOUVEAU -->  <con:confidence pdf="normal">67</con:confidence>
             </gp:location-info>
           </gp:geopriv>
         </pidf:status>
       </dm:device>
</pidf:presence>

Le schéma XML complet de ces extensions à PIDF-LO figure dans la section 7. L'espace de noms nécessaire, urn:ietf:params:xml:ns:pidf:geopriv:conf est désormais enregistré à l'IANA.

Avoir l'information ne suffit pas. Il faudra l'utiliser et on peut se demander, par exemple (section 4.3 du RFC) comment présenter une confiance à l'utilisateur, de manière à la fois techniquement correcte et compréhensible pour le non-spécialiste. Par exemple, si la confiance est indiquée de manière trop subtile, avec une légère variation de couleur, l'utilisateur pourrait croire que deux positions sont équivalentes alors que l'une d'elles est plus exacte.

La section 5 du RFC se penche ensuite sur les calculs effectués à partir de localisations comportant une incertitude. Elle est bien plus riche en mathématiques et sa lecture est plutôt pour celles et ceux qui sont à l'aise avec les centroïdes, la forme de la Terre, le calcul matriciel, et la géométrie en général. Ces calculs sont d'autant plus complexes que les opérations sur des données comportant une incertitude ne sont pas intuitives. Par exemple, l'incertitude sur la différence entre deux positions est la somme des incertitudes, pas l'incertitude maximale, encore moins la différence des incertitudes comme un calcul naïf risquerait de le faire. Les fanas de maths peuvent aussi lire les annexes A et B, qui contiennent des formules utiles.

Un petit mot sur la sécurité, pour finir (section 9 du RFC). Indiquer l'incertitude peut donner des indications sur le mécanisme de localisation utilisé, ce qui peut être vu comme excessivement bavard. Ceci dit, la section 13.5 du RFC 6772 rappelle que les services de localisation distribuent de l'information et qu'il est très difficile de diminuer les fuites (sans rendre le service inutilisable).


Téléchargez le RFC 7459


L'article seul

RFC 7464: JavaScript Object Notation (JSON) Text Sequences

Date de publication du RFC : Février 2015
Auteur(s) du RFC : N. Williams (Cryptonector)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF json
Première rédaction de cet article le 26 février 2015


Un document JSON est normalement formé d'un texte JSON tel qu'un tableau ou un objet. Mais certains usages de JSON auraient besoin d'un autre genre de documents, une suite de textes JSON, séparés par un caractère de séparation bien défini. C'est ce que normalise ce RFC. Le nouveau type de document, application/json-seq, est formé d'une suite de textes JSON, séparés par les caractères ASCII U+001E, alias RS (record separator) et U+000A, alias LF (line feed).

JSON est normalisé dans le RFC 7159. Il est très utilisé dans un grand nombre de contextes. Du fait qu'un document JSON est un texte JSON (par exemple un objet ou un tableau), une grande partie des analyseurs JSON lisent tout et mettent tout en mémoire avant de le passer à l'application. Ce n'est pas bien adapté au cas où on écrit du JSON dans un journal, par exemple, et où on ne connait pas à l'avance la fin du document. Souvent, il n'y a pas à proprement parler de fin, et on ne peut donc pas utiliser un tableau car on ne saurait pas où mettre le ] final. Pire, imaginons une séquence d'un million d'entrées, chacune faisant un kilo-octet. Avec un analyseur ordinaire, cela ferait un giga-octet à mettre en mémoire, une quantité non triviale. Certes, il existe des analyseurs en flux (streaming), mais ils ne sont pas très répandus, et notre RFC les trouve difficiles d'utilisation.

D'où l'idée de ce RFC : une séquence de textes JSON, qui n'est pas elle-même un texte JSON, et qui peut être produite et consommée de manière incrémentale.

La définition rigoureuse figure en section 2. À noter que deux grammaires ABNF sont données, une pour les générateurs de séquences JSON et une pour les analyseurs. En application du principe de robustesse, la grammaire est plus tolérante pour les seconds : elle permet que les membres d'une séquence ne soient pas des textes JSON valides, afin que l'analyseur puisse continuer à traiter la séquence (cf. section 2.3). En revanche, le générateur doit produire une séquence composée uniquement de textes JSON valides. La grammaire stricte, pour les générateurs, est donc :


JSON-sequence = *(RS JSON-text LF)
     
RS = %x1E
LF = %x0A

JSON-text = <given by RFC7159, using UTF-8 encoding>

RS et LF sont définis dans le RFC 20. À noter que RS, caractère ASCII très peu utilisé, se nomme Record Separator en ASCII mais INFORMATION SEPARATOR TWO dans Unicode. Le choix de ce séparateur a suscité d'intenses débats dans le groupe de travail, avant que le consensus se fasse sur RS. En langue naturelle, cette grammaire se résume en « une séquence JSON est composée d'un nombre quelconque de textes JSON, chacun précédé d'un RS et suivi d'un LF ». Ils sont forcément encodés en UTF-8 (RFC 3629). Comme RS est un caractère de contrôle, il ne peut pas apparaitre directement dans un texte JSON (RFC 7159, section 7) et il n'y a donc pas de risque de collision avec un vrai RS. Je laisse mes lecteurs aventureux chercher comment on entre un caractère RS dans un fichier, avec leur éditeur favori...

Autre grammaire, plus laxiste, pour les analyseurs. Elle est :


JSON-sequence = *(1*RS possible-JSON)
...
possible-JSON = 1*(not-RS)
not-RS = %x00-1d / %x1f-ff; any octets other than RS

Elle est bien plus tolérante que la grammaire du générateur. L'idée est que, si l'analyse d'un texte « possiblement JSON » échoue, l'analyseur pourra sauter au suivant (éventuellement en signalant à l'application qu'il y a eu un problème) et traiter le reste de la séquence. Comme le décrit bien la section 2.3, une erreur n'est pas forcément fatale. Si l'analyseur était trop puriste, il ne pourrait pas traiter un journal où certaines entrées ont été tronquées (et ne sont donc plus des textes JSON valides) suite à, par exemple, un disque plein.

Ce principe de robustesse ne pose pas de problèmes si les textes JSON sont des tableaux ou des objets : une éventuelle troncation se détecte sans ambiguité. Ainsi, [116, 943, 234, 3879 a clairement été tronqué (il manque le crochet final). Il y a davantage de problèmes dans les cas où les textes JSON sont des entiers ou des littéraux comme true. Si on trouve 3879, était-ce bien 3879 ou bien la troncation d'un entier plus long ? C'est là que le LF (U+000A) à la fin de chaque texte JSON est utile, comme canari pour détecter une troncation. Un analyseur doit donc vérifier sa présence (le RFC est plus tolérant, en acceptant n'importe quel ws - RFC 7159, section 2) si le texte JSON n'était pas auto-délimité (les tableaux, objets et chaînes sont auto-délimités, mais pas les nombres ou certains littéraux comme null).

Au passage, un mot sur la sécurité (section 3) : les analyseurs de séquences JSON, comme tous les analyseurs de JSON, seront souvent utilisés sur des documents venus de l'extérieur, pas forcément validés. Ils doivent donc être robustes et ne pas faire de buffer overflow sous prétexte qu'ils rencontrent du JSON bizarre. Et, si vous voulez signer vos séquences JSON, n'oubliez pas que JSON n'a pas de forme canonique, et les séquences encore moins (comme l'analyseur est plus laxiste que le générateur, lire et écrire une séquence peut la changer, par exemple en ajoutant des LF à la fin des textes). Toute opération peut donc potentiellement invalider une signature.

Question mises en œuvre, il semble (je n'ai pas encore testé) que le couteau suisse de JSON, jq, gère ce nouveau format. (Si vous ne connaissez pas jq, je vous recommande cet article.)


Téléchargez le RFC 7464


L'article seul

Fiche de lecture : André Marie, sur les traces d'un homme d'État

Auteur(s) du livre: Christophe Bouillon, Mathieu Bidaux
Éditeur: Autrement
978-2-7467-4006-8
Publié en 2014
Première rédaction de cet article le 25 février 2015


De temps en temps, je lis des livres qui ne parlent pas d'informatique. Alors, pourquoi ne pas s'intéresser à la vie d'un homme politique des IIIe et IVe républiques ? Ce n'est pas qu'André Marie a fait des choses extraordinaires, que ce soit en bien ou en mal. Mais il est bien représentatif d'une époque désormais lointaine.

La première chose qui m'a frappé, dans la biographie, c'est qu'André Marie lui-même a laissé peu de traces de son enfance et sa jeunesse et a peu écrit sur le sujet. Les auteurs ont donc choisi de remplir ces chapitres avec des récits d'autres personnes, ayant vécu plus ou moins au même endroit et à la même époque, comme André Maurois. Même chose pour la participation de Marie comme combattant à la Première Guerre mondiale, vue à travers des textes militaires mais pas des récits de Marie.

Ensuite commence la carrière politique d'André Marie. Là, c'est mieux documenté. Mais comme André Marie n'a rien fait d'exceptionnel, c'est plutôt une peinture de la vie politique française de l'entre-deux-guerres qu'une biographie. Si la postérité a surtout gardé le souvenir d'une république de notables, aimant les banquets lourdement arrosés, les auteurs nous font aussi revivre la violence de la politique à l'époque, les meetings, même ceux des hommes politiques les plus modérés, systématiquement attaqués par des gens violents, les menaces d'enlèvement de sa fille par des fascistes lorsque Marie s'oppose aux émeutiers du 6 février. Bref, être un notable de province du Parti Radical n'était pas de tout repos.

À propos de facisme, si André Marie a été plutôt lucide face à la montée du nazisme, voyant le danger et la nécessité de le contrer, il ne faut pas croire que toute sa politique a été aussi clairvoyante. Il s'est par exemple opposé jusqu'au bout (et même après) à l'indépendance de l'Algérie.

Comme l'avait prévu Marie, une nouvelle guerre éclate. Il est mobilisé, et fait prisonnier. Il était député avant la guerre mais sa captivité l'empêche de participer au vote donnant le pouvoir aux collaborateurs. On ne saura donc pas ce qu'il aurait voté. Marie est libéré, participe à la Résistance, est fait prisonnier et termine la guerre à Buchenwald. À son retour, si sa santé est sérieusement compromise, sa carrière politique décolle, il devient ministre et même, pendant un temps très court, président du Conseil. Que fait-il ? Pas grand'chose, à part essayer de maintenir son gouvernement le plus longtemps possible. Redevenu simple ministre, il donne son nom à une loi de financement de l'enseignement privé par l'argent public.

Une seconde fois, il sera pressenti pour devenir président du conseil et les auteurs de sa biographie consacrent plusieurs pages à des négociations... qui ne déboucheront finalement sur rien. Beau résumé de la politique politicienne sous la 4e République : on écrit un chapitre sur un événement qui ne s'est finalement pas produit.

Comme beaucoup de chevaux de retour de la 3e et de la 4e, André Marie ne survivra pas politiquement à la 5e république et se contentera d'une activité de notable de province classique, caractérisée par une extrême longévité au même poste (maire de Barentin pendant vingt-neuf ans).

Bref, une vie bien remplie et un livre pas ennuyeux du tout mais pour quel bilan finalement ?

Voir aussi le site officiel du livre.


L'article seul

RFC 7398: A Reference Path and Measurement Points for Large-Scale Measurement of Broadband Performance

Date de publication du RFC : Février 2015
Auteur(s) du RFC : M. Bagnulo (UC3M), T. Burbridge (BT), S. Crawford (SamKnows), P. Eardley (BT), A. Morton (AT&T Labs)
Pour information
Réalisé dans le cadre du groupe de travail IETF ippm
Première rédaction de cet article le 19 février 2015


Ce nouveau RFC est situé à l'intersection du groupe de travail IETF ippm et du plus récent groupe lmap. Ce dernier travaille pour les Large-Scale Measurements of Broadband Performance, c'est-à-dire pour les mesures objectives des performances des différents FAI, telles qu'elles sont menées par des associations de consommateur, ou l'État, ou un régulateur (comme ce que fait l'ARCEP avec son Observatoire sur la qualité du service fixe d'accès à l'Internet). Ces mesures peuvent être faites à des fins de comparaison, mais aussi de diagnostic. La référence normalisée en matière de métrologie est évidemment composée des RFC du groupe ippm (hélas non cités dans le rapport ARCEP mentionné plus haut). Ces RFC définissent les métriques essentielles comme le temps d'acheminement d'un paquet (RFC 2679) ou comme la capacité (RFC 5136). Comme la valeur de ces métriques dépend du point où se fait la mesure, il fallait pouvoir exprimer cette information. C'est le but de ce RFC, exprimer rigoureusement la mesure a été faite.

Prenons l'exemple d'une sonde Atlas « pinguant » un amer situé sur un autre continent, par exemple une ancre Atlas. Le résultat peut être très différent selon que la sonde soit située chez M. Michu et connectée avec du WiFi, ou bien qu'elle soit dans un data center, toute proche d'un gros point d'échange. Comment exprimer cette information sur la localisation de la sonde ? La terminologie utilisée aujourd'hui est souvent floue. Par exemple, on va dire que la sonde est « située chez l'utilisateur ». Mais ce n'est pas assez précis. Est-elle directement sur la box ou bien derrière, connectée par un réseau WiFi bien surchargé ?

On définit donc un chemin de référence (reference path) qui est le chemin suivi par les paquets IP de la mesure. Sur ce chemin se trouvent des points de mesure (measurement points) où peuvent être installés les appareils de mesure. Ces termes viennent de la norme UIT Y.1541, de la section 5.1 du RFC 3432 et de la section 4 du RFC 5835.

Donc, d'abord (section 3 du RFC), la terminologie essentielle :

  • Le chemin de référence (reference path) est une suite d'équipements (routeurs, commutateurs, bornes WiFi...) et de liens qui sont traversés par les paquets.
  • Un abonné (subscriber) est la personne ou l'organisation qui a loué les services d'un prestataire, peut-être avec des restrictions sur ce qu'il peut faire (cf. la norme UIT Q.1741).
  • Un composant dédié (dedicated component) est une ressource (matérielle ou virtuelle) du chemin de référence qui est entièrement dédiée à un abonné. Un composant partagé est, lui, partagé entre les abonnés.
  • Une démarcation (service demarcation point) est la frontière où les responsabilités du prestataire s'arrêtent. Par exemple, dans le cas d'un accès ADSL typique, la démarcation est juste avant la box (côté utilisateur), le FAI n'étant pas responsable du réseau local à la maison. Pour un McDo avec WiFi, la démarcation est les murs du restaurant (les ondes peuvent sortir mais McDo ne s'engage nullement à ce que le WiFi fonctionne dehors).
  • Les segments du chemin de référence peuvent être gérés ou non-gérés (managed paths and unmanaged paths). Attention, le terme est très chargé, car souvent utilisé de manière propagandiste dans les discussions sur la neutralité du réseau. Ici, la définition se place du point de vue du prestataire, par exemple du FAI : est géré ce dont il est responsable, le reste étant considéré comme non-géré (il faudrait plutôt dire « géré par quelqu'un d'autre »).

La section 4 donne un exemple typique de chemin de référence : la machine de l'utilisateur, le réseau local privé de l'utilisateur, une démarcation avant d'arriver dans le réseau du FAI, l'interconnexion entre le FAI et son transitaire, éventuellement plusieurs transitaires, encore une interconnexion avec le FAI du destinataire, une nouvelle démarcation, qui mène au réseau local privé du destinataire, puis la machine de destination. Dommage que traceroute ne montre pas les chemins comme cela :-) Ces démarcations et interconnexions ne se voient en effet pas facilement dans les paquets IP et doivent donc être documentées explicitement lorsqu'on fait des mesures.

La section 5 est ensuite consacrée aux points de mesure. Chacun doit recevoir un numéro unique, pour permettre de décrire précisement la mesure, et le RFC propose un schéma de numérotation : mpXNN où X est le numéro du réseau (0 chez l'utilisateur, 9 chez le destinataire, et obligation de changer de numéro quand on change d'acteur) et NN une machine ou un lien sur le réseau, avec des numéros croissants quand on s'éloigne de l'utilisateur. Ainsi, on aura, par exemple mp000 pour la machine de départ chez l'utilisateur (la sonde Atlas dans mon exemple plus haut), mp120 pour une mesure faite sur le DSLAM du FAI, mp200 pour le premier routeur du transitaire, etc. À noter que les contraintes pratiques fait que les points de mesure ne sont pas forcément placés idéalement. Par exemple, on voudrait mesurer dans la box mais elle ne le permet pas et on place alors un point de mesure dans un appareil externe. Ce n'est pas idéal, par exemple du fait que la connexion entre la box et cet appareil peut introduire des problèmes.


Téléchargez le RFC 7398


L'article seul

RFC 7454: BGP operations and security

Date de publication du RFC : Février 2015
Auteur(s) du RFC : J. Durand (CISCO), I. Pepelnjak (NIL), G. Doering (SpaceNet)
Réalisé dans le cadre du groupe de travail IETF opsec
Première rédaction de cet article le 19 février 2015


Tout l'Internet repose sur le protocole BGP, qui permet l'échange de routes entre opérateurs Internet. (BGP est normalisé dans le RFC 4271.) La sécurité de BGP est donc cruciale pour l'Internet, et elle a fait l'objet de nombreux travaux. Ce nouveau RFC résume l'état actuel des bonnes pratiques en matière de sécurité BGP. Du classique, aucune révélation, juste la compilation de l'état de l'art. Ce RFC porte aussi bien sur la protection du routeur, que sur le filtrage de l'information (les routes) reçues et transmises.

Ce genre de compilation aurait plutôt due être faite dans le cadre du project BCOP mais celui-ci semble mort.

La section 2 de ce RFC rappelle qu'il n'a pas de caractère obligatoire : il expose des pratiques de sécurité générales, et il est toujours permis de faire des exceptions, en fonction des caractéristiques spécifiques du réseau qu'on gère.

Donc, au début (sections 4 et 5 du RFC), la protection de la discussion entre deux routeurs, deux pairs BGP qui communiquent (sécurité du canal). Ensuite (sections 6 à 11), la protection des informations de routage échangées, le contrôle de ce qui est distribué (sécurité des données).

Commençons par sécuriser le routeur (section 4). Il devrait idéalement être protégé par des ACL qui interdisent les connexions vers le port 179, celui de BGP, sauf depuis les pairs connus. Les protections de TCP ne suffisent pas forcément, la mise en œuvre de TCP dans les routeurs est parfois faite de telle façon qu'on peut planter le routeur juste en envoyant plein de demandes de connexion. Il faut donc les jeter avant même que TCP ne les voit. De telles ACL sont parfois mise en place automatiquement par le logiciel du routeur, mais dans d'autres cas elles doivent être installées manuellement.

Rappelez-vous qu'un router a à la fois des fonctions de contrôle (control plane, ce qui inclut BGP) et de transmission (data plane). Idéalement, les ACL pour protéger le contrôle devraient être spécifiques à cette fonction et ne pas affecter la transmission des paquets (mais le matériel et le logiciel ne permettent pas toujours cette séparation). Certains routeurs permettent également de mettre en place un limiteur de trafic, pour éviter du trafic excessif, même en provenance de pairs connus. Le RFC 6192 décrit avec plus de détails la protection des fonctions de contrôle d'un routeur.

Ensuite (section 5 du RFC), la protection des sessions BGP avec les pairs légitimes (cf. RFC 6952). Si les deux routeurs ne prennent aucune précaution, un attaquant pourrait, par exemple, couper leur session BGP en envoyant de faux paquets TCP de type RST (cf. RFC 5961). Pire, il pourrait, avec des techniques comme l'usurpation ARP, injecter de faux paquets dans une session BGP existante. Pour se protéger contre les attaques TCP, il faut utiliser une authentification TCP, comme la traditionnelle (et bien dépassée) TCP-MD5 du RFC 2385. Beaucoup d'opérateurs exigent une telle authentification lorsqu'on fait du BGP avec eux (particulièrement sur un point d'échange, où des inconnus peuvent facilement fabriquer de faux paquets). Mais on ne peut pas dire que 100 % des sessions BGP dans le monde sont protégées, en raison du surcoût d'administration qui en résulte (choisir les mots de passe, les distribuer, les changer, etc). En outre, MD5 étant désormais bien affaibli (RFC 6151), il faudrait désormais utiliser le mécanisme AO du RFC 5925. Le RFC note que, malgré le caractère antédiluvien de TCP-MD5, c'est toujours la solution la plus utilisée par les opérateurs. Mes lecteurs qui configurent tous les jours des appairages BGP connaissent-ils des gens qui utilisent AO ?

Une autre solution serait de se servir d'IPsec entre les routeurs mais personne ne le fait.

Autre précaution, filtrer les paquets IP en entrée du réseau de l'opérateur pour interdire les paquets prétendant avoir une adresse IP source située dans le réseau de l'opérateur. Sans cette précaution, même les sessions iBGP pourraient être attaquées.

Dernière protection des sessions BGP, GTSM (RFC 5082) qui consiste à tester que le TTL des paquets entrants est à la valeur maximale (255), et que le paquet vient donc bien du réseau local (s'il était passé par, ne serait-ce qu'un seul routeur, le TTL aurait été décrémenté).

Après avoir protégé les routeurs, et la session BGP sur TCP qui les relie, voyons les données. Sécuriser la session ne sert à rien si le pair légitime et authentifié nous envoie des informations fausses. La section 6 de notre RFC se consacre donc au filtrage des préfixes annoncés. D'abord, les préfixes non routables (ceux marqués Global: false dans le registre des adresses spéciales IPv4 ou son équivalent IPv6) devraient évidemment être rejetés. Mais il est également recommandé de ne pas accepter les préfixes non alloués (par le système d'allocation d'adresses IP IANA->RIR->LIR). Comme la liste de ces préfixes change tout le temps, les filtres doivent être mis à jour automatiquement, à partir de la liste à l'IANA. Comme il y a un délai entre l'allocation d'un préfixe à un RIR et son utilisation réelle sur ce terrain, il n'est pas nécessaire de tester tous les jours (le RFC recommande de tester au moins une fois par mois). Si, pour une raison ou pour une autre, on ne peut pas vérifier la liste en ligne, il vaut mieux ne pas filtrer les préfixes, plutôt que de le faire sur la base d'une liste dépassée : une des plaies de l'Internet est la nécessité de dé-bogoniser (faire retirer des listes de bogons ces listes d'adresses IP non allouées) tout nouveau préfixe, processus qui peut être lent et nécessite pas mal de tests sur les looking glasses. En IPv4, il ne reste plus de préfixes non alloués et ce test régulier n'est donc plus nécessaire.

Tester auprès de l'IANA ne permet que des filtres grossiers, éliminant les annonces de préfixes non alloués à un RIR, ce qui ne sert que pour IPv6, ne vérifie pas les préfixes plus spécifiques que ce que l'IANA alloue, et n'empêche pas un malveillant ou un maladroit d'annoncer les préfixes d'un autre AS. Il peut donc être intéressant de filtrer de manière plus précise, en regardant les IRR. Un IRR est une base de données publiquement accessible, stockant les préfixes et l'AS autorisé à les annoncer (en langage RPSL, cf. RFC 4012). Ces IRR sont gérés par certains opérateurs, ou par les RIR. Par exemple, la base de données du RIPE-NCC contient cette information :

route:          217.70.176.0/20
descr:          GANDI is an ICANN accredited registrar
descr:          for more information:
descr:          Web:   http://www.gandi.net
origin:         AS29169
mnt-by:         GANDI-NOC

On voit ici que seul l'AS 29169 (Gandi) est autorisé à annoncer le préfixe 217.70.176.0/20. En opérant récursivement (car un AS peut être un fournisseur d'un autre AS situé derrière lui et il faudra donc suivre les informations sur les AS relayés), on peut établir une liste de tous les préfixes qu'un pair peut annoncer, et ne pas accepter les autres. Des outils existent pour produire automatiquement des filtres sur le routeur à partir du RPSL (comme IRRToolSet). Malheureusement, aucun IRR n'est parfait (et certains sont vraiment imparfaits) : préfixes absents (surtout les plus spécifiques, en cas de dés-agrégation des annonces), information dépassée, etc. Les IRR des RIR sont proches des opérateurs et donc a priori ont une information fiable mais ce n'est que théorique (les préfixes IP « du marais », alloués avant l'existence des RIR, sont une source particulièrement importante de problèmes). En outre, l'IRR d'un RIR ne couvre que la région de ce RIR, et on peut donc avoir besoin d'en consulter plusieurs (on a un pair états-unien, on regarde la base de l'ARIN, mais ce pair a des clients sud-américains et on doit donc aussi regarder la base de LACNIC...), ce qui justifie les IRR privés, comme RADB, qui essaient de consolider l'information des RIR.

Si vous trouvez que cette imperfection des IRR est bien ennuyeuse, le RFC recommande que vous agissiez de votre côté : vérifiez que vos préfixes sont correctement publiés dans les IRR.

Actuellement, la sécurité des données BGP repose essentiellement sur ce filtrage à partir des IRR et sur la réactivité des administrateurs réseau. Dans le futur, il est possible qu'un système plus fiable soit adopté et déployé, le couple RPKI+ROA, alias SIDR pour Secure Inter-Domain Routing. SIDR repose sur une infrastructure de certification, la RPKI (RFC 6480), et sur des objets signés, les ROA (RFC 6482), annonçant quel AS peut annoncer tel préfixe. SIDR fournit deux services, dont seul le premier est un peu déployé aujourd'hui :

  • La validation de l'origine de l'annonce (le premier AS sur le chemin). Décrite dans le RFC 6811, elle est aujourd'hui disponible dans la plupart des routeurs, et des ROA sont effectivement publiés.
  • La validation du chemin d'AS complet. Surnommé « BGPsec » (RFC 7353 et RFC 7132), la normalisation technique de ce service est loin d'être complétée et il n'existe donc pas de mise en œuvre disponible.

Ces mécanismes SIDR devraient, une fois largement déployés, résoudre la plupart des problèmes décrits dans cette section 6 de notre RFC 7454. Mais cela prendra de nombreuses années et il est donc nécessaire de ne pas abandonner les méthodes actuelles comme les systèmes d'alarme.

Pour la validation de l'origine de l'annonce, notre RFC recommande que la politique de filtrage des annonces (qui est une décision locale de chaque routeur) suive les règles du RFC 7115. Pour les résumer, lorsqu'une annonce BGP est comparée au contenu de la RPKI :

  • S'il existe un ROA et que l'annonce est valide selon ce ROA, on accepte l'annonce,
  • S'il existe un ROA mais que l'annonce n'est pas valide, on rejette l'annonce (attention, rappelez-vous qu'au début de toute nouvelle technique de sécurité, il y a pas mal de faux positifs),
  • S'il n'existe pas de ROA, on accepte l'annonce, avec une préférence plus faible.

Le système RPKI+ROA pose de nouveaux et intéressants problèmes et il est donc recommandé de lire « On the Risk of Misbehaving RPKI Authorities » d'abord.

D'autres filtrages sont possibles en entrée. Par exemple, les opérateurs filtrent les annonces trop spécifiques, afin notamment d'éviter la croissance indéfinie de leurs bases de données et tables de routage. Chacun choisit les valeurs quantitatives précises et il n'y a pas de consensus documenté sur ce point (on peut consulter les documents RIPE-399 et RIPE-532) mais on peut observer qu'un préfixe plus long que /24 en IPv4 et /48 en IPv6 a très peu de chances d'être accepté dans l'Internet. Voici un exemple de filtrage IPv4 sur JunOS :

policy-statement no-small-and-big-prefixes {
        from {
            route-filter 0.0.0.0/0 prefix-length-range /25-/32 reject;
            route-filter 0.0.0.0/0 prefix-length-range /0-/7 reject;
        }
}
protocols {
            bgp {
               ...
               import no-small-and-big-prefixes;

Typiquement, on filtre aussi en entrée les annonces portant sur les préfixes internes. Normalement, ce n'est pas à nos voisins d'annoncer nos routes !

Autres préfixes souvent filtrés, les routes par défaut, 0.0.0.0/0 en IPv4 et ::0/0 en IPv6.

Naturellement, les recommandations de filtrage dépendent du type d'appairage BGP : on ne filtre pas pareil selon qu'on parle à un pair, à un client ou à un transitaire (voir la section 6 du RFC pour tous les détails). Ainsi, pour reprendre le paragraphe précédent, sur la route par défaut, certains clients d'un opérateur demandent à recevoir une telle route et c'est tout à fait acceptable.

La section 7 est consacrée à une pratique très utilisée et très discutée, l'amortissement (damping). Lorsqu'une route vers un préfixe IP donné passe son temps à être annoncée et retirée, on finit par l'ignorer, pour éviter que le routeur ne passe son temps à recalculer ses bases de données. Pour réaliser cela, à chaque changement d'une route, on lui inflige une pénalité, et au bout d'un certain nombre de pénalités, on retire la route. Malheureusement, cette technique mène parfois à supprimer des routes et à couper un accès (voir RIPE-378). Avec de meilleurs paramètres numériques, comme recommandé par le RFC 7196 et RIPE-580, l'amortissement redevient utilisable et recommandable.

Autre technique de filtrage des erreurs, décrite en section 8, l'imposition d'un nombre maximum de préfixes annoncés par un pair BGP. S'il en annonce davantage, on coupe la session BGP. Un dépassement du nombre maximal est en effet en général le résultat d'une fuite, où, suite à une erreur de configuration, le routeur ré-annonce des routes reçues d'un autre. Parfois, c'est toute la DFZ qui est ainsi annoncée par accident aux pairs ! Notre RFC demande donc instamment qu'on limite le nombre de préfixes accepté pour une session BGP. Pour un pair sur un point d'échange, le seuil devrait être inférieur au nombre de routes de la DFZ (dans les 530 000 en IPv4 aujourd'hui, et 21 000 en IPv6), pour détecter les annonces accidentelles de toute la DFZ. On peut aussi avoir des seuils par pair, fondés sur le nombre de routes qu'ils sont censés annoncer. Pour un transitaire, par contre, le seuil doit être plus élevé que le nombre de routes dans la DFZ, puisqu'on s'attend à tout recevoir d'eux (mais une valeur maximale est quand même utile en cas de désagrégation intensive). Comme l'Internet change tout le temps, il faut réviser ces limites, et suivre les alertes (sur certains routeurs, on peut configurer deux seuils, un pour déclencher une alerte, et un autre, supérieur, pour réellement couper la session). Voici un exemple sur JunOS :

group Route-Server-LINX-V4 {
    family inet {
        unicast {
            prefix-limit {
               maximum 100000;
            }
	}
}

Après le filtrage par préfixe, il peut aussi y avoir du filtrage par chemin d'AS (section 9 de notre RFC) et par routeur suivant (next hop, section 10). Voyons d'abord le filtrage par chemin d'AS. Par exemple, un client d'un opérateur ne devrait pas annoncer des routes avec n'importe quels AS mais seulement avec un chemin comportant uniquement son propre AS (et, si le client a lui-même des clients, avec l'AS de ces clients secondaires). Si l'opérateur n'arrive pas à avoir une liste complète des AS qui peuvent se retrouver dans les chemins de ses clients, au moins peut-il limiter la longueur de ces chemins, pour éviter la ré-annonce accidentelle de routes. D'autre part, on n'accepte pas, dans le cas normal, de routes où un AS privé (64512 à 65534 et 4200000000 à 4294967294, voir RFC 6996) apparait dans le chemin. Conséquence logique, on n'annonce pas à ses voisins de routes avec des chemins d'AS qui incluent un AS privé, sauf arrangement spécifique. Et le chemin d'AS dans une annonce BGP doit toujours commencer par l'AS du voisin (sauf si on parle à un serveur de routes). Enfin, un routeur BGP n'acceptera pas d'annonces où il voit son propre AS dans le chemin, et ce comportement par défaut ne devrait pas être débrayé.

Quant au filtrage sur le routeur suivant (section 10 du RFC), il consiste à refuser une route si l'attribut BGP NEXT_HOP (RFC 4271, section 5.1.3) n'est pas l'adresse du voisin. Attention, ce test doit être débrayé si on parle à un serveur de routes, celui-ci ne souhaitant pas traiter les paquets IP. Idem (débrayage du test) si on fait du RTBH (RFC 6666).

Pour finir, je recommande trois lectures,


Téléchargez le RFC 7454


L'article seul

Articles des différentes années : 2015  2014  2013  2012  2011  2010  2009  Précédentes années

Syndication : Flux Atom avec seulement les résumés et Flux Atom avec tout le contenu