Je suis Charlie

Autres trucs

Accueil

Seulement les RFC

Seulement les fiches de lecture

Mon livre « Cyberstructure »

Ève

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


RFC 7719: DNS Terminology

Date de publication du RFC : Décembre 2015
Auteur(s) du RFC : P. Hoffman (ICANN), A. Sullivan (Dyn), K. Fujiwara (JPRS)
Pour information
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 19 décembre 2015


Comme beaucoup de protocoles très utilisés sur l'Internet, le DNS est ancien. Très ancien (la première norme, le RFC 882, date de 1983). Les normes techniques vieillissent, avec l'expérience, on comprend mieux, on change les points de vue et donc, pour la plupart des protocoles, on se lance de temps en temps dans une révision de la norme. Mais le DNS est une exception : la norme actuelle reste fondée sur des textes de 1987, les RFC 1034 et RFC 1035. Ces documents ne sont plus à jour, modifiés qu'ils ont été par des dizaines d'autres RFC. Bref, aujourd'hui, pour comprendre le DNS, il faut s'apprêter à lire de nombreux documents. En attendant qu'un courageux et charismatique participant à l'IETF se lance dans la tâche herculéenne de faire un jeu de documents propre et à jour, ce nouveau RFC 7719 se limitait à une ambition plus modeste : fixer la terminologie du DNS. Depuis, il a été remplacé par un document plus récent, le RFC 8499.

En effet, chacun peut constater que les discussions portant sur le DNS sont difficiles : on manque de terminologie standard, et celle des RFC officielles ne suffit pas, loin de là. Souvent, le DNS a tellement changé que le RFC officiel est même trompeur : les mots ne veulent plus dire la même chose. D'autres protocoles ont connu des mises à jour de la norme. Cela a été le cas de SMTP, passé successivement du RFC 772 à l'actuel RFC 5321, en passant par plusieurs révisions successives. Ou de XMPP, qui a vu sa norme originale mise à jour dans le RFC 6120. Et bien sûr de HTTP, qui a connu récemment un toilettage complet. Mais personne n'a encore osé faire pareil pour le DNS. Au moins, ce nouveau RFC 7719 traite l'un des problèmes les plus criants, celui du vocabulaire. Le RFC est évidemment en anglais, les traductions proposées dans cet article, et qui n'ont pas de valeur « officielle » sont de moi seul.

Notre RFC 7719 rassemble donc des définitions pour des termes qui étaient parfois précisément définis dans d'autres RFC (et il fournit alors un lien vers ce RFC original), mais aussi qui n'étaient définis qu'approximativement ou parfois qui n'étaient pas définis du tout (et ce RFC fournit alors cette définition). Du fait du flou de certains RFC anciens, et des changements qui ont eu lieu depuis, certaines définitions sont différentes de l'original. Le document a fait l'objet d'un consensus relatif auprès des experts DNS mais quelques termes restent délicats. Notez aussi que d'autres organisations définissent des termes liés au DNS par exemple le W3C a sa propre définition de « domaine ».

Ironiquement, un des termes les plus difficiles à définir est « DNS » lui-même. D'accord, c'est le sigle de Domain Name System mais ça veut dire quoi ? « DNS » peut désigner le schéma de nommage (les noms de domaine comme signal.eu.org, leur syntaxe, leurs contraintes), la base de données répartie (et faiblement cohérente) qui associe à ces noms des informations (comme des certificats, des adresses IP, etc), ou le protocole requête/réponse (utilisant le port 53) qui permet d'interroger cette base. Parfois, « DNS » désigne uniquement le protocole, parfois, c'est une combinaison des trois éléments indiqués plus haut (personnellement, quand j'utilise « DNS », cela désigne uniquement le protocole).

Bon, et ces définitions rigoureuses et qui vont mettre fin aux discussions, ça vient ? Chaque section du RFC correspond à une catégorie particulière. D'abord, en section 2, les noms eux-même, ces fameux noms de domaine :

  • Nom de domaine (domain name) : on reprend la définition du RFC 1034, section 3.1, dans une structure arborescente, le nom est une suite de composants (labels), la racine de l'arbre étant à la fin. Aucune restriction n'est imposée dans ces composants (tant pis pour la légende comme quoi le DNS serait limité à ASCII). Comme on peut représenter les noms de domaine sous forme d'un arbre, ou bien sous forme texte (www.madmoizelle.com), le vocabulaire s'en ressent. Par exemple, on va dire que com est « au-dessus de madmoizelle.com » (vision arborescente) ou bien « à la fin de www.madmoizelle.com » (vision texte). Notez aussi que la représentation des noms de domaine dans les paquets IP n'a rien à voir avec leur représentation texte (par exemple, les points n'apparaissent pas).
  • FQDN (Fully Qualified Domain Name, nom de domaine complet) : apparu dans le RFC 819, ce terme désigne un nom de domaine où tous les composants sont cités (par exemple, ldap.potamochère.fr. est un FQDN alors que ldap tout court ne l'est pas). En toute rigueur, un FQDN devrait toujours s'écrire avec un point à la fin (pour représenter la racine) mais ce n'est pas toujours le cas.
  • Composant (label) : un nœud de l'arbre des noms de domaine, dans la chaîne qui compose un FQDN. Dans www.laquadrature.net, il y a trois composants, www, laquadrature et net.
  • Nom de machine (host name) : ce n'est pas la même chose qu'un nom de domaine. Utilisé dans de nombreux RFC (par exemple RFC 952) mais jamais défini, un nom de machine est un nom de domaine avec une syntaxe plus restrictive : uniquement des lettres, chiffres, points et le tiret. Ainsi, brienne.tarth.got.example peut être un nom de machine mais www.&#$%?.example ne peut pas l'être. Le terme de « nom de machine » est parfois aussi utilisé pour parler du premier composant d'un nom de domaine (brienne dans brienne.tarth.got.example).
  • TLD (Top Level Domain, domaine de premier niveau ou domaine de tête) : le dernier composant d'un nom de domaine, celui juste avant (ou juste en dessous) de la racine. Ainsi, fr ou name sont des TLD. N'utilisez surtout pas le terme erroné d'« extension ».
  • IDN (Internationalized Domain Name, nom de domaine internationalisé) : un nom de domaine en Unicode, normalisé dans le RFC 5890.
  • Sous-domaine (subdomain) : domaine situé sous un autre, dans l'arbre des noms de domaines. Sous forme texte, un domaine est sous-domaine d'un autre si cet autre est un suffixe. Ainsi, www.cl.cam.ac.uk est un sous-domaine de cl.cam.ac.uk, qui est un sous-domaine de cam.ac.uk et ainsi de suite, jusqu'à la racine, le seul domaine à n'être sous-domaine de personne.
  • Alias (alias) : attention, il y a un piège. Le DNS permet à un nom d'être un alias d'un autre, avec le type d'enregistrement CNAME (voir la définition suivante). L'alias est le terme de gauche de l'enregistrement CNAME. Ainsi, si on met dans un fichier de zone vader IN CNAME anakin, l'alias est vader (et c'est une erreur de dire que c'est « le CNAME »).
  • CNAME (Canonical Name, nom canonique, le « vrai » nom) : le membre droit dans l'enregistrement CNAME. Dans l'exemple de la définition précédente, anakin est le CNAME, le « nom canonique ».
  • Suffixe public (public suffix) : ce terme pas très officiel est parfois utilisé pour désigner un suffixe de noms de domaine qui est contrôlé par un registre public (au sens où il accepte des enregistrements du public). Le terme est ancien mais est apparu pour la première fois dans un RFC avec le RFC 6265, section 5.3. com, co.uk et eu.org sont des suffixes publics. Rien dans la syntaxe du nom n'indique qu'un nom de domaine est un suffixe public, puisque ce statut ne dépend que d'une politique d'enregistrement (qui peut changer).

Fini avec les noms, passons à l'en-tête des messages DNS et aux codes qu'il peut contenir. Cet en-tête est défini dans le RFC 1035, section 4.1. Il donne des noms aux champs mais pas forcément aux codes. Ainsi, le code de réponse 3 indiquant qu'un domaine demandé n'existe pas est juste décrit comme name error et n'a reçu son mnémonique de NXDOMAIN (No Such Domain) que plus tard. Notre RFC définit également :

  • NODATA : un mnémonique pour une réponse où le nom de domaine demandé existe bien mais ne contient aucun enregistrement du type souhaité. Le code de retour est 0, NOERROR, et le nombre de réponses (ANCOUNT pour Answer Count) est nul.
  • Réponse négative (negative answer) : le terme recouvre deux choses, une réponse disant que le nom de domaine demandé n'existe pas, ou bien une réponse indiquant que le serveur ne peut pas répondre (code de retour SERVFAIL ou REFUSED). Voir le RFC 2308.
  • Renvoi (referral) : le DNS étant décentralisé, il arrive qu'on pose une question à un serveur qui ne fait pas autorité pour le domaine demandé, mais qui sait vous renvoyer à un serveur plus proche. Ces renvois sont indiqués dans la section Authority d'une réponse.

Voici un renvoi depuis la racine vers .fr :


% dig @l.root-servers.net A blog.imirhil.fr 
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 16572
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 5, ADDITIONAL: 11
...
;; AUTHORITY SECTION:
fr.			172800 IN NS d.ext.nic.fr.
fr.			172800 IN NS d.nic.fr.
fr.			172800 IN NS e.ext.nic.fr.
fr.			172800 IN NS f.ext.nic.fr.
fr.			172800 IN NS g.ext.nic.fr.

    

Passons maintenant aux enregistrements DNS, stockés dans cette base de données répartie (section 4 du RFC) :

  • RR (Resource Record, un enregistrement DNS).
  • Ensemble d'enregistrements (RRset pour Resource Record set) : un ensemble d'enregistrements ayant le même nom (la même clé d'accès à la base), la même classe, le même type et le même TTL. Cette notion avait été introduite par le RFC 2181. Notez que la définition originale, reprise par notre RFC, parle malheureusement de label dans un sens incorrect. La terminologie du DNS est vraiment compliquée !
  • EDNS (Extension for DNS, également appelé EDNS0) : normalisé dans le RFC 6891, EDNS permet d'étendre l'en-tête du DNS, en spécifiant de nouvelles options, en faisant sauter l'antique limitation de taille de réponses à 512 octets, etc.
  • OPT (pour Option) : une astuce d'EDNS pour encoder les informations de l'en-tête étendu. C'est un enregistrement DNS un peu spécial, défini dans le RFC 6891, section 6.1.1.
  • Propriétaire (owner ou owner name) : le nom de domaine d'un enregistrement. Ce terme est très rarement utilisé, même par les experts.
  • Champs du SOA (SOA field names) : ces noms des enregistrements SOA (comme MNAME ou RNAME) sont peu connus et peu utilisés (RFC 1035, section 3.3.13). Notez que la sémantique du champ MINIMUM a complètement changé avec le RFC 2308.
  • TTL (Time To Live) : la durée de vie maximale d'un enregistrement dans les caches des résolveurs. C'est un entier non signé (même si le RFC 1035 dit le contraire), en secondes.

Voici un ensemble d'enregistrements (RRset), comptant ici deux enregistrements :


rue89.com.		600 IN MX 50 mx2.typhon.net.
rue89.com.		600 IN MX 10 mx1.typhon.net.	       
	       
    

Et voici un pseudo-enregistrement OPT, tel qu'affiché par dig, avec une indication de la taille maximale et l'option client subnet (RFC pas encore publié) :

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 512
; CLIENT-SUBNET: 13.176.144.0/24/0
    

Ensuite, un sujet chaud où le vocabulaire est particulièrement peu défini, et très mal utilisé (voir les forums grand public sur le DNS où les discussions prennent un temps fou car les gens utilisent mal les mots) : les différents types de serveurs et clients DNS (section 5) :

  • Résolveur (resolver) : un client DNS qui va produire une réponse finale (pas juste un renvoi, pas juste une information ponctuelle comme le fait dig). Il existe plusieurs types de résolveurs (voir ci-dessous) et, en pratique, quand on dit « résolveur » tout court, c'est en général un « résolveur complet ».
  • Résolveur minimum (stub resolver) : un résolveur qui ne sait pas suivre les renvois et qui dépend donc d'un ou de plusieurs résolveurs complets pour faire son travail. Ce type est défini dans la section 6.1.3.1 du RFC 1123. C'est ce résolveur minimum qu'appelent les applications lorsqu'elles font un getaddrinfo() ou getnameinfo(). Sur Unix, le résolveur minimum fait en général partie de la libc et trouve l'adresse du ou des résolveurs complets dans /etc/resolv.conf.
  • Résolveur complet (full resolver) : un résolveur qui sait suivre les renvois et donc fournir un service de résolution complet. Des logiciels comme Unbound ou PowerDNS Resolver assurent cette fonction. Le résolveur complet est en général situé chez le FAI ou dans le réseau local de l'organisation où on travaille, mais il peut aussi être sur la machine locale. On le nomme aussi « résolveur récursif ».
  • Serveur faisant autorité (authoritative server et traduire ce terme par « serveur autoritaire » montre une grande ignorance de l'anglais, un adjudant est autoritaire, un serveur DNS fait autorité) : un serveur DNS qui connait une partie des données du DNS (il « fait autorité » pour une ou plusieurs zones) et peut donc y répondre (RFC 2182, section 2). Ainsi, au moment de l'écriture de cet article, f.root-servers.net fait autorité pour la racine, d.nic.fr fait autorité pour pm, etc. Des logiciels comme NSD ou Knot assurent cette fonction. Les serveurs faisant autorité sont gérés par divers acteurs, les registres, les hébergeurs DNS (qui sont souvent en même temps bureaux d'enregistrement), mais aussi par M. Michu. La commande dig NS $ZONE vous donnera la liste des serveurs faisant autorité pour la zone $ZONE.
  • Serveur mixte : ce terme n'est pas dans ce RFC. Autrefois, il était courant que des serveurs DNS fassent à la fois résolveur et serveur faisant autorité. Cette pratique est fortement déconseillée depuis de nombreuses années (entre autres parce qu'elle complique sérieusement le débogage, mais aussi pour des raisons de sécurité parce qu'elle mène à du code plus complexe) et n'est donc pas dans ce RFC.
  • Initialisation (priming) : le processus par lequel un résolveur complet vérifie l'information sur les serveurs de la racine. Au démarrage, le résolveur ne sait rien. Pour pouvoir commencer la résolution de noms, il doit demander aux serveurs de la racine. Il a donc dans sa configuration leur liste. Mais ces configurations ne sont pas forcément mises à jour souvent. La liste peut donc être trop vieille. La première chose que fait un résolveur est donc d'envoyer une requête « NS . » à un des serveurs de sa liste. Ainsi, tant qu'un moins un des serveurs de la vieille liste répond, le résolveur est sûr d'apprendre la liste actuelle.
  • Mémorisation des négations (negative caching, ou « cache négatif ») : mémoriser le fait qu'il n'y a pas eu de réponse, ou bien une réponse disant qu'un nom de domaine n'existe pas.
  • Serveur primaire (primary server mais on dit aussi master server) : un serveur faisant autorité qui a accès à la source des données (fichier de zone, base de données, etc). Attention, il peut y avoir plusieurs serveurs primaires (autrefois, ce n'était pas clair et beaucoup de gens croient qu'il y a un serveur primaire, et qu'il est indiqué dans l'enregistrement SOA). Attention bis, le terme ne s'applique qu'à des serveurs faisant autorité, l'utiliser pour les résolveurs (« on met en premier dans /etc/resolv.conf le serveur primaire ») n'a pas de sens.
  • Serveur secondaire (secondary server mais on dit aussi « serveur esclave », slave server) : un serveur faisant autorité qui n'est pas la source des données, qui les a prises d'un serveur primaire (dit aussi serveur maître), via un transfert de zone (RFC 5936).
  • Serveur furtif (stealth server) : un serveur faisant autorité mais qui n'apparait pas dans l'ensemble des enregistrements NS. (Définition du RFC 1996, section 2.1.)
  • Maître caché (hidden master) : un serveur primaire qui n'est pas annoncé publiquement (et n'est donc accessible qu'aux secondaires). C'est notamment utile avec DNSSEC : s'il signe, et donc a une copie de la clé privée, il vaut mieux qu'il ne soit pas accessible de tout l'Internet (RFC 6781, section 3.4.3).
  • Transmission (forwarding) : le fait, pour un résolveur, de faire suivre les requêtes à un autre résolveur (probablement mieux connecté et ayant un cache partagé plus grand). On distingue parfois (mais ce n'est pas forcément clair, même dans le RFC 5625) la transmission, où on émet une nouvelle requête, du simple relayage de requêtes sans modification.
  • Transmetteur (forwarder) : le terme est confus (et a suscité plein de débats dans le groupe de travail DNSOP lors de la mise au point de ce RFC). Il désigne parfois la machine qui transmet une requête et parfois celle vers laquelle on transmet (c'est dans ce sens qu'il est utilisé dans la configuration de BIND, avec la directive forwarders).
  • Résolveur politique (policy-implementing resolver) : un résolveur qui modifie les réponses reçues, selon sa politique. On dit aussi, moins diplomatiquement, un « résolveur menteur ». C'est ce que permet, par exemple, le système RPZ. Sur l'utilisation de ces « résolveurs politiques » pour mettre en œuvre la censure, voir entre autres mon article aux RIPE Labs. Notez que le résolveur politique a pu être choisi librement par l'utilisateur (par exemple comme élément d'une solution de blocage des publicités) ou bien qu'il lui a été imposé.
  • Résolveur ouvert (open resolver) : un résolveur qui accepte des requêtes DNS depuis tout l'Internet. C'est une mauvaise pratique (cf. RFC 5358) et la plupart de ces résolveurs ouverts sont des erreurs de configuration. Quand ils sont délibérement ouverts, comme Google Public DNS, on parle plutôt de résolveurs publics.
  • Collecte DNS passive (passive DNS) : désigne les systèmes qui écoutent le trafic DNS, et stockent tout ou partie des messages DNS échangés. Le cas le plus courant est celui où le système de collecte ne garde que les réponses (ignorant donc les adresses IP des clients et serveurs), afin de constituer une base historique du contenu du DNS (c'est ce que font DNSDB ou le système de PassiveDNS.cn).
  • Anycast : le fait d'avoir un service en plusieurs sites physiques, chacun annonçant la même adresse IP de service (RFC 4786). Cela résiste mieux à la charge, et permet davantage de résilience en cas d'attaque par déni de service. Les serveurs de la racine, ceux des « grands » TLD, et ceux des importants hébergeurs DNS sont ainsi « anycastés ».

Voici, vu par tcpdump, un exemple d'initialisation d'un résolveur BIND utilisant la racineYeti :

15:07:36.736031 IP6 2a01:e35:8bd9:8bb0:21e:8cff:fe76:29b6.35721 > 2001:6d0:6d06::53.53: \
       21476% [1au] NS? . (28)
15:07:36.801982 IP6 2001:6d0:6d06::53.53 > 2a01:e35:8bd9:8bb0:21e:8cff:fe76:29b6.35721: \
       21476*- 16/0/1 NS yeti-ns.tisf.net., NS yeti-ns.lab.nic.cl., NS yeti-ns.wide.ad.jp., NS yeti.ipv6.ernet.in., NS yeti-ns.as59715.net., NS ns-yeti.bondis.org., NS yeti-dns01.dnsworkshop.org., NS dahu2.yeti.eu.org., NS dahu1.yeti.eu.org., NS yeti-ns.switch.ch., NS bii.dns-lab.net., NS yeti.bofh.priv.at., NS yeti-ns.conit.co., NS yeti.aquaray.com., NS yeti-ns.ix.ru., RRSIG (619)
    

La question était « NS . » (quels sont les serveurs de la racine) et la réponse contenait les noms des seize serveurs racine.

Voici aussi des exemples de résultats avec un résolveur ou bien avec un serveur faisant autorité. Si je demande à un serveur faisant autorité (ici, un serveur racine), avec mon client DNS qui, par défaut, demande un service récursif (flag RD, Recursion Desired) :


% dig @2001:620:0:ff::29 AAAA www.iab.org 
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 54197
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 9, ADDITIONAL: 13
;; WARNING: recursion requested but not available
...
;; AUTHORITY SECTION:
org.			172800 IN NS b0.org.afilias-nst.org.	       
...
	       
    

C'est pour cela que dig affiche WARNING: recursion requested but not available. Notez aussi que le serveur, ne faisant autorité que pour la racine, n'a pas donné la réponse mais juste un renvoi aux serveurs d'Afilias. Maintenant, interrogeons un serveur récursif (le service de résolveur public Yandex DNS) :


% dig @2a02:6b8::feed:0ff AAAA www.iab.org           
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 63304
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
...
;; ANSWER SECTION:
www.iab.org.		1800 IN	AAAA 2001:1900:3001:11::2c
	       
    

Cette fois, j'ai obtenu une réponse, et avec le flag RA, Recursion Available. Si je pose une question sans le flag RD (Recursion Desired, avec l'option +norecurse de dig) :


% dig +norecurse @2a02:6b8::feed:0ff AAAA www.gq.com  
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 59438
;; flags: qr ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
...
;; ANSWER SECTION:
www.gq.com.		293 IN CNAME condenast.map.fastly.net.
	       
    

J'ai obtenu ici une réponse car l'information était déjà dans le cache (la mémoire) de Yandex DNS (on le voit au TTL, qui n'est pas un chiffre rond, il a été décrémenté du temps passé dans le cache). Si l'information n'est pas dans le cache :

    
% dig +norecurse @2a02:6b8::feed:0ff AAAA blog.keltia.net
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 19893
;; flags: qr ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0
...
	       
    

Je n'obtiens alors pas de réponse (ANSWER: 0). Si je demande au serveur faisant autorité pour cette zone :


% dig +norecurse @2a01:e0d:1:3:58bf:fa61:0:1 AAAA blog.keltia.net  
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 62908
;; flags: qr aa; QUERY: 1, ANSWER: 2, AUTHORITY: 6, ADDITIONAL: 15
...
;; ANSWER SECTION:
blog.keltia.net.	86400 IN AAAA 2a01:240:fe5c:1::2
...
	       
    

J'ai évidemment une réponse et, comme il s'agit d'un serveur faisant autorité, elle porte le flag AA (Authoritative Answer, qu'un résolveur ne mettrait pas). Notez aussi le TTL qui est un chiffre rond (et qui ne change pas si on rejoue la commande).

Passons maintenant à un concept relativement peu connu, celui de zones, et le vocabulaire associé :

  • Zone : un groupe de domaines contigus et gérés ensemble, par le même ensemble de serveurs de noms (ma définition, celle du RFC étant très abstraite). Beaucoup de gens croient que tout domaine est une zone, mais c'est faux. Ainsi, au moment de la publication de ce RFC, gouv.fr n'est pas une zone séparée, il est dans la même zone que fr (cela se teste facilement : gouv.fr n'a pas d'enregistrement NS ou de SOA).
  • Parent : le domaine « du dessus ». Ainsi, le parent de wikipedia.org est org.
  • Apex : le sommet d'une zone, là où on trouve les enregistrements NS et SOA. Si la zone ne comprend qu'un domaine, l'apex est ce domaine. Si la zone est plus complexe, l'apex est le domaine le plus court.
  • Coupure de zone (zone cut) : l'endoit où on passe d'une zone à l'autre. Au-dessus de la coupure, la zone parente, en dessous, la zone fille.
  • Délégation (delegation) : un concept évidemment central dans le DNS, qui est un système décentralisé. En ajoutant un ensemble d'enregistrements NS pointant vers les serveurs de la zone fille, une zone parente délègue une partie de l'arbre des noms de domaine à une aure entité. L'endroit où se fait la délégation est donc une coupure de zone.
  • Colle (glue records) : lorsqu'une zone est déléguée à des serveurs dont le nom est dans la zone fille, la résolution DNS se heurte à un problème d'œuf et de poule. Pour trouver l'adresse de ns1.mazone.example, le résolveur doit passer par les serveurs de mazone.example, qui est déléguée à ns1.mazone.example et ainsi de suite... On rompt ce cercle vicieux en ajoutant, dans la zone parente, des données qui ne font pas autorité sur les adresses de ces serveurs (RFC 1034, section 4.2.1). Il faut donc bien veiller à les garder synchrones avec la zone fille. (Tanguy Ortolo me suggère d'utiliser « enregistrement de raccord » plutôt que « colle ». Cela décrit bien leur rôle, en effet.)
  • Dans le bailliage (in bailiwick) : terme absent des textes DNS originaux et qui peut désigner plusieurs choses. Il est (très rarement, selon mon expérience) parfois utilisé pour parler d'un serveur de noms dont le nom est dans la zone servie (et qui nécessite donc de la colle, voir la définition précédente), mais le sens le plus courant désigne des données pour lesquelles le serveur qui a répondu fait autorité, soit pour la zone, soit pour un ancêtre de cette zone. L'idée est qu'il est normal dans la réponse d'un serveur de trouver des données situées dans le bailliage et, par contre, que les données hors-bailliages sont suspectes (elles peuvent être là suite à une tentative d'empoisonnement DNS). Un résolveur DNS prudent ignorera donc les données hors-bailliage.
  • ENT (Empty Non-Terminal pour nœud non-feuille mais vide) : un domaine qui n'a pas d'enregistrements mais a des sous-domaines. C'est fréquent, par exemple, sous ip6.arpa ou sous les domaines très longs de certains CDN.
  • Zone de délégation (delegation-centric zone) : zone composée essentiellement de délégations vers d'autres zones. C'est typiquement le cas des TLD et autres suffixes publics.
  • Joker (wildcard) : une source de confusion considérable depuis les débuts du DNS. Si on pouvait refaire le DNS en partant de zéro, ces jokers seraient la première chose à supprimer. Pour les résumer, le nom * dans une zone déclenche la synthèse automatique de réponses pour les noms qui n'existent pas dans la zone. Si la zone foo.example contient bar.foo.example et *.foo.example, une requête pour thing.foo.example renverra le contenu de l'enregistrement avec le joker, une requête pour bar.foo.example donnera les données de bar.foo.example.
  • Changement rapide (fast flux) : une technique notamment utilisée par les botnets pour mettre leur centre de commande à l'abri des filtrages ou destructions. Elle consiste à avoir des enregistrements d'adresses IP avec des TTL très courts et à en changer fréquemment.

Voyons ici la colle retournée par un serveur faisant autorité (en l'occurrence un serveur de .net) :


% dig @a.gtld-servers.net AAAA labs.ripe.net 
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 18272
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 8, ADDITIONAL: 9
...
;; AUTHORITY SECTION:
ripe.net.		172800 IN NS ns3.nic.fr.
ripe.net.		172800 IN NS sec1.apnic.net.
ripe.net.		172800 IN NS sec3.apnic.net.
ripe.net.		172800 IN NS tinnie.arin.net.
ripe.net.		172800 IN NS sns-pb.isc.org.
ripe.net.		172800 IN NS pri.authdns.ripe.net.
...
;; ADDITIONAL SECTION:
sec1.apnic.net.		172800 IN AAAA 2001:dc0:2001:a:4608::59
sec1.apnic.net.		172800 IN A 202.12.29.59
sec3.apnic.net.		172800 IN AAAA 2001:dc0:1:0:4777::140
sec3.apnic.net.		172800 IN A 202.12.28.140
tinnie.arin.net.	172800 IN A 199.212.0.53
tinnie.arin.net.	172800 IN AAAA 2001:500:13::c7d4:35
pri.authdns.ripe.net.	172800 IN A 193.0.9.5
pri.authdns.ripe.net.	172800 IN AAAA 2001:67c:e0::5
	     
    

On notera :

  • La section ANSWER est vide, c'est un renvoi.
  • Le serveur indique la colle pour pri.authdns.ripe.net : ce serveur étant dans la zone qu'il sert, sans son adresse IP, on ne pourrait jamais le joindre.
  • Le serveur envoie également les adresses IP d'autres machines comme sec1.apnic.net. Ce n'est pas strictement indispensable (on pourrait l'obtenir par une nouvelle requête), juste une optimisation.
  • Les adresses de ns3.nic.fr et sns-pb.isc.org ne sont pas renvoyées. Le serveur ne les connait probablement pas et, de toute façon, elles seraient hors-bailliage.

Voyons maintenant, un ENT, gouv.fr :

   
% dig @d.nic.fr ANY gouv.fr 
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 42219
;; flags: qr aa rd; QUERY: 1, ANSWER: 0, AUTHORITY: 2, ADDITIONAL: 1

    

Le serveur fait bien autorité pour ce domaine (flag AA dans la réponse), le domaine existe (autrement, le status aurait été NXDOMAIN, pas NOERROR) mais il n'y a aucun enregistrement (ANSWER: 0).

Allez courage, ne faiblissons pas, il reste encore la question de l'enregistrement des noms de domaine (section 7) :

  • Registre (registry) : l'organisation ou la personne qui gère les délégations d'une zone. Le terme est parfois employé uniquement pour les gérants de grandes zones de délégation, mais ce n'est pas obligatoire. Je suis à moi tout seul le registre de bortzmeyer.org :-) C'est le registre qui décide de la politique d'enregistrement, qui peut être très variable selon les zones (sauf dans celles contrôlées par l'ICANN, où une certaine uniformité est imposée). Mes lecteurs français noteront que, comme le terme « registre » est court et largement utilisé, le gouvernement a inventé un nouveau mot, plus long et jamais vu auparavant, « office d'enregistrement ».
  • Titulaire (registrant, parfois holder) : la personne ou l'organisation qui a enregistré un nom de domaine.
  • Bureau d'enregistrement (registrar) : dans le modèle RRR (Registry-Registrar-Registrant, mais ce modèle n'est pas obligatoire et pas universel), c'est un intermédiaire entre le titulaire et le registre.
  • Hébergeur DNS (DNS operator) : la personne ou l'organisation qui gère les serveurs DNS. Cela peut être le titulaire, son bureau d'enregistrement, ou encore un acteur spécialisé dans cette gestion.
  • EPP (Extensible Provisioning Protocol) : normalisé dans le RFC 5730, c'est le protocole standard entre bureau d'enregistrement et registre. Ce protocole n'a pas de lien avec le DNS, et tous les registres ne l'utilisent pas.
  • Whois (nommé d'après la question Who Is?) : un protocole réseau, sans lien avec le DNS, normalisé dans le RFC 3912. Il permet d'interroger les bases de données du registre pour trouver les informations qui ne sont pas dans le DNS (comme le nom du titulaire, et des moyens de le contacter). Les termes de « base Whois » ou de « données Whois » sont parfois utilisés mais ils sont erronés puisque les mêmes bases peuvent être interrogées par d'autres protocoles que Whois, comme RDAP (voir définition suivante).
  • RDAP (Registration Data Access Protocol) : un protocole concurrent de Whois, mais plus moderne.

Enfin, pour terminer, la section 8 de notre RFC couvre DNSSEC. Pas grand'chose de nouveau ici, DNSSEC étant plus récent et donc mieux défini.

Je rappelle que ce RFC n'est plus le document final, ce rôle est désormais tenu par son successeur, le RFC 8499.


Téléchargez le RFC 7719


L'article seul

RFC 7700: Preparation, Enforcement, and Comparison of Internationalized Strings Representing Nicknames

Date de publication du RFC : Décembre 2015
Auteur(s) du RFC : P. Saint-Andre (&yet)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF precis
Première rédaction de cet article le 15 décembre 2015


Bien des protocoles Internet manipulent des noms qui doivent être parlants pour les utilisateurs et donc, de nos jours, doivent pouvoir être en Unicode. Les noms purement ASCII appartiennent à un passé révolu. Le groupe de travail PRECIS de l'IETF établit des règles pour ces noms, de manière à éviter que chaque protocole, chaque application, ne soit obligé de définir ses propres règles. Ce nouveau RFC contient les règles pour un sous-ensemble de ces noms : les noms qui visent plutôt à communiquer avec un utilisateur humain (par opposition aux noms qui sont indispensables aux protocoles réseaux, traités dans le RFC 7613). Ce RFC a été depuis remplacé par le RFC 8266.

Ces noms « humains » sont typiquement ceux qui sont présentés aux utilisateurs. Ils doivent donc avant tout être « parlants » et il faut donc qu'ils puissent utiliser la plus grande part du jeu de caractères Unicode, sans restrictions arbitraires (contrairement aux identificateurs formels du RFC 7613, pour lesquels on accepte des limites du genre « pas d'espaces »).

Le terme utilisé par le RFC pour ces noms « humains » est nicknames, terme qui vient du monde de la messagerie instantanée. Il n'y a pas de terme standard pour les désigner, certains protocoles (comme le courrier) parlent de display names (par opposition au login name ou account name), d'autres utilisent encore d'autres termes (l'article « An Introduction to Petname Systems » peut vous intéresser). Par exemple, dans un message électronique, on pourrait voir :

From: Valérie Pécresse <vp@les-républicains.fr>
    

Et, dans cet exemple, vp serait le nom formel (mailbox name dans le courrier, login name pour se connecter), alors que Valérie Pécresse est le nickname, le nom montrable aux humains. (Le concept de display name dans le courrier est normalisé dans la section 3.4.1 du RFC 5322, son exact équivalent XMPP, le nickname, est dans XEP-0172.)

Comme l'illustre l'exemple ci-dessus, on veut évidemment que le nom puisse être en Unicode, sauf pour la petite minorité des habitants de la planète qui utilisent une langue qui peut s'écrire uniquement en ASCII.

Ces noms « parlants », ces nicknames, ne servent pas qu'à désigner des humains, ils peuvent aussi être utilisés pour des machines, des sites Web (dans les signets), etc.

On pourrait penser qu'il n'y a rien à spécifier pour permettre leur internationalisation. On remplace juste ASCII par Unicode comme jeu de caractères autorisé et vas-y, poupoule. Mais Unicode recèle quelques surprises et, pour que les nicknames fonctionnent d'une manière qui paraitra raisonnable à la plupart des utilisateurs, il faut limiter légèrement leur syntaxe.

Ces limites sont exposées dans la section 2 de notre RFC, qui définit un profil de PRECIS. PRECIS, Preparation, Enforcement, and Comparison of Internationalized Strings est le sigle qui désigne le projet « Unicode dans tous les identificateurs » et le groupe de travail IETF qui réalise ce projet. PRECIS définit (RFC 7564) plusieurs classes d'identificateurs et les nicknames sont un cas particulier de la classe FreeformClass, la moins restrictive (celle qui permet le plus de caractères).

Outre les restrictions de FreeformClass (qui n'est pas complètement laxiste : par exemple, cette classe ne permet pas les caractères de contrôle), le profil Nickname :

  • Convertit tous les caractères Unicode de type « espace » (la catégorie Zs) en l'espace ASCII (U+0020),
  • Supprime les espaces en début et en fin du nickname, ce qui fait que " Thérèse" et "Thérèse" sont le même nom,
  • Fusionne toutes les suites d'espaces en un seul espace,
  • Met tout en minuscules (donc les nicknames sont insensibles à la casse),
  • Normalise en NFKC, plus violent que NFC, et réduisant donc les possibilités que deux nicknames identiques visuellement soient considérés comme distincts (cf. section 6, qui prétend à tort que ce serait un problème de sécurité ; comme souvent à l'IETF, le groupe de travail a passé beaucoup de temps sur un faux problème de « confusabilité », cf. UTS#39).

À noter qu'un nickname doit avoir une taille non nulle, après l'application des ces règles (autrement, un nickname de trois espaces serait réduit à... zéro).

Une fois ce filtrage et cette canonicalisation faite, les nicknames sont encodés en UTF-8 et peuvent être comparés par une simple égalité bit à bit.

La section 3 de notre RFC fournit quelques exemples amusants et instructifs de nicknames :

  • "Foo" et "foo" sont acceptables, mais sont le même nom (en application de la régle d'insensibilité à la casse),
  • "Foo Bar" est permis (les espaces sont autorisés, avec les quelques restrictions indiquées plus haut),
  • "Échec au roi ♚" est permis, rien n'interdit les symboles comme cette pièce du jeu d'échecs, le caractère Unicode U+265A,
  • "Henri Ⅳ" est permis (ouvrez l'œil : c'est le chiffre romain à la fin, U+2163) mais la normalisation NFKC (précédée du passage en minuscules) va faire que ce nom est équivalent à "henri iv" (avec, cette fois, deux caractères à la fin).

Comme le rappelle la section 4 de notre RFC, les applications doivent maintenant définir l'utilisation de ces noms parlants, où peut-on les utiliser, etc. L'application peut donc avoir des règles supplémentaires, comme une longueur maximale pour ces nicknames, ou des caractères interdits car ils sont spéciaux pour l'application.

L'application ou le protocole applicatif a également toute latitude pour gérer des cas comme les duplicatas : j'ai écrit plus haut que "Foo Bar" et "foo bar" étaient considérés comme le même nickname mais cela ne veut pas dire que leur coexistence soit interdite : certaines applications permettent à deux utilisateurs distincts d'avoir le même nickname. Même chose avec d'autres règles « métier » comme la possibilité d'interdire certains noms (par exemple parce qu'ils sont grossiers).

Le profil Nickname est désormais ajouté au registre IANA (section 5 du RFC).


Téléchargez le RFC 7700


L'article seul

RFC 7687: Report from the Strengthening the Internet (STRINT) workshop

Date de publication du RFC : Décembre 2015
Auteur(s) du RFC : S. Farrell (Trinity College, Dublin), R. Wenning, B. Bos (W3C), M. Blanchet (Viagenie), H. Tschofenig (ARM)
Pour information
Première rédaction de cet article le 15 décembre 2015


Depuis les révélations d'Edward Snowden, les initiatives se multiplient pour « durcir l'Internet », c'est-à-dire le rendre plus résistant à la surveillance généralisée, telle que pratiquée par plusieurs pays (par exemple la France, où les politiques profitent cyniquement des attentats islamistes pour faire passer de plus en plus de lois liberticides). Début 2014, à Londres, s'est ainsi tenu l'atelier STRINT, qui a rassemblé une centaine de participants pour réfléchir à la meilleure façon de renforcer l'Internet contre cet espionnage. Ce RFC est le compte-rendu (très tardif) de cet atelier. Il résume les principales interventions, et les suggestions faites à cette occasion.

L'engagement de l'IETF à lutter contre la surveilance généralisée date de sa réunion de Vancouver, et a été formalisé dans le RFC 7258. C'est à la suite de cette réunion canadienne qu'a été tenu l'atelier STRINT, coorganisé par le projet STREWS, l'IAB et le W3C. STRINT signifie « Strengthening the Internet Against Pervasive Monitoring » et l'atelier s'est tenu juste avant la réunion IETF 89 à Londres.

L'atelier a été un succès. Prévu pour un petit nombre de participants (cent maximum : le but était de travailler, pas de faire des discours devant une immense salle), il a été rempli en peu de temps. (Outre les 100 participants physiques, jusqu'à 165 personnes ont suivi l'atelier à distance.) 67 articles avaient été soumis.

La section 2 du RFC résume les conclusions de l'atelier :

  • La cryptographie bien faite est une protection efficace contre la surveillance massive et son usage plus intense est souhaitable.
  • L'analyse de trafic est une menace réelle, et la cryptographie est ici moins efficace. Mais le problème reste insuffisamment connu et mérite d'avantage d'études.
  • La surveillance massive est quelque chose de relativement nouveau et mérite des analyses du modèle de menace plus détaillées (le travail était en cours à l'époque, et cela a mené, entre autres, au RFC 7624).
  • Cette surveillance massive mérite qu'on s'attaque à une mise à jour du RFC 3552.
  • Le terme de « opportunistic security » a été brandi plusieurs fois pendant l'atelier. Il faut savoir que ce terme n'a pas de définition rigoureuse et est utilisé dans le monde de la sécurité pour désigner des tas de choses différentes. Depuis, l'IETF a publié sa définition, dans le RFC 7435.
  • Un effort d'explication auprès des décideurs reste nécessaire, pour expliquer les problèmes techniques que pose la surveillance massive. (Belle naïveté de techniciens honnêtes qui croient que les politiques prennent des mauvaises décisions parce qu'ils ne sont pas bien informés.)
  • La question des interfaces utilisateur est très importante et très difficile. Il existe désormais un net consensus chez les gens de la sécurité que l'utilisateur est un maillon crucial (et souvent fragile) de la chaîne de sécurité. Il reste à tirer des conséquences pratiques de ce consensus de principe. Par exemple, faut-il arrêter de présenter à l'utilisateur des choix dangereux, comme « le certificat n'a pas le bon nom, voulez-vous continuer ? » Si on répond « il ne faut pas proposer de tels choix », une coordination entre les auteurs de logiciels est nécessaire autrement ceux qui respectent le plus la sécurité risquent d'être considérés comme moins bon que ceux de leurs concurrents (comme on l'a déjà vu avec DNSSEC). Globalement, ce problème des interfaces utilisateur reste un champ de recherche ouvert.
  • Développer des exemples de configurations sûres à copier/coller pour mettre dans son logiciel aiderait certainement (regardez par exemple la documentation de l'ANSSI sur HTTPS, section 2.1). Ce n'est pas un travail de normalisation et cela ne concerne donc pas directement l'IETF ou le W3C mais c'est certainement important.
  • Plus directement de la responsabilité de ces SDO : faire un effort pour que les protocoles soient sûrs par défaut (un contre-exemple est SMTP, qui est en clair par défaut.)
  • Apparemment plus anecdotique, mais néanmoins crucial vu leur vaste déploiement, résoudre le problème des portails captifs aiderait : aujourd'hui, ces portails utilisent les mêmes techniques que des attaquants et sont donc indistinguables d'une attaque.

La section 3 de notre RFC revient sur les buts de l'atelier. Une fois qu'on a décidé que la surveillance généralisée était une attaque, et qu'il fallait la combattre (RFC 7258), que faire de plus ?

  • Se mettre d'accord sur des concepts comme celui de « sécurité opportuniste »,
  • Mieux comprendre les compromis à faire (la sécurité n'est pas gratuite),
  • Identifier les « maillons faibles » de la sécurité du Web,
  • Et surtout, identifier les tâches concrètes qui relèvent des organismes de normalisation comme l'IETF ou le W3C et celles qui, sans relever directement de ces organismes, les aideraient dans leur tâche.

Pour atteindre ces buts, l'atelier était structuré pour maximiser les discussions (section 4 du RFC). Les papiers acceptés n'étaient pas présentés (les participants étaient supposés les avoir lus avant).

Quels furent les sujets couverts dans les sessions de l'atelier (section 5 du RFC) ? La session d'ouverture a discuté de questions plutôt « méta » comme la quantité minimale de métadonnées qui est vraiment nécessaire aux protocoles IETF pour faire leur travail, comme la recherche de « fruits à portée de main » (des solutions qui pourraient être déployées très rapidement), ou comme le niveau de sécurité considéré comme « suffisant » (il ne faut pas espérer atteindre une sécurité parfaite, quand l'attaquant a les moyens de la NSA).

La première session portait (section 5.2) sur les menaces. Pas de sécurité sérieuse sans une étude détaillée des menaces. Ce n'est pas la même chose de se protéger contre la DGSE ou le FSB et de se protéger contre le lycéen boutonneux dans son garage. La surveillance généralisée met en cause un modèle traditionnel de menaces, fondé sur une étude coût/bénéfice de la défense (ou de l'attaque d'ailleurs). Dans ce modèle traditionnel, on regardait ce que valait l'objectif à défendre et on calculait les dépenses de sécurité réalistes en fonction de cela. (L'attaquant faisait un calcul similaire, et pouvait migrer vers un autre objectif, si le premier envisagé était trop coûteux.) Mais, avec la surveillance généralisée, il n'y a plus de décisions d'attaquer tel ou tel objectif : on attaque tout le monde. Et l'attaquant étant en général un État, il ne fait pas de calcul de ROI (certaines bureaucraties étatiques sont même contentes quand c'est cher, cela permet de se « construire un empire » en réclamant des budgets toujours plus élevés).

Est-ce que la surveillance généralisée est plus facile s'il y a un petit nombre de silos très protégés (les GAFA, Google, Facebook, etc) ou s'il y a une multitude de petits sites, chacun avec son CozyCloud ou son YunoHost, chacun moins bien protégé que les grosses entreprises professionnelles, mais bénéficiant de la dispersion des données ? Si Facebook est certainement, pour un attaquant, un objectif plus difficile à craquer que le VPS de M. Michu, c'est également un objectif beaucoup plus intéressant : si on le craque, on a les données de centaines de millions de M. Michu. Le RFC suggère donc qu'il vaut mieux ne pas tout mettre chez les GAFA et disperser les objectifs. (Gentiment, il oublie de rappeler que certains attaquants n'ont pas besoin de pirater les GAFA : ils ont PRISM pour cela.)

La session a aussi mis en évidence l'importance d'utiliser un vocabulaire rigoureux quand on parle des menaces et des solutions techniques, surtout quand on s'adresse à un public non-spécialiste. Ainsi, les solutions contre les attaques de l'Homme du Milieu ne « protègent » pas contre ces attaques : elles les rendent simplement visibles. C'est la réaction aux alertes qui déterminera si on est protégé ou pas (pensez au traditionnel avertissement des navigateurs Web : « voulez-vous continuer malgré ce certificat mal fichu ? »).

Une autre session portait sur l'usage des outils de sécurité (section 5.3). Ce n'est pas tout de concevoir des outils géniaux, il faut encore qu'ils soient utilisés. Aujourd'hui, on constate que ce n'est pas assez le cas. Combien de messages circulent en clair quand ils devraient être chiffrés avec PGP ? Combien de SMS envoyés de manière à être lisibles par tous alors qu'il faudrait utiliser Signal (ex-TextSecure) ? Combien de webmestres renoncent à activer HTTPS parce qu'ils ne veulent pas payer une AC et subir ses procédures et son interface Web mal faite ?

Le RFC note que, dans ce dernier cas, ils ont raison, vu la faille fondamentale de ce système des AC : n'importe quelle AC peut émettre un certificat pour n'importe quel domaine. Donc, il suffit qu'une seule des centaines d'AC reconnues par le logiciel soit compromise pour faire s'effondrer tout l'édifice. Des solutions techniques existent (cf. RFC 6962 ou le RFC 6698, curieusement oublié ici).

Un des problèmes à l'usage des outils de sécurité peut être le modèle de confiance utilisé. Dans X.509, c'est « toutes les AC ont raison ». C'est très dangereux pour la sécurité. PGP a un modèle « réseau de confiance » qui a l'inconvénient de ne bien marcher que pour des petites communautés (il n'est pas réellement transitif). Un modèle longtemps méprisé par les experts en sécurité (ceux avec qui, si on les écoute, on ne déploie jamais aucune solution de sécurité, car aucune n'est parfaite) est le TOFU, utilisé par SSH ou Signal. Il a l'avantage d'être beaucoup plus facile pour les utilisateurs, mais l'attaque de l'Homme du Milieu reste possible pour la première connexion. La technique de l'« épinglage des clés » (RFC 7469) est une variante de TOFU.

Et pour SIP ? La constatation de l'atelier était que les fonctions de cryptographie dans SIP, pourtant bien normalisées, étaient peu utilisées. L'argument des opérateurs SIP est que les mises en œuvre de ce protocole sont peu interopérables et que la seule solution pour que ça marche est de modifier les échanges en cours de route, rajoutant ou enlevant des en-têtes SIP pour s'adapter à chaque logiciel. (S'ils ont raison, cela signifie que les RFC sur SIP n'étaient pas clairs, ou bien que les programmeurs ne les ont pas lus.)

Peut-être que WebRTC en tirera les leçons (RFC 8827). Après tout, WebRTC est mis en œuvre par les auteurs de navigateurs et ceux-ci n'ont pas les mêmes intérêts que les opérateurs SIP (les intermédiaires adorent modifier les données et détestent la sécurité de bout en bout).

Et pour XMPP (RFC 6120), pourquoi les techniques de sécurité existantes ne sont-elles pas plus fréquemment utilisées ? XMPP a de l'authentification et du chiffrement du canal, grâce à TLS, et de l'authentification et du chiffrement de bout en bout, grâce à OTR (qui a par contre le gros défaut d'être mal intégré au protocole XMPP). Mais le problème identifié pendant la session est plutôt que XMPP est peu utilisé. Contrairement au courrier électronique, où tout le monde utilise les solutions standard (SMTP et IMF), pour la messagerie instantanée, M. Michu fait une confiance aveugle à des systèmes fermés et privatifs comme Skype, dont la sécurité est inconnue ou inexistante.

Il y avait bien sûr une session consacrée aux questions non techniques (section 5.4) car on sait bien maintenant que « la sécurité n'est pas un produit, c'est un processus ». Installer un outil technique ne suffit pas. Il faut aussi traiter les questions d'éducation des utilisateurs, les questions politiques, les questions juridiques... Ainsi, l'excuse du terrorisme est largement utilisée par les États pour justifier des politiques répressives, tellement répressives qu'elles auraient été largement considérées comme inacceptables il y a seulement quelques années (voir par exemple ce qui se fait en France en ce moment avec l'état d'urgence). Il y aussi, note le RFC, le problème des traités internationaux pro-commerce (comme TTIP) qui contiennent souvent des mesures anti-vie privée.

On note que, d'une façon générale, ces problèmes non techniques étaient traditionnellement peu pris en compte par les organisations comme l'IETF, ou par les informaticiens en général. Cela fait très longtemps que les chercheurs en médecine, par exemple, ont des comités d'éthique qui se penchent sur les conséquences de leur travail. Faudrait-il faire la même chose pour les SDO ? Pour l'instant, les normes qui ont reçu une évaluation extérieure sur les questions de vie privée (comme l'API de géolocalisation) l'ont été ponctuellement, sans démarche systématique.

Cela n'interdit pas d'améliorer les outils et une session était consacrée à cette activité (section 5.5 du RFC). D'abord, l'atelier a discuté de la sécurité opportuniste (au sens de « essayer de chiffrer autant que possible, même sans authentification, ce serait mieux que rien »), en considérant qu'elle n'avait pas été assez utilisée jusqu'à présent. L'une des difficultés de cet opportunisme est de ne pas donner de faux sentiments de sécurité à l'utilisateur. Par exemple, il y avait un consensus dans l'atelier que, si un logiciel tente TLS et y réussit, mais sans authentification, il ne doit pas présenter à l'utilisateur des signes rassurants, genre petit cadenas. Le chiffrement ainsi obtenu est un progrès mais il ne faut pas donner l'impression qu'on s'arrête là.

Un aspect délicat à l'heure actuelle est de l'attitude à avoir lorsqu'on ne peut pas chiffrer : est-ce parce que le pair ne sait effectivement pas ou bien parce qu'un Homme du Milieu a réussi à empêcher le chiffrement ? Pour des sessions qu'on veut sécurisées (https://... vers sa banque), il faut évidemment s'arrêter là. Mais pour les autres, il serait intéressant, plutôt que de se rabattre sur de la communication en clair, ce qui est souvent le choix, de se souvenir des communications précédentes avec ce pair et de décider en fonction du passé si ce problème de chiffrement est normal (une forme de TOFU).

Là aussi, la terminologie est importante. Les descriptions des connexions utilisant le « chiffrement, si possible » (sécurité opportuniste) parlent souvent d'« échec » si la session chiffrée n'a pu être établie alors qu'un tel échec n'est pas pire que si on n'avait même pas essayé. Il faudrait plutôt parler d'« amélioration » quand on a réussi à lancer le chiffrement (et ne rien dire si on n'y est pas arrivé). Là aussi, le fait que les concepteurs de protocoles, les experts en sécurité et les programmeurs ne soient pas des spécialistes de l'interface utilisateur va jouer : il n'est pas évident de communiquer des informations sur le niveau de sécurité à l'utilisateur.

Autre point sur lequel il faudrait améliorer les outils, le fait de chiffrer systématiquement, sans action explicite de l'utilisateur. Sinon, il y a un risque que l'utilisateur ne chiffre que les documents sensibles, ce qui facilite la tâche des espions, en leur indiquant quels sont les documents importants. (C'est un des problèmes de PGP, je trouve.)

Il serait également intéressant d'améliorer TOFU. Un des gros problèmes de ce modèle, tel qu'il est utilisé dans SSH, est qu'il n'existe pas de mécanisme propre pour changer la clé d'un serveur (par exemple parce qu'on a mis à jour le logiciel). Idem si on utilise Signal : si votre correspondant a perdu son téléphone et en a acquis un nouveau, il faut manuellement vérifier la nouvelle identité (TOFU ne peut pas savoir si c'est un changement de clé légitime ou bien une attaque de l'Homme du Milieu).

Un sujet qui fait l'objet de nombreuses discussions dès qu'on parle de vie privée et de surveillance est celui des métadonnées (section 5.6). Chiffrer protège en effet très bien le contenu. Malgré quelques rumeurs, il est peu probable que même les plus puissants attaquants arrivent aujourd'hui à craquer le chiffrement bien fait (attention : bien chiffrer est beaucoup plus dur que ce n'en a l'air). Pour un attaquant rationnel, voler les clés, acheter ou menacer un destinataire légitime, ou encore corrompre le logiciel de chiffrement est bien plus aisé que de casser le chiffrement lui-même (c'est d'ailleurs pour cela que les discussions de détail sur la longueur des clés sont assez ridicules). Mais ce chiffrement n'aide pas si les métadonnées sont, elles accessibles. Pour prendre un exemple classique, imaginons deux personnes qui se téléphonent et chiffrent la communication. Le fait qu'ils se téléphonent est lui-même une information, qui peut être suffisante pour un espion, même s'il n'a pas accès au contenu des communications. C'est encore plus vrai si on a accès à plusieurs communications : si, à chaque fois que A appelle B au téléphone, B, immédiatement après avoir raccroché, appelle C, D et E, on en déduira facilement qu'on a identifié une chaîne de commandement, même si on n'a pas le contenu de leurs conversations. Cet exemple illustre bien le danger des métadonnées. Parfois, même la taille des messages donne des indications (si vingt fichiers de taille différente sont sur un serveur, l'observation du trafic, même chiffré, permet de savoir quel fichier a été récupéré).

Or, ces métadonnées sont partout, soit qu'elle soient absolument indispensables au fonctionnement des protocoles (comme l'adresse IP de destination dans les paquets IP), soit que leur potentiel d'indiscrétion n'ait pas été perçu tout de suite. Les supprimer n'est pas évident : un routeur a bien besoin de l'adresse de destination pour router !

Il y a trois techniques pour lutter contre l'espionnage par les métadonnées : l'agrégation, le détour (contraflow), et la dispersion (multipath). L'agrégation consiste à regrouper des conversations différentes dans un même flux de données. Par exemple, si votre résolution DNS passe par un gros résolveur partagé, les serveurs qu'interroge ce résolveur auront du mal à identifier vos requêtes, toutes passant par le résolveur. Idem en HTTP si on utilise un relais partagé, sauf évidemment si celui-ci laisse passer, ou, pire, ajoute, des informations discriminantes comme le User-Agent:. Même chose côté serveur : si vos pages « sensibles » sont hébergées sur un serveur mutualisé, un observateur aura du mal à dire ce qui était demandé (là encore, tout est dans les détails : par exemple, SNI peut trahir la communication).

Le détour consiste à passer délibérement par des chemins supplémentaires. C'est ce que fait un VPN ou, en encore mieux, Tor. Un espion qui voudrait identifier votre trafic devrait observer l'Internet en de nombreux points, et corréler ce qu'il voit.

Quant à la dispersion, elle consiste à envoyer les données par des moyens différents. Si vous commencez une conversation XMPP via de la 4G et que vous continuez en Wifi, l'attaquant aura davantage de mal que si toute la communication passe par un seul canal.

L'analyse de trafic donne souvent des résultats surprenants d'efficacité, dont les concepteurs de protocole ne se rendent pas compte. (Voir la bibliographie de FreeHaven, par exemple.) Il existe des méthodes pour la contrarier, comme d'ajouter des messages vides (padding, voir par exemple le RFC 7540, sections 6.1 et 10.7) mais elles ont un coût (par exemple en terme de débit) et ne sont pas faciles à utiliser.

Notez que les protections de bas niveau (couche 3) ne sont pas très utiles si les applications elle-même font fuiter des données. Un navigateur Web est particulièrement terrible sur ce point, voir le Panopticlick. C'est pour cela que Tor recommande l'usage du Tor Browser qui ne se contente pas de router les données via Tor, mais qui s'assure aussi que le navigateur ne vous trahit pas, et n'envoie qu'un minimum de données.

Un problème fréquent pour tous les systèmes de sécurité est celui des middleboxes, ces équipements intermédiaires qui se permettent de filtrer les messages, voire de les modifier. Beaucoup de protocoles de sécurité de l'Internet sont conçus pour une connexion de bout en bout : c'est le cas de TLS, par exemple. La middlebox viole cette supposition. On voit, par exemple, des middleboxes qui terminent la session TLS, analysent le trafic, puis re-chiffrent de l'autre côté. Pour passer l'authentification TLS, elles imposent en général de mettre le certificat d'une AC complice sur les ordinateurs clients. À noter que, dans la configuration TLS typique, le client authentifie le serveur mais pas le contraire. Ce qui veut dire qu'un serveur, même ultra-paranoïaque, n'a aucun moyen, contrairement au client, de détecter qu'une middlebox est présente.

Un autre exemple typique de middlebox courante est le portail captif (cf. RFC 6585 mais aussi le RFC 7710, issu des réflexions de cet atelier). Certains systèmes d'exploitation utilisent diverses heuristiques pour détecter la présence d'un portail captif afin, par exemple, de permettre une connexion automatisée. Mais ces heuristiques ne marchent évidemment pas toujours. (D'autant plus qu'il semble que certains points d'accès font tout pour empêcher ces heuristiques de marcher, afin d'empêcher les connexions automatisées.)

Idéalement, il faudrait un protocole nouveau permettant aux portails captifs de se signaler, sans avoir à jouer les Hommes du Milieu. Mais, même si un tel protocole était nnormalisé demain, il faut se rappeler que la plupart des points d'accès ne sont jamais mis à jour... (Un hôtel, par exemple, se moque pas mal de si son portail captif marche bien ou pas.)

L'atelier STRINT a ensuite vu les participants se répartir en petits groupes (break-outs) pour discuter en profondeur certains sujets. Par exemple, l'un de ces groupes s'attaquait à l'analyse des clients. Si certains ignorants ne considèrent que les navigateurs Web, les participants à l'atelier savaient bien, eux, qu'il existe une grande variété de logiciels clients. L'un des problèmes de ces clients est « que faire lorsqu'un certificat pose un problème ? » Certains administrateurs système disent simplement aux utilisateurs « continuez, ne vous inquiétez pas de cet avertissement », conseil qu'il sera difficile de faire désapprendre aux utilisateurs ensuite. Peut-être faudrait-il que les logiciels clients ne fournissent plus d'option pour passer outre un problème de certificat. Mais un tel changement devrait être fait plus ou moins simultanément par tous les auteurs de logiciels de cette catégorie. Autrement, il y a un risque que l'utilisateur croit que les logiciels les plus sûrs sont en tort, en l'empêchant de se connecter à son serveur.

Autre problème d'interaction entre la sécurité informatique et les facteurs humains, le cas des certificats auto-signés. Si un tel certificat est évidemment inacceptable pour une banque ou pour GitHub, pour un site personnel, il peut être tout à fait valable et en tout cas meilleur qu'une communication en clair. Un des aspects délirants de l'usage de HTTPS aujourd'hui est que bien des gérants de serveurs personnels n'activent pas HTTPS car obtenir un certificat est cher et compliqué, et utiliser un certificat auto-signé provoquerait des avertissements de sécurité injustifiés. Résultat : on reste en clair...

Un autre groupe travaillait sur l'activation par défaut des meilleurs choix de sécurité. Quant l'IETF dit que tous les programmes DOIVENT (MUST, cf. RFC 2119) mettre en œuvre tel protocole ou tel algorithme, cela veut dire qu'il doit être présent dans le code (MTI ou Mandatory To Implement, cf. RFC 3365). Mais cela ne signifie pas qu'il sera utilisé, s'il faut une action explicite de l'utilisateur ou de l'administrateur système pour l'activer. La très grande majorité des utilisateurs, et la plupart des administrateurs système, ne changent pas les réglages par défaut. Si on veut vraiment combattre la surveillance généralisée, il ne suffit pas d'avoir 2 ou 3 % des utilisateurs qui sont protégés. Il faut que presque tous le soient, donc passer du MTI au MTU (Mandatory To Use).

Enfin, un autre groupe break-out a planché sur la notion de « sécurité opportuniste » (opportunistic security). Le terme est très utilisé dans les milieux de la sécurité informatique mais n'a pas de définition précise. Plusieurs auteurs ont essayé d'en donner une définition (voir par exemple le RFC 4322) mais ces définitions sont très différentes les unes des autres. Depuis, l'IETF a publié la sienne, dans le RFC 7435.

On l'a dit, ce RFC arrive bien tard après l'atelier. Depuis, du travail a été fait. Juste après l'atelier, la réunion IETF de Londres a logiquement beaucoup couvert ces questions de protection contre l'espionnage. Ce fut par exemple la « DNSE BoF », première réunion physique du projet « DNS et vie privée », qui a depuis débouché sur le RFC 7626.

La totalité des articles présentés est en ligne.


Téléchargez le RFC 7687


L'article seul

RFC 7710: Captive-Portal Identification Using DHCP or Router Advertisements (RAs)

Date de publication du RFC : Décembre 2015
Auteur(s) du RFC : W. Kumari (Google), O. Gudmundsson (CloudFlare), P. Ebersman (Comcast), S. Sheng (ICANN)
Chemin des normes
Première rédaction de cet article le 14 décembre 2015


Les portails captifs sont une des plaies de l'accès à l'Internet. À défaut de pouvoir les supprimer, ce nouveau RFC propose des options aux protocoles DHCP et RA pour permettre de signaler la présence d'un portail captif, au lieu que la malheureuse machine doive le détecter elle-même. depuis, il a été remplacé par le RFC 8910.

On trouve de tels portails captifs en de nombreux endroits où de l'accès Internet est fourni, par exemple dans des hôtels ou des cafés. Tant que l'utilisateur ne s'est pas authentifié auprès du portail captif, ses capacités d'accès à l'Internet sont très limitées. Quels sont les problèmes que pose un portail captif ?

  • Le plus important est qu'il détourne le trafic normal : en cela, le portail captif est une attaque de l'Homme du Milieu et a donc de graves conséquences en terme de sécurité. Il éduque les utilisateurs à trouver normal le fait de ne pas arriver sur l'objectif désiré, et facilite donc le hameçonnage.
  • Le portail captif ne marche pas ou mal si la première connexion est en HTTPS, ce qui est de plus en plus fréquent. Là encore, il éduque les utilisateurs à trouver normaux les avertissements de sécurité (« mauvais certificat, voulez-vous continuer ? »).
  • Le portail captif n'est pas authentifié, lui, et l'utilisateur est donc invité à donner ses informations de créance à un inconnu.
  • En Wifi, comme l'accès n'est pas protégé par WPA, le trafic peut être espionné par les autres utilisateurs.
  • Spécifique au Web, le portail captif ne marche pas avec les activités non-Web (comme XMPP). Même les clients HTTP non-interactifs (comme une mise à jour du logiciel via HTTP) sont affectés.

Pourquoi est-ce que ces hôtels et cafés s'obstinent à imposer le passage par un portail captif ? On lit parfois que c'est pour authentifier l'utilisateur mais c'est faux. D'abord, certains portails captifs ne demandent pas d'authentification, juste une acceptation des conditions d'utilisation. Ensuite, il existe une bien meilleure solution pour authentifier, qui n'a pas les défauts indiqués plus haut. C'est 802.1X, utilisé entre autres dans eduroam (voir RFC 7593). La vraie raison est plutôt une combinaison d'ignorance (les autres possibilités comme 802.1X ne sont pas connues) et de désir de contrôle (« je veux qu'ils voient mes publicités et mes CGU »).

L'IETF travaille à développer un jour un protocole complet d'interaction avec les portails captifs, pour limiter leurs conséquences. En attendant, ce RFC propose une option qui permet au moins au réseau local de signaler « attention, un portail captif est là, ne lance pas de tâches - comme Windows Update - avant l'authentification ». Cette option peut être annoncée par le serveur DHCP (RFC 2131 et RFC 8415) ou par le routeur qui envoie des RA (RFC 4861).

Cette option (section 2 du RFC) annonce au client qu'il est derrière un portail captif et lui fournit l'URI de la page d'authentification (ce qui évite d'être détourné, ce qui est grave quand on utilise HTTPS). Dans cet URI, le serveur HTTP doit être désigné par son adresse IP, pour éviter d'avoir à faire du mensonge DNS.

Les sections 2.1, 2.2 et 2.3 de notre RFC donnent le format de l'option en DHCP v4, DHCP v6 et en RA. Le code DHCP v4 est 160 (qui était malheureusement squatté, ce qui a nécessité son changement dans le RFC 8910), le DHCP v6 est 103 et le type RA est 37.

La section 4 de notre RFC étudie les conséquences de cette option pour la sécurité. Elle rappelle que DHCP et RA ne sont pas sécurisés, de toute façon. Donc, un méchant peut envoyer une fausse option « il y a un portail captif, allez à cet URI pour vous authentifier » mais le même méchant peut aussi bien annoncer un faux routeur...

Il est même possible que cette option nouvelle améliore la sécurité, en n'encourageant pas les utilisateurs à couper les mécanismes de validation comme la vérification des certificats, contrairement à ce que font les portails captifs actuels.

Pour DHCP, la plupart des serveurs permettent de servir une option quelconque, en mettant ses valeurs manuellement et une future mise à jour ne servira donc qu'à rendre l'usage de cette option plus simple. Autrement, il n'existe pas encore de mise en œuvre côté clients DHCP ou RA. (Pour des nouvelles plus récentes, voir le RFC 8910.)


Téléchargez le RFC 7710


L'article seul

RFC 7720: DNS Root Name Service Protocol and Deployment Requirements

Date de publication du RFC : Décembre 2015
Auteur(s) du RFC : M. Blanchet (Viagenie), L-J. Liman (Netnod)
Première rédaction de cet article le 13 décembre 2015


L'Internet repose en grande partie sur le DNS (si ce dernier est en panne, presque plus rien ne fonctionne) et le DNS doit à sa nature arborescente de dépendre de sa racine ou plus exactement de ses serveurs racine. La gestion de ces derniers est donc une question cruciale, même si les débats sur la gouvernance de l'Internet se focalisent plutôt sur des sujets moins concrets comme la création (ou non) du TLD .vin. Ce très court RFC précise les obligations des serveurs racine en terme de protocoles réseau à suivre. D'autres documents décrivent les exigences opérationnelles. (Voir notamment le RSSAC 001: Service Expectation of Root Servers.)

Avant, ces obligations étaient dans un seul RFC, le RFC 2870. Il contenait des recommandations concernant les protocoles, donc plutôt du ressort de l'IETF, et d'autres concernant les règles quotidiennes des opérations d'un serveur racine, considérées aujourd'hui comme relevant plutôt du RSSAC (Root Server System Advisory Committee, qui publie ses propres recommandations dans le document nommé RSSAC-001). Ce RFC est donc encore plus court que son prédécesseur, désormais document historique.

À noter que les serveurs racine ne servent pas que la racine, mais aussi root-servers.net, domaine dans lequel ils sont nommés. Certains d'entre eux servent également .arpa.

Le cœur de notre RFC est la section 2 qui exige que les serveurs racine :

  • Suivent le protocole DNS (encore heureux...),
  • Soient capables de répondre en IPv4 et IPv6 (en octobre 2015, deux serveurs, E et G, n'avaient toujours pas d'IPv6),
  • Soient capables de répondre en UDP et en TCP,
  • Doivent gérer les sommes de contrôle UDP,
  • Doivent évidemment gérer DNSSEC, pour pouvoir servir la racine, qui est signée,
  • Doivent gérer EDNS (RFC 6891).

La plupart de ces règles vont de soi mais, en 2015, on rencontre hélas encore des serveurs DNS qui n'ont pas EDNS ou bien qui n'ont pas TCP (sans même parler d'IPv6...)

Moins liées aux protocoles, il y a deux autres exigences dans la section 3 :

  • Répondre à tous les clients (c'est un principe de neutralité du réseau, qui a d'amusantes conséquences de gouvernance, par exemple les serveurs gérés par l'armée US doivent répondre aux requêtes venant d'Iran...),
  • Servir l'unique racine « officielle », cf. RFC 2826 et pas une éventuelle racine alternative. Évidemment, cela implique de ne pas la modifier : les serveurs racine sont des imprimeurs, pas des éditeurs.

Merci à Lancelot et Atlal (et Opale), qui savent pourquoi...


Téléchargez le RFC 7720


L'article seul

RFC 7682: IRR & Routing Policy Configuration Considerations

Date de publication du RFC : Décembre 2015
Auteur(s) du RFC : D. McPherson (Verisign), S. Amante (Apple), E. Osterweil (Verisign), L. Blunk (Merit Network), D. Mitchell (Singularity Networks)
Pour information
Réalisé dans le cadre du groupe de travail IETF grow
Première rédaction de cet article le 13 décembre 2015


On le sait, il n'y a pas de chef de l'Internet. Personne ne reste dans un bureau toute la journée avec pour mission l'envoi de règles qui seront immédiatement appliquées par tous les acteurs de l'Internet. C'est même le cas des fonctions les plus essentielles de l'Internet comme l'échange des tables de routage. Tout l'Internet ne tient que parce que les opérateurs sont d'accord entre eux pour s'échanger l'information qui se retrouvera dans ces tables « pour joindre le préfixe 2001:db8:fe2::/48, passez par moi, je connais un chemin que j'ai appris des AS 64499 puis 429496613 ». Cet accord de principe se double d'un accord technique sur le protocole à utiliser : BGP, normalisé dans le RFC 4271. Et au-delà, rien, aucun accord : chaque opérateur est libre de sa politique et notament de ce qu'il accepte ou refuse. Un opérateur peut refuser les préfixes plus spécifiques que /32, par exemple. Chacun est maître chez soi. En pratique, bien des opérateurs refusent les préfixes qui ne sont pas dans un IRR. C'est quoi, un IRR ? Qui les gère ? Qui décide de ce qu'on met dans un IRR ?. Ce nouveau RFC explore la question.

Un IRR (Internet Routing Registry) est une base de données stockant des préfixes d'adresses IP et des informations de politique associées comme, par exemple, le ou les AS qui sont autorisés à annoncer ce préfixe en BGP ou bien les communautés BGP (RFC 1997) utilisées. Le RFC 1787, dans sa section 7, décrit l'importance de partager l'information entre les opérateurs. Certes, chacun est maître chez lui, mais tout serait plus simple si chacun partageait avec les autres, pour limiter le risque de décisions malencontreuses.

Mais les IRR ont des problèmes et des limites (introduction en section 3). Première catégorie de problèmes, l'exactitude et l'intégrité des données stockées (section 4). Comme tous les registres utilisés sur l'Internet, les IRR sont plein de données fausses ou dépassées. Les personnes qui mettent ces données dans les registres n'ont guère de motivations pour mettre des données correctes et encore moins pour les mettre à jour. Les données sont donc souvent erronées.

En outre, il n'existe pas de moyen largement déployé de vérifier ces données dès le départ. Si Pakistan Telecom met dans un IRR qu'ils sont autorisés à annoncer le préfixe de YouTube, comment vérifier qu'ils ont le droit de le faire ? Le langage utilisé pour les IRR, RPSL (normalisé dans le RFC 2622) le permet techniquement mais en l'absence d'un mécanisme de signature cryptographique entre le préfixe et l'AS, cela ne permet pas de s'assurer de l'authenticité du contenu de l'IRR. Le RFC note à juste titre que cette absence de mécanisme de signature vient en partie d'un manque d'intérêt de la communauté des opérateurs : tout le monde se plaint des détournements BGP mais personne n'est prêt à faire les considérables efforts qu'il faudrait pour tout certifier.

Bien sûr, certains IRR ont des mesures de sécurité (par exemple, dans la base RIPE, seul le titulaire d'un préfixe peut ajouter des routes pour ce préfixe, cf. RFC 2725 et c'est une obligation contractuelle, cf. ripe-637) mais cela ne s'étend pas aux autres IRR, qui ne peuvent pas vérifier que cette sécurité a été respectée. Difficile donc de savoir quelle politique de sécurité a été utilisée par un IRR donné.

Même quand les données sont correctes, en l'absence de mécanismes de vérification fondés sur la cryptographie, on peut parfois se retrouver avec des données fausses alors qu'elles étaient justes au départ.

Il existe de nombreuses propositions pour créer de tels systèmes de vérification et de certification (TASRS, HotNets-X et bien sûr la RPKI) mais aucune n'a encore un déploiement suffisant.

Comme indiqué plus haut, une partie du problème est le manque de motivation : le titulaire d'une ressource Internet (un préfixe IP, par exemple) peut avoir un intérêt direct à ajouter une information dans un IRR (par exemple parce que son transitaire est strict, et lui impose cet ajout, avant d'accepter l'annonce BGP du titulaire) mais il a rarement de raison objective de le maintenir à jour ou, surtout, de le détruire quand il n'est plus utilisé. Certains acteurs bâtissent leurs filtres d'annonces BGP à partir des IRR, ce qui fait qu'une information manquante se paie d'un manque de visibilité BGP. Mais il n'y a aucune pénalité à avoir de l'information en trop. Si un client, titulaire d'un préfixe IP, passe d'un transitaire strict, qui lui imposait une entrée dans un IRR (par exemple un objet route dans la base RIPE-NCC) vers un transitaire laxiste qui n'impose rien, le client n'a aucune motivation (à part la pureté de l'IRR, qui n'intéresse qu'une poignée de barbus fanatiques utilisant OpenBSD) à changer l'ancienne entrée. Il la laissera probablement telle quelle. Le nouveau transitaire, qui ignore l'IRR, n'en tiendra pas compte.

Une des rares motivations concrètes qui pourrait mener à un nettoyage des IRR est le manque de mémoire dans les routeurs : les filtres pourraient devenir trop gros, si personne ne nettoie jamais. Heureusement pour les utilisateurs des routeurs, mais malheureusement pour la pureté de l'IRR, les routeurs PE modernes ont en général assez de mémoire dans leur module de routage (control plane) pour que cela ne soit plus un problème.

Autre problème avec les IRR, le fait que leur modèle de sécurité soit en général basé sur « le titulaire peut tout, les autres ne peuvent rien ». Si une information est dépassée, un tiers qui s'en aperçoit ne peut rien faire, seul le titulaire est autorisé à la modifier. Pas moyen de nettoyer pour compenser la négligence d'un titulaire. C'est pour cela que le RFC 2725 avait prévu le mécanisme auth-override, qui semble n'avoir jamais été mis en œuvre.

Pour accéder aux données des IRR, on utilise souvent whois. Un exemple (une liste des IRR existe en ligne) :

%  whois -h whois.radb.net 192.134.5.10  
route:          192.134.5.0/24
descr:          NIC-FR-SITE-TH3
origin:         AS2485
mnt-by:         FR-NIC-MNT
mnt-lower:      FR-NIC-MNT
mnt-routes:     FR-NIC-MNT
changed:        jean-philippe.pick@nic.fr 20110214
remarks:        Peering:   peering@nic.fr
remarks:        NOC:       noc@nic.fr
remarks:        Info:      http://www.nic.fr/
source:         RIPE
remarks:        ****************************
remarks:        * THIS OBJECT IS MODIFIED
remarks:        * Please note that all data that is generally regarded as personal
remarks:        * data has been removed from this object.
remarks:        * To view the original object, please query the RIPE Database at:
remarks:        * http://www.ripe.net/whois
remarks:        ****************************
    

On y voit que seul l'AS 2485 est autorisé à être l'origine d'une annonce pour le préfixe 192.134.5.0/24.

Un plaisir des IRR existants est qu'on n'a pas de moyen simple, étant donné une ressource Internet (par exemple un préfixe IP), de savoir quel IRR utiliser. Les clients logiciels existants doivent utiliser diverses heuristiques. Par exemple GNU whois utilise un fichier de configuration local - /etc/whois.conf, des règles incluses dans le client - fichier ip_del_list dans le source, et compte sur le serveur whois de l'ARIN pour le rediriger, pour les ressources inconnues (cette fonction de redirection étant une extension absente du protocole officiel whois, normalisé dans le RFC 3912).

À noter que whois ne fournit aucune confidentialité : le protocole est du simple TCP en clair sur le port 43. (Le protocole RDAP, lui, fournit un mécanisme de chiffrement via TLS.)

La section 5 de notre RFC se penche sur le fonctionnement interne des IRR et notamment sur leur synchronisation. Il est fréquent en effet que les IRR copient les données gérées par d'autres IRR. Cela se fait en général avec le protocole NRTM (protocole ressemblant à whois, et qui est peu ou pas documenté). Ce protocole n'a aucun mécanisme de sécurité (en pratique, la seule protection est la limitation d'accès à certaines adresses IP) et est peu robuste (des erreurs de synchronisation ont déjà eu lieu). Il fonctionne en mode pull et il n'y a pas de mécanisme de notification pour indiquer la présence de données récentes. Une autre façon de synchroniser des IRR est de télécharger un fichier plat, par exemple en FTP, qu'on applique ensuite à la copie locale (ce qui facilite l'application de modifications locales). Ce téléchargement et cette synchronisation sont typiquement faits toutes les 24 heures (une période qui date de l'époque où les réseaux étaient plus lents qu'aujourd'hui, et qui n'a pas toujours été réévaluée depuis), ce qui fait que les données ne sont pas forcément de la première fraicheur. On notera que le logiciel irrd synchronise toutes les dix minutes, par défaut.

Un standard existe pour cette réplication d'IRR, le RFC 2769, mais il ne semble pas avoir jamais eu le moindre succès, peut-être parce qu'il dépend du standard de sécurité RFC 2725, également peu ou pas répandu.

Les filtres effectivement utilisés par les routeurs de l'opérateur sont créés à partir d'un IRR, et cette création implique une autre étape (et les délais associés). Typiquement, l'opérateur utilise un logiciel comme IRRtoolset, qui va traduire les objets trouvés dans l'IRR en règles pour un type de routeur donné. Ce logiciel ne tourne pas en permanence. Conséquence pratique : un changement dans l'IRR a intérêt à ne pas être urgent ! Il n'y a aucun moyen de forcer les opérateurs à télécharger tout de suite les nouvelles données, et à faire tourner la « moulinette » qui va produire les règles pour les routeurs. Si on est un client payant de l'opérateur, on peut parfois les appeler et obtenir que cette opération soit faite de suite, mais ce n'est pas toujours le cas.

Idéalement, lorsqu'une politique change (par exemple un AS annonce un nouveau préfixe), il « suffit » de changer l'IRR, d'attendre les copies dans les autres IRR, puis l'exportation des données depuis les IRR vers les routeurs. Mais le protocole BGP ne permettait pas forcément de changer les caractéristiques d'une session en vol (section 6 de notre RFC) et exigeait une opération de réinitialisation, pour que le routeur accepte les nouvelles routes. Pendant cette opération, tout ou partie du travail normal du routeur était mis en attente... Résultat, cette opération (clear ip bgp neighbor... sur les Cisco...) ne pouvait se faire que pendant les périodes de maintenance. C'est un bon exemple d'un cas où les « bonnes pratiques » (n'accepter que les préfixes décrits dans les IRR) sont irréalisables dans un environnement de production (cf. section 8). Le yakafokon ne marche pas bien dans le monde des réseaux.

Heureusement, ce problème spécifique appartient largement au passé : les extensions à BGP des RFC 2918 et RFC 7313 ont largement supprimé ces obligations.

Il y a aussi les limites inhérentes à certaines mises en œuvre de BGP (section 7 du RFC). Par exemple, au milieu des années 1990, la plupart des routeurs ne permettaient pas de modifier les listes de préfixes acceptés de manière incrémentale : il fallait effacer la liste, puis installer une nouvelle liste, créant ainsi une fenêtre de vulnérabilité pendant laquelle des routes pouvaient fuir. Là aussi, ce problème a largement disparu avec les progrès des routeurs (voir aussi les sections 1 et 8, qui expliquent bien que certains problèmes historiques d'utilisation des IRR sont désormais du passé).

Rien n'est gratuit en informatique : le stockage des listes de préfixes IP acceptés nécessite de la mémoire et, pendant longtemps, les routeurs disposaient de trop peu de mémoire (une NVRAM bien limitée, et très lente en écriture). Les routeurs modernes ont des mémoires flash ou SSD, voire des disques durs et ont donc une bien meilleure capacité. D'un autre côté, les exigences ont crû et la taille de certaines configurations peut toujours poser des défis aux mémoires des routeurs (voir « NTT BGP Configuration Size and Scope »).

Dernier problème, l'envoi aux routeurs des changements. Autrefois, il n'y avait aucun standard en ce sens. Chaque routeur avait son CLI et il fallait générer depuis l'IRR les quelques lignes de commandes qui allaient changer la configuration du routeur, lui faisant accepter de nouveaux préfixes, ou bien refuser ceux qui étaient acceptés. Le routeur recevait ensuite en telnet, puis SSH, l'ordre de charger ces quelques lignes en TFTP ou FTP, puis, plus tard, en SCP. On pouvait alors activer la nouvelle configuration.

De nos jours, il existe une norme pour cela, NETCONF (RFC 6241). On génère toujours des données depuis l'IRR, puis on utilise NETCONF pour les charger. Les données issues de la RPKI peuvent, elles, être envoyées en RTR (RFC 6810) mais cela ne concerne pas tout le reste de la configuration du routeur.

Un petit mot de sécurité pour finir (section 9 du RFC). Le but des IRR étant d'influencer le routage à distance, ces IRR sont donc des ressources sensibles : si quelqu'un peut pirater un IRR et y injecter de fausses données, il peut perturber le routage Internet. Si ce problème est trop fréquent, les opérateurs pourraient en arriver à ne plus utiliser les IRR. Une gestion rigoureuse de leur sécurité est donc cruciale.

Voilà, si vous voulez en savoir davantage sur les IRR, il y a bien sûr l'incontournable site http://www.irr.net/.


Téléchargez le RFC 7682


L'article seul

RFC 7704: An IETF with Much Diversity and Professional Conduct

Date de publication du RFC : Novembre 2015
Auteur(s) du RFC : D. Crocker (Brandenburg InternetWorking), N. Clark (Pavonis Consulting)
Pour information
Première rédaction de cet article le 12 décembre 2015


La question de la diversité dans les organisations qui contribuent d'une manière ou d'une autre au bon fonctionnement de l'Internet a souvent été discutée. Un simple coup d'œil à une réunion IETF permet de voir de nets déséquilibres (peu de femmes, peu de gens originaires d'Afrique ou d'Amérique Latine...). Comme le dit le résumé de ce nouveau RFC : « a small group of well-funded, American, white, male technicians ». Même si ce résumé est exagéré, et si le mécanisme ouvert de l'IETF a largement prouvé son efficacité, il n'est pas interdit de creuser la question « comment accroitre la diversité ? », dans l'espoir d'augmenter encore cette efficacité. (Un tel document suscitera forcément des controverses. Par exemple, personnellement, il me semble que la diversité est plutôt une question de justice - faire sauter les éventuelles discriminations - que d'une supposée meilleure efficacité.)

L'état actuel d'une organisation dépend évidemment de son histoire (section 1 du RFC). L'IETF est née d'un effort commencé à la fin des années 1960, et financé par l'ARPA. Au début, il n'y avait donc que des États-Uniens. La participation s'est ensuite étendue à d'autres milieux aux États-Unis, comme ceux financés par la NSF et non plus l'ARPA. À la création formelle de l'IETF, à la fin des années 1980, le projet a été complètement ouvert. Tout le monde peut participer, sans distinction de genre, de nationalité ou de couleur de peau, au moins en théorie.

L'IETF est à juste titre fière du résultat : le processus ouvert s'est avéré particulièrement efficace, permettant aux protocoles TCP/IP d'être très largement déployés, à la place des protocoles conçus par des SDO traditionnelles et fermées. Mais rien n'est éternel et on ne peut évidemment pas garantir que l'IETF gardera éternellement cette ouverture. Une « vigilance citoyenne » permanente est donc nécessaire.

La culture spécifique de l'IETF est née. Elle se caractérise par une grande franchise dans les discussions, loin de l'hypocrisie de beaucoup d'organisations, où on n'affiche jamais ouvertement les désaccords. Comme toute chose peut être vue de deux façons différentes, le RFC parle non pas de franchise mais de « singularly aggressive behavior, including singularly hostile tone and content ». Il ajoute que ce style n'est pas « professionnel », un terme très curieux, comme si l'aggressivité était le privilège des amateurs... Ce qui est sûr, c'est que ce style, qui allait bien aux participants du début, peut être un problème pour la diversité. Un comportement qui serait considéré « un peu trop direct » aux Pays-Bas peut être vu comme « très impoli » au Japon. (Le RFC parle de « more polite cultures », qui peuvent se sentir mal à l'aise face au style franc et direct de l'IETF.)

La section 2 du RFC décrit ensuite pourquoi le manque de diversité est un problème. D'abord, précisons que tous les attributs sont concernés, le genre, la nationalité, la religion, l'orientation sexuelle, etc. Cette section reprend l'idée que des groupes divers prennent des meilleures décisions (en citant, c'est amusant, uniquement des études états-uniennes, et presque toutes limitées au monde du management capitaliste, comme « Better Decisions Through Diversity: Heterogeneity can boost group performance »).

La question de la diversité étant ancienne, il n'est pas étonnant que le débat sur les solutions le soit aussi, et que de nombreuses techniques aient déjà été proposées, et expérimentées. Par exemple, le RFC note que des mesures purement statistiques, comme des quotas, peuvent être difficile à mettre en œuvre dans des groupes restreints. S'il y a deux Area Directors pour la Routing Area de l'IETF, ils ou elles ne peuvent pas représenter à eux deux toute la diversité souhaitée. En outre, le but est la diversité, pas juste des nombres appliqués aveuglément (avoir X % de membres de tel groupe ne sert à rien si ces X % sont silencieux et ne participent pas).

Quels sont les mécanismes qui peuvent, en pratique, limiter la diversité dans l'IETF (puisque, en théorie, tout le monde peut participer) ? Il y a plein d'exemples :

  • En théorie, la participation à l'IETF peut se faire à distance, par le biais des listes de diffusion et des différents outils de travail en groupe. En pratique, les réunions physiques sont difficiles à ignorer. La participation à ces réunions coûte de l'argent (inscription, voyage, hôtel) et cela limite la diversité en favorisant les riches. La participation à distance ne résout pas tout (par exemple en raison du décalage horaire). Accroitre l'importance des réunions par rapport aux listes de diffusion serait donc un problème pour la diversité.
  • Les participants à l'IETF sont évidemment (et heureusement) des passionnés. Cela peut mener à affirmer un peu trop vigoureusement ses préférences, d'une manière qui peut intimider certains participants, et donc limiter la diversité, en excluant les groupes qui sont traditionnellement exclus de la prise de parole publique.
  • L'IETF travaille sur la technique. Il est parfaitement normal de privilégier l'opinion de ceux et celles qui sont techniquement plus compétents. Mais même une organisation technique comme l'IETF a des activités non techniques (comme le choix des personnes qui assumeront des responsabilités) et, là, il n'y a aucune raison de n'écouter que les gens très forts en technique.
  • D'ailleurs, une partie du travail de l'IETF est de produire des documents (les RFC) qui ne doivent pas seulement être techniquement corrects, mais aussi être lisibles et compréhensibles, et pas seulement par les participants à l'IETF et pas non plus uniquement par des experts. Là encore, les compétences pour ce travail d'éducation ne sont pas forcément les mêmes que pour la technique pure et ne devraient donc pas être sous-estimées.

Mais il y a aussi des comportements anti-diversité plus directs et plus actifs comme le harcèlement ou l'intimidation. Ils peuvent être dirigés contre toutes les personnes appartenant (ou supposées appartenir) à tel ou tel groupe (comme « les femmes » ou « les homosexuels ») ou bien dirigés contre des individus spécifiques (comme l'abominable GamerGate). Aucun cas précis n'a été dénoncé à l'IETF, contrairement à ce qui arrive dans d'autres organisations, mais cela ne veut pas dire que cela n'arrivera jamais, ni même que cela n'est pas déjà arrivé : tous les cas ne sont pas publics, par exemple parce que les victimes peuvent hésiter à se plaindre, en raison du risque de représailles. Un futur RFC décrira la politique de l'IETF au sujet du harcèlement.

Malheureusement, ce RFC 7704 continue à décrire un environnement sans harcèlement comme « professional » comme si des actions aussi graves que celles du GamerGate étaient juste un manque de professionnalisme !

La section 3 du RFC s'occupe plutôt de propositions constructives : comment faire pour que tout le monde se sente bienvenu, de manière à augmenter la diversité ? Par exemple, le RFC recommande aux anglophones (la langue de travail de l'IETF est l'anglais) de parler lentement et clairement, et d'éviter les idiosyncrasies locales, ou les références culturelles trop locales (ah, ces allusions agaçantes à des émissions télé US que les non-États-Uniens n'ont pas vu...) Ainsi, la participation des non-anglophones pourra augmenter. Je note personnellement que, lorsqu'une réunion de l'IETF se tient aux États-Unis, les participants parlent bien plus vite et font moins attention à la diversité linguistique.

On peut aussi :

  • Encourager les timides à participer,
  • Avoir une attitude chaleureuse envers les nouveaux,
  • Ne pas laisser les plus expérimentés monopoliser la parole.

Tout cela n'est pas facile car il faut aussi tenir compte des exigences du travail : le but n'est pas juste d'être gentil mais surtout de créer les nouvelles normes techniques. Un exemple où il est difficile d'atteindre un bon équilibre est celui des réunions physiques des groupes de travail. L'IETF privilégie normalement l'efficacité : on saute directement dans le sujet, on ne passe pas son temps à expliquer, de toute façon, tout le monde est censé avoir travaillé avant, lisant les drafts et les discussions sur la liste de diffusion. Mais cette excellente façon de faire peut décourager les nouveaux, qui n'ont pas compris tous les tenants et aboutissants de la discussion.

Enfin, que faut-il faire contre les gens qui se comportent d'une manière qui peut faire fuir certain·e·s (section 4 du RFC) ? On peut les ignorer si ce n'est pas trop grave mais, au-delà d'un certain niveau de perturbation, il faut faire appel aux autorités (présidents du groupe de travail, ombudsperson, et président de l'IETF si nécessaire).

Quelques ressources supplémentaires sur l'activité de l'IETF à ce sujet :


Téléchargez le RFC 7704


L'article seul

RFC 7706: Decreasing Access Time to Root Servers by Running One on Loopback

Date de publication du RFC : Novembre 2015
Auteur(s) du RFC : W. Kumari (Google), P. Hoffman (ICANN)
Pour information
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 26 novembre 2015


Toute résolution DNS commence par la racine (de l'arbre des noms de domaine). Bien sûr, la mémorisation (la mise en cache) des réponses fait qu'on n'a pas besoin tout le temps de contacter un serveur racine. Mais c'est quand même fréquent et les performances de la racine sont donc cruciales. L'idée documentée dans ce RFC est donc d'avoir en local un serveur esclave de la racine, copiant celle-ci et permettant donc de répondre localement aux requêtes. Notez que ce RFC a depuis été remplacé par le RFC 8806.

Le problème est particulièrement important pour les noms qui n'existent pas. Si les TLD existants comme .com ou .fr vont vite se retrouver dans la mémoire (le cache) du résolveur DNS, les fautes de frappe ou autres cas où un TLD n'existe pas vont nécessiter la plupart du temps un aller-retour jusqu'au serveur racine le plus proche. Les réponses négatives seront également mémorisées mais 1) il y a davantage de noms non existants que de noms existants 2) le TTL est plus court (actuellement deux fois plus court). Ces noms non existants représentent ainsi la majorité du trafic de la racine.

Bien qu'il existe aujourd'hui des centaines de sites dans le monde où se trouve une instance d'un serveur racine, ce nombre reste faible par rapport au nombre total de réseaux connectés à l'Internet. Dans certains endroits de la planète, le serveur racine le plus proche est assez lointain. Voici les RTT en millisecondes avec les serveurs racine observés depuis un réseau tunisien (notez les deux serveurs qui répondent bien plus vite que les autres, car ils ont une instance à Tunis) :

% check-soa -4 -i .
a.root-servers.net.
	198.41.0.4: OK: 2015112501 (54 ms)
b.root-servers.net.
	192.228.79.201: OK: 2015112501 (236 ms)
c.root-servers.net.
	192.33.4.12: OK: 2015112501 (62 ms)
d.root-servers.net.
	199.7.91.13: OK: 2015112501 (23 ms)
e.root-servers.net.
	192.203.230.10: OK: 2015112501 (18 ms)
f.root-servers.net.
	192.5.5.241: OK: 2015112501 (69 ms)
g.root-servers.net.
	192.112.36.4: OK: 2015112501 (62 ms)
h.root-servers.net.
	128.63.2.53: OK: 2015112501 (153 ms)
i.root-servers.net.
	192.36.148.17: OK: 2015112501 (67 ms)
j.root-servers.net.
	192.58.128.30: OK: 2015112501 (55 ms)
k.root-servers.net.
	193.0.14.129: OK: 2015112501 (72 ms)
l.root-servers.net.
	199.7.83.42: ERROR: Timeout
m.root-servers.net.
	202.12.27.33: OK: 2015112501 (79 ms)
    

Ces délais peuvent sembler courts mais ils ne forment qu'une partie du travail de résolution, il est donc légitime de vouloir les réduire encore.

En outre, ces requêtes à la racine peuvent être observées, que ce soit par les opérateurs de serveurs racine, ou par des tiers sur le projet, ce qui n'est pas forcément souhaitable, question vie privée (cf. RFC 7626).

Donc, l'idée de base de ce RFC est de :

  • Mettre un serveur esclave de la racine sur sa machine, écoutant sur l'adresse locale (loopback),
  • Configurer le résolveur pour interroger d'abord ce serveur.

Cette idée est documentée dans ce RFC mais n'est pas encouragée (c'est un très vieux débat, dont j'avais déjà parlé). En effet, cela ajoute un composant à la résolution (le serveur local faisant autorité pour la racine), composant peu ou pas géré et qui peut défaillir, entrainant ainsi des problèmes graves et difficiles à déboguer. Mais pourquoi documenter une idée qui n'est pas une bonne idée ? Parce que des gens le font déjà et qu'il vaut mieux documenter cette pratique, et en limiter les plus mauvais effets. C'est pour cela, par exemple, que notre RFC demande que le serveur local n'écoute que sur les adresses locales, pour limiter les conséquences d'une éventuelle défaillance à une seule machine.

Dans tous les cas, le RFC recommande que la configuration décrite ici ne soit pas celle par défaut : l'utilisateur doit l'activer explicitement (et en supporter les conséquences).

Pas découragé ? Vous voulez encore le faire ? Alors, les détails pratiques. D'abord (section 2 du RFC), les pré-requis. DNSSEC est indispensable (pour éviter de se faire refiler un faux fichier de zone par de faux serveurs racine). Ensuite (section 3), vous mettez un serveur faisant autorité (par exemple NSD ou Knot) qui écoute sur une des adresses locales (en 127.0.0.0/8, IPv6 est moins pratique car il ne fournit paradoxalement qu'une seule adresse locale à la machine) et qui est esclave des serveurs racine. À noter que votre serveur, n'étant pas connu des serveurs racine, ne recevra pas les notifications (RFC 1996) et sera donc parfois un peu en retard sur la vraie racine (ce qui n'est pas très grave, elle bouge peu).

Il est important de lister plusieurs serveurs maîtres dans sa configuration. En effet, si la mise à jour de la racine dans votre serveur esclave échoue, ce sera catastrophique (signatures DNSSEC expirées, etc) et cette configuration locale, contrairement à la « vraie » racine, n'a aucune redondance. (Une autre raison pour laquelle ce n'est pas une idée géniale.) Quels serveurs maîtres indiquer ? Certains serveurs racine permettent le transfert de zone (RFC 5936) mais ce n'est jamais officiel, ils peuvent cesser à tout moment (l'annexe A du RFC donne une liste et discute de ce choix). Une raison de plus de se méfier.

Il est donc important d'avoir un mécanisme de supervision, pour être prévenu si quelque chose échoue. On peut par exemple interroger le numéro de série dans l'enregistrement SOA de la racine et vérifier qu'il change.

Ensuite, une fois ce serveur faisant autorité configuré, il ne reste qu'à indiquer à un résolveur (comme Unbound) de l'utiliser (section 4 du RFC).

Voici un exemple, pris dans l'annexe B du RFC et testé. J'ai choisi l'exemple avec NSD et Unbound mais il y en a d'autres dans le RFC. D'abord, la configuration de NSD (notez la longue liste de maîtres, pour maximiser les chances que l'un d'eux fonctionne ; notez aussi l'adresse loopback choisie, 127.12.12.12) :

# RFC 7706
server:
       ip-address: 127.12.12.12
zone:
       name: "."
       request-xfr: 192.228.79.201 NOKEY # b.root-servers.net
       request-xfr: 192.33.4.12 NOKEY    # c.root-servers.net
       request-xfr: 192.5.5.241 NOKEY    # f.root-servers.net
       request-xfr: 192.112.36.4 NOKEY   # g.root-servers.net
       request-xfr: 193.0.14.129 NOKEY   # k.root-servers.net
       request-xfr: 192.0.47.132 NOKEY   # xfr.cjr.dns.icann.org
       request-xfr: 192.0.32.132 NOKEY   # xfr.lax.dns.icann.org
       request-xfr: 2001:500:84::b NOKEY # b.root-servers.net
       request-xfr: 2001:500:2f::f NOKEY # f.root-servers.net
       request-xfr: 2001:7fd::1 NOKEY    # k.root-servers.net
       request-xfr: 2620:0:2830:202::132 NOKEY  # xfr.cjr.dns.icann.org
       request-xfr: 2620:0:2d0:202::132 NOKEY  # xfr.lax.dns.icann.org  

Le démarrage de NSD (notez qu'il faut patienter un peu la première fois, le temps que le premier transfert de zone se passe) :

Nov 25 19:50:43 machine-locale nsd[2154]: [2015-11-25 19:50:43.791] nsd[2175]: notice: nsd started (NSD 4.1.2), pid 2154
Nov 25 19:50:56 machine-locale nsd[2154]: zone . serial 0 is updated to 2015112501.
Nov 25 19:50:56 machine-locale nsd[2154]: [2015-11-25 19:50:56.166] nsd[2154]: info: zone . serial 0 is updated to 2015112501.

C'est bon, on a transféré la zone. Testons (notez le bit AA - Authoritative Answer - dans la réponse) :


% dig  @127.12.12.12 SOA . 
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 61984
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 14, ADDITIONAL: 25
...
;; ANSWER SECTION:
.			86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. (
				2015112501 ; serial
... 

C'est bon.

Maintenant, la configuration d'Unbound (prise dans le RFC) :

server:
    # RFC 7706
    do-not-query-localhost: no
    
# RFC 7706
# Requires a slave auth. running (normally, nsd)
stub-zone:
       name: "."
       stub-prime: no
       stub-addr: 127.12.12.12

Et le test :


% dig www.cnam.fr
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 23562
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 3, ADDITIONAL: 3
...
;; ANSWER SECTION:
www.cnam.fr.		0 IN CNAME sarek.cnam.fr.
sarek.cnam.fr.		86400 IN A 163.173.128.52

Ça a marché. Avec tcpdump, on voit le trafic (faible, en raison du cache) vers le serveur racine local :

08:37:24.869569 IP (tos 0x0, ttl 64, id 7734, offset 0, flags [none], proto UDP (17), length 76)
    127.0.0.1.10908 > 127.12.12.12.53: 42633% [1au] A? www.tunisair.com.tn. (48)
08:37:24.869671 IP (tos 0x0, ttl 64, id 12657, offset 0, flags [none], proto UDP (17), length 685)
    127.12.12.12.53 > 127.0.0.1.10908: 42633- 0/8/13 (657)
08:38:04.734565 IP (tos 0x0, ttl 64, id 12887, offset 0, flags [none], proto UDP (17), length 71)
    127.0.0.1.45221 > 127.12.12.12.53: 25787% [1au] A? www.edreams.es. (43)
08:38:04.734645 IP (tos 0x0, ttl 64, id 19270, offset 0, flags [none], proto UDP (17), length 749)
    127.12.12.12.53 > 127.0.0.1.45221: 25787- 0/10/14 (721)
08:38:04.734867 IP (tos 0x0, ttl 64, id 12888, offset 0, flags [none], proto UDP (17), length 70)
    127.0.0.1.40575 > 127.12.12.12.53: 61589% [1au] AAAA? ns-ext.nic.cl. (42)
08:38:04.734932 IP (tos 0x0, ttl 64, id 19271, offset 0, flags [none], proto UDP (17), length 622)
    127.12.12.12.53 > 127.0.0.1.40575: 61589- 0/8/11 (594)
08:44:00.366698 IP (tos 0x0, ttl 64, id 27563, offset 0, flags [none], proto UDP (17), length 62)
    127.0.0.1.22009 > 127.12.12.12.53: 30565% [1au] A? po.st. (34)
08:44:00.389126 IP (tos 0x0, ttl 64, id 34039, offset 0, flags [none], proto UDP (17), length 404)
    127.12.12.12.53 > 127.0.0.1.22009: 30565- 0/6/5 (376)
08:44:01.229635 IP (tos 0x0, ttl 64, id 27693, offset 0, flags [none], proto UDP (17), length 69)
    127.0.0.1.65173 > 127.12.12.12.53: 32911% [1au] AAAA? ns3.perf1.eu. (41)
08:44:01.229705 IP (tos 0x0, ttl 64, id 34207, offset 0, flags [none], proto UDP (17), length 560)
    127.12.12.12.53 > 127.0.0.1.65173: 32911- 0/8/10 (532)
    

À noter qu'il existe un brevet futile (comme tous les brevets...) de Verisign sur cette technique : déclaration #2539 à l'IETF.


Téléchargez le RFC 7706


L'article seul

RFC 7695: Distributed Prefix Assignment Algorithm

Date de publication du RFC : Novembre 2015
Auteur(s) du RFC : P. Pfister, B. Paterson (Cisco Systems), J. Arkko (Ericsson)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF homenet
Première rédaction de cet article le 25 novembre 2015


Le projet Homenet, qui vise à relier en un réseau local autonome tous les objets électroniques de la maison, avance (cf. RFC 7368). Parmi les briques indispensables à l'édification de ce réseau de la maison, il fallait un mécanisme d'allocation des adresses IP. Un réseau Homenet devant fonctionner sans administration système, ce mécanisme devait être entièrement automatique. C'est ce que propose ce RFC.

Contrairement au traditionnel réseau domotique actuel, le réseau Homenet peut être constitué de plusieurs réseaux (au sens IP du terme), avec chacun son préfixe IPv6. Si la maison a un préfixe IPv6 délégué, il faut le découper et affecter les sous-préfixes à chaque réseau de la maison. Normalement, c'est le travail de l'administrateur réseaux, qui centralise l'information puis la distribue. Mais, à la maison, il n'y a personne qui puisse ou veuille faire ce travail, il faut donc l'automatiser. Et ce doit être un algorithme réparti car un réseau Homenet n'a pas de machine « chef ».

Cet algorithme prend en entrée une liste de préfixes (le ou les préfixes délégués à la maison), et répartit les sous-préfixes à chaque lien de façon à ce que chaque lien reçoive au plus un sous-préfixe de chacun des préfixes délégués, qu'il n'y ait pas de recouvrement entre les préfixes, et que le tout soit stable, tant que la topologie du réseau ne change pas (cf. section 3 sur les conditions d'usage de cet algorithme).

Le principe (section 4) est que chaque routeur (je simplifie : ce n'est pas forcément un routeur qui choisit le préfixe) va, pour chaque lien, tirer au hasard (pour minimiser le risque de collision), un préfixe plus spécifique que le préfixe délégué et le transmettre ensuite à tout le réseau, via un algorithme d'inondation. Notez bien que c'est une présentation simplifiée : par exemple, le préfixe initial n'est pas forcément tiré au hasard (cf. section 5).

Cet algorithme dépend donc de l'existence d'un algorithme d'inondation, qui n'est pas spécifié dans ce RFC, plusieurs sont envisageables (comme ceux de OSPF - cf. RFC 7503 - ou de HNCP - Home Networking Control Protocol). Il dépend aussi de l'existence d'un identificateur unique par nœud (rappelez-vous que ce RFC n'est qu'une seule des briques d'Homenet, il n'est pas utilisable seul, par exemple il ne dit pas comment cet identificateur est attribué), et que ces identificateurs ont un ordre. Cela servira au cas où plusieurs routeurs veulent le même préfixe, avec la même priorité (celui qui a l'identificateur le plus grand gagne).

Parmi les nombreuses options de l'algorithme, notez qu'il gère également le cas où le lien a déjà eu un préfixe alloué et souhaite le réutiliser. (Une telle stabilité est souhaitable.)

Enfin, la section 8, sur la sécurité, rappelle que ce protocole n'a pas de protection contre un acteur malveillant. Par exemple, un routeur gourmand qui se prend le préfixe entier pour l'un de ses liens empêche les autres de le réclamer. Un méchant peut aussi annoncer quelque chose tout le temps pour empêcher la convergence, réalisant ainsi une attaque par déni de service. En outre, cet algorithme dépend de la sécurité de l'algorithme d'inondation et de celle du mécanisme de sélection de l'identificateur.

Une mise en œuvre de HNCP en logiciel libre existe, hnetd. Elle contient cet algorithme (cf. fichiers src/pa_core*, « pa » signifiant prefix assignment).


Téléchargez le RFC 7695


L'article seul

Ah, il y a une différence entre nom de domaine et nom de machine ?

Première rédaction de cet article le 24 novembre 2015


Un cas intéressant cité par Phil Mayers sur la liste des utilisateurs de BIND va me permettre, cher lecteur, de t'instruire sur la différence entre nom de domaine et nom de machine.

La question originale était de savoir pourquoi on pouvait faire une résolution DNS (par exemple avec dig) de nexistesurementpas.um.outlook.com alors que les commandes comme ping ne pouvaient pas utiliser ce nom :

% dig +short nexistesurementpas.um.outlook.com
*.um.outlook.com.glbdns2.microsoft.com.
wildcard-emeasouth.um.outlook.com.
157.55.9.252
    

On récupère bien une adresse IP (c'est pareil avec d'autres outils DNS comme host) mais :

% ping nexistesurementpas.um.outlook.com
ping: unknown host nexistesurementpas.um.outlook.com
    

Mais, alors, pourquoi est-ce que ping prétend que ce nom n'existe pas ? (Le problème n'est pas spécifique à ping, d'autres commandes comme telnet font le même diagnostic.)

L'explication est qu'il existe une différence entre les noms de domaine (domain names) et les noms de machines (host names). Les premiers permettent à peu près tous les caractères possibles (cf. RFC 2181, section 11, et regardez le nom &-funny-%-syntax-$.bortzmeyer.org pour s'en convaincre). Les seconds obéissent à une syntaxe bien plus restrictive, documentée dans le RFC 1123, section 2.1. En gros, un nom de machine est restreint à LDH (Letters, Digits and Hyphen). C'est pour cela que je peux résoudre le nom rigolo indiqué plus haut :

% dig +short +nodnssec '&-funny-%-syntax-$.bortzmeyer.org'
www.bortzmeyer.org.
204.62.14.153
    

Mais que je ne peux pas l'utiliser :

% ping '&-funny-%-syntax-$.bortzmeyer.org'
ping: unknown host &-funny-%-syntax-$.bortzmeyer.org
    

(Notez qu'il a fallu l'encadrer d'apostrophes car certains caractères sont spéciaux pour le shell Unix.)

Arrivé à ce stade, mes lecteurs et lectrices, qui sont très malins, se grattent la tête « OK dans l'exemple avec &-funny-%-syntax-$.bortzmeyer.org mais le nom au début, nexistesurementpas.um.outlook.com, est parfaitement conforme au RFC 1123, lui ! » Il faut examiner de plus près le processus de résolution DNS :

% dig  nexistesurementpas.um.outlook.com 
...
;; ANSWER SECTION:
nexistesurementpas.um.outlook.com. 0 IN	CNAME *.um.outlook.com.glbdns2.microsoft.com.
*.um.outlook.com.glbdns2.microsoft.com.	0 IN CNAME wildcard-emeasouth.um.outlook.com.
wildcard-emeasouth.um.outlook.com. 300 IN A 157.55.9.252
    

Le nom est en fait un pointeur (enregistrement DNS de type CNAME) vers un nom canonique, *.um.outlook.com.glbdns2.microsoft.com (qui, à son tour, pointe vers un autre nom canonique, wildcard-emeasouth.um.outlook.com, mais ce n'est pas important ici).

Or, le sous-programme getaddrinfo(), qu'appellent les applications pour résoudre un nom en adresse IP, teste la validité de ces noms. Sur les systèmes utilisant la GNU libc (ce qui est le cas de l'Ubuntu sur laquelle j'ai fait les tests), getaddrinfo est encore plus violent, il teste tous les noms de la chaîne. Arrivant au *.um.outlook.com.glbdns2.microsoft.com, il le rejette car contenant un caractère invalide, l'astérisque. Ainsi, la résolution échoue et le nom est considéré comme inconnu. (Les fanas du DNS noteront que, dans un fichier de zone, l'astérisque a un sens spécial, faisant du nom un joker. Mais ça n'a pas d'importance ici : c'est un caractère illégal, point.)

À noter que le résultat dépend du système d'exploitation utilisé car toutes les mises en œuvre de getaddrinfo ne sont pas aussi sévères. Apparemment, FreeBSD refuse ces noms, mais pas Mac OS ou Windows. Ainsi, sur Mac OS, même le nom le plus bizarre est accepté :

$ ping -c 1 '&-funny-%-syntax-$.bortzmeyer.org'
PING www.bortzmeyer.org (204.62.14.153): 56 data bytes
64 bytes from 204.62.14.153: icmp_seq=0 ttl=51 time=73.471 ms

--- www.bortzmeyer.org ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 73.471/73.471/73.471/0.000 ms

Windows, lui, accepte le premier nom (la machine ne répond pas aux requêtes ICMP mais peu importe) :

E:\Users\moi>ping -n 1 nexistesurementpas.um.outlook.com

Envoi d'une requête 'ping' sur wildcard-emeacenter.um.outlook.com [157.55.9.252] avec 32 octets de données :
Délai d'attente de la demande dépassé.

Statistiques Ping pour 157.55.9.252:
    Paquets : envoyés = 1, reçus = 0, perdus = 1 (perte 100%),

Les programmeurs n'ont qu'à jeter un œil au code source de la GNU libc, dans resolv/res_comp.c :


#define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \
		   || ((c) >= 0x61 && (c) <= 0x7a))
#define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)

#define borderchar(c) (alphachar(c) || digitchar(c))
#define middlechar(c) (borderchar(c) || hyphenchar(c) || underscorechar(c))
#define	domainchar(c) ((c) > 0x20 && (c) < 0x7f)

int
res_hnok(const char *dn) {
	int pch = PERIOD, ch = *dn++;

	while (ch != '\0') {
		int nch = *dn++;

		if (periodchar(ch)) {
			(void)NULL;
		} else if (periodchar(pch)) {
			if (!borderchar(ch))
				return (0);
		} else if (periodchar(nch) || nch == '\0') {
			if (!borderchar(ch))
				return (0);
		} else {
			if (!middlechar(ch))
				return (0);
		}
		pch = ch, ch = nch;
	}
	return (1);
}	

    

Ce code teste que le nom de machine suit l'expression rationnelle [a-z0-9\.\-]+ (pas tout à fait : il autorise aussi le trait bas à certains endroits, ce qui est une erreur). Le code équivalent pour FreeBSD est gethostbydns.c.

À noter qu'on a testé que le cas où le nom illégal est au milieu de la chaîne des pointeurs. Il serait intéressant de refaire le test avec tous ces systèmes d'exploitation pour les cas où le nom illégal est au début ou à la fin de cette chaîne.

Un post-scriptum pour mes lecteurs juristes : les définitions de domaine et de machine utilisées ici sont évidemment celles des RFC. Mais le gouvernement se moque bien de la terminologie existante et, dans sa hâte de contrôler l'Internet, il invente un vocabulaire bizarre. C'est ainsi que le décret français n° 2015-125 du 5 février 2015, qui institue la censure administrative en France a cette définition pittoresque « Les adresses électroniques figurant sur la liste 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. »

Merci à Kim-Minh Kaplan pour la discussion et à Vincent Archer et Pascal Courtois pour avoir prêté des machines à la science.


L'article seul

RFC 7696: Guidelines for Cryptographic Algorithm Agility and Selecting Mandatory-to-Implement Algorithms

Date de publication du RFC : Novembre 2015
Auteur(s) du RFC : R. Housley (Vigil Security)
Première rédaction de cet article le 22 novembre 2015


Bien des protocoles de l'IETF utilisent la cryptographie. Ils s'en servent pour la confidentialité, pour l'authentification, pour la signature. L'utilisation pour la confidentialité a évidemment crû en importance depuis les révélations d'Edward Snowden, malgré la guerre contre le chiffrement que mènent de nombreux gouvernements, qui voudraient pouvoir continuer à espionner tranquillement leurs citoyens. Or, un problème de la cryptographie est que les algorithmes ne sont pas éternels : la cryptanalyse trouve parfois, au bout d'un temps plus ou moins long, des moyens de casser un algorithme, qui doit alors être abandonné. Ce fut le cas, par exemple, de RC4, rejeté dans le RFC 7465. Il est donc indispensable que les protocoles utilisant la cryptographie aient la propriété d'agilité. Cette propriété désigne le fait qu'on puisse changer d'algorithme sans changer le protocole.

Pour des raisons d'interopérabilité, l'IETF désigne toujours un algorithme cryptographique comme obligatoire : ainsi, deux mises en œuvre d'un protocole donné auront toujours au moins un algorithme en commun, l'algorithme obligatoire, et pourront donc interopérer. Mais l'algorithme obligatoire peut lui aussi céder un jour face à la cryptanalyse, et il faut donc également prévoir le moyen de le remplacer.

[Au passage, la plupart des protocoles IETF utilisent non pas un algorithme unique mais une liste d'algorithmes, la cipher suite. Par exemple, pour TLS, cette liste comprend un algorithme de chiffrement asymétrique (comme RSA), un de chiffrement symétrique (comme AES) et un de condensation (comme SHA-2).]

Revenons à la cryptanalyse. Les algorithmes « vieillissent » donc avec le temps, au fur et à mesure que les cryptanalystes découvrent de nouvelles méthodes pour casser l'algorithme. Ce vieillissement n'est pas régulier et n'est pas prévisible. Certains algorithmes sont cassés dans les années qui suivent immédiatement leur publication, d'autres résistent encore (plus ou moins bien) des dizaines d'années après. Ce qui est sûr, c'est que les attaques, au pire stagnent, au mieux se perfectionnent avec le temps : un algorithme ne peut donc pas « rajeunir ». C'est ce vieillissement inéluctable (quoique de durée très variable) qui justifie le principe d'agilité cryptographique.

Le principe est simple et semble excellent. Mais l'expérience de la communauté Internet est qu'il est difficile de changer les vieux algorithmes vulnérables par des nouveaux. Même une fois le nouvel algorithme normalisé par l'IETF, et une fois qu'il est mis en œuvre dans les logiciels les plus répandus, on constate souvent que la mise à jour des logiciels est lente et que, des années après l'abandon officiel d'un algorithme, il est toujours disponible et activé dans des millions de machines (et parfois, il est même le seul disponible). Il est donc difficile de supprimer un vieil algorithme vulnérable (comme MD5, cf. RFC 6151), ne serait-ce que pour des raisons d'interopérabilité : si une machine ne sait condenser qu'avec MD5, les machines équipées d'un logiciel plus récent, qui gère SHA-2 et d'autres, devront bien accepter de parler avec MD5 ou, sinon, plus de communication. Bref, les algorithmes morts continuent à hanter l'Internet pendant très longtemps. Pensons par exemple aux administrateurs système qui hésitent encore à supprimer le protocole SSLv3 (cf. RFC 7568) de leurs serveurs HTTPS, de peur de ne plus pouvoir accepter les clients MSIE 6. Il faut souvent recourir à des méthodes de name and shame comme le test de SSLlabs (qui fait aussi de la gamification, avec ses notes) pour TLS : « cette banque est nulle, leur serveur HTTPS accepte encore 3DES » (ce que le RFC nomme pudiquement « social pressure »).

Passons au concret avec la section 2 de notre RFC. Il s'agit de règles internes à l'IETF qu'il est fortement recommandé de suivre lors du développement de nouveaux protocoles, pour permettre l'agilité cryptographique. D'abord, évidemment, les protocoles IETF ne doivent pas être liés à un algorithme unique, puisque le cassage de celui-ci entrainerait la fin du protocole. Pour permettre le choix d'un algorithme, il faut que chaque algorithme (ou chaque liste d'algorithmes) ait un identificateur, un nombre ou une chaîne de caractères qui désigne un algorithme donné. Ainsi, pour DNSSEC, ces identificateurs (8 pour la liste RSA avec SHA-256, 13 pour la liste ECDSA avec la courbe P-256 et SHA-256, etc) sont stockés dans un registre IANA. TLS, lui, utilise des chaînes de caractères comme TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 qui veut dire « échange de clés Diffie-Hellman avec courbes elliptiques, authentification avec RSA, chiffrement symétrique en AES mode GCM, condensation avec SHA-256 ». Cet identificateur est donc la première étape indispensable vers l'agilité cryptographique.

Faut-il un identificateur par algorithme, identificateurs que l'on combine ensuite pour obtenir la liste utilisée, comme le fait IKE (RFC 7296) ou bien un identificateur par liste, comme c'est le cas pour TLS (RFC 5246) ? La question n'est pas évidente. La première méthode permet d'avoir moins d'enregistrements. Mais toutes les combinaisons possibles n'ont pas forcément un sens donc enregistrer les listes (les combinaisons) peut être préférable. Notre RFC ne tranche pas là-dessus.

Dans tous les cas, pour que nos amis Alice et Bob puissent communiquer, il faut qu'ils aient un jeu d'algorithmes en commun (RFC 3365). D'une manière générale, l'IETF prête une grande attention à cette interopérabilité, d'où la notion d'algorithme obligatoire, ou plutôt « obligatoire à implémenter » (à mettre dans les programmes). Sans ces algorithmes obligatoires, on pourrait avoir deux implémentations parfaitement correctes du protocole, mais qui seraient dans l'impossibilité de dialoguer, puisqu'elles n'auraient aucun algorithme en commun. C'est pour cela que chaque protocole doit avoir un ou plusieurs algorithmes (ou listes, si on enregistre les listes) qui soient obligatoires. Pour DNSSEC, par exemple, c'est RSA-SHA1.

Et comme les algorithmes obligatoires peuvent eux aussi être cassés un jour, il est recommandé, pour faciliter leur changement, que le RFC spécifiant le protocole n'indique pas quels sont les algorithmes obligatoires, mais se réfère à un RFC plus court, sur ce sujet. On pourra ainsi modifier le RFC « Algorithmes » sans toucher au protocole. DNSSEC n'utilise pas cette méthode (l'algorithme obligatoire est défini dans le RFC 4034) mais JOSE (cryptographie pour JSON) le fait (les algorithmes sont définis dans le RFC 7518).

Pour la taille des clés utilisées pour ces algorithmes, notre RFC renvoie au RFC 3766 pour la cryptographie asymétrique et au RFC 7525 pour la symétrique.

En général, la mort d'un algorithme cryptographique n'est pas instantanée. Si, en théorie, il est possible qu'un mathématicien génial fasse une percée théorique inattendue qui rende tout à coup le cassage de tel algorithme trivial, en pratique, cela n'arrive que très rarement : on voit plutôt des attaques de plus en plus perfectionnées, un algorithme de plus en plus déconseillé jusqu'à son abandon officiel. C'est un domaine où il y a peu de « coups de tonnerre dans un ciel bleu ». Le passage de DES à AES s'est ainsi étalé sur des dizaines d'années, et celui de RSA vers les courbes elliptiques prendra sans doute autant de temps.

Pour prévenir les programmeurs des changements qu'on peut sans doute attendre, notre RFC recommande, dans l'esprit du RFC 4307, d'augmenter les termes normatifs définis dans le RFC 2119. Ce RFC définissait l'usage de MUST, SHOULD et MAY (en majuscules) dans les RFC. Notre nouveau RFC recommande d'utiliser également SHOULD+, SHOULD- et MUST-. Un SHOULD+ est la même chose qu'un SHOULD aujourd'hui (« cet algorithme devrait être implémenté, sauf si on a une très bonne raison et qu'on sait ce qu'on fait »). Mais, dans le futur, il est probable qu'il deviendra un MUST (algorithme obligatoire). Un SHOULD- est un SHOULD qui sera probablement dégradé en un simple MAY dans le futur. Quant au MUST-, il indique que l'algorithme est aujourd'hui obligatoire mais ne le restera sans doute pas.

Passer d'un algorithme à l'autre, on l'a vu, n'est pas trivial. Intuitivement, on se dit que l'IETF normalise le nouvel (et meilleur algorithme), que les programmeurs le programment dans les logiciels et que, au bout d'un moment, les nouveaux logiciels sont assez répandus pour qu'on puisse abandonner officiellement l'ancien algorithme.

Cela suppose qu'on sache mesurer l'état du déploiement et, pour beaucoup de protocoles, il n'y a pas de mécanisme de centralisation des statistiques. On ne sait donc pas si on peut « couper le cordon » et abandonner l'ancien algorithme.

C'est pour cela que la tendance est à mettre dans les nouveaux protocoles un mécanisme de signalisation, permettant de voir le déploiement du nouvel algorithme (par exemple le RFC 6975 pour DNSSEC).

Comme le déploiement est toujours trop long, on peut potentiellement se retrouver dans des situations ennuyeuses où l'ancien algorithme, désormais facilement cassé, est encore largement utilisé. Faut-il alors le supprimer des implémentations, remettant ainsi en cause l'interopérabilité, ou bien le laisser alors qu'on sait que cela met en cause la sécurité ? Débat cornélien qui agite régulièrement le monde TLS, par exemple. Il y a quelques années, la tendance était plutôt à laisser les algorithmes mourir tranquillement, de nos jours, elle est plutôt à éliminer rapidement les « canards boiteux », quitte à renoncer à la communication avec les vieux logiciels. C'est ainsi que l'abandon progressif de SHA-1, désormais largement attaqué, a été souvent fait de manière brutale (par exemple Google Chrome décidant soudainement de marquer les certificats utilisant SHA-1 comme étant dangereux).

L'agilité cryptographique n'a pas que des avantages. On a vu qu'elle était indispensable, pour tenir compte des progrès de la cryptanalyse. Mais, si un protocole accepte plusieurs algorithmes, comment s'assurer que les deux pairs qui négocient utilisent bien le plus fort ? Imaginons un protocole de chiffrement où le serveur indique à la connexion les algorithmes qu'il sait gérer et où le client en choisit un dans la liste, a priori le plus solide, et où le chiffrement démarre ensuite, avec l'algorithme choisi. Un attaquant actif, par exemple un Homme du Milieu, peut modifier la liste d'algorithmes pour mettre l'algorithme le plus faible, qu'il pourra ensuite casser. C'est ce qu'on nomme une attaque par repli (downgrade attack) et c'est la plaie des protocoles qui offrent l'agilité cryptographique. Il faut donc trouver un mécanisme de protection et ne pas garder éternellement les algorithmes trop vieux.

Un problème du même ordre se pose avec les protocoles qui permettent, non seulement de négocier les algorithmes de cryptographie, mais également le mécanisme d'échange initial des clés. C'est le cas d'EAP, par exemple (RFC 3748). Les concepteurs de protocole doivent se souvenir que la complexité est souvent la principale ennemie de la sécurité.

Compte tenu des problèmes que peut entrainer l'agilité cryptographique, notamment la complexité accrue du code, certains pourraient être tentés de concevoir des protocoles à un seul algorithme. Le protocole serait plus simple, et n'offrirait pas de possibilités d'attaques par repli. Un exemple de ce choix avait été WEP. Lié à un seul algorithme, ne pouvant pas évoluer, WEP avait été très long et compliqué à remplacer par un nouveau protocole, qu'il avait fallu concevoir, implémenter puis déployer. WEP est donc un bon exemple de l'importance de l'agilité cryptographique.

La section 3 de notre RFC examine sur quels critères choisir les algorithmes et notamment ceux qui seront obligatoires, et qui doivent donc être de haute qualité cryptographique. Évidemment, le choix ne doit pas être laissé à l'utilisateur final, qui n'a pas les éléments pour le faire. Il vaut mieux aussi qu'il ne soit pas laissé à l'administrateur système, qui n'est typiquement pas un expert en cryptographie. (Regardez la difficulté qu'il y a aujourd'hui à gérer un serveur HTTPS, avec tous ces choix pointus à faire en matière d'algorithmes. TLS est probablement un bon exemple du syndrome « trop de choix ».)

D'abord, les algorithmes obligatoires doivent évidemment faire l'objet d'une spécification publique (pendant longtemps, RC4 était secret). Il doivent avoir fait l'objet d'examens attentifs et de tentatives de cassage par des experts. De préférence, ils ne doivent pas faire l'objet de brevets. Ils doivent évidemment aussi répondre à des exigences plus techniques : ils doivent être rapides, implémentables dans un code de taille réduite, résister aux attaques par canal auxiliaire, etc.

Il existe des algorithmes de cryptographie dits « nationaux » parce que normalisés par une organisation de normalisation nationale officielle et parfois rendus obligatoires par une loi locale (si l'organisation de normalisation est le NIST, on ne les appelle pas « nationaux », le terme est réservé à ceux normalisés en dehors des États-Unis). Ils n'ont pas forcément fait l'objet d'une étude sérieuse et leur but est souvent de simple protectionnisme de l'industrie de sécurité nationale. Auquel cas ils ne doivent pas être choisis dans les protocoles IETF et en tout cas pas activés par défaut. (La section 3.4 du RFC fait pas mal de FUD : il existe d'excellents algorithmes « nationaux » comme ceux du GOST.)

Enfin, la section 4 du RFC, qui examine les questions de sécurité restantes, note que la force de l'algorithme n'est pas tout. Des faiblesses peuvent apparaitre, par exemple en raison de l'ordre des opérations de cryptographie (cf. RFC 7366)


Téléchargez le RFC 7696


L'article seul

Enrichir la communication ou les publicitaires ?

Première rédaction de cet article le 25 octobre 2015


Les FAI ne manquent pas d'imagination lorsqu'il s'agit de violer la neutralité du réseau. Un exemple récent est décrit dans l'article de Narseo Vallina-Rodriguez, Srikanth Sundaresan, Christian Kreibich et Vern Paxson, « Header Enrichment or ISP Enrichment? Emerging Privacy Threats in Mobile Networks », qui consiste à modifier les flux HTTP automatiquement pour ajouter, à l'insu de l'utilisateur, des informations personnelles qui seront utiles aux publicitaires qui gèrent les sites Web. Et cela se nomme cyniquement l'« enrichissement des en-têtes ».

Un exemple de fournisseur de matériel et logiciel qui propose cette technique est Juniper mais il y en a plein d'autres qui fournissent aux FAI sans scrupules des moyens de modifier les flux HTTP (HTTPS, pour l'instant, protège contre ces manipulations).

Est-ce que cette pratique est répandue ? On sait que, dans le monde de l'accès Internet par mobile, la neutralité du réseau est violée bien plus souvent (ce qui explique les campagnes marketing répétant en boucle que bientôt, X % des accès Internet seront par un mobile : il est important de convaincre les utilisateurs de passer à des technologies où la triche est plus fréquente). Avec quelle ampleur ? Les auteurs de l'article ont utilisé l'application Netalyzr pour récolter des données à ce sujet. Sur les 300 opérateurs mobile identifiés, 5 ajoutent des en-têtes qui compromettent la vie privée de l'utilisateur, 6 ajoutent des en-têtes qui permettent de suivre un utilisateur à la trace (remplaçant les cookies désormais trop bien connus des utilisateurs), 24 mettent des informations techniques dans ces en-têtes, informations qui peuvent mener également à des problèmes de vie privée (cf. RFC 7239).

Inutile de dire que la majorité des opérateurs en question sont situés dans les pays du Sud, où la vigilance des citoyens et leurs connaissances techniques sont plus faibles : nettement moins de chances de se faire prendre en Jordanie qu'en Californie ! Orange Jordanie fait partie des « enrichisseurs d'en-têtes » et ajoute le numéro de téléphone du client aux en-têtes HTTP qui seront récupérables par les publicitaires sur le site Web visité ! L'en-tête utilisé est msisdn:. (Notez que la documentation de Juniper citée plus haut utilisait exactement cela comme exemple, avec juste le préfixe x- qui indique traditionnellement qu'il s'agit d'un en-tête non standard.)

Le record appartient apparemment à Vodafone Afrique du Sud pour publier dans les en-têtes ajoutés le numéro de téléphone et l'IMEI (depuis la parution de l'article, ils semblent avoir arrêté).

Si la signification de l'en-tête ajouté subrepticement est parfois évidente (comme msidn:, Mobile Subscriber ISDN, cité plus haut), ce n'est pas toujours le cas. Par exemple, Verizon met un en-tête x-uidh: qui semble dédié au traçage : il est unique par abonné.

Enfin, il y a les en-têtes techniques, indiquant les logiciels utilisés pour cette opération. En France, SFR ajoute ainsi des x-bluecoat-via: (cf. la page Wikipédia sur cette sympathique entreprise), et des x-nokia-gateway-id:. Très souvent, l'opérateur (par exemple Bouygues et SFR en France) ajoute un x-forwarded-for: (en-tête depuis remplacé par un en-tête standard, cf. RFC 7239) qui indique l'adresse IP privée et peut aider au traçage d'un utilisateur. Sans compter les en-têtes mystérieux comme le x-vfstatus: chez SFR.

Bref, cet excellent travail de recherche montre que la neutralité de l'Internet n'est pas un problème abstrait : elle est violée tous les jours, et il est donc crucial qu'elle soit défendue.


L'article seul

RFC 7669: Assigning Digital Object Identifiers to RFCs

Date de publication du RFC : Octobre 2015
Auteur(s) du RFC : J. Levine (Taughannock Networks)
Pour information
Première rédaction de cet article le 25 octobre 2015


Depuis mai 2015, tous les RFC ont un DOI. C'est quoi et à quoi ça sert ? C'est ce qu'explique ce RFC avec lequel, je vous préviens, je ne suis pas du tout d'accord.

Les DOI sont un mécanisme d'identification formel de documents numériques. Par exemple, le RFC 7626 a désormais le DOI 10.17487/RFC7626. Les DOI sont désormais attribués à tous les RFC (et c'est rétroactif : le RFC 1 a le DOI 10.17487/RFC0001). Ils étaient prévus à l'origine pour être utilisé avec le système de résolution Handle (RFC 3650). Celui-ci s'étant complètement cassé la figure (et à juste titre), les DOI sont aujourd'hui résolus via un URI (par exemple, pour le RFC 7676, l'URI est https://dx.doi.org/10.17487/rfc7676).

Ce RFC explique que les DOI sont largement utilisés (y compris, désormais, par les RFC) mais oublie de dire que c'est souvent par obligation, par exemple parce que certaines bibliothèques numériques anglo-saxonnes refusent les documents qui n'ont pas de DOI.

Les DOI sont techniquement décrits par une norme ISO, la ISO 26324:2012. Comme presque toutes les normes du dinosaure ISO, elle n'est pas en accès libre. Si vous tenez à la lire, il vous en coûtera 88 francs suisses, et vous n'aurez pas le droit de la distribuer ensuite aux copains. (On note l'incohérence de l'IETF, qui avait signé une grandiose déclaration en faveur des SDO ouvertes.) Les DOI sont ensuite attribués de manière hiérarchique, l'IDF accréditant des agences qui attribuent ensuite des DOI.

Pourquoi des DOI et pas un autre type d'identificateurs ? La section 1 du RFC cite un passage du « Report on best practices for citability of data and on evolving roles in scholarly communication » qui tape sur les URI en montrant une grande incompréhension du sujet. Le document en question reproche aux URI leur manque de permanence, en oubliant la règle numéro 1 de la permanence des identificateurs : la permanence est une fonction de l'organisation, pas de la technique. Autrement dit, un URI peut être stable, s'il est géré par une organisation sérieuse. C'est exactement pareil pour un DOI. Si l'IDF, organisation purement privée, disparait, que deviendront les DOI ?

Notez aussi une particularité des RFC, qui peut être très intéressante pour leur trouver des identificateurs : les RFC sont immuables. Une fois publiés, ils ne sont jamais changés, même pas d'une virgule (le seul moyen de faire un changement est de publier un nouveau RFC). Résultat, on pourrait parfaitement désigner les RFC par un identificateur très stable, leur condensat, comme avec les NI du RFC 6920 (au passage, ce RFC 7669 a le NI ni:///sha256;NAuLJduQ-wP7LBI5nYQw0-Ubxh8DsQdVVaxooj4oYB4).

Un autre argument tout aussi erroné figure dans la section 1 : que les DOI permettent de trouver plus facilement la version gratuite des RFC en ligne. Il est vrai que des gens peu honnêtes ont vendu des versions payantes des RFC (ce qui est légal, les RFC sont libres d'utilisation) sans prévenir leurs acheteurs qu'ils pouvaient les obtenir gratuitement en ligne (ce qui est assez inéthique). Mais croire que les gens ont besoin des DOI pour trouver un RFC en ligne est assez fort de café ! (Cet argument est pourtant repris dans la section 3.)

La section 2 du RFC explique comment sont formés les DOI des RFC. Notez bien qu'un DOI est normalement opaque pour l'utilisateur : contrairement à un URI, il ne faut pas l'analyser pour en chercher des composantes. Néanmoins, si vous aimez savoir comment les choses sont faites, un DOI pour un RFC commence avec le préfixe 10.17487 (les DOI commencent toujours par 10, d'autres utilisations avaient été prévues avec d'autres nombres, mais n'ont jamais décollé), préfixe attribué aux RFC, et est suivi du texte rfc et du numéro du RFC. Le texte est apparemment insensible à la casse (en tout cas, les exemples du RFC sont tantôt en minuscules, tantôt en majuscules) mais, la norme n'étant pas librement accessible, je n'ai pas pu vérifier. Comme le DOI est opaque, il ne faut pas chercher à deviner un DOI pour un RFC donné. Par exemple, le numéro est actuellement formaté avec quatre chiffres mais cela pourra changer après le RFC 9999...

Comme indiqué plus haut, les vendeurs de DOI, après avoir répandu plein de FUD contre les URI, on finalement renoncé à leurs grandioses projets de déploiement de nouveaux protocoles et utilisent le même HTTP que tout le monde, avec les mêmes URI que tout le monde. Pour accéder à un DOI, on le préfixe par https://dx.doi.org/. On accède alors à une page Web fournie par l'entité qui a publié le document (et dont rien ne garantit donc la stabilité...) Cette page peut être le document recherché lui-même, une page de métadonnées avec un accès au document (c'est le cas des RFC) ou bien une page de métadonnées sans le document (cas des documents privés, non accessibles publiquement). Voir à ce sujet le « DOI Handbook »

Le processus d'attribution d'un DOI pour un RFC est décrit dans la section 4. Comme on l'a vu, il existe plusieurs agences d'attribution de DOI, dont plusieurs sont spécialisées dans un secteur très particulier. Le RFC Editor a choisi CrossRef, émanation des éditeurs. (Et qui n'est pas l'unique agence, contrairement à ce que dit le Wikipédia francophone.) Le coût d'adhésion à Crossref est de 660 dollars et chaque DOI attribué à un document coûte un dollar de plus.

Le DOI du RFC est maintenant inclus dans les bases distribuées par le RFC Editor. Tous les RFC qui citent un autre RFC doivent maintenant inclure le DOI (une obligation imposée par l'IDF, cf. la section 4.4 du RFC.) C'est fait automatiquement quand on utilise les outils comme xml2rfc (faut juste penser à vider le cache, en ~/.cache/xml2rfc d'abord, sinon certains RFC auront des DOI et pas d'autres).

L'attribution de DOI aux RFC parus précédemment a nécessité un peu de développement logiciel, utilisant l'API de Crossref pour solliciter les sept mille et quelques DOI des RFC existants.

Notez que tout cela s'est fait sans aucune concertation, ce qui est en contradiction avec les valeurs de l'IETF. Lorsque ce RFC a été soumis, la décision était déjà prise et mise en œuvre (l'annonce officielle date de mai 2015, avant, il fallait prêter attention à des appels d'offre du RFC Editor comme celui-ci).

D'autres solutions auraient pourtant été possibles. D'abord, l'IETF elle-même a plein de mécanismes d'identificateurs, à commencer évidemment par les URI du RFC 3986. Au sein des URI, des plans particulier (comme NI, cité plus haut) étaient possibles. En dehors de l'IETF, des identificateurs plus ouverts comme ARK auraient été un choix mais il semble que les éditeurs scientifiques anglo-saxons ont décidé d'imposer le DOI partout.

Concevoir un système d'identificateurs est moins simple qu'il n'y parait et les DOI ont été conçus par des gens qui n'avaient pas de compétences particulières en ce domaine. Ici, le but était clairement de respectabilité plus que d'améliorer la vie des utilisateurs (comme cela avait été le cas pour l'ISSN).


Téléchargez le RFC 7669


L'article seul

RFC 7686: The .onion Special-Use Domain Name

Date de publication du RFC : Octobre 2015
Auteur(s) du RFC : J. Appelbaum (The Tor Project,), A. Muffett (Facebook)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 24 octobre 2015


Le TLD .onion est utilisé par Tor pour nommer des serveurs Internet dont la localisation exacte est cachée. Tor est surtout connu pour permettre aux clients de demeurer relativement intraçables pendant leurs activités sur l'Internet, et .onion étend cette possibilité aux serveurs. Ce TLD n'avait aucune forme d'existence officielle avant, il avait juste été choisi comme cela et était reconnu par les logiciels Tor. Désormais, il est stocké dans le registre des noms de domaine spéciaux créé par le RFC 6761.

C'est politiquement une certaine forme de reconnaissance de la part de l'IETF pour ces services cachés de Tor (que TF1 et les ministres nomment le Dark Web). Mais cela ne changera pas grand'chose en pratique, .onion était utilisé depuis des années, illustrant d'ailleurs la déconnexion entre la réalité et certains professionnels de la gouvernance Internet, qui croient que l'ICANN est le « régulateur de l'Internet ».

Techniquement, cet enregistrement de .onion dans le registre des noms de domaine spéciaux mènera peut-être certains logiciels à intégrer une connaissance de ce TLD, pour ne pas faire de requêtes .onion dans le DNS (requêtes involontaires et qui peuvent « trahir » un utilisateur de Tor).

La section 1 de notre RFC rappelle le principe de Tor et des .onion. Tor est spécifié dans « Tor: the second-generation onion router ». Ses services cachés (dont la localisation du serveur est caché : le service lui-même est parfaitement visible, c'est le but) sont identifiés par un nom de domaine en .onion. Par exemple, celui de Facebook, société dont un employé est co-auteur du RFC, est facebookcorewwwi.onion. Comme c'est un nom de domaine, il peut s'utiliser partout où on utilise un nom de domaine, par exemple dans les URI. Ainsi, le blog d'Amaelle Guiton est accessible en http://ozawuyxtechnopol.onion/. Comme ce nom est spécial, on n'utilise pas le DNS pour trouver des données comme l'adresse IP. Un nom en .onion est un identificateur cryptographique (c'est le condensat de la clé publique du serveur). Il est « auto-authentifiant » ce qui veut dire que le client peut s'assurer qu'il parle au bon serveur, via la signature de la communication par la clé du serveur, sans avoir besoin, par exemple, d'un certificat, et ceci que le réseau sous-jacent soit de confiance ou pas. Comme l'identificateur est un condensat cryptographique, il n'est normalement pas compréhensible par un humain (voir la section 4 pour une nuance à cette affirmation, comme dans le cas du nom de Facebook ci-dessus).

Les noms en .onion sont générés localement, sans utiliser une autorité distincte (voir les explications pour mon blog). Aucun registre n'est utilisé (lors de la chaude discussion à l'IETF sur ce RFC, une minorité avait protesté contre le fait que cet enregistrement du TLD privait l'ICANN d'une source de revenus). On n'enregistre pas un nom en .onion, on ne le vend pas, on n'en est « propriétaire » que parce qu'on connait la clé privée correspondante (au passage, comme avec tous les identificateurs cryptographiques, de Namecoin à BitMessage, attention à vos clés privées ! Si elles sont perdues, vous n'avez aucun recours).

On a vu que .onion n'utilise pas le DNS. Pour éviter les collisions entre un nom extérieur au monde du DNS et un nom identique qui serait dans le DNS, le RFC 6761 avait introduit le concept de « noms de domaine spéciaux ». Ces noms ont la syntaxe et une partie de la sémantique des noms utilisés dans le DNS mais ne sont jamais supposés apparaitre dans le DNS. Dans le registre des noms spéciaux, on précise ce que doivent faire les différents composants du DNS (bibliothèques, résolveurs, registres, etc) s'ils rencontrent ces noms. À part les noms du RFC 2606, devenus « spéciaux » par la suite, le premier nom spécial enregistré était le .local d'Apple, via le RFC 6762. Comme pour .local, notre nouveau RFC demande que .onion soit traité spécialement par les logiciels DNS. En pratique, évidemment, cette demande ne sera pas honorée par tous et il y aura donc pendant encore longtemps des « fuites », des requêtes DNS pour .onion qui arrivent aux serveurs racine. Au moment de la publication de notre RFC, .local était le troisième TLD le plus demandé à la racine (derrière les indéboulonnables .com et .net, cf. les statistiques du serveur racine L) et le premier, de très loin, des TLD inexistants. Par comparaison, les fuites pour .onion sont négligeables.

La section 2 du RFC décrit quelles sont ces règles que devraient suivre les logiciels DNS (cette section est obligatoire pour mettre un nom dans le registre des noms spéciaux, cf. RFC 6761, section 5). Donc, voici les différents composants du DNS qui devraient (idéalement) traiter les .onion à part :

  • Les utilisateurs humains doivent savoir que les .onion ont des propriétés de sécurité particulières, et qu'ils ne sont accessibles qu'avec un logiciel spécial (comme le Tor Browser).
  • Les applications comme les navigateurs Web qui mettent en œuvre Tor doivent reconnaitre les noms en .onion et les passer à Tor. Les autres devraient générer une erreur tout de suite et ne pas tenter ces noms dans le DNS.
  • Les bibliothèques qui font de la résolution de noms (comme la glibc) doivent passer ces noms à Tor ou bien générer une erreur « ce nom n'existe pas », sans utiliser le DNS.
  • Les résolveurs DNS doivent renvoyer l'erreur NXDOMAIN (No Such Domain), idéalement sans utiliser le DNS, comme dans les deux catégories précédentes.
  • Les serveurs faisant autorité (a priori, cela ne concerne que ceux de la racine, les autres n'ayant aucune raison d'être interrogés pour ce nom) doivent également répondre NXDOMAIN.
  • D'ailleurs, les opérateurs de serveurs DNS ne doivent pas configurer un serveur pour répondre pour ces noms, qui ne doivent être traités que par Tor.
  • Les registres et BE ne doivent évidemment pas accepter d'enregistrer des noms en .onion...

Le RFC précise explicitement que l'IANA est autorisée à mettre dans la zone racine un mécanisme pour réserver le nom (comme, je suppose, celui du RFC 7535). Et que les opérateurs non-DNS (par exemple les AC, voir la déclaration du CAB sur les .onion) peuvent évidemment stocker des noms en .onion.

Pourquoi ces demandes répétées de ne pas tenter de résoudre les noms dans le DNS ? Car cela ferait connaitre à l'extérieur, en clair, les services Tor cachés auquel vous tentez d'accéder, ce qui annulerait l'effet anonymisant de Tor. Par exemple, ici j'utilise par erreur un logiciel non-Tor pour accéder au blog d'Aeris :

% curl http://blog.aeriszyr4wbpvuo2.onion/
curl: (6) Could not resolve host: blog.aeriszyr4wbpvuo2.onion
   

Et si quelqu'un d'indiscret, sur un serveur racine, regardait le trafic, il a vu (ici, avec tcpdump) :

18:36:10.252749 IP6 2001:db8:8bd9:8bb0:21e:8cff:fe76:29b6.33562 > 2001:1608:10:167:32e::53.53: \
                65162% [1au] A? blog.aeriszyr4wbpvuo2.onion. (56)
18:36:10.284260 IP6 2001:1608:10:167:32e::53.53 > 2001:db8:8bd9:8bb0:21e:8cff:fe76:29b6.33562: \
                65162 NXDomain*- 0/9/1 (1129)

que non seulement je suis un mauvais citoyen qui utilise Tor malgré les injonctions d'un gouvernement bienveillant qui explique qu'il ne faut utiliser que la « cryptographie légale », mais en plus l'indiscret a le nom du site qui m'intéressait (RFC 7626).

En parlant du risque de fuite, la section 4 de notre RFC est consacrée à la sécurité. Outre ce problème de logiciels trop bavards qui en révèlent trop à l'extérieur via les requêtes DNS, elle mentionne le risque de se tromper de nom .onion.

En effet, les noms en .onion sont certes auto-vérifiables, via la cryptographie, mais cela suppose d'utiliser le bon nom. Si un utilisateur se trompe, ou bien fait trop confiance à un nom indiqué sur un canal IRC de numéristes radicalisés, il peut atterrir sur le mauvais site .onion. Le risque est d'autant plus élevé que les noms en .onion sont typiquement illisibles par un humain (des techniques, coûteuses en temps de calcul, permettent de générer des noms plus jolis, comme celui de Facebook cité plus haut).

Les utilisateurs pourraient aussi se faire avoir par ignorance de la syntaxe des noms de domaine. Par exemple, un utilisateur ordinaire pourrait être trompé en croyant que www.onion.example est protégé par Tor ce qui n'est pas du tout le cas.

Il y a aussi des attaques plus techniques. Un nom en .onion est le condensat d'une clé cryptographique. Casser cette clé (trouver la partie privée en n'ayant que la partie publique) nécessite des ressources de calcul colossales mais trouver une clé ayant le même condensat (et donc le même nom .onion) est moins coûteux (tout est relatif : il faudra quand même de la puissance de calcul et du temps), et cela pourrait permettre de créer un faux service caché indistinguable du vrai.

Si vous voulez en savoir plus sur comment fonctionnent ces noms en .onion (je trouve personnellement que la documentation disponible est insuffisante), voyez les guides officiels « Special Hostnames in Tor » et « Tor Rendezvous Specification ».

L'enregistrement de .onion dans les noms de domain spéciaux a été l'occasion d'un long et houleux débat à l'IETF, tournant parfois au psychodrame, comme toujours quand on parle des TLD. En gros, il opposait les « conservateurs », méfiants vis-à-vis de ces nouveaux services pair à pair et soucieux de rester « respectable » aux yeux de l'ICANN, aux « pairàpairistes » qui ne se soucient pas de l'ICANN et ne sont pas satisfaits du système de nommage actuel. Le RFC 6761, qui fournit la base de cet enregistrement, a été très contesté (bien plus que lorsqu'il a servi à enregistrer le TLD d'Apple .local...). L'IETF a finalement pris la décision d'enregistrer .onion mais de fermer la porte juste après aux autres demandes en attente (comme .gnu ou .bit) en attendant une éventuelle révision du RFC 6761. Voici l'article qui annonce cette décision. Ce sera un des points chauds de la prochaine réunion de l'IETF à Yokohama.


Téléchargez le RFC 7686


L'article seul

RFC 7676: IPv6 Support for Generic Routing Encapsulation (GRE)

Date de publication du RFC : Octobre 2015
Auteur(s) du RFC : C. Pignataro (Cisco Systems), R. Bonica (Juniper Networks), S. Krishnan (Ericsson)
Chemin des normes
Première rédaction de cet article le 23 octobre 2015


Le protocole GRE est le plus simple mécanisme de tunnel normalisé. Il est mis en œuvre sur d'innombrables systèmes, et très largement répandu. Pour reprendre la formule de James Raftery, GRE est « The AK-47 of guerrilla networking. Cheap, simple, gets all sorts of dirty jobs done. ». Il ne fonctionnait traditionnellement qu'avec IPv4 mais bien des mises en œuvre de GRE avaient été adaptées à IPv6 depuis longtemps. Ce RFC décrit cette adaptation.

GRE, spécifié dans les RFC 2784 et RFC 2890, permet de transporter n'importe quoi sur n'importe quoi. On peut faire de l'IPv4 dans IPv4, de l'IPv6 dans l'IPv6, de l'IPv4 dans IPv6 ou le contraire. En termes GRE, IPv6 peut être la charge utile (payload, IPv6 sur autre chose) ou bien le support (delivery, quelque chose sur IPv6).

Le format des en-têtes GRE (RFC 2784, section 2) ne change pas avec ce RFC. Il y a juste la forte recommandation de ne pas utiliser la somme de contrôle GRE. Cela diminue la charge de calcul pour les machines aux extrémités du tunnel GRE, charge qui était peu utile car cette somme de contrôle GRE est largement redondante avec celle que fournissent IP (pour IPv4 seulement), TCP ou UDP. Néanmoins, on a toujours le droit de mettre une somme de contrôle, en cas d'environnement très hostile. (Cf. RFC 6935 à propos des sommes de contrôle et des tunnels.)

D'abord, le cas où IPv6 est la charge utile (section 3 de notre RFC), encapsulé dans... ce qu'on veut, IPv4 ou IPv6. Dans l'en-tête GRE, le champ Protocol Type (RFC 2784, section 2.4) doit être mis à 0x86DD (c'est la même valeur que lorsque IPv6 est porté sur Ethernet, cf. RFC 7042).

Qui dit tunnel dit problèmes de MTU. Pour limiter les dégâts, notre RFC impose que tout tunnel GRE qui transporte de l'IPv6 ait une MTU d'au moins 1 280 octets, ce qui est la valeur minimum requise par IPv6. (Plus précisement, notre RFC demande que le tunnel puisse transporter des paquets de 1 280 octets sans utiliser la fragmentation IP. Cela peut se faire en ayant une MTU >= 1 280 octets ou bien en ayant un système de fragmentation et réassemblage sous IP.) Avec cette règle, on est au moins sûrs que les paquets IPv6 prudents (ceux limités à 1 280 octets) passeront.

En théorie, une mise en œuvre standard de GRE doit tester cette possibilité, avant d'envoyer des paquets IPv6. (Celles d'aujourd'hui ne le font apparemment pas souvent, cf. RFC 7588.)

Et si le point d'entrée du tunnel GRE reçoit un paquet qui est plus grand que la MTU du tunnel ? Rappelez-vous qu'une des principales différences entre IPv4 et IPv6 est que, en IPv6, les routeurs sur le trajet n'ont pas le droit de fragmenter : si c'est nécessaire, cela doit être fait à la source. (Notez aussi que les machines d'entrée et de sortie du tunnel font un travail proche de celui d'un routeur mais que ce ne sont pas exactement des routeurs.) Donc, si le paquet trop gros arrive, le point d'entrée du tunnel doit faire ce que fait un routeur IPv6 : jeter le paquet et envoyer un message ICMP Packet Too Big.

Et le contraire, IPv6 comme réseau sous-jacent, pour transporter n'importe quoi, de l'IPv4 ou de l'IPv6 (section 4 de notre RFC) ? Le paquet IPv6 va comporter l'en-tête IPv6, zéro, un ou davantage en-têtes d'extensions, puis la charge utile, faite d'un en-tête GRE et des données (un paquet IPv4 ou IPv6). S'il n'y a pas d'en-têtes d'extension IPv6, le champ Next Header d'IPv6 vaut 47 (la valeur enregistrée pour GRE). S'il y a un ou plusieurs en-têtes d'extension, le dernier doit avoir, dans son champ Next Header, cette même valeur 47.

Comme l'en-tête IPv6 n'a pas de somme de contrôle, une distribution du paquet à la mauvaise machine est toujours possible. Le comportement normal de cette machine qui reçoit un paquet inattendu est de le jeter silencieusement. Si elle parle GRE elle-même, elle peut faire la décapsulation et faire suivre le paquet (cela me semble très dangereux, permettant de faire relayer les paquets par des machines « ouvertes »).

Enfin, la section 6 de notre RFC se penche sur la sécurité de GRE. Cela va vite car elle est à peu près nulle (cf. RFC 6169). Notamment, contrairement à beaucoup de tunnels modernes, GRE ne chiffre pas. Si on veut de la confidentialité pour les données transportées, il ne faut pas utiliser GRE. GRE reste très utile quand on veut simplement contourner le routage IP normal et établir une forme de routage manuellement contrôlée (j'ai décrit un exemple réel d'un tel cas).

Comme indiqué plus haut, il existe déjà plusieurs mises en œuvre de GRE IPv6. Faisons quelques essais avec des machines Linux. D'abord, IPv6 dans IPv4 (oui, il existe d'autres protocoles que GRE pour tunneler IPv6 dans IPv4, je suis au courant, cf. RFC 7059 pour une comparaison des tunnels), donc en mode « IPv6 payload ».

% sudo ip tunnel add tun0 mode gre remote  10.254.112.180 \
             local 192.168.43.49  ttl 255
% sudo ip link set tun0 up
    

On a ici créé un tunnel GRE entre la machine locale, 192.168.43.49 et l'autre extrémité du tunnel, 10.254.112.180. On attribue maintenant des adresses IPv6 à l'interface tun0 :

% sudo ip -6 addr add fda1:1a36:de6d::2 dev tun0
% sudo ip -6 route add  fda1:1a36:de6d::/48 dev tun0
    

On fait pareil de l'autre côté du tunnel (en inversant évidemment remote et local). On peut maintenant se pinguer en IPv6 même si le FAI ne le fournissait pas (c'est le cas ici, avec un VPS OVH) :

% ping6  fda1:1a36:de6d::2 
PING fda1:1a36:de6d::2(fda1:1a36:de6d::2) 56 data bytes
64 bytes from fda1:1a36:de6d::2: icmp_seq=1 ttl=64 time=1.22 ms
64 bytes from fda1:1a36:de6d::2: icmp_seq=2 ttl=64 time=0.761 ms
64 bytes from fda1:1a36:de6d::2: icmp_seq=3 ttl=64 time=0.689 ms
^C
--- fda1:1a36:de6d::2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 0.689/0.893/1.229/0.239 ms
    

Plus amusant, tcpdump sait décoder le GRE et affiche donc bien ce qui s'est passé dans le tunnel :

16:46:02.240707 IP 10.254.112.180 > 192.168.43.49: GREv0, length 108: \
    IP6 fda1:1a36:de6d::1 > fda1:1a36:de6d::2: ICMP6, echo request, seq 1, length 64
16:46:02.240957 IP 192.168.43.49 > 10.254.112.180: GREv0, length 108: \
    IP6 fda1:1a36:de6d::2 > fda1:1a36:de6d::1: ICMP6, echo reply, seq 1, length 64
    

tcpdump a décapsulé le GRE, trouvé les paquets ICMP d'IPv6 et les a affichés.

Essayons maintenant l'inverse, « IPv6 delivery », c'est-à-dire de l'IPv4 encapsulé dans IPv6 (cela pourra servir lorsqu'on verra apparaître des FAI uniquement IPv6). Créons le tunnel (notez que le mode est ip6gre et plus gre) :

% sudo  ip -6 tunnel add tun0 mode ip6gre remote 2001:db8:2:245b::42 \
      local 2001:db8:8bd9:8bb0:666:6c7c:9bed:b390  ttl 255
% sudo ip -6 link set tun0 up
    

Donnons des adresses IPv4 :

% sudo ip  addr add 172.17.0.2 dev tun0
% sudo ip route add 172.17.0.0/24 dev tun0
    

Et on peut désormais pinguer en IPv4. tcpdump, là encore, sait décapsuler et afficher ce qui se passe dans le tunnel :

21:19:17.158171 IP6 2001:db8:2:245b::42 > 2001:db8:8bd9:8bb0:666:6c7c:9bed:b390: GREv0, length 88: \
         IP 172.17.0.1 > 172.17.0.2: ICMP echo request, id 32762, seq 1, length 64
21:19:17.238950 IP6 2001:db8:8bd9:8bb0:666:6c7c:9bed:b390 > 2001:db8:2:245b::42: GREv0, length 88: \
         IP 172.17.0.2 > 172.17.0.1: ICMP echo reply, id 32762, seq 1, length 64

Téléchargez le RFC 7676


L'article seul

RFC 7583: DNSSEC Key Rollover Timing Considerations

Date de publication du RFC : Octobre 2015
Auteur(s) du RFC : S. Morris (ISC), J. Ihren (Netnod), J. Dickinson (Sinodun), W. Mekking (NLnet Labs)
Pour information
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 22 octobre 2015


Contrairement au DNS classique, le système de sécurité DNSSEC est très dynamique : il faut changer les signatures régulièrement et il est souvent recommandé de remplacer (changer) les clés. Compte-tenu du fait que le DNS n'est pas synchrone (les changements n'apparaissent pas instantanément partout dans l'Internet), ce changement, ce remplacement (rollover, dans la langue d'Alan Turing) est une opération délicate et qui nécessite le strict respect d'un certain nombre de durées. Ce RFC donne des conseils sur la temporalité des opérations DNSSEC.

Pourquoi faut-il changer les clés cryptographiques utilisées ? Il y a plusieurs écoles à ce sujet. Les minimalistes considèrent qu'on ne change les clés que quand c'est nécessaire, par exemple pour passer à des clés plus longues et donc moins vulnérables à la cryptanalyse, ou évidemment quand les clés privées ont été copiées par un méchant. Les maximalistes estiment qu'il faut changer de clé régulièrement, pour être mieux préparé en cas de changement d'urgence, ou pour priver un méchant discret qui aurait réussi à copier une clé privée sans qu'on s'en aperçoive du fruit de son forfait, ou tout simplement parce que l'utilisation d'une clé fournit du matériau, qui peut être utile à un éventuel cryptanalyste. Changer de clé est une opération délicate et, à mon avis, devrait être automatisé : autrement, le risque d'erreur est trop important, comme l'avait montré mon article à la conférence SATIN.

En effet, les facteurs qui rendent l'opération compliquée sont :

  • Les enregistrements DNSSEC, comme les clés (DNSKEY), les signatures (RRSIG) et les pointeurs vers les clés (DS) ne sont pas seulement dans les serveurs faisant autorité mais sont également mémorisés (« cachés ») dans les résolveurs. Si le TTL d'un DNSKEY est de 24 h, il faudra continuer, pendant une journée entière, à permettre la validation avec l'ancienne clé.
  • Il n'y a pas que le remplacement des clés dans les zones déjà signées, il y a aussi la première introduction de la signature dans les zones existantes.
  • Tous les remplacements de clés ne vont pas se faire de manière planifiée : il risque d'y avoir des remplacements d'urgence et ils peuvent nécessiter une préparation spécifique, avec des clés de secours pré-publiées, par exemple.
  • Tout serait plus simple si on pouvait publier toutes les clés possibles, y compris celles non utilisées depuis longtemps. Mais les requêtes DNS pour des enregistrements DNSKEY renvoient toutes les clés et cela peut dépasser la taille qu'on accepte pour des réponses DNS (typiquement 1480 ou bien 4096 octets). Il faut donc supprimer les anciennes clés, et cela ne doit pas se faire trop tôt : il faut être sûr que plus aucun résolveur n'ait ces clés dans son cache.

Une description de ce processus de remplacement de clés (key rollover) figure dans le RFC 6781. Un exemple avec OpenDNSSEC est raconté dans un de mes articles. Notre nouveau RFC détaille la description du RFC 6781, notamment sur les aspects temporels. Deux points à garder en tête avant de le lire :

  • Il est très courant d'avoir deux types de clés, les KSK (Key-Signing Key) qui servent à signer les clés, et qui sont pointées depuis la zone parente, et les ZSK (Zone-Signing Key) qui signent tout le reste. Comme la KSK, elle, est pointée depuis une zone gérée par une organisation différente (la zone parente), elle pose des problèmes particuliers et les deux types de clés sont donc traités séparement dans ce RFC. Le cas moins courant où on n'utilise qu'un seul type de clé n'est pas couvert.
  • Le RFC ne traite pas le cas (très délicat et surtout très peu testé dans le monde réel) des remplacements d'algorithmes (comme le passage de clés RSA à des clés ECDSA, cf. RFC 6605). On trouvera sans doute bien des bogues quand on essaiera cela en vrai ! (Cf. section 5)

Rappelez-vous en outre qu'une requête DNS d'un type donné (par exemple, A, NS, DNSKEY) récupère toujours tous les enregistrements de ce type. Si l'ensemble des enregistrements (RRset pour Resource Record Set) a changé entre temps, mais qu'un ensemble plus ancien est dans le cache, il y restera jusqu'à l'expiration du TTL.

Après ces rappels, les méthodes pour faire un remplacement de clé (section 2 de notre RFC). D'abord, les ZSK (Zone-Signing Keys). Il faut que tout résolveur validant qui a accès à une signature ait également accès à la ZSK correspondante, et ce à tout moment, que l'information soit dans le cache ou pas. Pas question donc de se contenter de publier la nouvelle ZSK et de l'utiliser immédiatement pour signer (les résolveurs ayant l'ancien enregistrement DNSKEY dans leur cache ne pourraient pas valider les nouvelles signatures, et idem si c'est la signature qui est dans le cache mais pas la clé). Il y a trois techniques pour un remplacement qui marche :

  • La pré-publication, décrite dans le RFC 6781. On met la nouvelle ZSK dans l'enregistrement DNSKEY (en laissant les anciennes), et on attend le TTL du DNSKEY, pour être sûr que tous les caches qui ont le DNSKEY ont le nouveau. On peut alors signer avec la nouvelle clé. Puis on attend le TTL des RRSIG, et on est alors certain qu'il ne reste plus de signatures faites avec l'ancienne clé dans les caches. On peut alors supprimer l'ancienne clé du DNSKEY. C'est la technique utilisée par OpenDNSSEC. zsk-prepub
  • La double-signature (un nom pas très rigoureux, car cette technique repose aussi sur une double clé, pas uniquement une double signature), également dans le RFC 6781. On introduit la nouvelle clé dans le DNSKEY et on l'utilise tout de suite pour faire des signatures mais en gardant les anciennes signatures (d'où le nom de double-signature). Une fois le maximum des TTL de DNSKEY et de RRSIG passé, on peut retirer l'ancienne clé et les anciennes signatures. zsk-doublesig
  • La double-RRSIG qui est une vraie « double signature ». On signe avec la nouvelle clé (en gardant les anciennes signatures) mais sans la publier. Une fois le TTL de RRSIG expiré, on change la ZSK. Puis, une fois le TTL de DNSKEY passé, on peut retirer les anciennes signatures.

La double-signature est probablement la plus facile à comprendre : à tout moment, durant la transition, on aura à la fois l'ancienne et la nouvelle clé, les anciennes et les nouvelles signatures. Elle n'a que deux étapes (introduire la nouvelle clé et les nouvelles signatures, puis retirer l'ancienne clé et les anciennes signatures). Son principal inconvénient est d'augmenter la taille des réponses puisqu'il faut transmettre deux fois plus de signatures. La pré-publication est plus compliquée (trois étapes) mais maintient la taille des réponses au minimum nécessaire. Notez que « plus compliqué » est surtout un problème si vous voulez tout comprendre, ou bien si vous êtes le programmeur qui va devoir automatiser l'opération. Mais, si vous utilisez un logiciel déjà fait, comme OpenDNSSEC, vous ne verrez pas cette complexité. La double-RRSIG a les inconvénients des deux autres techniques sans leurs avantages. C'est pour cela qu'elle ne figure pas dans le RFC 6781 et qu'elle n'est pas davantage mentionnée ici.

Et pour un remplacement de KSK ? Le problème est plus simple car la KSK n'est utilisée que pour signer le DNSKEY et clé et signatures voyagent donc ensemble (mais n'ont pas forcément le même TTL, ce que le RFC oublie de dire, donc l'une peut expirer du cache avant l'autre). Mais il est aussi plus compliqué car la KSK est pointée par un lien de confiance (trust anchor), typiquement un enregistrement DS dans la zone parente. Il faut donc coordonner le remplacement de KSK avec celui de ces liens. Et, comme le sait tout administrateur réseau, tout est plus compliqué quand on doit se coordonner avec le monde extérieur. Contrairement au remplacement d'une ZSK, où tout peut être automatisé car le passage d'une phase à l'autre ne dépend que de l'écoulement du temps, le remplacement d'une KSK nécessite une observation manuelle du parent, dont le délai de réaction est imprévisible.

Si le lien de confiance est un enregistrement DS (cas le plus fréquent), il faudra une interaction avec le gestionnaire de la zone parente. Si ce lien a été configuré manuellement (c'est rare, sauf pour la zone racine, qui n'a pas de parente), il faudra faire le changement dans tous les résolveurs qui ont configuré ce lien (une tâche difficile), ou bien utiliser le RFC 5011 (cf. section 3.3.4). C'est en raison des incertitudes à ce sujet qu'il n'y a jamais eu de remplacement de la KSK de la racine.

Comme pour le changement de ZSK, il y a trois techniques :

  • La double-KSK. On met la nouvelle KSK dans l'ensemble DNSKEY. On attend le TTL de la DNSKEY (on est alors sûr que les caches contiennent la nouvelle clé). On change le DS. Une fois celui-ci changé par le parent, on attend le TTL du DS, puis on supprime l'ancienne KSK. C'est la technique utilisée par OpenDNSSEC. ksk-doubleksk
  • Le double-DS. On publie un DS pour la nouvelle KSK. Après que le TTL du DS se soit écoulé, on change la clé. Après que le TTL de la DNSKEY se soit écoulé, on supprime l'ancien DS. ksk-doubleds
  • Le double-RRset. On publie la nouvelle clé, on signe le DNSKEY avec l'ancienne et la nouvelle clé et on publie le nouveau DS. Une fois le maximum du TTL du DS et du TTL de la DNSKEY sont passés, on supprime l'ancien DS et l'ancienne DNSKEY. ksk-doublerrset

Le double-KSK est le plus simple à comprendre, mais cette technique augmente la taille de l'ensemble DNSKEY. Le double-DS n'a pas ce défaut mais nécessite deux interactions avec le parent (certaines zones parentes, comme la racine, sont très lentes à réagir). Le double-RRset a les inconvénients des deux autres techniques mais est aussi la technique qui minimise le temps total de remplacement.

La section 3 du RFC présente les frises chronologiques (timeline) détaillées. Elle s'appuie sur une liste d'états des clés (états qu'affiche un logiciel comme OpenDNSSEC) :

  • Generated : clé créée mais pas encore utilisée. (Les clés peuvent être créées à l'avance.)
  • Published : la clé est publiée dans le DNS.
  • Ready : la clé est publiée depuis suffisamment longtemps pour qu'on soit sûr que, si le DNSKEY est dans un cache, il inclut cette clé.
  • Active : la clé est utilisée pour signer (si c'est une ZSK) ou bien elle permet de valider le DNSKEY (si c'est une KSK).
  • Retired : la clé n'est plus utilisée pour signer mais est encore publiée (certains caches peuvent avoir des vieilles signatures qui nécessitent cette clé).
  • Dead : les caches ont tous la nouvelle clé, elle ne sert plus à rien.
  • Removed : la clé n'est plus publiée.
  • Revoked : cet état n'existe que si on utilise le RFC 5011. Il indique que la clé va être retirée et que les résolveurs qui l'utilisent comme lien de confiance doivent se préparer à ne plus l'utiliser.

Les sections 3.2 et 3.3 présentent les frises chronologiques (timelines) des différentes techniques de remplacement d'une ZSK et d'une KSK (en art ASCII...) Les frises sont un peu complexes car, à chaque fois, on voit deux introductions d'une nouvelle clé, la N et la N+1. L'annexe A détaille les abréviations utilisées. Je n'ai pas reproduit ici les frises du RFC mais juste une version très simplifiée. Quelques points sont dignes d'être notés. D'abord, il peut être prudent, lorsqu'on met en œuvre ces frises, d'ajouter une marge à chaque opération (les éléments <PublishSafety> et <RetireSafety> dans la configuration d'OpenDNSSEC). Si une clé est publiée à l'instant T, et que le TTL est de N secondes, on peut compter que cette clé soit accessible à tous les caches à T + N mais il est plus prudent d'utiliser T + N + M où M est une marge qui permet de faire face à certains imprévus (un retard dans la mise à jour de certains serveurs faisant autorité, par exemple).

On peut améliorer la technique de pré-publication en introduisant des clés en attente (standby keys, section 4). Ces clés sont pré-publiées mais ne sont pas utilisées même lorsque le TTL de DNSKEY est passé. Elles attendent simplement. En général, elles sont là pour des cas d'urgence. Un exemple est celui d'une clé normale, stockée sur la machine qui fait les signatures DNSSEC, et une clé en attente, stockée sur une clé USB dans un coffre-fort. On pré-publie la clé en attente. Si, un matin, on découvre que la machine de signature a été piratée, on peut basculer tout de suite vers la clé en attente, puisqu'elle est dans les caches (la clé en attente est en permanence dans l'état Ready). À noter que, pour une KSK et pour la technique du Double-DS, ce n'est pas la clé qu'on publie mais le DS correspondant. On a donc un standby DS (c'est le cas aujourd'hui sur .fr, si vous regardez). Notez aussi un point de sécurité : une clé en attente n'a de sens que si elle se trouve stockée dans un endroit différent des autres clés. Autrement, elle sera piratée avec les autres.

Donc, en résumé (section 6) :

  • Pour les ZSK, la pré-publication est sans doute la technique la plus raisonnable.
  • Pour les KSK, le double-RRset est sans doute la meilleure technique, en raison du temps total qu'elle prend, plus court que pour les deux autres techniques.

Téléchargez le RFC 7583


L'article seul

RFC 7663: IAB Workshop on Stack Evolution in a Middlebox Internet (SEMI) Report

Date de publication du RFC : Octobre 2015
Auteur(s) du RFC : B. Trammell, M. Kuehlewind (ETH Zurich)
Pour information
Première rédaction de cet article le 22 octobre 2015


Une caractéristique importante de l'Internet d'aujourdhui, et qui le distingue considérablement de l'architecture initialement prévue, est la prévalence de middleboxes un peu partout sur le trajet. Alice et Bob ne peuvent plus, dans la plupart des cas, se parler directement, ils doivent passer par des middleboxes, dont les intérêts ne sont pas ceux des utilisateurs, et qui sont en outre fréquemment boguées et/ou limitées dans leurs fonctions. Un des effets est l'ossification de l'Internet : innover devient de plus en plus difficile, car il y aura toujours une middlebox sur le trajet qui ne sera pas d'accord. Quelles sont les conséquences de cette middleboxation de l'Internet ? Comment peut-on résoudre les problèmes qu'elle posent ? C'est le but du programme IP Stack Evolution de l'IAB que de trouver des réponses à ces questions. C'est dans ce cadre qu'un atelier a été organisé en janvier 2015 à Zurich pour explorer la question. Ce RFC est le compte-rendu de l'atelier SEMI (Stack Evolution in a Middlebox Internet).

On comprend mieux le problème en revenant à l'architecture prévue pour l'Internet (très bien décrite dans le RFC 1958), et qui a assuré son succès, le principe de bout en bout, formalisé dans l'article de J.H. Saltzer, D.P. Reed et David Clark, « End-To-End Arguments in System Design » (ACM TOCS, Vol 2, Number 4, November 1984). Ce principe dit en gros que deux machines connectées à l'Internet doivent décider elles-mêmes de ce qui est bon pour elles, les équipements intermédiaires qui forment le réseau ne sont pas bien placés pour prendre des décisions. Ce principe a pour conséquence un réseau « bête », où les routeurs transmettent les paquets sans chercher à comprendre. Des décisions comme le contrôle de congestion sont faites aux extrémités du réseau, dans les machines terminales. Par exemple, un protocole de transport, dont l'une des fonctions est de réagir en cas de congestion, sera mis en œuvre uniquement dans ces machines. Conséquence de ce principe, l'innovation ne nécessite pas de changement dans l'infrastructure. Si on trouve que le protocole de transport TCP n'est pas terrible, on en invente un autre (comme SCTP) et du jour au lendemain, tout couple de machines Internet peut l'utiliser, sans qu'on ait eu à modifier les routeurs de l'Internet.

Mais l'Internet a bien dégénéré depuis le RFC 1958. D'innombrables équipements supplémentaires, les middleboxes ont été installés et leur but n'est pas de fournir des services aux utilisateurs mais au contraire de les contrôler et de limiter ce qu'ils peuvent faire. C'est ainsi que boitiers NAT, pare-feux, et autres middleboxes se permettent désormais de regarder le trafic et de dire, par exemple « ah, non, SCTP, je ne connais pas, je ne laisse pas passer ». C'est ce qu'on nomme l'ossification : déployer un nouveau protocole de transport, voire un nouveau protocole d'application (« un seul autorisé, HTTP », est un principe fréquent sur les middleboxes), devient de plus en plus difficile. Peut-on encore désossifier l'Internet ? Le problème a été identifié il y a longtemps (cf. l'exposé de S. Deering, « Watching the Waist of the Protocol Hourglass »), il reste à travailler sur les solutions.

L'atelier SEMI avait donc invité les experts à soumettre des articles autour de questions comme « quels chemins dans l'Internet acceptent encore tous les transports ? », « quels chemins sont ouverts à toutes les applications ? », « comment les applications peuvent-elle faire pour contourner les blocages ? », « comment revenir à une situation plus saine ? ». Des tas de pistes étaient possibles :

  • Migrer certaines fonctions de la couche transport vers la couche application (d'une certaine façon, c'est un peu ce que fait HTTP/2, cf. RFC 7540),
  • Développer de meilleurs outils pour que l'application puisse découvrir si un chemin est propre ou pas (et, dans ce cas, quels contournements auront le plus de chances de marcher),
  • Développer des méthodes pour découvrir les middleboxes et leurs caractéristiques,
  • Réfléchir aux questions business : ce n'est pas tout d'avoir des solutions, il faut aussi les déployer et pour cela, avoir des arguments sonnants et trébuchants, pas juste « on va rétablir les principes originels ».

Les articles acceptés sont tous disponibles sur le site Web de l'atelier SEMI. Ce RFC est très court et n'en fait qu'un résumé (et moi, dans cet article, un résumé du résumé).

À l'époque de l'exposé de Deering cité plus haut, le principal type de middlebox repéré était le routeur NAT. Aujourd'hui, les problèmes causés par le NAT, sans avoir été supprimés, sont bien compris et il existe des solutions de contournement (imparfaites, contrairement à ce que laisse entendre l'optimisme du RFC, qui parle d'un problème « largement résolu »). Plusieurs groupes de travail de l'IETF ont travaillé pour cela, notamment BEHAVE. Mais les middleboxes sont devenues plus variées et plus intrusives, au fur et à mesure que leurs possibilités techniques augmentaient (section 2 de notre RFC). Aujourd'hui, le problème qu'elles posent devient d'autant plus intolérable que les préoccupations de sécurité, et notamment de protection de la vie privée, poussent au développement de la cryptographie. Celle-ci permet de préserver l'intégrité des communications de bout en bout et s'oppose donc directement aux middleboxes. (C'était le coeur de l'exposé de Huitema à SEMI.)

Qu'est-ce qui fait que des middleboxes sont déployées ? La section 3 du RFC se penche sur les motivations ; après tout, il y a peu de chances de pouvoir revenir sur ce déploiement si on ne comprend pas pourquoi il a lieu. Parmi les causes, il y a la loi de Moore, qui fait qu'il est de plus en plus réaliste de mettre des traitements importants sur le chemin des communications, malgré la concentration de trafic. Il y a le désir des opérateurs réseau de ne pas être « uniquement un tuyau » (ce que voudraient les utilisateurs) mais d'imposer des traitements (qu'on baptise « valeur ajoutée ») qui justifieront des augmentations de tarif, ou des violations de la neutralité. Il y a des services informatiques qui trouvent qu'il est plus facile de déployer une politique dans le réseau que dans les machines terminales, d'autant plus qu'ils ne contrôlent pas forcément celles-ci (cas du BYOD). Et il y a bien sûr le marketing des vendeurs de middleboxes qui insiste lourdement pour qu'on achète ces boitiers, dotés de vertus miraculeuses (en sécurité ou en performances). C'est vrai qu'acheter est un acte simple, et il est tentant de se procurer un service juste en faisant un chèque. Toutes ces motivations contribuent à l'ossification du réseau.

Les organisateurs de SEMI se placent dans le cadre d'un système capitaliste pur (rebaptisé, car c'est plus joli, « libre marché »), vu comme incontournable. Dans ce cadre, les désaccords ne sont adressables que par le jeu du marché et il faut donc fournir des motivations business pour tout changement. Cela mène à la question « comment vendre les alternatives aux middleboxes ? »

La section 4 explore ce que font exactement les middleboxes. Car il y en a de plein de sortes différentes et, pour résoudre les problèmes qu'elles posent, il faut les étudier et les classer (c'était le papier de Edeline et Donnet).

Cette étude est notamment nécessaire pour savoir si les applications pourront coopérer avec les middleboxes ou bien s'il faudra envisager des mesures plus « ninja » comme de tout tunneler (la contribution de Raiciu et Olteanu).

Et sur les protocoles de transport ? La section 5 discute de comment faire évoluer la couche 4 dans un Internet gelé par les middleboxes. S'inspirant d'un épisode du film « La vie de Brian », le RFC classe les propositions en deux camps :

  • Le « TCP Liberation Front », ceux qui veulent avant tout permettre de reprendre l'évolution de TCP, déployer de nouvelles extensions (qui entrainent actuellement souvent une réaction négative des middleboxes).
  • Le « People's Front of UDP », qui considère que c'est fichu et que tous les services « couche 4 ou à peu près » futurs devront être encapsulés dans l'UDP (c'est par exemple ce que propose le RFC 6951 pour arriver à faire passer SCTP et c'est également pour cette raison que LISP est forcément transporté dans UDP alors qu'il aurait très bien pu être directement sur IP).

Ajoutez la crypto à cela et la solution UDP se traduira peut-être dans le futur par « tout sur DTLS »... Des tas de solutions ont été imaginées par les « transporteurs », les gens de la couche 4. Par exemple, la contribution de Briscoe propose de mettre les options et extensions nouvelles de TCP dans la charge utile et non pas dans l'en-tête TCP, les mettant ainsi à l'abri des middleboxes (jusqu'à ce qu'elles se mettent à faire du DPI lourd...)

À noter que tous les chemins sur l'Internet ne sont pas forcément affligés de middleboxes. Quelles que soient les solutions de contournement adoptées, il serait dommagee qu'elles soient imposées à tous, avec leurs coûts en octets gaspillés et en complexité, alors qu'on peut s'en passer dans beaucoup de cas. Welzl, Fairhurst et Ros avaient ainsi proposé de consacrer des efforts à la détection des middleboxes. On teste le chemin et, s'il est propre, on se dispense des horreurs nécessitées par le contournement des middleboxes. Comme ce test va prendre du temps, il faudra sans doute le faire en parallèle des tentatives de connexion, comme dans le cas du RFC 6555.

Bon, maintenant, place à l'action. Qu'est-ce qui doit être fait pour avancer ? La section 6 de notre RFC liste les points à traiter. D'abord, est-ce qu'on ne pourrait pas envisager de signaler au réseau certaines informations sémantiques (du genre « ce paquet est le début d'un nouveau flot »), dispensant les middleboxes d'essayer de (mal) trouver cette information elles-mêmes ? Cela serait d'autant plus utile que cette information est masquée en cas de chiffrement. Cette idée est à la base du projet SPUD (Substrate Protocol for User Datagrams, « un traité de paix entre machines et réseau »). Ce projet a suscité des controverses lors de sa présentation à l'IETF 92 à Dallas (si on chiffre, ce n'est pas ensuite pour donner des informations à un réseau en qui on n'a pas confiance) et aucun groupe de travail n'a encore été créé. Les objections à SPUD portent notamment sur le fait que la publication des informations devrait être volontaire, et le résultat d'un choix délibéré.

Autre sujet sur lequel il faudrait travailler, la mesure. Cela ne vaudrait pas la peine de développer des hacks d'enfer dans les couches 4 ou 7 pour contourner une perturbation qui est rare. Or, à l'heure actuelle, on manque de données sur les différents types de problèmes causés par les middleboxes. Par exemple, combien de chemins dans l'Internet ne laissent pas passer un protocole de transport inconnu ? (Avant de crier « aucun, tout le monde est derrière un routeur NAT », pensez aux réseaux d'entreprise ou d'organisation, aux réseaux IPv6, etc.) Ces mesures sont le travail de la liste de diffusion hops (How Ossified is the Protocol Stack?) qui discute des meilleurs moyens de collecter cette information, par exemple à partir des journaux des applications qui tentent d'utiliser tel ou tel protocole mais se replient ensuite sur une autre solution. Le pourcentage de repli serait une information utile.

Le RFC n'en parle pas mais un des problèmes posés par les middleboxes est typiquement que leurs programmeurs sont inconnus, et ne participent pas aux forums comme le RIPE ou l'IETF, où se discutent les problèmes de l'Internet. Même si on rédige des bonnes pratiques à suivre pour les auteurs de logiciel de middlebox, il y a peu de chances qu'ils les lisent, ou même apprennent leur existence. (Les middleboxes actuelles ont manifestement été programmées sans lire les RFC ou en tout cas sans lire tous les RFC pertinents, cf. RFC 5625 pour des exemples).

Mais l'IETF est optimiste et croit que l'humanité peut s'améliorer : d'où des documents comme le RFC 3234. Un travail est en cours pour le compléter avec des conseils pratiques.

Bref, la lutte entre les machines terminales, qui veulent un tuyau bête et neutre, et le réseau qui cherche à imposer ses propres vues, n'est pas terminée, loin de là.


Téléchargez le RFC 7663


L'article seul

RFC 7665: Service Function Chaining (SFC) Architecture

Date de publication du RFC : Octobre 2015
Auteur(s) du RFC : J. Halpern (Ericsson), C. Pignataro (Cisco)
Pour information
Réalisé dans le cadre du groupe de travail IETF sfc
Première rédaction de cet article le 22 octobre 2015


Aujourd'hui, des flots de paquets IP qui voyagent d'un point à un autre de l'Internet ont peu de chances de le faire sans passer par divers traitements, des plus honorables (statistiques, lutte contre une attaque par déni de service) aux moins avouables (étranglement du trafic pour pousser un fournisseur de contenu à payer, censure). Actuellement, ces traitements sont rigidement liés à la topologie du réseau sous-jacent et manquent donc de souplesse. Dès qu'on veut chaîner plusieurs traitements, le résultat de la configuration devient difficile à lire et à maintenir (le problème est décrit plus en détail dans le RFC 7498). L'idée de base du projet SFC (Service Function Chaining) est de spécifier une architecture (ce RFC) et peut-être plus tard des protocoles pour organiser ces traitements de manière plus souple.

Le RFC 7498 avait très bien décrit le problème qu'on essaye de résoudre. Ce nouveau RFC 7665 est plus concret, décrivant l'architecture des SFC mais je trouve personnellement qu'il reste encore très abstrait et qu'il ne fait pas beaucoup avancer la compréhension, par rapport à son prédécesseur.

Donc, l'architecture des SFC (Service Function Chaining). On veut avoir des chaînes ordonnées des traitements appliqués aux flux réseau, et on veut pouvoir les créer, les modifier et les détruire facilement, avec bien plus de souplesse que le système actuel (section 1 du RFC).

Les paquets entrent et sont classés, les traitements étant ensuite appliqués en fonction du classement. Ces traitements sont appliqués dans l'ordre de la chaîne et, attention, il peut y avoir une re-classification dans un des ces traitements, menant à une autre chaîne.

Pour définir l'architecture, on suppose que :

  • Les traitements sont tellement variés qu'il est impossible de les normaliser ou même de les décrire de manière exhaustive. On va donc, dans le projet SFC, s'intéresser uniquement à l'ordonnancement de ces traitements, pas au traitement lui-même. Chaque traitement est une « boîte noire ».
  • La liste des traitements appliqués, les critères d'application, et l'ordre d'application, sont des décisions purement locales. Il n'y aura pas de normalisation des traitements (du genre « il faut commencer par un filtrage IP »).
  • L'application de ces traitements en chaîne dépend évidemment du réseau sous-jacent qui va déplacer les bits d'une machine à l'autre mais ce réseau n'est pas décrit par SFC, chacun peut utiliser ce qu'il veut.

Chaque traitement (on le nomme un SF pour Service Function) est identifié de manière unique dans le domaine (dans les exemples du RFC, l'identificateur est un simple nombre). Une suite de SF est une SFC (Service Function Chain). Une SFC peut être unidirectionnelle (par exemple des paquets qui sont d'abord comptés, puis filtrés, puis modifiés) ou bidirectionnelle.

Un SFF (Service Function Forwarder) est responsable d'acheminer le trafic d'une SF à une autre. Un SFP (Service Function Path) est la réalisation concrète d'une SFC et un RSP (Rendered Service Path) est la suite des SF effectivement visités. Prenons comme exemple une SFC qui dit que le trafic doit passer par deux SF, un pare-feu et un cache. Le SFP, plus concret, va indiquer quelle instance des deux DF, et dans quel centre de données, on va utiliser. Et le RSP indiquera où le trafic est réellement passé (il peut différer du SFP si ce dernier laissait une certaine latitude, ou bien si quelque chose ne s'est pas passé comme prévu).

La section 3 du RFC liste les grands principes, notamment :

  • Indépendance par rapport à la toplogie du réseau : pas besoin de recâbler quand on modifie une SFC.
  • Séparation entre les SFP et la transmission des paquets par les routeurs.
  • Classification des paquets, qui décidera du SFP où on enverra le trafic.
  • Métadonnées accessibles, par exemple le résultat de la classification sera visible par les SF (voir plus loin la notion d'encapsulation).
  • Indépendance des SFC entre elles, et de la SFC par rapport aux SF, nécessaire à la souplesse du dispositif.

La section 4 de notre RFC détaille les composants du système vus plus haut (SF, SFF, etc). Ces composants sont reliés par l'encapsulation SFC, qui définit comment on va encapsuler le trafic pour l'acheminer d'un composant à l'autre. Attention, ce n'est pas un remplaçant d'IP : lorsque les SF sont sur des machines séparées, il faudra toujours un réseau sous-jacent pour transmettre les paquets. Le plan de contrôle (comment trouver où acheminer le trafic) n'est pas décrit, il est hors-sujet pour ce projet, qui reposera sur des protocoles déjà existants.

D'ailleurs, en parlant de réseau, la section 5, qui couvre divers problèmes de réalisation, note entre autres que qui dit encapsulation dit problèmes de MTU, suite aux octets d'en-tête de l'encapsulation. Il n'y a pas de solution idéale pour les futurs protocoles concrets qui instancieront cette vision abstraite des Service Function Chains mais il faut au moins garder ce problème en tête.

Autre problème pratique dans la même section 5, la fiabilité. Si on met des services supplémentaires dans le réseau, cela ne doit pas trop diminuer sa résilience. Par exemple, prenons une SFC qui ne comporte qu'un seul SF, chargé de mesurer le trafic. La panne de l'équipement qui porte ce SF ne doit pas arrêter tout le trafic. Ici, c'est relativement facile car le SF « compteur » n'a pas besoin d'être en série sur le trajet, il peut être placé en dérivation. Mais d'autres SF ont besoin de modifier le trafic et donc doivent être placés en série. Il faut alors prévoir des solutions de secours, par exemple à base de VRRP (RFC 5798).

Le déploiement des SFC peut aussi avoir des conséquences sur la sécurité. On passe d'un réseau assez statique avec peu de fonctions à un réseau très dynamique pouvant assurer plein de fonctions (section 6 de notre RFC).


Téléchargez le RFC 7665


L'article seul

RFC 7671: Updates to and Operational Guidance for the DANE Protocol

Date de publication du RFC : Octobre 2015
Auteur(s) du RFC : V. Dukhovni (Unaffiliated), W. Hardaker (Parsons)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dane
Première rédaction de cet article le 21 octobre 2015


Le protocole DANE (RFC 6698) de sécurisation des communications utilisant TLS est encore très peu déployé. Donc, il n'y a pas vraiment de retours d'expériences mais les premiers essais ont quand même permis de se faire des idées, et, pour aider ceux et celles qui vont déployer DANE dans les années à venir, ce nouveau RFC rassemble quelques conseils pratiques.

Donc, DANE permet d'améliorer l'authentification des sessions TLS en publiant dans le DNS, sécurisés par DNSSEC, des enregistrements nommés TLSA (non, ce n'est pas un acronyme, ce nom est à utiliser sans comprendre son étymologie). Ces enregistrements indiquent le certificat utilisé pour la connexion TLS. Ainsi, un gérant d'un serveur TLS n'est plus obligé de dépendre d'une tierce partie, genre AC.

J'ai simplifié car il y en a fait beaucoup de choix : DANE permet de publier des clés brutes, pas seulement des certificats, il permet de publier un certificat d'AC, pas seulement le certificat final, etc. Le RFC 6698 normalise trois champs dans l'enregistrement TLSA (cf. section 2 de notre RFC), « Utilisation du certificat » (quatre valeurs possibles), « Sélecteur » (deux valeurs possibles) et « Méthode de correspondance » (trois valeurs possibles). En tout, il existe vingt-quatre combinaisons, ce qui est probablement trop (combien de clients DANE ont-ils vraiment été testés avec les vingt-quatre combinaisons différentes ?). Notre RFC réduit ce choix par ses conseils.

Voici un exemple d'un enregistrement DANE à peu près conforme aux recommandations du RFC, celui de mon blog :

% dig TLSA _443._tcp.www.bortzmeyer.org

;; ->>HEADER<<- opcode: QUERY; status: NOERROR; id: 60895
;; Flags: qr rd ra; QUERY: 1; ANSWER: 1; AUTHORITY: 8; ADDITIONAL: 6

;; QUESTION SECTION:
;; _443._tcp.www.bortzmeyer.org.		IN	TLSA

;; ANSWER SECTION:
_443._tcp.www.bortzmeyer.org.	86400	IN	TLSA	2 0 2 EB0AD84F11B4B08BF76C7866EF32842292BBB2862FB6FC49C0A3F807629CA8F5DD28A0DE7B0C04D566020AC4FF2BA44E2F612AA58A1AE4CCACE486D244952FC2
      
    

L'« utilisation du certificat » est DANE-TA (valeur 2, mais le RFC 7218 a introduit de jolis noms pour ces codes), le « sélecteur » est CERT (valeur : 0, on testera tout le certificat, pas juste la clé publique) et la « méthode de correspondance » 2, ce qui veut dire qu'on publie un condensat en SHA-512 de ce certificat.

Notre RFC 7671 ne fait pas qu'ajouter des conseils opérationnels au RFC 6698, il le modifie légèrement sur certains points (section 3 de notre RFC), par exemple en ajoutant qu'un client DANE doit utiliser l'extension TLS nommée SNI (Server Name Indication, cf. RFC 6066).

Que mettre dans le champ « utilisation du certificat » de l'enregistrement TLSA ? La section 4 de notre RFC s'attaque à ce problème. Les quatre valeurs possibles sont PKIX-TA (le certificat utilisé pour TLS doit être vérifié par les mécanismes X.509 classiques et le certificat publié dans le TLSA doit être celui de l'AC), PKIX-EE (le certificat utilisé pour TLS doit être vérifié par les mécanismes X.509 classiques et le certificat publié dans le TLSA doit être celui du serveur TLS), DANE-TA (le certificat publié dans le TLSA est celui d'une AC à partir de laquelle on vérifie le certificat du serveur TLS) et enfin DANE-EE (le certificat publié dans le TLSA est celui du serveur TLS). Pour DANE-TA et DANE-EE, il n'y a pas besoin d'un magasin de certificats pré-existant sur le client TLS.

Il n'y a pas forcément besoin, pour un client DANE, de gérer les quatre utilisations. S'il le fait, un attaquant qui arrive à modifier les enregistrements DNS peut remplacer un PKIK-EE par un DANE-EE et la sécurité supplémentaire de la vérification X.509 qu'impose X.509 est donc assez illusoire. Un client paranoïaque et traditionnaliste qui veut imposer des vérifications X.509 doit donc ignorer purement et simplement les enregistrements avec DANE-EE ou DANE-TA.

Mais notre RFC donne le conseil contraire : ne gérer que DANE-EE et DANE-TA, en raison du manque de confiance qu'on peut avoir dans les centaines d'AC existantes, dont beaucoup ont déjà fait la preuve qu'on ne pouvait pas leur faire confiance. La vérification X.509 de ces AC n'apporte pas grand'chose en sécurité. En outre, il n'existe aucune liste standard d'AC reconnues, ce qui rend PKIX-TA et PKIX-EE très fragiles : le magasin du client doit être un sur-ensemble du magasin de tous les serveurs possibles ce qui mène à des listes d'AC délirantes (regardez celle de votre navigateur Web).

Depuis la publication de DANE, d'autres techniques visant à boucher les trous de X.509 sont apparues, comme les certificats au grand jour du RFC 6962. Comme la liste publique décrite dans ce RFC ne stocke que des certificats émis par des AC connues de la liste, les vérifications du RFC 6962 ne doivent pas être faites pour les utilisations DANE-TA et DANE-EE.

La section 5 rassemble ensuite des conseils spécifiques à chaque usage particulier du certificat publié avec DANE. D'abord, l'usage DANE-EE (valeur : 3). Dans cet usage, le certificat du serveur est publié dans l'enregistrement TLSA et les vérifications X.509 (RFC 5280) ne doivent pas être faites. Le RFC 6698, qui normalisait DANE, ne disait apparemment pas ce qu'il fallait faire des autres informations contenues dans le certificat comme la date d'expiration. Notre RFC 7671 précise (et c'est un des points où il met à jour le RFC 6698, ne se contentant pas d'ajouter des conseils, cf. section 12 pour les autres cas) que les autres informations doivent être ignorées. Si le certificat est dans un enregistrement TLSA, il est bon, quelle que soit la date d'expiration. Idem pour le nom de serveur dans le certificat.

Le sélecteur recommandé, pour cet usage, est SPKI (valeur : 1) qui indique qu'on ne trouve pas dans l'enregistrement TLSA tout le certificat mais juste la clé publique. Raisons de cette recommandation :

  • Cela évite de changer l'enregistrement TLSA quand les métadonnées dans le certificat changent (cas des certificats CAcert, qui ne durent que six mois),
  • C'est compatible avec les clés nues du RFC 7250,
  • C'est cohérent avec l'obligation d'ignorer les données du certificat, à l'exception de la clé publique.

Il n'est pas recommandé d'envoyer le certificat entier (méthode de correspondance Full, valeur 0), notamment en raison des problèmes du DNS avec des enregistrements de grande taille (ce qui est souvent le cas des certificats). Il faut plutôt utiliser un condensat du certificat. En cas de doute, notre RFC recommande donc DANE-EE + SPKI + SHA-256 (notez que l'enregistrement TLSA de mon serveur HTTP, cité plus haut, ne suit pas cette recommandation mais ce que le RFC présente comme un second choix).

Mais ce n'est pas impératif. L'usage DANE-TA, où on publie dans l'enregistrement TLSA le certificat de l'AC et pas celui du serveur, est tout à fait légitime (c'est celui que j'utilise). Attention, il impose d'envoyer toute la chaîne de certificats dans la réponse TLS. (Avec OpenSSL et GnuTLS, il suffit de concaténer tous ces certificats, dans le bon ordre - du plus spécifique au plus général, cf. RFC 5246, section 7.4.2 - dans un seul fichier PEM, qui sera celui indiqué au serveur.) Cette nouvelle obligation a été ajoutée pour le cas où l'AC choisie par le gérant du serveur DANE ne soit pas dans le magasin du client (pour CAcert, c'est fréquent).

Contrairement à l'usage DANE-EE, il est recommandé, avec cet usage DANE-TA, d'utiliser le sélecteur Cert (valeur : 0), car, cette fois, il faut tenir compte du contenu complet du certificat (comme les limites de longueur, par exemple, ou bien les restrictions sur les noms que l'AC peut approuver, cf. RFC 5280, section 4.2.1.10).

Un rappel de sécurité pour finir la section sur DANE-TA : cet usage vous protège contre les autres AC, malhonnêtes ou piratées, mais pas contre les autres utilisateurs de la même AC. Choisissez donc bien votre Autorité de Certification !

Deux autres usages possibles de l'enregistrement TLSA maintiennent des validations X.509 classiques. Ce sont les usages PKIK-EE (valeur : 1) et PKIX-TA (valeur : 0).

Un risque important de l'utilisation de DANE est la désynchronisation entre le ou les certificat(s) envoyés en TLS et ceux publiés dans le DNS, dans l'enregistrement TLSA (section 6 de notre RFC). Il faut absolument maintenir ces informations en cohérence, ce qui est d'autant plus difficile que les outils de supervision actuels n'offrent en général pas grand'chose pour DANE. Ainsi, si on utilise DANE-EE ou PKIX-EE, quand on change de clé publique sur le serveur TLS, il faut penser à mettre à jour l'enregistrement TLSA. Compte-tenu de l'importance de la mise en cache des données dans le DNS, cela nécessite de publier le nouveau certificat dans le DNS à l'avance (cf. section 8.4). Bref, notre RFC fait remarquer à juste titre qu'il est très recommandé que le DNS et le TLS soient gérés par la même organisation, autrement, le risque de cafouillage est trop élevé. (DANE est encore d'utilisation récente et on n'a pas encore vu beaucoup de cas de changement de certificat. Quand ça arrivera, il est à craindre qu'il y ait quelques malheurs, lorsque l'administrateur système oubliera qu'il avait publié un enregistrement TLSA.)

La section 8 met en garde les gérants de serveurs utilisant DANE contre le fait qu'on ne peut pas espérer que tous les clients DANE comprennent tous vos enregistrements TLSA. Ceux-ci peuvent spécifier un algorithme de condensation récent que tout le monde ne gère pas encore. Ou bien ils peuvent utiliser les clés nues du RFC 7250, que tout le monde n'accepte pas, loin de là. Attention donc, surtout lorsque vous décidez des paramètres.

La même section traite du difficile problème du remplacement : en raison des caches du DNS, les changements de clé ou de paramètres ne sont pas vus immédiatement partout. Il faut donc suivre quelques précautions quand on est hébergeur DNS d'un domaine qui utilise DANE :

  • Publier à l'avance les nouveaux enregistrements TLSA (quelle avance ? Le TTL de l'ensemble TLSA.)
  • Une fois le serveur TLS reconfiguré pour la nouvelle clé, virer les anciens enregistrements TLSA.
  • Si on change les paramètres (par exemple on passe d'un sélecteur CERT à un sélecteur SPKI ou bien le contraire), bien vérifier que tous les cas sont couverts pour les anciennes et les nouvelles chaînes de certificat.

À noter que le problème des clients DANE ne gérant pas toutes les valeurs possibles des paramètres est d'autant plus agaçant qu'il n'y a pas forcément de règles précises sur le choix d'un enregistrement TLSA, si plusieurs conviennent. Imaginons que vous ayez deux enregistrements TLSA, identiques sauf la méthode de correspondance qui vaut SHA-256 pour l'un et SHA-512 pour l'autre. Lequel sera utilisé par le client DANE ? Il faudrait évidemment que ce soit le plus fort (SHA-512) mais le RFC 6698 ne dit pas comment. Notre nouveau RFC demande au contraire que tout client DANE ait un classement des algorithmes de condensation, idéalement configurable par l'utilisateur, et qui soit par défaut l'ordre des valeurs (SHA-256 : 1, SHA-512 : 2, etc). Le client DANE, lorsqu'il a le choix, doit prendre le mieux classé (ou la méthode Full - valeur : 0 - qui n'utilise pas d'algorithme de condensation cryptographique, si un enregistrement TLSA l'utilise).

La section 10 de notre RFC rassemble des conseils divers pour la conception de protocoles utilisant DANE. D'abord, la taille des enregistrements, importante car le DNS a souvent des limites de taille. Par exemple, la plupart des serveurs faisant autorité ont une taille maximale de 4 096 octets pour les réponses se faisant en UDP. Même si la réponse est inférieure à cette valeur, une taille plus grande que 1 500 octets a de grandes chances de mener à une fragmentation de la réponse UDP, avec des conséquences négatives sur les performances voire, pire, sur la fiabilité de l'acheminement de la réponse (pas mal de pare-feux bogués bloquent stupidement les fragments). En théorie, on peut alors utiliser TCP pour transmettre les données mais lui aussi est souvent bloqué par des logiciels configurés par des incompétents.

Avec les grands certificats qu'on trouve souvent dans le monde X.509, le risque de paquets trop grands est bien plus élevé qu'avec les données de petite taille qu'on trouve habituellement dans le DNS. D'où les conseils de notre RFC : n'utilisez pas ensemble le sélecteur CERT (valeur : 0, il indique qu'il faut comparer tout le certificat, pas juste la clé publique) et la méthode de correspondance FULL (valeur : 0, elle indique que l'enregistrement TLSA contient les données complètes, pas juste un condensat). En effet, cette combinaison oblige à mettre un certificat entier dans l'enregistrement TLSA, ce qui dépasse en général la taille raisonnable. (D'autant plus qu'en cas de remplacement, il faudra publier simultanément deux enregistrements TLSA.) Avec un sélecteur SPKI (valeur : 1, on ne vérifie que la clé publique), le problème est moins grave, néanmoins autant ne jamais utiliser la méthode de correspondance FULL.

Notre RFC contient aussi des conseils pour le certificat envoyé par TLS. Il y a normalement des règles précises sur le nom (subject, en terminologie X.509) qui doit être mis dans le certificat, afin de permettre l'authentification. Néanmoins, ces règles sont complexes (donc pas toujours bien comprises) et ont changé dans le temps. Il peut être prudent de rajouter des noms « au cas où ». Ainsi, pour un service auquel on accès via un enregistrement SRV, le RFC 7673 prescrit de vérifier le nom en partie droite du SRV. Mais comme on ne peut pas être sûr de ce que feront tous les clients DANE, autant essayer de mettre aussi dans le certificat le nom qui est en partie gauche du SRV.

La section 11 se penche, elle, sur DNSSEC. DANE est complètement dépendant de DNSSEC : sans lui, plus aucun enregistrement TLSA n'est accepté. La sécurité de DNSSEC est donc cruciale pour DANE. Avec X.509, la sécurité de l'AC que vous choisissez a peu d'importance, puisque n'importe quelle AC peut émettre un certificat pour votre serveur. (Les « Name constraints » - section 4.2.1.10 du RFC 5280 - sont très peu utilisées.) Avec DNSSEC, au contraire, vous ne dépendez que d'acteurs que vous choisissez : votre hébergeur DNS, votre BE (souvent le même que l'hébergeur), votre registre...

DNSSEC dépendant du DNS, il va donc falloir sécuriser votre configuration DNS (cf. le bon guide de l'ANSSI). Par exemple, il est recommandé de placer un verrou (registry lock) pour limiter les risques de détournement de votre domaine, ou de modification non autorisée.

Certaines opérations dans le DNS sont délicates à faire lorsqu'un domaine est signé : le passage d'un BE à l'autre lorsque chacun est également l'hébergeur DNS. Une technique parfois recommandée est de dé-signer la zone temporairement. On retire le DS, on attend l'expiration dans les caches, on migre, on met un nouveau DS. Cette méthode est sûre et simple mais elle laisse une fenêtre d'insécurité, où la zone n'est pas signée. Sans DANE, c'est un inconvénient supportable (il faut juste espérer que l'attaquant ne frappe pas à ce moment), avec DANE, c'est impossible car les enregistrements DANE seront ignorés pendant cette période d'insécurité. S'ils sont d'usage PKIK-EE ou PKIK-TA, ce n'est pas trop grave, le certificat sera toujours validé par X.509 mais s'ils sont d'usage DANE-TA ou surtout DANE-EE, on ne pourra plus se connecter au serveur. Voilà pourquoi il faut étudier les conditions de migration du domaine avant de déployer DANE.

DNSSEC n'a pas de notion de révocation (là encore, sauf si on utilise les usages PKIX-EE ou PKIK-TA, où les vérifications de la révocation du certificat peuvent être faites). Attention donc de ne pas mettre des TTL trop longs à vos enregistrements TLSA (section 13 du RFC, au début) et surtout pas des périodes de validité des signatures trop longues pour éviter des attaques par rejeu. Pour ces périodes de validité, le RFC recommande quelques jours pour des clés importantes et quelques semaines pour les autres. Regardez par exemple l'enregistrement TLSA de mon serveur de courrier :

_25._tcp.mail.bortzmeyer.org. 86400 IN TLSA 2 0 1 (
				FF2A65CFF1149C7430101E0F65A07EC19183A3B633EF
				4A6510890DAD18316B3A )
_25._tcp.mail.bortzmeyer.org. 86400 IN RRSIG TLSA 8 5 86400 (
				20151101223339 20151012192513 53605 bortzmeyer.org.
				BEiYRQh4i4Z3RH0h3yZqDjltCmv...
    

Le TTL est d'une journée (ce qui fait qu'un changement d'urgence du certificat pourrait casser la vérification pendant une journée, dans le pire des cas). La durée de validité de la signature est de 20 jours (<Validity><Default>P20D</Default></Validity> dans la configuration OpenDNSSEC). Avec des courtes validités, on ne peut pas se permettre d'avoir un serveur DNS maître en panne très longtemps, et des périodes de quelques jours ne doivent donc être utilisées que si on dispose d'une équipe professionnelle et réactive.

Enfin, il est évidemment crucial de superviser sa configuration DNSSEC.

Enfin, dernier conseil, section 14 (mais on l'a déjà dit plus haut), attention au fait que certains enregistrement TLSA seront considérés comme inutilisables par certains clients DANE. En TLS « opportuniste » (RFC 7435), cela se traduira par une absence de vérification du certificat par le client. Mais en mode plus sécurisé (très rare à l'heure actuelle), cela peut se traduire par une impossibilité de se connecter en TLS.

Terminons avec un peu de ligne de commande Unix. Comment on génère un enregistrement TLSA ? Par exemple, pour le mien, d'usage DANE-TA (valeur : 2), je prends le certificat de mon AC, CAcert (wget https://www.cacert.org/certs/root.crt) et voici deux méthodes possibles, avec OpenSSL, puis avec hash-slinger. D'abord, avec OpenSSL (voir cet article) :

%  openssl x509 -in  root.crt -outform DER | openssl sha256
(stdin)= ff2a65cff1149c7430101e0f65a07ec19183a3b633ef4a6510890dad18316b3a

Et on n'a plus qu'à mettre :

_25._tcp.MXSERVER.DOMAIN.  IN TLSA 2 0 1  ff2a65cff1149c7430101e0f65a07ec19183a3b633ef4a6510890dad18316b3a

dans sa configuration DNS. Avec hash-slinger :

%  tlsa --create --port  25 --certificat root.crt --usage 2 --selector 0 --mtype 1 \
              mail.bortzmeyer.org
_25._tcp.mail.bortzmeyer.org. IN TLSA 2 0 1 ff2a65cff1149c7430101e0f65a07ec19183a3b633ef4a6510890dad18316b3a

Troisième possibilité, le faire en ligne.

Et si je voulais un enregistrement TLSA d'usage DANE-EE (valeur : 3) ? Avec OpenSSL, ce serait :

printf '_25._tcp.%s. IN TLSA 3 1 1 %s\n' \
        $(uname -n) \
        $(openssl x509 -in server.pem -noout -pubkey |
            openssl pkey -pubin -outform DER |
            openssl dgst -sha256 -binary |
            hexdump -ve '/1 "%02x"')
_25._tcp.www.foobar.example. IN TLSA 3 1 1 755b35d2c34c54729d92f97e25d8a8be020235d5b1c6b7751bfefc896b8e5164

Avec hash-slinger, il suffit de modifier les paramètres de la ligne de commande.

Si vous voulez tester vos enregistrements TLSA, ce qui est très recommandé :

Et pour lire davantage, vous pouvez voir le dossier thématique de l'AFNIC sur DANE.


Téléchargez le RFC 7671


L'article seul

Le coupable d'un problème de réseau n'est pas toujours celui qu'on croit

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


Le lancement raté d'un site Web gouvernemental (détails plus loin, analyse technique détaillée à la fin) est l'occasion de revenir sur un phénomène qui arrive assez souvent lorsqu'une partie de l'Internet est en panne : le coupable désigné sur les réseaux sociaux n'est pas toujours le bon (enfin, le méchant). Notamment, en cas de mauvaise configuration des techniques de sécurité, ceux qui appliquent ces techniques peuvent être « accusés » de la panne, puisque ça continue à marcher chez les « laxistes ».

Le dernier exemple que j'ai en tête s'est produit il y a quelques jours lors du lancement de http://www.images-art.fr/, un site Web gouvernemental de distribution d'images. Ce site est un scandale mais ce n'est pas le problème ici. Le problème est que les gérants du site Web avaient fait une erreur de configuration, et que ce site n'était donc pas visible depuis une partie de l'Internet, notamment depuis Free. La réaction de beaucoup d'utilisateurs avait été de reprocher ce problème à Free puisque « ça marche chez les autres ». Mais c'était injuste. En effet, Free est un des rares FAI français à déployer DNSSEC, une technique de sécurité qui vise à protéger les utilisateurs contre certaines attaques sur le réseau. Malheureusement, la plupart des autres FAI ne se soucient pas de sécurité et n'ont pas déployé cette technique. (Si vous préférez des exemples états-uniens, un incident similaire s'était produit lorsque la NASA avait cafouillé dans sa configuration, et que Comcast, principal FAI à utiliser DNSSEC, avait été accusé, bien à tort, de bloquer la NASA.)

Or, le nom de domaine images-art.fr avait un problème de configuration. Cela le rendait invisible depuis les opérateurs qui mettaient en œuvre DNSSEC (Free mais aussi Google Public DNS). En effet, ce problème de configuration était indistinguable d'une attaque.

Et c'est là un paradoxe fréquent de la sécurité : la sécurité gêne les utilisateurs. Imaginons un petit village qui n'a jamais connu de cambriolage. Les habitants ne ferment pas la porte à clé ou, quand ils le font, ils laissent la clé sous le pot de fleurs près de l'entrée. Maintenant, si la situation change et qu'il commence à y avoir quelques cambriolages, certains habitants vont commencer à faire plus attention. Et les ennuis commenceront parce que, pour un cambriolage évité grâce à une porte fermée, il y aura dix ou vingt incidents dus à la sécurité : une personne claque la porte en laissant la clé dedans, une autre a oublié qu'un membre de sa famille devait passer et n'avait pas la clé, un troisième perd la clé dans la journée... Tous réagiront probablement au début en disant « la sécurité, c'est pénible » (ce qui est parfaitement exact).

Quittons notre histoire et revenons à l'Internet. images-art.fr a cafouillé (voir l'analyse technique détaillée plus loin). Mais ce cafouillage n'a eu aucune conséquence chez les FAI qui ne vérifient pas. Ils n'ont pas de quoi s'en vanter. Bien au contraire, ils laissent leurs utilisateurs vulnérables. Et ce sont donc Free ou Google qui avaient raison : les mesures de sécurité déployées étaient bonnes, la responsabilité de la panne n'était pas chez eux. Notons que ce problème n'a rien de spécifique à DNSSEC et que, par exemple, HTTPS (le petit cadenas et la barre verte...) connait largement autant de semblables « bavures ».

Pour les techniciens, voici maintenant quelques informations concrètes. La panne était due au fait que images-art.fr n'était pas signé par DNSSEC mais qu'il y avait dans la zone parente (.fr) un enregistrement DS (Delegation Signer, un pointeur de la zone parente vers la clé de la zone fille, celui-ci pointait vers la clé 60840). Cet enregistrement DS est interprété par les résolveurs DNSSEC comme voulant dire « la zone est signée ». Si le résolveur découvre qu'elle ne l'est pas, il interprète cela comme une attaque. Pourquoi cette erreur ? On peut supposer plein de choses mais je note en examinant DNSDB que le DS n'a jamais changé alors que les clés dans la zone (et les signatures) ne sont apparues que le 19 octobre dans l'après-midi. Il est donc probable que la zone était prévue pour être signée, mais que c'est la zone non signée qui a été publiée, sans que cela n'empêche l'administrateur système de publier le DS, sans avoir vérifié (la plupart des professionnels ne testent jamais la configuration qu'ils déploient). Une hypothèse proche était que le processus (signature + envoi du DS au registre) était automatisé mais que le programme avait une bogue : l'échec de la signature n'a pas suspendu la publication du DS.

Voici ce que montraient deux logiciels de débogage DNSSEC au moment de la panne : ZoneMaster (« Server at 46.105.206.200 sent 2 DNSKEY records, and 0 RRSIG records ») et DNSviz. Voici ce que voyait l'outil dig, d'abord avec Google Public DNS :


% dig @8.8.8.8 www.images-art.fr 

; <<>> DiG 9.9.5-12-Debian <<>> @8.8.8.8 www.images-art.fr
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 11922
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 512
;; QUESTION SECTION:
;www.images-art.fr.     IN A

;; Query time: 24 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Mon Oct 19 15:30:06 CEST 2015
;; MSG SIZE  rcvd: 46

    

Le code SERVFAIL signifie Server Failure. Si on demande à Google de ne pas valider avec DNSSEC (CD = Checking Disabled) :

    
% dig +cd @8.8.8.8 www.images-art.fr

; <<>> DiG 9.9.5-12-Debian <<>> +cd @8.8.8.8 www.images-art.fr
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 4472
;; flags: qr rd ra cd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 512
;; QUESTION SECTION:
;www.images-art.fr.     IN A

;; ANSWER SECTION:
www.images-art.fr.      3599 IN A 213.186.33.5

;; Query time: 15 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Mon Oct 19 15:30:09 CEST 2015
;; MSG SIZE  rcvd: 62

C'était une autre preuve que le problème avait un lien avec DNSSEC. Essayons ensuite chez Free avec le résolveur de la Freebox :


% dig www.images-art.fr

; <<>> DiG 9.10.2-P2 <<>> www.images-art.fr
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 52045
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;www.images-art.fr.     IN A

;; Query time: 51 msec
;; SERVER: 192.168.2.254#53(192.168.2.254)
;; WHEN: Mon Oct 19 15:34:37 CEST 2015
;; MSG SIZE  rcvd: 46


% dig +cd www.images-art.fr

; <<>> DiG 9.10.2-P2 <<>> +cd www.images-art.fr
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 50409
;; flags: qr rd ra cd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;www.images-art.fr.     IN A

;; ANSWER SECTION:
www.images-art.fr.      3361 IN A 213.186.33.5

;; Query time: 8 msec
;; SERVER: 192.168.2.254#53(192.168.2.254)
;; WHEN: Mon Oct 19 15:34:40 CEST 2015
;; MSG SIZE  rcvd: 62

    

À noter que ce problème de « fausse alerte » ou de « faux positif » avec DNSSEC a été identifié il y a longtemps. Une des solutions possibles est le Negative Trust Anchor décrit dans le RFC 7646.

Merci à Kanor pour avoir attiré mon attention sur ce problème.


L'article seul

RFC 7672: SMTP security via opportunistic DANE TLS

Date de publication du RFC : Octobre 2015
Auteur(s) du RFC : V. Dukhovni (Two Sigma), W. Hardaker (Parsons)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dane
Première rédaction de cet article le 18 octobre 2015


L'état actuel de la sécurisation de SMTP par TLS n'est pas très satisfaisant : la grande majorité des certificats est auto-signée (pour éviter les prix et les délais des Autorités de certification) et, souvent, expirée. Conséquence logique, les serveurs SMTP ne vérifient pas les certificats : s'ils le faisaient, ils ne pourraient plus envoyer de courrier, ou bien ils se rabattraient sur du SMTP en clair, sans TLS, ce qui serait pire que d'accepter un certificat pourri. Comment améliorer la situation ? Ce nouveau RFC propose d'utiliser DANE en publiant dans le DNS, sécurisé par DNSSEC, le certificat du serveur. DANE était déjà normalisé pour HTTP, voici comment l'utiliser pour le courrier, où il y a un petit piège supplémentaire : le nom du serveur est indiqué via les enregistrements MX.

Le courrier a des spécificités qui font qu'on ne peut pas appliquer directement DANE de la même façon qu'avec HTTP (section 1 du RFC). Outre l'indirection entre nom du service (ce qui est à droite du @ dans une adresse) et nom de serveur (la partie droite de l'enregistrement MX), il y a le fait que rien n'indique si un service ou un serveur donné a TLS. Résultat, un attaquant actif peut supprimer la requête STARTTLS (RFC 3207), forçant ainsi un repli vers l'envoi de courrier en clair (c'est une des plus grosses vulnérabilités de SMTP-sur-TLS).

Généraliser TLS pour SMTP va prendre du temps (en France, il faut apparemment une charte signée avec le ministre juste pour activer TLS sur son Postfix). La sécurité de SMTP va donc forcément être « opportuniste » (RFC 7435), c'est-à-dire « on chiffre quand on peut » (au passage, attention en lisant les textes sur la sécurité en anglais : « opportunistic security » est un terme flou, qui désigne des choses très différentes selon les auteurs. Ce n'est pas du vocabulaire standardisé de la sécurité).

Notre nouveau RFC 7672 propose de résoudre ce problème avec des enregistrements DANE. Cela permet notamment de résister aux attaques par repli telles que celle où un attaquant actif retire STARTTLS de la liste des extensions SMTP d'un serveur. De même, DANE permet de se protéger contre un Homme du Milieu, en authentifiant le serveur (ce qui est théoriquement possible avec TLS aujourd'hui mais, comme on l'a vu, n'est quasiment jamais fait). À noter qu'un attaquant actif, avec le courrier d'aujourd'hui, n'a même pas besoin de supprimer STARTTLS : s'il n'y a pas de DNSSEC, il peut se contenter d'un empoisonnement DNS pour changer le MX, vers un serveur qui collabore davantage avec lui.

DANE, normalisé dans le RFC 6698, doit sa création à la constatation des faiblesses de X.509. La principale est le nombre excessif d'autorités de certification à qui il faut faire confiance (regardez le magasin de certificats dans votre navigateur Web...) Qu'une seule d'entre elles trahisse ou soit piratée et tout est fichu, même pour les gens qui ne sont pas clients de cette AC.

Bon, mais HTTPS utilise TLS et les AC de X.509 depuis des années et, plus ou moins, ça marche. Pourquoi SMTP serait-il différent ? La section 1.3 de notre RFC explique les différences (lisez bien cette partie si vous voulez comprendre en détail le problème qu'on essaie de résoudre) :

  • Un URL https://... indique clairement la volonté de protéger la session avec TLS. Au contraire, rien dans une adresse de courrier électronique ne permet d'indiquer cette volonté. Cela serait d'ailleurs difficile : SMTP-sur-TLS fonctionne étape par étape alors que l'adresse est de bout en bout. La seule solution est donc d'opportunité : si le serveur SMTP à l'autre bout annonce STARTTLS (RFC 3207) dans sa bannière, tenter sa chance en TLS. Cela permet évidemment des attaques par repli (un attaquant actif peut supprimer le STARTTLS de la bannière), qui sont la plaie de SMTP-sur-TLS.
  • HTTP, hélas, n'utilise pas d'indirection entre le nom de service (par exemple dnsviz.net) et un nom de serveur assurant ce service (par exemple www1.dnsviz.net). Cela a des tas de conséquences négatives pour HTTP (difficulté de faire de la répartition de charge côté client, obligation de « squatter » l'apex du domaine avec des enregistrements A ou AAAA, etc). Si HTTP était à refaire, il faudrait absolument lui faire utiliser les enregistrements SRV. Mais l'indirection, que ce soit par les enregistrements SRV ou bien par la forme simplifiée, les enregistrements MX, qu'utilise SMTP, a un défaut : il faut sécuriser la liaison entre nom de service (la partie gauche du MX, celle qui apparait dans l'adresse de courrier) et nom de serveur (la partie droite du MX). Imaginons un domaine internautique.fr dont le courrier est servi par mail1.provider.example. Même si ce dernier utilise TLS, si l'enregistrement MX n'est pas sécurisé (typiquement via DNSSEC), un attaquant pourrait tout simplement rediriger le courrier vers un autre serveur que mail1.provider.example, plus favorable à ses noirs desseins. Une solution à ce problème serait que le certificat de mail1.provider.example contienne également (subject alternative name ou un truc de ce genre) le nom du service (ici internautique.fr). Ce n'est pas du tout réaliste pour un gros hébergeur ayant des dizaines ou des centaines de milliers de clients.
  • Une solution au problème de l'attaque par repli est de configurer en dur les serveurs SMTP pour exiger de certains destinataires une session TLS ou rien du tout. Cela protège bien contre un attaquant actif mais cela ne passe évidemment pas à l'échelle. Une telle méthode est utilisée dans le système Email Made in Germany, où les gros serveurs SMTP allemands s'engagent à configurer en dur le certificat des autres (peut-être fera-t-on la même chose en France mais cela n'est pas explicite dans les projets actuels). Cela marche au sein d'un cartel de gros, pas pour le courrier en général, où on veut pouvoir écrire à des gens avec qui on n'a pas de relation pré-établie.
  • Une des méthodes les plus utilisées par HTTP pour gérer les problèmes de certificat est de demander à l'utilisateur : « le certificat pour https://www.bortzmeyer.org/ n'est pas signé par une autorité reconnue, voulez-vous continuer ? » D'innombrables études auprès des utilisateurs ont montré que cela ne marchait pas : l'utilisateur ne connait pas assez X.509 et la sécurité pour pouvoir prendre une décision informée. Mais, de toute façon, cette méthode n'a pas de sens pour SMTP, qui n'est pas interactif : le MTA n'a pas d'utilisateur humain à qui demander.

Ça, c'était le problème. Le reste du RFC est consacré à la solution, « DANE pour SMTP ». L'idée est que le MTA émetteur fasse une requête DNS pour le type TLSA (le type utilisé par DANE : ce n'est pas un acronyme, ne cherchez pas sa signification). Une fois les enregistrements TLSA récupérés et validés (par DNSSEC), l'émetteur se connecte au récepteur en SMTP et lance TLS. Il récupère alors le certificat et le compare à ce qu'il a trouvé dans l'enregistrement TLSA. Si c'est bon, il continue, si non il avorte. Un tel système protège contre les attaques par repli : si on trouve un enregistrement TLSA, c'est que le récepteur sait faire du TLS et veut le faire.

Donc, première étape de cette méthode, trouver les TLSA (section 2) du RFC. Si on en trouve, ils indiquent clairement la volonté du pair SMTP de faire du TLS (contrairement à l'indication STARTTLS dans la bannière, qui est parfois envoyée par des serveurs qui ne savent pas faire de TLS). C'est donc l'équivalent du HSTS de HTTP (RFC 6797), une promesse. Administrateurs système, ne mettez pas un TLSA dans le DNS si vous ne savez pas ce que vous faites !

En résultat de la requête DNS pour trouver les TLSA, il y a quatre possibilités :

  • Une réponse validée avec DNSSEC, et avec au moins un enregistrement utilisable. C'est un engagement du destinataire à faire du TLS. On y va et on chiffre. Si la session TLS échoue ou si le certificat obtenu en TLS ne correspond pas, on doit renoncer, plutôt que de livrer du courrier à l'Homme du Milieu.
  • Une réponse validée mais où aucun enregistrement n'est utilisable. Au passage, « utilisable » et « non utilisable » sont définis dans la section 4.1 du RFC 6698, celui qui normalise DANE. Un enregistrement est utilisable s'il est signé, avec signature valide, et si son contenu est accepté par le client (par exemple, le champ « usage du certificat » a une valeur connue). Le client doit alors utiliser TLS mais peut se dispenser d'authentifier, puisqu'il n'a pas d'enregistrement TLSA pour cela.
  • Une réponse non validée par DNSSEC ou bien une réponse validée qu'il n'existe aucun enregistrement TLSA. C'est la situation la plus courante actuellement, et on fait comme si DANE n'avait pas été inventé, en tentant TLS, puis en se rabattant sur du texte en clair si TLS échoue.
  • Une erreur, notamment un échec DNSSEC, par exemple parce que les données ont été modifiées par un attaquant actif. On ne doit pas transmettre le courrier à ce serveur.

En fait, j'ai un peu exagéré, la première étape n'est pas de trouver les enregistrements TLSA mais de trouver les enregistrements MX. Naturellement, on ne doit utiliser DANE que si le MX est signé par DNSSEC. S'il y a plusieurs enregistrements MX, certains peuvent pointer vers des serveurs qui n'ont pas DANE, voire pas TLS. Il est important de se rappeler que l'algorithme de choix parmi ces enregistrements MX (RFC 5321, section 5.1) ne tient pas compte de TLS : le premier serveur peut ne pas avoir TLS alors que les suivants l'ont. DANE ne modifie pas les algorithmes de SMTP et le choix d'un relais de courrier ne dépend donc pas de leur sécurité. Si on veut imposer TLS, il faut donc mettre TLS sur tous ses serveurs annoncés par les enregistrements MX. (Si SMTP avait été conçu plus récemment, il utiliserait les enregistrements SRV et on devrait donc lire le RFC 7673 à la place de celui-ci.)

Ah, et où trouver l'enregistrement TLSA ? Le nom de domaine à utiliser avec DANE est _port._protocole.nom.du.serveur. Pour SMTP, le port est normalement 25. Donc, en général, on cherchera l'enregistrement TLSA en _25._tcp.... Voyons un cas réel avec le domaine sources.org. On cherche d'abord le MX (je fais ici avec dig ce qu'un MTA DANE ferait automatiquement) :

% dig MX sources.org
...
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 5, ADDITIONAL: 1
...
;; ANSWER SECTION:
sources.org.		86400 IN MX 10 uucp.bortzmeyer.org.

On trouve un MX, sécurisé par DNSSEC (le flag AD - Authentic Data - dans la réponse ; notez au passage qu'il faut un résolveur DNSSEC validant pour faire du DANE). Cherchons maintenant le TLSA :

 % dig TLSA _25._tcp.uucp.bortzmeyer.org
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 9, ADDITIONAL: 9
...
;; ANSWER SECTION:
_25._tcp.uucp.bortzmeyer.org. 86400 IN TLSA 2 0 1 (
				FF2A65CFF1149C7430101E0F65A07EC19183A3B633EF
				4A6510890DAD18316B3A )

On a un TLSA utilisable, donc on va faire du TLS et vérifier que le certificat obtenu en TLS correspond bien au contenu de l'enregistrement TLSA.

Et quels enregistrements TLSA suggérer pour les serveurs SMTP, parmi les nombreuses combinaisons possibles ? Notre RFC recommande DANE-EE (usage 3) + SPKI (sélecteur 1) + SHA-256 (méthode de correspondance 1). Pourquoi ces recommandations (vous noterez, sur mon domaine personnel, que je ne les ai pas suivies, utilisant le « second choix » du RFC...) ? DANE-EE (c'est-à-dire qu'on ne fait pas de vérifications X.509 à partir des autorités de certification dans le magasin et que le certificat dans l'enregistrement TLSA est celui du serveur) est recommandé parce que les trois autres possibilités ont des défauts gênants. Avec DANE-TA (usage 2, que j'utilise personnellement), le certificat est celui de l'AC, pas celui du serveur. Comme tous les clients DANE n'ont pas forcément « mon » AC dans leur magasin, il faut envoyer le certificat de l'AC en sus de celui du serveur (ce que je fais sur mon serveur SMTP : cela ne me semble pas si difficile que ça). PKIX-TA et PKIX-EE (où on continue à faire les vérifications X.509 classiques) ont le même problème (la variété des AC présentes dans les différents magasins, qui interdit de compter sur une AC de référence). Mettre ces deux usages est donc dangereux, bien des MTA ne pourront plus vous authentifier.

Pour l'usage DANE-EE, qui est recommandé, le sélecteur suggéré est SPKI (l'enregistrement TLSA contient juste la clé, pas tout le certificat) car les autres informations du certificat (comme la date d'expiration ou le nom du serveur) sont inutiles (toute l'information utile est dans le DNS).

Pour l'usage DANE-TA, en revanche, il est recommandé de mettre un sélecteur CERT, qui indique que le client DANE doit vérifier tout le certificat, pas juste la clé.

Quant aux méthodes de correspondance (le troisième champ de l'enregistrement TLSA), la valeur 0 (on met le certificat entier, au lieu de juste un condensat) est déconseillée, en raison de la difficulté du DNS à faire passer des données de trop grande taille.

Au fait, on a surtout ici parlé de DANE pour sécuriser la communication entre deux serveurs SMTP, deux MTA. Mais entre un MUA et un MTA ? Pour les protocoles comme IMAP (RFC 6186), on utilise DANE+SRV (RFC 7673). Pour SMTP (soumission d'un message par le MUA), qui utilise rarement le RFC 6186 pour l'instant, les configurations statiques traditionnelles marchent encore.

Les administrateurs système seront intéressés par la section 9 du RFC, consacrée aux problèmes opérationnels. Par exemple, un administrateur peut hésiter à activer DANE sur le serveur SMTP dont il a la responsabilité : et si, se dit-il, mon courrier n'est plus transmis, par exemple parce que trop d'informaticiens font des erreurs et publient des configuration DANE cassées ? Cet administrateur prudent peut envisager d'utiliser DANE seulement pour certaines destinations, « pour voir », ou bien utiliser DANE en mode « on regarde et on journalise » mais on ne vérifie pas.

Autre problème opérationnel important, un changement de certificat : il faut bien penser à publier le nouveau TLSA à l'avance, pour que l'ancien ensemble TLSA ait disparu de tous les caches DNS avant que le serveur SMTP n'utilise le nouveau certificat.

Et pour faire du DANE avec SMTP en pratique ? Un MTA qui gère DANE existe, Postfix, depuis la version 2.11 (cf. la documentation officielle). Vous vérifiez bien que votre serveur SMTP utilise un résolveur DNSSEC validant, vous mettez dans la configuration :

smtp_dns_support_level = dnssec

smtp_tls_security_level = dane
   

Et c'est parti. Essayons d'envoyer un message à DENIC qui a annoncé avoir déployé DANE (certificat auto-signé donc normalement pas validable) :

Oct 18 21:58:08 aetius postfix/smtp[26542]: Verified TLS connection established \
      to mx2.denic.de[81.91.161.38]:25: \
      TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)
   

Et voilà, on se connecte en TLS après avoir vérifié que tout allait bien. En effet, DENIC a un enregistrement TLSA :

% dig TLSA _25._tcp.mx1.denic.de
...
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 3, ADDITIONAL: 5
...
;; ANSWER SECTION:
_25._tcp.mx1.denic.de.	3600 IN	TLSA 3 0 1 (
				17CBD8A164851E86C94A534438D02A4202CC71FCAE6C
				24E1F98214BD586F67A1 )
  

Ça, c'était la configuration en émetteur. Et en réception ? Il faut avoir déjà activé TLS sur son serveur (ce qui a été fait il y a pas mal d'années sur tous les serveurs SMTP sérieux). Il faut avoir une zone (correctement) signée avec DNSSEC. Il faut ensuite publier un enregistrement TLSA. Ici, j'ai choisi, comme expliqué plus haut, de publier le certificat de mon AC, CAcert. J'utilise la commande tlsa dans l'outil hash-slinger :

% tlsa --usage 2 --selector 0 --mtype 1 --output rfc --certificate ~/tmp/cacert.pem \
       --port 25 mail.bortzmeyer.org                                             
_25._tcp.mail.bortzmeyer.org. IN TLSA 2 0 1 ff2a65cff1149c7430101e0f65a07ec19183a3b633ef4a6510890dad18316b3a

Et je mets cet enregistrement dans ma zone DNS :

% dig TLSA _25._tcp.mail.bortzmeyer.org
...
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 8, ADDITIONAL: 7
...
;; ANSWER SECTION:
_25._tcp.mail.bortzmeyer.org. 86400 IN TLSA 2 0 1 (
				FF2A65CFF1149C7430101E0F65A07EC19183A3B633EF
				4A6510890DAD18316B3A )

Pour tester, on peut faire appel aux copains en leur demandant d'envoyer des messages, ou bien on peut se servir de https://www.tlsa.info/, qui teste tout (DNSSEC, DANE et TLS en se connectant au serveur SMTP). Il n'essaie pas uniquement le DNS mais aussi le fait que le certificat corresponde bien à l'enregistrement TLSA. Si je publie un mauvais enregistrement, il proteste :

bortzmeyer.fr

The domain lists the following MX entries:
0 uucp.bortzmeyer.org

All TLSA RRs failed. (See details.)

Usable TLSA Records
2, 0, 1 ff2a65cff1149c74[...]10890dad18316b3b - application verification failure: (50)

Un autre outil de test est https://arp.simson.net/dane_check.cgi.


Téléchargez le RFC 7672


L'article seul

RFC 7673: Using DNS-Based Authentication of Named Entities (DANE) TLSA Records with SRV Records

Date de publication du RFC : Octobre 2015
Auteur(s) du RFC : T. Finch (University of Cambridge), M. Miller (Cisco Systems), P. Saint-Andre (&yet)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dane
Première rédaction de cet article le 15 octobre 2015


Le protocole DANE, normalisé dans le RFC 6698, permet d'associer au nom d'un serveur un certificat qu'on peut comparer avec celui qui est présenté par le serveur lors d'une session TLS, authentifiant ainsi directement ou indirectement le serveur. Cela permet de boucher certaines failles de X.509. Mais DANE ne marche qu'avec un nom de serveur, tel que l'utilise HTTP. La quasi-totalité des protocoles ont, au contraire, une indirection supplémentaire entre nom de service et nom de serveur, typiquement via un enregistrement SRV (RFC 2782). Dans un tel cas, où trouver les enregistrements TLSA, ceux utilisés par DANE ? Le choix est de vérifier le domaine pointé (nom du serveur, celui du prestataire) et pas le pointeur (nom de service, celui de l'utilisateur).

Voici un exemple d'un enregistrement TLSA (au passage, ne cherchez pas à quels mots correspondent les lettres de TLSA : ce n'est officiellement pas un acronyme) classique, pour un serveur HTTP, en l'occurrence pour https://www.freebsd.org :


% dig TLSA _443._tcp.www.freebsd.org 
...
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 4, ADDITIONAL: 13
...
;; ANSWER SECTION:
_443._tcp.www.freebsd.org. 600 IN TLSA 3 0 1 (
				A9F16D689F5AEE122E86A8468A8586DDA4440A7298C6
				4AD4EED1AAE8BEB2A892 )
				...

    

Mais, à part HTTP (dont c'est l'une des principales faiblesses, menant à un mélange entre nom de service et nom de serveur), les protocoles utilisent en général un nom de service (vu par l'utilisateur) et un nom de serveur (récupéré automatiquement dans le DNS via les enregistrements SRV ou, dans le cas du courrier, des enregistrements MX). Il fallait donc étendre la définition originelle de DANE, celle du RFC 6698, pour ces protocoles. Pour SMTP et ses MX, c'est le RFC 7672. Pour les protocoles à SRV, comme XMPP, c'est ce RFC 7673.

Le choix principal qui se posait lors de la rédaction de ce RFC était « l'enregistrement TLSA doit-il être associé au service (l'origine, en partie gauche de l'enregistrement SRV) ou bien au serveur (la cible, en partie droite) ? » Le choix a été fait d'accrocher le TLSA, l'enregistrement DNS contenant le certificat au serveur. Ainsi, si on a cet enregistrement SRV pour XMPP à example.com :

_xmpp-client._tcp.example.com. SRV     1 0 5222 im.example.net.
    

L'enregistrement TLSA sera en im.example.net, pas en example.com. Les raisons de ce choix sont expliquées dans l'annexe B du RFC et résumées plus loin.

Pour la sécurité du lien entre service et serveur, on compte sur DNSSEC, qui signera l'enregistrement SRV (ainsi que, bien sûr, le TLSA). Maintenant, place aux détails concrets.

La section 3 du RFC commence par les tests DNS. Si l'utilisateur veut se connecter à un service foobar dans example.com, il va demander le SRV de _foobar._tcp.example.com. Supposons qu'il existe un alias (enregistrement CNAME) vers foobar.example.net et qu'ensuite on trouve le SRV qui liste un seul serveur, foobar1.example.org. Pour pouvoir utiliser DANE, il faut que toute la chaîne DNS soit sécurisée par DNSSEC. Dans cet exemple, les deux enregistrements qui forment la chaîne (le CNAME puis le SRV) doivent donc tous les deux être signés et validés. Sinon, si l'un de ces enregistrements n'est pas signé, pas question de lancer DANE puisqu'on ne peut pas avoir confiance dans leur contenu.

On n'en a pas fini avec le DNS : il faut maintenant trouver l'adresse IP des serveurs (ici, un seul), ce qui doit être également validé avec DNSSEC. Enfin, on fait les requêtes pour les enregistrements TLSA, en utilisant comme nom (le QNAME ou Query Name) le nom du serveur, préfixé du numéro de port. Si l'application foobar fonctionne sur le port 5634 (il est indiqué dans l'enregistrement SRV), on demandera ici le ou les TLSA de _5634._tcp.foobar1.example.org (et non pas d'example.com). Autre exemple, emprunté au RFC, avec IMAP, le SRV pour example.com valait :

      _imap._tcp.example.com. 86400 IN SRV 10 0 9143 imap.example.net.
    

On demandera donc un enregistrement TLSA pour _9143._tcp.imap.example.net. Évidemment, on vérifie la validité de cet enregistrement avec DNSSEC (ignorer les enregistrements non signés et donc non validés est un principe de base de DANE, cf. RFC 6698, section 4.1).

Le client se connecte en TLS au serveur. Quelles vérifications doit-il faire (section 4) ? S'il n'a trouvé aucun enregistrement TLSA utilisable (par exemple parce qu'il n'y en avait pas, ou bien parce qu'ils n'étaient pas signés avec DNSSEC), il doit faire la validation habituelle d'un certificat X.509 (à partir des AC que le client a dans son magasin), décrite dans le RFC 5280. Il peut être nécessaire d'utiliser quelques règles spécifiques à l'application, cf. RFC 6125. Au passage, notons que la terminologie est variable : ce que notre RFC 7673 nomme service et serveur est appelé dans la RFC 6125 « domaine source » et « domaine dérivé ».

Par contre, s'il y a des enregistrements TLSA et qu'ils sont utilisables (ce qui implique notamment qu'ils soient signés et validés), alors le client doit valider le certificat obtenu dans le dialogue TLS avec DANE (RFC 6698, section 2.1). Notamment, si l'enregistrement TLSA indique un usage « DANE-EE » (DANE End Entity), alors le client ne doit pas faire de vérification X.509 du tout et donc ignorer les RFC 5280 et RFC 6125.

Si vous êtes l'auteur d'un protocole qui utilise des enregistrements SRV, lisez la section 5 de notre RFC : elle écrit les détails auxquels vous devez penser pour votre protocole. Ce sont notamment :

  • Les éventuels mécanismes de repli si le client n'arrive pas à se connecter de manière sûre,
  • Comment les clients doivent-il faire s'ils ne trouvent pas d'enregistrement SRV ou s'ils ne savent pas faire de requêtes SRV (ce qui est un problème fréquent avec le JavaScript exécuté dans un navigateur Web).
  • La méthode générique en TLS pour indiquer le nom de domaine auquel on veut se connecter est l'extension SNI du RFC 6066. Certains protocoles ont une méthode à eux et il faut donc la documenter (par exemple, XMPP utilise l'élément <to> de son flux XML).
  • Utilisation d'éventuels autres mécanismes de découverte, en sus des SRV, comme les NAPTR (RFC 3403) utilisés par SIP.

Si vous êtes opérateur d'un service sécurisé avec TLS, voyez la section 6. Elle rappelle la nécessité de signer les enregistrements DNS SRV et TLSA avec DNSSEC. D'autre part, en créant le certificat qui sera servi en TLS, il faut suivre certaines règles :

  • Si l'enregistrement TLSA prévoit un usage DANE-EE, le ou les noms indiqué(s) dans le certificat n'ont pas d'importance pour DANE (cf. la section 9.2). D'un autre côté, les clients non-DANE ne pourront pas se connecter en TLS si les noms ne correspondent pas à ce qu'ils attendent.
  • Avec d'autres usages que DANE-EE, ou bien si on veut que le certificat marche même avec les clients non-DANE, il faut que le nom dans le certificat soit le nom de serveur et de préférence qu'il y ait aussi le nom de service (les règles exactes, compliquées, sont dans le RFC 6125). Dans un environnement où un fournisseur sert un grand nombre de domaines hébergés (environnement multi-tenant), mettre le nom du service va souvent être difficile.

L'extension SNI du RFC 6066, déjà citée, permet d'envoyer au client le bon certificat, si le serveur en a plusieurs. Un exemple d'un usage de TLSA où il faut vérifier le nom est l'usage DANE-TA où le certificat dans l'enregistrement TLSA autorise l'AC, pas le certificat du serveur. Cet usage empêche les attaques par une autre AC mais pas celles par un autre utilisateur de la même AC. Il faut donc vérifier que le(s) nom(s) dans le certificat est(sont) bien celui attendu (cf. section 9.2).

Après les auteurs de protocoles et les administrateurs système, place aux développeurs (section 7). Pour limiter le temps d'attente pour les utilisateurs, le RFC leur recommande de faire les différentes résolutions aussi en parallèle que possible. Par exemple, une fois obtenu un SRV, on peut faire les résolutions d'adresse (enregistrements A et AAAA) en même temps que le TLSA.

La section 9 du RFC revient sur quelques pièges de sécurité. D'abord, un ensemble d'enregistrements SRV pouvant contenir plusieurs noms de serveurs, il ne faut pas croire que tous auront le même niveau de sécurité, surtout si l'un d'eux est sous-traité à un opérateur ne servant qu'en cas de problème avec les serveurs « principaux ». Par exemple, certains peuvent accepter TLS et d'autres pas. Il sera donc inutile de chercher des enregistrements TLSA pour les seconds. Ce point est d'autant plus important que le traitement des enregistrements SRV ne donne aucune priorité aux serveurs ayant TLS.

L'annexe B de notre RFC est cruciale et doit absolument être lue. Elle revient sur un choix qui a été délicat et très discuté à l'IETF : l'enregistrement TLSA doit-il se situer sur le nom de service (domaine originellement indiqué par l'utilisateur et donc a priori le domaine important qu'on veut vérifier) ou bien sur le nom de serveur (obtenu après une requête SRV et information normalement purement technique) ? Le choix de notre RFC 7673 est clair : le TLSA pertinent est situé sur le nom du serveur, essentiellement parce que c'est la seule méthode réaliste pour les services hébergés chez un gros opérateur qui a des milliers, voire des millions, de client hébergés.

Des raisons diverses viennent à l'appui de ce choix :

  • Le certificat fait partie de la configuration du serveur. Il est donc logique de mettre le TLSA au nom du serveur.
  • Pensez à un changement de certificat : si le TLSA est lié au serveur, il n'y a qu'un seul changement dans le DNS. S'il est lié au client, il y en aura autant que de domaines hébergés (et certains l'oublieront probablement).
  • Si le client n'utilise pas SNI, le certificat servi devra lister tous les domaines de tous les hébergés (comme on le voit sur des gros hébergeurs comme CloudFlare, où https://www.republique-numerique.fr/ partage son certificat avec un site porno chinois, https://renxxx.com/).
  • Avec la méthode choisie, le même certificat marchera pour une connexion via un SRV et aussi pour une connexion directe quand on connait le nom du serveur, ce qui peut être pratique pour le débogage.
  • Certains protocoles applicatifs permettent d'envoyer des messages pour plusieurs domaines en une seule transaction. Cela ne serait plus possible si l'enregistrement TLSA était lié au service. Un exemple d'un tel protocole est SMTP (qui n'utilise pas SRV mais c'est juste un exemple) lors de plusieurs RCPT TO vers des domaines différents.
  • Pour certains protocoles (là encore, c'est le cas de SMTP), un serveur peut jouer plusieurs rôles (par exemple, pour SMTP, cible des enregistrements MX, en réception, mais aussi envoyeur). Il est plus simple de n'avoir qu'un certificat pour tous les cas.

Bien sûr, il y a des cas où le TLSA sur le nom du service (du domaine source) serait préférable. L'IETF avait envisagé de permettre cette possibilité, en plus de la « normale » mais y a renoncé pour garder le protocole simple. Dans certains cas (clients non-DNSSEC, par exemple, qui ne peuvent donc pas valider le SRV et doivent donc vérifier le domaine d'origine), cela compliquera les choses (SNI aidera parfois).

Allez, un exemple réel d'un enregistrement SRV avec DANE au bout :

% dig +nodnssec +short SRV _xmpp-server._tcp.mailbox.org           
0 5 5269 xmpp.mailbox.org.

%  dig +nodnssec +short TLSA _5269._tcp.xmpp.mailbox.org
3 1 1 4758AF6F02DFB5DC8795FA402E77A8A0486AF5E85D2CA60C294476AA DC40B220
    

Et je vous recommande de lire cet excellent article sur la sécurisation de XMPP avec DNSSEC et DANE.


Téléchargez le RFC 7673


L'article seul

Free, noblogs.org et un curieux problème DNS / DNSSEC

Première rédaction de cet article le 9 octobre 2015


Quelques mois après le problème juralib.noblogs.org, les rézosocios ont bruissé de clameurs sur le domaine ladiscordia.noblogs.org, invisible depuis Free. Censure ou bavure ?

Beaucoup de gens ont crié à la censure, ce qui est raisonnable dans le contexte politique actuel, vu que le site Web derrière ce domaine sert en général des contenus politiquement radicaux. (Voir par exemple une discussion très foutraque sur Reddit.) Mais, si la censure existe, les bogues existent aussi, et il existe davantage de maladroits que de méchants. Étudions donc la question.

D'abord, plaçons nous sur une machine connectée par Free et utilisant les résolveurs DNS de Free (ce n'est pas obligatoire). On constate qu'on ne peut pas visiter la page Web citée plus haut. Des tests techniques montrent que le problème est dans la résolution DNS. Pas moyen de trouver l'adresse IP associée au nom. Testons avec dig :


%  dig ladiscordia.noblogs.org                
...
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 937
                                       ^^^^^^^^
                                       Server Failure

Ah, Houston, nous avons un problème. Le domaine noblogs.org étant signé avec DNSSEC (une excellente idée), regardons avec l'option +cd (Checking Disabled) qui coupe la validation DNSSEC :


%  dig +dnssec +cd ladiscordia.noblogs.org  

; <<>> DiG 9.10.2-P2 <<>> +cd ladiscordia.noblogs.org
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 16475
;; flags: qr rd ra cd; QUERY: 1, ANSWER: 15, AUTHORITY: 5, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;ladiscordia.noblogs.org. IN A

;; ANSWER SECTION:
ladiscordia.noblogs.org. 2284 IN CNAME www.l.autistici.org.
ladiscordia.noblogs.org. 2284 IN RRSIG CNAME 7 2 9600 (
                                20151101063004 20151002063004 64367 noblogs.org.
                                LuRSXa97Yjr+wYVGjq8yFxIOTXeufRMNaL6L31jqq3im
                                MphTYlJRGvwTzZTPwbbbkZjSuCtt5P7l3/iMx50ZEZ/B
                                x3q0PDD3Yo4ckrfcIzMQ9V+HeosW+W78UBTC0LyQIxSq
                                eRdlhsNZKSELmR8k9sVpJ5mrQPTQ3HzGzUr4z1w= )
ladiscordia.noblogs.org. 2284 IN CNAME www.l.autistici.org.
ladiscordia.noblogs.org. 2284 IN RRSIG CNAME 7 2 9600 (
                                20151101063004 20151002063004 64367 noblogs.org.
                                LuRSXa97Yjr+wYVGjq8yFxIOTXeufRMNaL6L31jqq3im
                                MphTYlJRGvwTzZTPwbbbkZjSuCtt5P7l3/iMx50ZEZ/B
                                x3q0PDD3Yo4ckrfcIzMQ9V+HeosW+W78UBTC0LyQIxSq
                                eRdlhsNZKSELmR8k9sVpJ5mrQPTQ3HzGzUr4z1w= )
ladiscordia.noblogs.org. 2284 IN CNAME www.l.autistici.org.
ladiscordia.noblogs.org. 2284 IN RRSIG CNAME 7 2 9600 (
                                20151101063004 20151002063004 64367 noblogs.org.
                                LuRSXa97Yjr+wYVGjq8yFxIOTXeufRMNaL6L31jqq3im
                                MphTYlJRGvwTzZTPwbbbkZjSuCtt5P7l3/iMx50ZEZ/B
                                x3q0PDD3Yo4ckrfcIzMQ9V+HeosW+W78UBTC0LyQIxSq
                                eRdlhsNZKSELmR8k9sVpJ5mrQPTQ3HzGzUr4z1w= )
  
ladiscordia.noblogs.org. 2284 IN CNAME www.l.autistici.org.
ladiscordia.noblogs.org. 2284 IN RRSIG CNAME 7 2 9600 (
                                20151101063004 20151002063004 64367 noblogs.org.
                                LuRSXa97Yjr+wYVGjq8yFxIOTXeufRMNaL6L31jqq3im
                                MphTYlJRGvwTzZTPwbbbkZjSuCtt5P7l3/iMx50ZEZ/B
                                x3q0PDD3Yo4ckrfcIzMQ9V+HeosW+W78UBTC0LyQIxSq
                                eRdlhsNZKSELmR8k9sVpJ5mrQPTQ3HzGzUr4z1w= )
ladiscordia.noblogs.org. 2284 IN CNAME www.l.autistici.org.
ladiscordia.noblogs.org. 2284 IN RRSIG CNAME 7 2 9600 (
                                20151101063004 20151002063004 64367 noblogs.org.
                                LuRSXa97Yjr+wYVGjq8yFxIOTXeufRMNaL6L31jqq3im
                                MphTYlJRGvwTzZTPwbbbkZjSuCtt5P7l3/iMx50ZEZ/B
                                x3q0PDD3Yo4ckrfcIzMQ9V+HeosW+W78UBTC0LyQIxSq
                                eRdlhsNZKSELmR8k9sVpJ5mrQPTQ3HzGzUr4z1w= )
ladiscordia.noblogs.org. 2284 IN CNAME www.l.autistici.org.
ladiscordia.noblogs.org. 2284 IN RRSIG CNAME 7 2 9600 (
                                20151101063004 20151002063004 64367 noblogs.org.
                                LuRSXa97Yjr+wYVGjq8yFxIOTXeufRMNaL6L31jqq3im
                                MphTYlJRGvwTzZTPwbbbkZjSuCtt5P7l3/iMx50ZEZ/B
                                x3q0PDD3Yo4ckrfcIzMQ9V+HeosW+W78UBTC0LyQIxSq
                                eRdlhsNZKSELmR8k9sVpJ5mrQPTQ3HzGzUr4z1w= )
www.l.autistici.org.    1800 IN A 94.23.50.208
www.l.autistici.org.    1800 IN A 82.94.249.234
www.l.autistici.org.    1800 IN RRSIG A 7 4 30 (
                                20151105063002 20151006063002 2207 l.autistici.org.
                                HDkkzb8afOIlk5P0HRmiVal7KmAu4bevmkAPpHuAMruS
                                9Pj2OkWjeWwJiLm7zX5MjqIcfUBvJ6gbODvRGr7dDJHn
                                7qqLNA3IXMvxm5trBWz2/YZsTs/2XEgIBDVgxRel+OBp
                                HD+riKX0ZylmTGXG7/fyRfcYLquwphS4gNTMWbk= )

;; AUTHORITY SECTION:
l.autistici.org.        1800 IN NS ns1.investici.org.
l.autistici.org.        1800 IN NS ns2.investici.org.
l.autistici.org.        1800 IN NS ns2-v6.investici.org.
l.autistici.org.        1800 IN NS ns1-v6.investici.org.
l.autistici.org.        1800 IN RRSIG NS 7 3 30 (
                                20151105063002 20151006063002 2207 l.autistici.org.
                                bA28B6AP9NQzyavLXFZoxDCsV1kDpZwid+QyPcR2qhrj
                                c3wfuB6P2PM7WBHzlbZevt1C3+z/FMqvXRr/TrhbseDy
                                ScKCai/LPD68z0bqUucz0uuFbDpTxvJNDf+0zJrMQTsw
                                +zse/UsiopBVrqCjOXRWte2DvDxyCPtN3WnEYJc= )

;; Query time: 26 msec
;; SERVER: 192.168.2.254#53(192.168.2.254)
;; WHEN: Fri Oct 09 11:09:32 CEST 2015
;; MSG SIZE  rcvd: 1648

Ouh là, là, c'est long. Bien trop long, la répétition de l'enregistrement CNAME et de sa signature est tout à fait anormale. Est-ce de la faute du résolveur DNS Free ou bien du domaine noblogs.org ? Allons sur une autre machine qui utilise son propre résolveur, un Unbound :


% dig +dnssec ladiscordia.noblogs.org

; <<>> DiG 9.9.5-9+deb8u3-Debian <<>> +dnssec ladiscordia.noblogs.org
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 62823
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 5, AUTHORITY: 7, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;ladiscordia.noblogs.org. IN A

;; ANSWER SECTION:
ladiscordia.noblogs.org. 6082 IN CNAME www.l.autistici.org.
ladiscordia.noblogs.org. 6082 IN RRSIG CNAME 7 2 9600 (
                                20151101063004 20151002063004 64367 noblogs.org.
                                LuRSXa97Yjr+wYVGjq8yFxIOTXeufRMNaL6L31jqq3im
                                MphTYlJRGvwTzZTPwbbbkZjSuCtt5P7l3/iMx50ZEZ/B
                                x3q0PDD3Yo4ckrfcIzMQ9V+HeosW+W78UBTC0LyQIxSq
                                eRdlhsNZKSELmR8k9sVpJ5mrQPTQ3HzGzUr4z1w= )
www.l.autistici.org.    30 IN A 94.23.50.208
www.l.autistici.org.    30 IN A 82.94.249.234
www.l.autistici.org.    30 IN RRSIG A 7 4 30 (
                                20151105063002 20151006063002 2207 l.autistici.org.
                                HDkkzb8afOIlk5P0HRmiVal7KmAu4bevmkAPpHuAMruS
                                9Pj2OkWjeWwJiLm7zX5MjqIcfUBvJ6gbODvRGr7dDJHn
                                7qqLNA3IXMvxm5trBWz2/YZsTs/2XEgIBDVgxRel+OBp
                                HD+riKX0ZylmTGXG7/fyRfcYLquwphS4gNTMWbk= )

;; AUTHORITY SECTION:
EDG28OM0KF8LV6JVVTUAE9R7GLNTNKMD.noblogs.org. 82 IN NSEC3 1 0 10 5CA1AB1E (
                                K1C26GO8L9TJ398E8MKH7QLSP4LB88UO
                                CNAME RRSIG )
EDG28OM0KF8LV6JVVTUAE9R7GLNTNKMD.noblogs.org. 82 IN RRSIG NSEC3 7 3 3600 (
                                20151101063004 20151002063004 64367 noblogs.org.
                                juTchEjZZFdj5WkhyKh/2qZxffIjahcjtWrC7aiM78QT
                                nuBLP6AqRatIwpbIauM9ZbBwXD1ZXwRhpZrLTDKqS8bK
                                qU5dsUCKsB3vIYba84I12t1bAg0YKv0HP8bkEMp9ftO+
                                bZNLtY+TXyaZ5FULNI26gMen2YYsqPovY0YnH0M= )

l.autistici.org.        30 IN NS ns2-v6.investici.org.
l.autistici.org.        30 IN NS ns2.investici.org.
l.autistici.org.        30 IN NS ns1.investici.org.
l.autistici.org.        30 IN NS ns1-v6.investici.org.
l.autistici.org.        30 IN RRSIG NS 7 3 30 (
                                20151105063002 20151006063002 2207 l.autistici.org.
                                bA28B6AP9NQzyavLXFZoxDCsV1kDpZwid+QyPcR2qhrj
                                c3wfuB6P2PM7WBHzlbZevt1C3+z/FMqvXRr/TrhbseDy
                                ScKCai/LPD68z0bqUucz0uuFbDpTxvJNDf+0zJrMQTsw
                                +zse/UsiopBVrqCjOXRWte2DvDxyCPtN3WnEYJc= )

;; Query time: 239 msec
;; SERVER: ::1#53(::1)
;; WHEN: Fri Oct 09 11:12:01 CEST 2015
;; MSG SIZE  rcvd: 977

On n'a pas cette fois la répétition des CNAME, c'est plus normal (et valide : le bit AD Authentic Data dans la réponse nous l'indique). Autre façon de vérifier qu'il y a bien un problème spécifique à Free, demander aux sondes RIPE Atlas françaises (avec ce programme) ce qu'elles voient :

% python resolve-name.py -r 500 -c FR -t A ladiscordia.noblogs.org 
Measurement #2490878 for ladiscordia.noblogs.org/A uses 500 probes
[ERROR: REFUSED] : 3 occurrences 
[ERROR: SERVFAIL] : 116 occurrences 
[82.94.249.234 94.23.50.208] : 338 occurrences 
Test done at 2015-10-08T08:58:30Z 

La plupart voient la bonne réponse (deux adresses IP), 116 d'entre elles reçoivent le SERVFAIL. Ce sont celles situées sur ce réseau de Free. Limitons la requête à l'AS de Free :

% python resolve-name.py -r 500 --as 12322 -t A ladiscordia.noblogs.org  
Measurement #2495118 for ladiscordia.noblogs.org/A uses 233 probes
[ERROR: REFUSED] : 1 occurrences 
[ERROR: SERVFAIL] : 161 occurrences 
[82.94.249.234 94.23.50.208] : 62 occurrences 
Test done at 2015-10-09T09:18:07Z

La majorité des sondes Atlas chez Free ont le problème (certains clients de Free ont leur propre résolveur et ne voient donc pas le problème).

Donc, c'est chez Free ? Il n'y a pas de problème dans la zone noblogs.org ? Je dois confesser que j'avais stupidement mis en cause cette zone sur Twitter, en confondant avec un autre cas. Comme les gens qui criaient à la censure, j'avais réagi trop vite en sens inverse. Toutes mes excuses au mainteneur de noblogs.org, cette zone ne semble pas avoir de problème DNSSEC grave, comme le montrent très bien DNSviz ou ZoneMaster (il y a des erreurs mais pas graves et sans lien avec DNSSEC).

Mais, alors, qu'est-ce qui se passe ? Y aurait-il bien censure délibérée par Free ? Sans doute pas. En effet, en comparant le résultat des commandes dig avec le résolveur DNS de Free et un autre résolveur, on voit le problème : l'enregistrement NSEC3 est manquant. Ça veut dire quoi ? NSEC3, normalisé dans le RFC 5155, sert à prouver qu'un nom n'existe pas. Ici, comme la zone noblogs.org utilise des jokers (tout nom, même gfcgf565FsdZE523SEDvgGFSS.noblogs.org va marcher, cf. RFC 1034, section 4.3.3), le NSEC3 doit être envoyé pour prouver que le nom demandé, ladiscordia.noblogs.org, n'existait pas réellement mais été synthétisé via le joker. Dans la réponse du résolveur correct, on a le NSEC3 :

EDG28OM0KF8LV6JVVTUAE9R7GLNTNKMD.noblogs.org. 82 IN NSEC3 1 0 10 5CA1AB1E (
                                K1C26GO8L9TJ398E8MKH7QLSP4LB88UO
                                CNAME RRSIG )

Mais on ne l'a pas dans la réponse du résolveur de Free. Si on teste avec DNSviz en local, en passant à travers le résolveur de Free, le rapport (en JSON) nous dit la même chose :

"errors": [
    {
        "description": "No NSEC RR(s) were returned to validate the wildcard response.",
        "code": "MISSING_NSEC_FOR_WILDCARD",
        "servers": [
            "192.168.2.254"
        ],
        "tags": [
            "UDP_272_EDNS0_32768_4096"
        ]
    }
...

(Au passage, notez que Free force un TTL minimum, ce qui fait également couiner DNSviz, car DNSSEC ne permet pas ce genre de manips :

"errors": [
       {
           "description": "The TTL of the RRset (1665) exceeds the value of the Original TTL field of the RRSIG RR covering it (900).",
           "code": "ORIGINAL_TTL_EXCEEDED"
       }
...

)

Comment un résolveur ayant ces données voit qu'il y a un problème DNSSEC (et va donc renvoyer SERVFAIL) ? Grâce au champ Number of labels de la signature (RFC 4034, section 3.1.3). Lorsque le nom existe, ce champ indique le nombre de composants dans le nom demandé :

www.noblogs.org.        9600 IN RRSIG CNAME 7 3 9600 (
                                20151101063004 20151002063004 64367 noblogs.org.
                                k7l/nfVCejZ+pO7BPIPEPaQs7w09CE/4SJL7rjItAEqf
                                ...

Le champ est le troisième après le type RRSIG. Ici, il vaut trois, ce qui est bien le nombre de composants du nom de domaine demandé. Mais lorsque le nom a été synthétisé grâce au joker :

ladiscordia.noblogs.org. 5073 IN RRSIG CNAME 7 2 9600 (
                                20151101063004 20151002063004 64367 noblogs.org.
                                LuRSXa97Yjr+wYVGjq8yFxIOTXeufRMNaL6L31jqq3im
				...

Alors, le champ ne vaut que deux, indiquant qu'il y a un joker dans le deuxième composant (la zone noblogs.org ; après tout, le joker pourrait être dans une zone parente ou grand-parente). Le résolveur DNSSEC voit donc que la signature couvre en fait le joker :

*.noblogs.org.          9600 IN RRSIG CNAME 7 2 9600 (
                                20151101063004 20151002063004 64367 noblogs.org.
                                LuRSXa97Yjr+wYVGjq8yFxIOTXeufRMNaL6L31jqq3im
                                ...

(Regardez la signature, c'est la même que pour ladiscordia mais pas la même que pour www.) Le résolveur validant va donc chercher un NSEC3 prouvant que le nom n'existe pas (un nom existant masque le joker), ne le trouve pas, et paf, SERVFAIL.

Pourquoi le résolveur de Free a-t-il omis le NSEC3, qui est bien envoyé par les serveurs faisant autorité pour noblogs.org ? L'investigation doit s'arrêter là, je n'ai pas accès à l'intérieur de ces résolveurs. Je soupçonne que la duplication anormale des CNAME a mené à une réponse trop grosse et que l'enregistrement NSEC3 a été abandonné.

Donc, ma conclusion est que les résolveurs de Free sont en tort, mais qu'il s'agit très probablement d'une bogue et pas d'une attaque délibérée. Quant à la zone noblogs.org, elle n'avait d'autres torts que de combiner des techniques compliquées (jokers et NSEC3).

Notez que, six mois plus tard, la bogue n'était pas réparée, et se déclenche même sans NSEC3.


L'article seul

Attaques par amplification : TCP aussi

Première rédaction de cet article le 8 octobre 2015


On a beaucoup parlé des attaques DoS par réflexion + amplification en les présentant souvent comme spécifiques à UDP. Mais un article récent (mais passé curieusement inaperçu) montre qu'on peut en faire également avec TCP.

Petit rappel du principe de cette attaque : il y a trois parties, l'attaquant A, la victime V et le réflecteur R. Ce dernier est innocent (il n'a rien contre la victime) mais souvent négligent (il a laissé un réflecteur ouvert alors qu'il n'aurait pas dû). A envoie un paquet IP dont l'adresse source est usurpée : il met l'adresse de V (cela implique que le FAI de A ait ignoré le RFC 2827). L'adresse de destination est celle de R. Celui-ci répond à celui qu'il croit être l'expéditeur, donc à V. Ainsi, R va bombarder V.

Sans amplification, les attaques par réflexion n'ont que peu d'intérêt. Mais ce qui est rigolo, c'est que certains protocoles envoient une réponse plus grande (en nombre de paquets ou bien en nombre d'octets) que la question. On a ainsi une amplification, A obtient plus de paquets ou d'octets qu'il n'en a envoyé. L'efficacité d'un réflecteur se mesure à son PAF (Packet Amplification Factor) ou à son BAF (Bandwidth Amplification Fcator).

Usurper une adresse IP en TCP est très difficile et c'est pour cela que ces attaques, dans la nature, étaient typiquement faites en UDP (en utilisant par exemple NTP). Le seul cas que je connaissais personnellement où on pouvait avoir une amplification avec TCP était la suivante : A envoie un paquet SYN, R transmet le SYN/ACK à V, puis, n'ayant pas de nouvelles de V, réémet le SYN/ACK, typiquement cinq fois. Cela donne donc un PAF de 5 et un BAF ayant la même valeur (le SYN/ACK ayant la même taille que le SYN). Comme toutes les attaques, la pratique est plus compliquée que cela (si V émet un RST en recevant ce SYN/ACK inattendu, cela stoppe la réémission) mais l'attaquant astucieux peut s'en tirer quand même. Ceci dit, un PAF et un BAF de 5 ne font pas une attaque bien terrifiante.

C'est là qu'arrive l'article de Kührer, Hupperich, Rossow et Holz, « Hell of a handshake: Abusing TCP for reflective amplification DDoS attacks » publié à USENIX en août 2014 et apparemment passé relativement inaperçu (merci à Paul Vixie pour me l'avoir signalé).

Les auteurs ont montré qu'il existait d'autres voies d'amplification avec TCP que le SYN/ACK indiqué plus haut et, pire, qu'il existait des machines dans l'Internet qui répondaient et qui étaient disponibles comme réflecteurs. Par exemple, certains systèmes répondent au SYN initial par des paquets de données, souvent de très grande taille, avant même que la triple poignée de mains (l'établissement de la connexion TCP) soit terminée ! (Ce qui justifie ma loi « si une connerie d'implémentation de TCP/IP est possible, alors il existe au moins une machine dans l'Internet qui la fait ».)

Les mesures décrites dans l'article sur un échantillon de vingt millions de machines montrent ainsi plus de 600 000 machines qui répondent sur le port de MySQL dont 8 sont des amplificateurs, avec un BAF moyen de 84 000 (oui, une réponse 84 000 fois plus grosse que la requête). Extrapolé à tout l'Internet IPv4, cela ferait 1 700 amplificateurs MySQL.

Le BAF est plus faible sur les ports FTP ou telnet (de l'ordre de 50) mais il y a beaucoup plus d'amplificateurs (des millions, en extrapolant à tout l'Internet IPv4).

Les analyses des réflecteurs semblent indiquer qu'il s'agit de machines très variées et qu'il n'y a donc pas un vendeur dont l'implémentation particulièrement boguée serait responsable. Par exemple, les machines avec un port telnet ouvert semblent être surtout des routeurs, mais de marques très variées. Les fanas de sécurité noteront toutefois que de nombreuses caméras de vidéosurveillance IP semblent être des réflecteurs. Joie de l'Internet des objets.

Les auteurs discutent aussi des solutions, pour l'instant peu convaincantes. Le mieux, pour la victime, est d'envoyer des RST ou, surtout, des ICMP port unreachable aux réflecteurs : souvent, cela les calme. Mais le problème de fond, surgi de la combinaison entre la possibilité de tricher sur son adresse IP et la disponibilité de nombreux réflecteurs amplificateurs, reste.


L'article seul

RFC 7616: HTTP Digest Access Authentication

Date de publication du RFC : Septembre 2015
Auteur(s) du RFC : R. Shekh-Yusef (Avaya), D. Ahrens (Independent), S. Bremer (Netzkonform)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF httpauth
Première rédaction de cet article le 8 octobre 2015


Dans les techniques d'authentification normalisées pour un client HTTP, la plus connue et la plus simple est le mécanisme Basic du RFC 7617. Mais elle a plusieurs failles de sécurité, comme le transmission explicite du mot de passe (et qui se fait en clair si on n'utilise pas HTTPS). D'où cette technique alternative, que je crois peu répandue, car plus complexe (et pas forcément plus sûre) : le mécanisme Digest. Dans ce cas, le serveur HTTP envoie un défi au client, défi auquel le client répondra sans divulguer au serveur aucun secret.

Avec les RFC 7615 et RFC 7617, ce nouveau RFC remplace le très ancien RFC 2617 (qui normalisait tous les mécanismes d'authentification de HTTP). Désormais, l'authentification HTTP comporte un cadre général (le RFC 7235) et un RFC spécifique par mécanisme d'authentification. Celui de notre nouveau RFC, le Digest, a assez peu changé depuis le RFC 2617.

L'essentiel du RFC actuel est dans la section 3. Le client s'authentifie avec un nom et un mot de passe mais le mot de passe n'est pas envoyé tel quel au serveur (quant au nom, ça dépend). Comme son nom l'indique (digest = condensation), les données sont condensées avant d'être envoyées au serveur, empêchant le serveur (ou un indiscret qui écoute) d'accéder à la valeur initiale.

Lorsque le client HTTP tente d'accéder à une ressource protégée, le serveur lui répond avec un code HTTP 401 et un en-tête WWW-Authenticate:, indiquant le mécanisme Digest. Cet en-tête contient le royaume (realm, un identificateur caractérisant le groupe d'utilisateurs attendus, cf. RFC 7235, section 2.2), le domaine (une liste d'URI pour qui cette protection s'applique), un numnique, une chaîne de caractères opaque, que le client renverra telle quelle, une indication de l'algorithme de condensation utilisé et quelques autres détails. Le numnique doit être différent à chaque réponse du serveur et de son mécanisme de génération dépend largement la sécurité de ce mécanisme d'authentification. Un attaquant ne doit pas pouvoir deviner le numnique qui sera utilisé. À part cela, le mécanisme de génération des numniques n'est pas spécifié, c'est une décision locale. Une méthode suggérée par le RFC est que le numnique soit la concaténation d'une estampille temporelle et de la condensation de la concaténation de l'estampille temporelle, de l'ETag de la ressource et d'un secret connu du seul serveur. L'estampille temporelle sert à éviter les attaques par rejeu. Elle est en clair au début du numnique, pour faciliter les comparaisons floues (estampille « pas trop ancienne »). Notez que le RFC ne conseille pas d'inclure l'adresse IP du client dans son calcul, cela défavoriserait trop les clients qui changent d'adresse IP, par exemple parce qu'ils passent par plusieurs relais de sortie possibles. (Alors que la section 5.5 du même RFC donne le conseil opposé...)

Le client HTTP doit répondre à ce défi en envoyant un en-tête Authorization: qui inclut la réponse condensée, le nom de l'utilisateur (qui peut être condensé ou pas, selon la valeur du paramètre userhash, cf. section 3.4.4 pour les détails), un numnique du client, et un compteur du nombre de tentatives d'authentification, qui permet de repérer les rejeux.

La réponse condensée est calculée (section 3.4.1) en condensant la concaténation de plusieurs valeurs, comprenant notamment une condensation de la concaténation du nom de l'utilisateur, de son mot de passe et du royaume, le numnique du serveur et celui du client. Un attaquant ne peut donc pas savoir à l'avance quelle sera la réponse, puisqu'il ne connait pas le numnique.

En recevant cette réponse à son défi, le serveur doit récupérer le mot de passe de l'utilisateur dans sa base de données, et refaire les mêmes opérations de concaténation et de condensation que le client, puis vérifier qu'il trouve le même résultat. (Notez qu'il n'y a pas besoin de stocker le mot de passe en clair, et que c'est même déconseillé, il suffit d'avoir accès à son condensat.) Par exemple, avec Apache, l'outil htdigest gère tout cela.

Le même mécanisme peut s'utiliser pour s'authentifier auprès d'un relais, mais dans ce cas les en-têtes se nomment Proxy-Authenticate: et Proxy-Authorization:.

Bon, c'est bien compliqué tout cela, place aux exemples. Un client veut accéder à http://www.example.org/dir/index.html (section 3.9.1 du RFC). Le royaume est http-auth@example.org, le nom d'utilisateur Mufasa et le mot de passe Circle of Life (n'oubliez pas les deux espaces entre les mots). Le serveur envoie le défi :

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Digest
       realm="http-auth@example.org",
       qop="auth, auth-int",
       algorithm=SHA-256,
       nonce="7ypf/xlj9XXwfDPEoM4URrv/xwf94BcCAzFZH4GiTo0v",
       opaque="FQhe/qaU925kfnzjCev0ciny7QMkPqMAFRtzCUYo5tdS"      
    

Le serveur demande qu'on condense avec SHA-256. Le client répond au défi :

Authorization: Digest username="Mufasa",
       realm="http-auth@example.org",
       uri="/dir/index.html",
       algorithm=SHA-256,
       nonce="7ypf/xlj9XXwfDPEoM4URrv/xwf94BcCAzFZH4GiTo0v",
       nc=00000001,
       cnonce="f2/wE4q74E6zIJEtWaHKaf5wv/H5QzzpXusqGemxURZJ",
       qop=auth,
       response="753927fa0e85d155564e2e272a28d1802ca10daf4496794697cf8db5856cb6c1",
       opaque="FQhe/qaU925kfnzjCev0ciny7QMkPqMAFRtzCUYo5tdS"

Le nom de l'utilisateur était en clair (non condensé). Le numnique et la chaîne opaque sont renvoyés tels quels. La réponse a été calculée en suivant l'algorithme de la section 3.4.1. Si vous voulez toutes les étapes (condensat calculé avec la commande Unix sha256sum) :

  • A1 = Mufasa:http-auth@example.org:Circle of Life
  • H(A1) = 7987c64c30e25f1b74be53f966b49b90f2808aa92faf9a00262392d7b4794232 (avec le nom de l'utilisateur, qui sert de clé d'accès, c'est la seule information à garder sur le serveur, cela évite des mots de passe stockés en clair)
  • A2 = GET:/dir/index.html (la réponse dépend de la partie locale de l'URI, ce qui limite l'ampleur d'un éventuelle attaque par rejeu)
  • H(A2) = 9a3fdae9a622fe8de177c24fa9c070f2b181ec85e15dcbdc32e10c82ad450b04
  • data = 7ypf/xlj9XXwfDPEoM4URrv/xwf94BcCAzFZH4GiTo0v:00000001:f2/wE4q74E6zIJEtWaHKaf5wv/H5QzzpXusqGemxURZJ:auth:9a3fdae9a622fe8de177c24fa9c070f2b181ec85e15dcbdc32e10c82ad450b04
  • secret:data = 7987c64c30e25f1b74be53f966b49b90f2808aa92faf9a00262392d7b4794232:7ypf/xlj9XXwfDPEoM4URrv/xwf94BcCAzFZH4GiTo0v:00000001:f2/wE4q74E6zIJEtWaHKaf5wv/H5QzzpXusqGemxURZJ:auth:9a3fdae9a622fe8de177c24fa9c070f2b181ec85e15dcbdc32e10c82ad450b04
  • KD (réponse) = 753927fa0e85d155564e2e272a28d1802ca10daf4496794697cf8db5856cb6c1

Parmi les points qui peuvent compliquer ce mécanisme (qui est ennuyeux mais simple à mettre en œuvre), l'internationalisation (section 4). Si le nom ou le mot de passe ne se limitent pas à ASCII, le serveur a intérêt à utiliser le paramètre charset pour indiquer le jeu de caractères dont le client devra se servir. La seule valeur légale de ce caractère est UTF-8, et les chaînes de caractères doivent être normalisées en NFC (cf. RFC 5198, notamment la section 3). Un exemple se trouve dans la section 3.9.2.

Maintenant que ce mécanisme est décrit, analysons sa sécurité (section 5 du RFC). D'abord, les mots de passe utilisés peuvent être trop faibles. Ce mécanisme Digest permet les attaques par dictionnaire (on essaie tous les mots d'un dictionnaire comme mots de passe) et, si le mot de passe figure dans les dictionnaires habituels (c'est le cas de azertyuipop et de 123456789), il finira par être trouvé. Cette attaque marche quelles que soient les qualités de l'algorithme de condensation employé. Il faut donc essayer de s'assurer qu'on n'utilise que des mots de passe forts. (Si la communication n'utilise pas HTTPS, et qu'un attaquant écoute passivement les défis et les réponses, il peut également les tester contre un dictionnaire, sans avoir besoin de faire des essais qui peuvent donner l'alarme.)

Ces mots de passe doivent être stockés sur le serveur. Bien sûr, on peut stocker uniquement leur forme condensée mais, comme c'est elle qui sert d'entrée à l'algorithme de calcul de la réponse, un attaquant qui met la main sur cette base a un accès complet aux ressources du serveur, sans étape de décryptage (comme cela serait le cas avec un attaquant mettant la main sur un /etc/passwd ou /etc/shadow Unix). Notez que le mécanisme Digest ne permet pas de saler les mots de passe. (À titre personnel, c'est pour cela que je ne trouve pas forcément ce mécanisme forcément plus sûr que Basic, contrairement à ce que dit le RFC en 5.13. Aujourd'hui, les piratages de bases des serveurs sont fréquents. La documentation d'Apache est sceptique aussi, disant « this [Digest authentication] does not lead to a significant security advantage over basic authentication » et « the password storage on the server is much less secure with digest authentication than with basic authentication »). C'est en raison de cette faiblesse que le royaume est inclus dans la condensation qu'on stocke dans la base : au moins l'attaquant ne pourra pas attaquer les autres sites, même si on a le même nom d'utilisateur et mot de passe.

Notez au passage que, comme le mécanisme Basic du RFC 7617, ce Digest permet au serveur d'authentifier le client, mais pas le contraire. Si on veut plus fort, il va falloir utiliser l'authentification permise par TLS (avec des certificats).

Et les attaques par rejeu ? La principale protection est fournie par le numnique. S'il est stupidement généré (par exemple, un simple compteur incrémental, trivial à deviner), les attaques par rejeu deviennent possibles. Avec l'algorithme conseillé, les attaques par rejeu sont plus difficiles mais pas impossibles : comme on peut réutiliser le numnique pendant un certain temps, un attaquant rapide peut faire plusieurs essais. Si c'est intolérable, la seule solution est d'avoir des numniques qui ne sont absolument pas réutilisables (par exemple, des numniques aléatoires, en prenant les précautions du RFC 4086). L'inconvénient est qu'il faut que le serveur les mémorise, au lieu de simplement les recalculer.

Il y a aussi les attaques classiques de l'Homme du Milieu (par exemple dans un relais Web). Un tel attaquant peut, par exemple, remplacer l'algorithme dans le défi par un algorithme plus faible, voir remplacer le défi de Digest par un appel à utiliser un mécanisme plus faible, tel que Basic. Le client HTTP peut prendre quelques mesures (se souvenir de l'authentification utilisée et avertir l'utilisateur si un site qui utilisait Digest passe à Basic) mais aucune n'est parfaite.

Le RFC recommande aussi de n'utiliser l'authentification qu'au-dessus de TLS. Même si le mot de passe n'est pas transmis, l'observation de l'authentification peut donner des informations (et donner accès au contenu des pages Web alors que, si on authentifie, cela peut être parce qu'il est confidentiel). Et TLS avec authentification du serveur protège contre les attaques de l'Homme du Milieu.

Le mécanisme Digest est dans le registre IANA des mécanismes d'authentification. Un nouveau registre est créé pour stocker les algorithmes de condensation.

Les changements depuis le RFC 2617 sont décrits dans l'annexe A. Les principaux ? SHA-256 et SHA-512 sont ajoutés aux algorithmes de condensation. MD5 est conservé, pour des raisons de compatibilité mais très déconseillé (RFC 6151). La possibilité de condenser le nom de l'utilisateur est ajoutée. L'internationalisation est ajoutée.

Si vous utilisez curl pour vous connecter au serveur HTTP, l'option --digest vous permettra d'utiliser le mécanisme de ce RFC (ou bien vous mettez l'option --anyauth et vous laissez curl se débrouiller pour trouver). Côté serveur, pour Apache, c'est bien documenté. Notez la directive Apache AuthDigestDomain pour spécifier le domaine, c'est-à-dire la liste des URI protégés. Pour Nginx, il n'y a apparement pas de solution standard, il faut utiliser un module supplémentaire (ou utiliser le mécanisme Basic + TLS, ce qui est probablement meilleur).

Deux bons textes à lire si vous voulez creuser la question, avec des exemples, un chez Microsoft, et sur le blog perso de Chua Hock-Chuan.


Téléchargez le RFC 7616


L'article seul

DNS, bien commun (à Brest « Temps des Communs »)

Première rédaction de cet article le 6 octobre 2015


Le 5 octobre, à Brest, j'ai eu le plaisir de parler du DNS, pas comme technique ou comme protocole réseau, mais comme bien commun.

Cette causerie s'inscrivait dans le cadre du festival « Brest en Biens Communs » qui comptait bien d'autres activités au cours de la semaine. Par exemple, j'y ai suivi un atelier de formation au sous-titrage, organisé par les Chats Cosmiques, avec le logiciel Aegisub.

La vidéo de ma conférence sera disponible, restez connectés. En attendant, voici :

Merci à la ville de Brest qui a payé mon voyage, à l'Université de Bretagne occidentale pour les locaux, à la Cantine numérique de Brest pour l'accueil et l'organisation, et à la Maison du Libre. Et merci aussi à Jessica et Nicolas.

Également, sur cette conf', l'article de la Cantine et les notes détaillées de Guigui.


L'article seul

RFC 7593: The eduroam architecture for network roaming

Date de publication du RFC : Septembre 2015
Auteur(s) du RFC : K. Wierenga (Cisco Systems), S. Winter (RESTENA), T. Wolniewicz (Nicolaus Copernicus University)
Pour information
Première rédaction de cet article le 6 octobre 2015


Le service eduroam permet aux étudiants et employés des universités et centres de recherche européens de se connecter en Wi-Fi même quand ils ne sont pas dans leur université habituelle. Ce RFC décrit le fonctionnement d'eduroam et les choix effectués lors de sa conception (notamment l'absence de ces abominables portails captifs). La taille d'eduroam et ses années de fonctionnement indiquent que ces choix étaient bons et qu'eduroam peut être un modèle pour bien d'autres déploiements de Wi-Fi.

Le projet d'un accès pour le monde académique européen a démarré en 2002 (cf. la proposition initiale, par un des auteurs du RFC). Aujourd'hui, eduroam couvre 10 000 sites (dont un en Papouasie Nouvelle-Guinée) et des millions d'utilisateurs.

Les buts d'eduroam étaient (section 1 du RFC) :

  • Identification unique des utilisateurs, gérée par leur établissement d'origine. Si un chercheur de l'Université Copernic visite l'Université de Pise, pas question que les Italiens soient obligés de lui créer un compte, de lui attribuer encore un nouveau mot de passe, etc. (Point de terminologie au passage : dans ce scénario, l'université d'origine du visiteur est l'IdP - Identity Provider - et celle qu'il visite est le SP - Service Provider, qui fournit l'accès.)
  • Accès au réseau de l'établissement visité et par là à tout l'Internet. (Ce qui n'interdit pas de mettre les visiteurs dans un VLAN à part, ce qui se fait souvent.)
  • Minimum de procédures administratives. Il faut éviter, par exemple, que chacun des 10 000 établissements membres ait à faire quelque chose (signer un contrat, échanger des certificats) avec chacun des 9 999 autres. Cela ne passerait pas à l'échelle.
  • Facile à configurer et utiliser : tous les académiques ne sont pas des experts en informatique.
  • Sûr. Pas question que n'importe quel craqueur de passage puisse avoir un accès gratuit et irresponsable via une université.
  • Raisonnablement respectueux de la vie privée. Par exemple, le SP, l'établissement d'accueil, ne devrait pas être en mesure de tout savoir de ses visiteurs.
  • Évidemment fondé sur des normes ouvertes, de manière à ne pas imposer l'utilisation d'un vendeur particulier.

Avec un tel cahier des charges (section 1), plutôt ambitieux, les solutions qui avaient été envisagées et testées étaient :

  • Utilisation de VPN. Sûre mais ne passant pas du tout à l'échelle.
  • Portail captif. Sécurité bien trop mauvaise (et, je rajoute, très pénible pour les utilisateurs). Les portails captifs ont tous les défauts (cf. l'excellente FAQ d'eduroam) : reposant sur un détournement du trafic, ils sont indistinguables d'une attaque de l'Homme du Milieu et ils contribuent donc à mal éduquer les utilisateurs (par exemple à ignorer les avertissements HTTPS), reposant sur du trafic Wi-Fi en clair, ils permettent tout un tas d'attaques comme la surveillance des communications du voisin, nécessitant une action manuelle d'interaction avec un site Web, ils ne fonctionnent pas avec des programmes automatiques comme Windows Update, ils ne font pas d'authentification de bout en bout (il faut donner son mot de passe au SP), etc. (Note personnelle : il est anormal qu'ils existent encore en 2015.)
  • 802.1X, la solution finalement choisie.

Désormais, eduroam repose sur trois piliers :

  • 802.1X pour l'authentification locale, avec le point d'accès Wi-Fi,
  • EAP (RFC 3748) pour transporter l'authentification, de manière sûre et confidentielle,
  • RADIUS (RFC 2865), pour le routage des requêtes, jusqu'à l'établissement d'origine (l'IdP).

L'utilisation d'EAP dans RADIUS est décrite dans le RFC 3579.

L'architecture d'eduroam est décrite en section 2 de notre RFC. Qui dit authentification dit confiance : d'où vient la confiance dans eduroam ? Il y a une relation de confiance entre l'utilisateur et l'IdP, son établissement d'origine, vérifiée par une authentification mutuelle. Et il y a une relation de confiance entre l'IdP et le SP (l'établissement d'accueil), fondée sur RADIUS.

Si une université, ou établissement analogue, participe au service eduroam, ses bornes Wi-Fi vont publier le SSID eduroam. C'est celui que choisit l'utilisateur la première fois, la connexion sera typiquement faite automatiquement les fois suivantes. Notez qu'il est toujours possible qu'un point d'accès méchant diffuse un faux eduroam : l'utilisateur ne doit pas considérer que tout SSID eduroam est sûr ! Notez aussi, mais c'est moins grave, qu'un utilisateur qui est dans son université habituelle peut se connecter via eduroam, avec les éventuelles limitations que cela implique, plutôt qu'au réseau local de son université. Pour s'accrocher au point d'accès Wi-Fi du SP, la machine de l'utilisateur utilise, on l'a vu, 802.1X. Les transmissions radio sont sécurisées par WPA2 avec AES. Il n'y a pas d'accès anonyme à eduroam, tout utilisateur doit avoir un compte sur un des IdP.

Et EAP, il sert à quoi ? Il permet une protection de bout en bout des informations d'authentification. Même si l'utilisateur s'est connecté à un faux réseau prétendant être eduroam, celui-ci ne pourra pas intercepter, par exemple les mots de passe. Seul l'IdP, l'institution d'origine de l'utilisateur, verra son mot de passe. EAP n'est pas directement un mécanisme d'authentification mais un protocole qui permet de négocier et transporter plusieurs mécanismes d'authentification (du « simple » mot de passe - RFC 4746 - aux certificats - RFC 5216). EAP est de bout en bout, entre l'utilisateur et son IdP, son fournisseur d'identité. Si l'université de rattachement de l'utilisateur déploie une technique d'authentification nouvelle et très rare, pas de problème : les SP, et les serveurs RADIUS n'ont pas à la gérer, seul EAP sera au courant. L'utilisateur s'identifie avec un NAI (RFC 7542), comportant un nom local à l'IdP, un @ et un domaine (ou royaume, realm) unique. Pour des raisons de protection de la vie privée, on peut utiliser un NAI ne comportant que le domaine (par exemple @ma-fac.example), le NAI complet n'étant transporté que dans EAP (pensez à un tunnel), et donc chiffré et inaccessible aux intermédiaires.

Le point d'accès Wi-Fi va ensuite être un client RADIUS pour transmettre les informations permettant l'authentification. (Du point de vue sécurité, notez que cette communication entre le client RADIUS et le premier serveur RADIUS est entièrement chez le SP, et sécurisée par lui, typiquement via les secrets partagés de RADIUS.)

Une fois qu'on est arrivé au serveur RADIUS du SP, que se passe-t-il ? Il faut relayer jusqu'au serveur RADIUS de l'IdP. Les serveurs RADIUS de eduroam sont organisés de manière arborescente, en suivant à peu près l'arbre du DNS. Si un professeur à soton.ac.uk visite l'Université de l'Utah, sa requête va d'abord passer par le serveur RADIUS de cette université. Ce serveur de l'université utah.edu ne connait que le serveur RADIUS et edu. Il lui transmet donc la requête, le serveur de edu passe à la racine (notez que, contrairement au DNS, on ne part pas de la racine) et la requête redescend ensuite vers le serveur de l'IdP (serveurs de ac.uk puis de soton.ac.uk).

Donc, pour détailler le processus, les étapes étaient :

  • Le professeur (enfin, son logiciel, ce qui se nomme dans WPA le supplicant) envoie une requête EAP au point d'accès Wi-Fi de l'Utah, avec une identité anonymous@soton.ac.uk,
  • Le point d'accès états-unien fait suivre au serveur RADIUS de l'Université de l'Utah,
  • Ce serveur voit que la requête n'est pas pour lui (le domaine soton.ac.uk n'est pas le sien), il fait suivre au serveur RADIUS de .edu,
  • Ce serveur voit que ce n'est pas pour lui (ce n'est pas un .edu), il transmet donc à la racine (au passage, notez que la racine est évidemment composée de plusieurs serveurs, pour des raisons de redondance),
  • La racine peut donc transmettre au serveur RADIUS de ac.uk (notez que la racine est généralement configurée avec des TLD mais ac.uk est une exception),
  • Et ce serveur va transmettre à l'université, puisqu'il connait soton.ac.uk,
  • Le serveur RADIUS de l'université britannique va alors décapsuler, trouver la requête EAP et la traiter (c'est-à-dire authentifier l'utilisateur),
  • La réponse (message RADIUS Access-Accept ou Access-Reject) est renvoyée dans l'Utah en suivant la hiérarchie RADIUS d'eduroam en sens inverse,
  • Le serveur RADIUS de l'Université de l'Utah peut alors informer le point d'accès Wi-Fi qu'il doit laisser passer (ou pas) l'utilisateur.

On voit qu'il faut en faire bouger des électrons, et très vite et de manière très fiable. eduroam a logiquement connu quelques malheurs (section 3 du RFC). Par exemple, les serveurs RADIUS à utiliser pour router la requête sont statiquement configurés (une grosse différence avec le DNS). Le RFC 2865 ne dit pas ce qu'il faut faire en cas de panne. RADIUS fonctionne sur UDP et la panne n'est donc pas indiquée explicitement, on a juste une absence de réponse. Pour l'utilisateur final, cela peut se traduire par un long délai, suivi d'un refus d'accès inexplicable. En prime, comme il y a plusieurs relais RADIUS successifs, l'administrateur d'une université, en cas de non-réponse, ne sait pas quel relais a défailli. Son RADIUS ne peut pas distinguer une panne du premier relais d'une panne de la racine, sauf en constatant que les éventuelles requêtes pour des domaines du même TLD marchent. Un processus de débogage pénible (cf. l'article « Dead-realm marking feature for Radiator RADIUS servers »). Et il n'y avait pas non plus dans RADIUS de message de retour indiquant la fin de la panne (ce point a toutefois été résolu avec le RFC 5997).

RADIUS est nettement faiblard en terme de signalisation des erreurs mais le protocole 802.1X ne permet pas non plus de transmettre à l'utilisateur final un message très détaillé. Un serveur RADIUS qui dépend d'un serveur dorsal extérieur (LDAP ou SGBD par exemple) a donc un choix cornélien si ce serveur extérieur est défaillant : le serveur RADIUS peut ne pas répondre du tout, mais cela va être interprété comme une panne par les relais RADIUS, qui risquent de ne plus envoyer de requêtes. Et le logiciel de l'utilisateur ne va pas transmettre de message utile, voire il donnera des avis erronés (« vérifiez votre mot de passe »), en raison du manque d'informations. Soit, autre solution, le serveur RADIUS répond par un refus (RFC 2865, section 4.3), ce qui serait mieux pour les autres relais RADIUS (ils verront que leur camarade répond toujours) mais très déroutant pour l'utilisateur final, qui verra des messages trompeurs et effrayants, par exemple « votre mot de passe est incorrect ou votre compte est fermé ». Ainsi, Windows, dans un tel cas, efface les informations d'authentification qui étaient enregistrées et oblige l'utilisateur à tout recommencer. Ce problème a suscité de nombreux appels à l'assistance utilisateur, car les gens avaient évidemment oublié le mot de passe qu'ils avaient configuré des semaines ou des mois auparavant...

Les innombrables discussions dans la communauté eduroam ou dans le groupe de travail RADEXT de l'IETF n'ont pas permis d'arriver à un consensus. Si RADIUS sur TCP, introduit depuis, résout une partie des problèmes, il ne solutionne pas celui du dorsal (LDAP ou SGBP) planté. Il faudrait un mécanisme analogue au code d'erreur 500 de HTTP mais RADIUS n'en a pas.

Autre problème, la complexité du routage entre les relais RADIUS. Le faire sur la base du TLD marche bien pour les ccTLD (le serveur RADIUS national est administré par l'association eduroam du pays) mais pas du tout pour .com. Il a fallu mettre des exceptions manuelles comme kit.edu routé vers le serveur allemand car le KIT est en Allemagne, ce qui n'était pas évident vu son TLD... Cela pose un problème de passage à l'échelle : s'il n'y a qu'environ 200 ccTLD (dont 50 sont aujourd'hui dans eduroam), il peut y avoir potentiellement des milliers d'établissements dans les gTLD, chacun avec son exception à mettre dans les tables de routage, et à propager vers tous les serveurs (pour des raisons de fiabilité, il y a plusieurs serveurs racines).

Je l'ai dit, RADIUS fonctionne sur UDP. Ce choix était raisonnable dans les configurations simples du début (un client RADIUS, le point d'accès, et un serveur RADIUS, sans relais), mais il a des conséquences désagréables pour la configuration bien plus complexe d'eduroam. EAP est un protocole bavard et il n'est pas rare d'avoir 8 à 10 aller-retours entre le serveur RADIUS du SP et celui de l'IdP. La perte d'un seul paquet nécessitera de tout recommencer, UDP n'ayant pas de retransmission. Dans certains cas, les données EAP sont de taille importante (c'est surtout le cas avec EAP-TLS, où il faut transmettre de gros certificats) et on peut voir des paquets RADIUS dépasser la MTU et être fragmentés. Si, en théorie, la fragmentation n'est pas un problème, en pratique, on sait qu'elle marche mal sur l'Internet, notamment en raison des nombreux pare-feux bogués ou mal configurés. Ces problèmes sont très difficiles à déboguer car, si Alice et Bob constatent que les paquets entre eux ne passent pas, la cause peut être un réseau tiers, situé sur le chemin, et qu'ils ne contrôlent pas. (RADIUS sur TCP, RFC 6613, résout ce problème. Le RFC 6613 discute plus en détail ce problème.)

Autre limite de RADIUS tel qu'il était au début d'eduroam : la protection de la vie privée. Le protocole permettait de chiffrer les mots de passe mais pas le reste du trafic. C'est donc à EAP de contourner ce problème, par exemple avec son authentification TLS. Mais cela ne suffit pas car il y a toujours des attributs « privés » transmis en clair par RADIUS comme Calling-Station-ID qui peut permettre de trouver le terminal de l'utilisateur, ou comme NAS-IP-Address qui permet de trouver le point d'accès. (Le problème se pose aussi dans la réponse : si le message d'acceptation est trop bavard, par exemple en indiquant le département de l'utilisateur à l'université, cela laisse fuiter des informations en clair.) Cela permet donc à un attaquant puissant, en surveillant tous les flux RADIUS (ce qui est largement dans les moyens de la NSA), de suivre à la trace bien des gens. À noter que une telle récolte d'informations n'a pas encore été documentée (on ne trouve pas RADIUS ou eduroam dans les documents Snowden) mais cela ne veut pas dire qu'elle n'a pas eu lieu. La seule solution est de chiffrer toute la session RADIUS, ce qui n'était pas possible dans le RADIUS original (mais le devient avec le RFC 6614).

EAP protège également en permettant l'utilisation d'identificateurs « anonymes », le vrai identificateur n'étant transmis que dans la session EAP chiffrée. Encore faut-il que l'utilisateur configure son logiciel pour cela, et tous les logiciels ne le permettent pas.

Ces sécurités fournies par EAP ne marchent que si on se connecte au bon serveur EAP. Si on se connecte à la place au terrible Homme du Milieu, plus aucune sécurité ne joue. Est-ce que les utilisateurs ont tous configuré leur logiciel pour tester la validité du certificat du serveur EAP, et la tester contre une liste d'AC sérieuses ? On peut en douter et il est donc sans doute possible de capturer des sessions Wi-Fi en présentant un faux serveur EAP.

Ces problèmes de configuration d'EAP sont d'autant plus pénibles que beaucoup des mises en œuvres d'EAP ne permettent pas aux administrateurs système de diffuser facilement des configurations pré-remplies (et, lorsqu'il y en a, elles sont spécifiques à un vendeur), où tous les paramètres de sécurité ont été fixés aux bonnes valeurs, et où l'utilisateur n'a plus qu'à taper nom et mot de passe (ou bien indiquer le certificat client).

Les difficultés pratiques rencontrées avec l'architecture d'eduroam ont mené à certains changements, décrits dans la section 4 du RFC. Certains changements ont nécessité une action normalisatrice à l'IETF. Ces changements peuvent cohabiter avec l'infrastructure actuelle (pas question de tout raser pour recommencer de zéro) et sont donc déployés progressivement. Les deux grands changements sont le remplacement progressif d'UDP par TCP, et l'utilisation de TLS pour sécuriser la session RADIUS (l'ancien système était un secret partagé entre les deux pairs RADIUS).

Au passage, pourquoi ne pas avoir remplacé RADIUS par Diameter (RFC 6733) ? Cela avait été envisagé puisque, sur le papier, le protocole Diameter, bien plus complexe et « enterprise-grade » (c'est-à-dire apprécié des DSI, et n'ayant pas de mise en œuvre en logiciel libre), disposait déjà des services voulus. Mais l'examen de l'offre Diameter existante, par rapport aux exigences d'eduroam (logiciels gratuits ou bon marché, gestion des authentifications EAP les plus courantes, accès à des dorsaux courants comme MySQL, etc) a été décevante. En prime, les points d'accès Wi-Fi existants n'avaient pas de client Diameter (et n'en ont toujours pas).

D'où le choix de travailler à l'IETF pour développer les nouveaux services (RFC 6613, RFC 6614), et avec les développeurs de logiciel libre pour les mettre en œuvre.

Déployer TCP et TLS dans l'infrastructure de serveurs RADIUS a permis de détecter les serveurs en panne (avec les keepalive de TCP, cf. RFC 6613, section 2.6) et de protéger le contenu échangé contre les écoutes. Les certificats X.509 d'eduroam, qui servent à authentifier les pairs RADIUS, sont fournis par un ensemble d'AC accréditées.

TCP et TLS laissent un problème, celui du routage statique des requêtes, dans la hiérarchie des serveurs eduroam. La solution se nomme « découverte dynamique ». Il y a deux problèmes à résoudre : trouver le serveur RADIUS responsable d'un domaine donné, et s'assurer de son authenticité. Pour le premier problème, eduroam utilise des enregistrements S-NAPTR (RFC 3958) avec le service privé x-eduroam:radius.tls, donnant accès à des enregistrements SRV indiquant le serveur à contacter. Par exemple, un cas réel chez RESTENA :

%  dig NAPTR restena.lu
...
restena.lu.  21600 IN NAPTR 100 10 "s" "x-eduroam:radius.tls" "" _radsec._tcp.eduroam.lu.
...

% dig SRV _radsec._tcp.eduroam.lu
...
_radsec._tcp.eduroam.lu. 43198 IN SRV 0 0 2083 tld1.eduroam.lu.
_radsec._tcp.eduroam.lu. 43198 IN SRV 10 0 2083 tld2.eduroam.lu.
    

Ces deux enregistrements nous disent que le domaine restena.lu a un serveur RADIUS joignable via le nom _radsec._tcp.eduroam.lu et que ce nom correspond à deux serveurs, tld1.eduroam.lu et tld2.eduroam.lu, tous les deux opérant sur le port 2083. (Ce système est décrit dans le RFC 7585.) Le RFC note aussi que le nouveau système de découverte dynamique rendra le système plus souple mais peut-être aussi plus fragile, par suite de la complexité ajoutée.

Le second problème est la vérification de l'authenticité d'un serveur. Après tout, n'importe qui peut mettre des enregistrements NAPTR et SRV dans son domaine et prétendre avoir un serveur RADIUS d'eduroam. La solution a été de réutiliser les AC qui émettent les certificats nécessaires pour RADIUS-sur-TLS. Le serveur RADIUS doit donc vérifier que le pair en face :

  • A un certificat émis par une des AC de la PKI d'eduroam (comme eduPKI, le nom dans le certificat étant alors /DC=org/DC=edupki/CN=eduPKI),
  • Que ce certificat contient un OID désignant la politique eduroam eduroam (cf. « Delivery of Advanced Network Technology to Europe, "eduPKI" »). Par exemple, aujourd'hui, un openssl s_client -connect $RADIUS_SERVER:$RADIUS_PORT |openssl x509 -text sur le serveur RADIUS doit montrer « Policy: 1.3.6.1.4.1.27262.1.13.1.1.1.3 » (je trouve des serveurs qui ont plutôt une vieille version de la politique, comme 1.3.6.1.4.1.27262.1.13.1.1.1.0).

Une dizaine de pays et une centaine de domaines utilisent ce nouveau système de découverte dynamique. Les principaux problèmes sont les problèmes classiques de X.509, gestion des CRL, par exemple.

Le progrès ne va évidemment pas s'arrêter là. eduroam considère aussi deux alternatives :

  • DANE (RFC 6698), qui a le gros avantage de permettre de se dispenser complètement de la PKI, en mettant les certificats dans le DNS. La principale limite de DANE, pour le cas d'eduroam, est que DANE permet au client d'authentifier le serveur mais pas (encore) le contraire, alors qu'eduroam a besoin de deux.
  • ABFAB (décrit dans l'Internet-Draft draft-ietf-abfab-arch), prometteur mais encore loin d'être complètement spécifié.

Vu le très grand nombre d'utilisateurs d'eduroam, il ne faut pas s'étonner qu'il y ait des incidents, des abus, etc. La section 5 du RFC décrit les mécanismes techniques permettant de gérer ces contrariétés. D'abord, la comptabilité : dans eduroam, c'est une affaire à gérer localement dans le SP (l'université d'accueil). L'IdP (l'université d'origine) n'est pas informée (cf. le « eduroam Compliance Statement »). Mesurer l'activité d'un utilisateur est un pré-requis pour la lutte contre certains abus. D'un autre côté, le SP ne voit pas forcément l'identité du visiteur, juste son domaine (si le visiteur a configuré les identificateurs « anonymes ») ce qui rend difficile la comptabilité. Le RFC 4372 fournit un mécanisme de comptabilité par utilisateur, chargeable user identity (qui envoie un pseudonyme, pas le « vrai » nom), mais il est très peu implémenté.

En dix ans de fonctionnement, eduroam n'a pas eu d'incident de sécurité sérieux. Cela peut indiquer que l'architecture de sécurité est bonne : il n'y a pas d'accès anonyme, chaque utilisateur est identifié, ce qui peut expliquer leur retenue. Le RFC note que cela veut peut-être dire plutôt que les réseaux utilisés par eduroam ne sont pas assez supervisés et que certains abus passent peut-être inaperçus.

Quoiqu'il en soit, la partie politique de la sécurité est traitée dans « eduroam Policy Service Definition », notre RFC ne décrivant que les moyens techniques. D'abord, le SP est évidemment libre de bloquer un utilisateur qui abuse. Comment ? Si l'utilisateur a activé les identifiants « anonymes », le SP ne possède que le nom de domaine et l'adresse MAC (sauf coopération avec l'IdP, forcément lente et complexe et donc pas utilisable en urgence). Le SP peut donc, si ses équipements le permettent, bloquer la requête EAP sur la base de ces deux éléments. Mais changer l'adresse MAC est trop facile, et un attaquant déterminé peut donc contourner cette protection. Autre solution, le SP peut attendre la réponse du serveur RADIUS de l'IdP et regarder si elle contient l'attribut Chargeable-User-Identity du RFC 4372, qui contient un identifiant unique de l'utilisateur (unique par SP : le SP envoie son Operator-NameRFC 5580, et l'IdP calcule un identifiant qui dépend du SP, pour les raisons décrites en section 6.1). C'est la meilleure solution car le SP peut alors bloquer cet utilisateur, et uniquement lui, soit en ne répondant pas à ses requêtes, soit en fabriquant des Access-Reject RADIUS. S'il n'y a pas de Chargeable-User-Identity dans la réponse ? La seule solution restant, et elle est violente, est de bloquer le domaine entier, ce qui aura l'effet de bord de bloquer les visiteurs qui ont le malheur d'avoir un compte au même endroit que l'abuseur.

Et bloquer au niveau de l'IdP, alors ? Lui peut facilement fermer un compte, empêchant ainsi l'utilisateur d'accèder à tout site eduroam. Si le SP envoie son nom dans la requête (avec l'attribut RADIUS Operator-Name du RFC 5580), on peut même ne bloquer un compte que pour certains SP, par exemple ceux qui se sont plaints de cet utilisateur. Cela permet des politiques plus fines. Par exemple, imaginons un SP qui interdise le partage d'œuvres culturelles. Un visiteur utilise BitTorrent et le SP demande à l'IdP de le bloquer, alors même que l'utilisation de BitTorrent n'est pas interdite sur le réseau de l'IdP. Bloquer l'utilisateur seulement s'il est sur le réseau du SP râleur permet de satisfaire les politiques du SP et de l'IdP. Sans cette finesse, que permet l'attribut Operator-Name, l'IdP risquerait de bloquer complètement un utilisateur, qui n'était peut-être même pas au courant des politiques restrictives du SP.

Passons maintenant à la protection de la vie privée, un des gros morceaux d'eduroam (section 6 du RFC). Si eduroam avait été conçu par Cazeneuve ou Facebook, tout aurait été enregistré tout le temps mais eduroam a au contraire été prévu avec des fortes préoccupations de vie privée. D'abord, on l'a vu, la possibilité de NAI « anonymes » n'indiquant que le domaine (outer identities). Ce système empêche, par exemple, deux SP de déterminer si deux visiteurs de leurs campus, ayant le même IdP, sont une seule et même personne. Excellent pour la vie privée, mais cela rend compliqué l'attribution d'une éventuelle mauvaise action. D'où l'ajout de l'attribut Chargeable-User-Identity dans eduroam. Étant calculé par l'IdP et différent pour chaque SP, il empêche les collusions de SP entre eux, mais permet de remonter les traces d'un éventuel abuseur.

À noter que le domaine, lui, est visible du SP, des différents serveurs RADIUS qui relaient (ils en ont besoin pour le routage) et, si on n'utilise pas TLS, de tous les indiscrets sur le trajet. Si l'IdP est une très grosse université, cela peut frustrer l'observateur mais, dans le cas de petits établissements, cela peut l'aider. Il serait difficile de résoudre ce problème sans refaire tout eduroam.

Par défaut, l'IdP ne sait pas où se trouvent ses utilisateurs, puisque son serveur RADIUS ne voit que les requêtes du serveur RADIUS supérieur (typiquement, celui du pays). Cet enchaînement de serveurs RADIUS, peut sembler lourd, et difficile à déboguer (le point discuté en section 3). Mais il est avantageux, question vie privée.

Par contre, cette protection de l'utilisateur contre son propre IdP peut être affaiblie si on utilise la découverte dynamique (l'IdP voit les requêtes DNS, cf. RFC 7626), et évidemment si le SP envoie son nom dans la requête RADIUS (attribut Operator-Name).

Et la sécurité, à part cette question de vie privée ? Il faut bien sûr relire les sections Sécurité des normes RADIUS, EAP et 802.1X, plus la section 7 de notre RFC, qui discute les problèmes plus spécifiques à eduroam. D'abord, la sécurité de bout en bout repose complètement sur EAP. Si un Homme du Milieu réussit à se faire passer pour le serveur EAP de l'IdP, il a table ouverte. Le client EAP doit donc exiger une authentification du serveur, et le serveur doit faire ce qu'il faut pour être authentifié (par exemple, publier le nom qui doit apparaitre dans le certificat).

En théorie, cette authentification du serveur résout complètement le problème. En pratique, il reste des pièges. Par exemple, certains clients EAP ne permettent de vérifier que l'AC, pas le nom (le sujet du certificat). Tout attaquant qui peut obtenir un certificat quelconque de la même AC peut donc se faire passer pour le serveur EAP. Il vaut donc mieux ne se fier qu'à des AC spécifiques à eduroam. D'autres clients EAP pratiquent le TOFU : ils se fient au premier certificat et le mémorisent pour la suite. Si un utilisateur était chez un point d'accès pirate la première fois, c'est le certificat de l'attaquant qui sera cru. Les utilisateurs doivent donc veiller à configurer leurs clients eduroam proprement (un outil existe pour cela). Pire, certains logiciels permettent à l'utilisateur de complètement sauter la vérification (« No CA certificate is required » sur NetworkManager, par exemple). L'utilisateur qui sélectionnerait cette option pour se faciliter la vie se rendrait très vulnérable aux attaques de l'Homme du Milieu. Dernier piège d'authentification : en utilisant les identités « anonymes » (NAI ne comportant que le nom du domaine), rien n'empêche un utilisateur malveillant de placer dans la session EAP un NAI indiquant un autre domaine. Si le serveur RADIUS de l'IdP indiqué dans le NAI « anonyme » accepte de relayer les requêtes, l'utilisateur pourra se faire authentifier, et le SP ne connaitra alors pas le vrai domaine d'origine. Cela diminue sérieusement la responsabilité de l'utilisateur et lui permet de brouiller ses traces. Voilà pourquoi les serveurs RADIUS d'eduroam ne doivent pas relayer ces requêtes.

Comme tout service sur l'Internet, eduroam est évidemment susceptible de recevoir des attaques par déni de service. Sur les points d'accès Wi-Fi, on peut voir des serveurs DHCP pirates (cf. RFC 7610), des émetteurs de RAcailles (cf. RFC 6105), etc. eduroam est moins vulnérable que le point d'accès Wi-Fi typique avec portail captif, car l'authentification préalable est nécessaire (ce qui limite les attaques par un client tentant d'épuiser la réserve d'adresses IP en faisant des requêtes DHCP répétées) et le Wi-Fi est chiffré (par WPA2), ce qui limite l'usurpation ARP.

Certaines attaques par déni de service spécifiques à eduroam existent. Par exemple, un attaquant situé physiquement à portée d'un point d'accès Wi-Fi eduroam peut envoyer de manière répétée des demandes d'accès en indiquant un domaine situé dans un TLD différent : cela obligera plusieurs serveurs RADIUS, y compris ceux de la racine, à traiter sa demande, et une négociation EAP à se lancer. Heureusement pour eduroam, EAP est synchrone, donc un attaquant donné ne peut lancer qu'une requête à la fois, pour un domaine donné. eduroam reçoit aujourd'hui des centaines de milliers de requêtes d'authentification réussies par jour (et bien plus qui échouent) et un attaquant qui voudrait tuer eduroam avec un afflux de requêtes devrait donc y consacrer de gros moyens. En tout cas, de telles attaques n'ont pas encore été vues.

À noter qu'il existe aussi des attaques involontaires. La plupart des demandes d'authentification qui échouent concernent des comptes qui étaient valides mais ne le sont plus (étudiant qui a terminé ses études, par exemple). Il est donc probable que les gens dont les comptes sont expirés aient oublié de déconfigurer leur logiciel et que celui-ci envoie toujours des demandes dès qu'il passe près d'un point d'accès eduroam. Il y a donc un « botnet de fait » composé de toutes ces machines d'ex-utilisateurs. Le changement de machine par l'utilisateur, lorsque l'ancienne est trop vieille, ne résout pas le problème : aujourd'hui, surtout sur les ordiphones, les données d'authentification sont sauvegardées dans le cloud (pour que Google et la NSA y aient plus facilement accès) et sont remises sur le nouveau jouet lorsque l'ancien est remplacé. Le botnet des anciens d'eduroam ne fait donc que grossir. Il n'y a pas encore de solution propre à ce problème, peut-être améliorer les logiciels client pour qu'ils arrêtent d'envoyer automatiquement des requêtes après N échecs sur une période de X jours.

Un point sur lequel le RFC passe assez rapidement est le problème d'interopérabilité qui peut se poser quand deux auteurs de logiciel n'ont pas compris de la même façon ces normes complexes qu'il faut programmer correctement. Un exemple d'alerte est « RADIUS Attribute Issues regarding RFC5580 (Operator-Name and others) with several RADIUS servers (including Microsoft IAS and NPS) », un amusant problème de normalisation avec le RFC 5580, RFC qui a été souvent cité précédemment.

Si vous êtes intéressé par ce système, je vous recommande la lecture du site Web d'eduroam.


Téléchargez le RFC 7593


L'article seul

RFC 7615: The Hypertext Transfer Protocol (HTTP) Authentication-Info and Proxy-Authentication-Info Response Header Fields

Date de publication du RFC : Septembre 2015
Auteur(s) du RFC : J. Reschke (greenbytes)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF httpbis
Première rédaction de cet article le 5 octobre 2015


Un très court RFC, probablement un des derniers du groupe de travail IETF qui a fait la réécriture de la norme HTTP 1.1. Il normalise l'en-tête HTTP Authentication-Info:, qui était précédemment dans le RFC 2617, et qui, depuis, est dans le RFC 9110.

Cet en-tête, et son équivalent pour les relais, Proxy-Authentication-Info:, sert au serveur HTTP à communiquer des informations après une authentification réussie.

Dans la nouvelle rédaction de la norme HTTP 1.1, l'authentification est décrite par le RFC 7235. L'ancien RFC sur les méthodes d'authentification, le RFC 2617, est désormais abandonné et plusieurs RFC ont repris ses spécifications, comme notre RFC 7615 pour les deux en-têtes d'information Authentication-Info: et Proxy-Authentication-Info:.

La section 3 de notre RFC décrit en détail le premier en-tête. Envoyé par le serveur après une authentification réussie, il contient une liste de paires {nom, valeur}. Les noms possibles dépendent du mécanisme d'authentification utilisé. Par exemple, le mécanisme Digest du RFC 7617 utilise Authentication-Info: pour des informations techniques nécessaires pour la prochaine authentification. Notre RFC 7615 ne normalise donc que la syntaxe, pas la sémantique. Voici un exemple :

Authentication-Info: rspauth="670ff3158cec20b73d7342932f8c40a1",
  cnonce="1672b410efa182c061c2f0a58acaa17d",  nc=00000001, qop=auth
    

L'en-tête Proxy-Authentication-Info:, décrit en section 4, est exactement le même, sauf qu'il est utilisé lors de l'authentification avec un relais intermédiaire et non pas avec le serveur HTTP final.

Les deux en-têtes peuvent être indiscrets, par les informations qu'ils donnent sur l'authentification (ne serait-ce que le simple fait qu'il y a eu authentification). La section 5 de notre RFC, consacrée à la sécurité, recommande donc l'utilisation de HTTPS.

Ces deux en-têtes HTTP sont enregistrés à l'IANA, dans le registre des en-têtes.

Apparemment aucun changement significatif dans ces en-têtes n'est apparu depuis l'ancienne norme, le RFC 2617.


Téléchargez le RFC 7615


L'article seul

RFC 7617: The 'Basic' HTTP Authentication Scheme

Date de publication du RFC : Septembre 2015
Auteur(s) du RFC : J. Reschke (greenbytes)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF httpauth
Première rédaction de cet article le 5 octobre 2015


Ce court RFC (re-)définit le mécanisme d'authentification « de base » (basic authentication scheme) de HTTP : un mécanisme trivial, où un nom d'utilisateur et un mot de passe sont transmis en Base64 au serveur HTTP. Ce RFC (et ses copains) annule et remplace l'ancien RFC 2617.

Depuis la réécriture générale des RFC sur HTTP, le cadre de l'authentification est décrit dans le RFC 7235. Chaque mécanisme spécifique fait ensuite l'objet de son propre RFC. L'authentification de base est le plus ancien et ce RFC 7617 n'apporte donc rien de bien nouveau, il se contente de toiletter une norme existante.

Le principe est simple : le serveur HTTP gère un ou plusieurs « royaumes » (realm). Dans chaque royaume, il connait une liste d'utilisateurs, identifiés par leur nom, et authentifiés par un mot de passe. Le client, à qui le serveur indique le royaume dont dépend la page Web convoitée, transmet cet identificateur et ce mot de passe, et, si cela correspond à ce qui est dans la base, le serveur lui donne accès. Et lui renvoie une code 403 (accès interdit) autrement.

Voici un exemple de dialogue. Le client a tenté d'accéder à la ressource /rapport.html qui est protégée. Le serveur répond par le code 401 (authentification nécessaire, cf. RFC 7235, section 3.1) et un défi : « essaie de t'authentifier dans le royaume Corporate », dans l'en-tête WWW-Authenticate: (RFC 7235, section 4.1).

HTTP/1.1 401 Unauthorized
Date: Mon, 04 Feb 2014 16:50:53 GMT
WWW-Authenticate: Basic realm="Corporate"  

Le client doit lui répondre avec un nom et un mot de passe. S'il est un navigateur Web, il demandera probablement interactivement à l'utilisateur http-auth.png

Si le client HTTP est un programme autonome, il cherchera dans sa configuration (par exemple, avec curl, ce sera dans le fichier ~/.netrc ou bien dans l'option --user de la ligne de commande). Une fois que le client HTTP aura nom et mot de passe, il les concatène (avec un deux-points comme séparateur) et les encode en Base64 (RFC 4648). Si le nom d'utilisateur est Aladdin et le mot de passe open sesame, voici un moyen simple, avec le shell Unix, de calculer la chaîne de caractères à envoyer :

% echo -n "Aladdin:open sesame" | base64
QWxhZGRpbjpvcGVuIHNlc2FtZQ==

Le client HTTP enverra donc sa requête avec l'en-tête :

Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==  

À noter que l'ancienne norme ne spécifiait pas quel encodage utiliser pour représenter nom et mot de passe avant de les passer à Base64. Certains utilisaient Latin-1, d'autres UTF-8. C'est déplorable mais il est trop tard pour changer cela (l'annexe B.3 explique ce choix), donc notre nouveau RFC ne spécifie pas non plus d'encodage, c'est un arrangement privé avec le serveur HTTP, sauf si un encodage a été spécifié dans le défi, avec le paramètre charset. Au passage, signalons que la syntaxe possible pour les noms d'utilisateur est désormais celle du RFC 8265.

Ce paramètre charset (qui aurait dû se nommer plutôt accept-charset car il indique ce que le serveur attend, pas ce qu'il envoie), n'a qu'une seule valeur autorisée, UTF-8. Cette valeur indique que le serveur s'attend à ce qu'identificateur et mot de passe soient normalisés en NFC (règles du RFC 5198), puis encodés en UTF-8.

Prenons un exemple, le nom est test et le mot de passe 123£ (le dernier caractère est U+00A3, qui devient C2 A3 en UTF-8, le terminal utilisé pour l'exemple ci-dessous est en UTF-8, ce qui tombe bien). On encode la chaîne test:123£ en Base64 :

% echo -n test:123£ | base64
dGVzdDoxMjPCow==

Et on a donc la valeur à utiliser dans le champ Authorization:.

Et le royaume, on peut le mettre en Unicode ? Eh bien, ce point est obscur (section 3 de notre RFC) et il faudra attendre une nouvelle mise à jour pour l'éclaircir.

La section 4 de notre RFC parle de sécurité. Elle rappelle que le mot de passe est transmis en clair (Base64 ne protège évidemment pas du tout) et qu'il est donc impératif de transporter la session HTTP dans du TLS (RFC 2818). La solution du RFC 7616 n'a pas ce défaut.

Ce mécanisme « de base » souffre également des faiblesses habituelles des mots de passe. Par exemple, si les utilisateurs peuvent les choisir, ils risquent de prendre des mots faibles (prénom, date de naissance...) ou bien de réutiliser le même mot de passe pour plusieurs services. S'ils ne peuvent pas les choisir, ils auront du mal à les mémoriser et seront donc tentés de les écrire... pas forcément dans un endroit protégé.

Dans tous les cas, que les mots de passe soient choisis par les utilisateurs ou pas, le serveur qui les stocke doit prendre des précautions. Ils ne doivent jamais être stockés en clair sur le serveur, car, si le serveur est piraté, le pirate aurait alors accès à tous les mots de passe, donc beaucoup pourront être utilisables avec d'autres serveurs. Les mots de passe doivent être stockés condensés et salés.

Le mode Basic a été enregistré à l'IANA (section 5 du RFC) dans le registre des mécanismes d'authentification.

Quels sont les changements concrets depuis RFC 2617, section 2, qui normalisait ce mécanisme avant ? L'annexe A les décrit : il y a la compatibilité avec le nouveau cadre d'authentification du RFC 7235, et une meilleure internationalisation avec le nouveau paramètre charset.


Téléchargez le RFC 7617


L'article seul

Consultation « République Numérique », mes observations

Première rédaction de cet article le 27 septembre 2015


La consultation gouvernementale sur le « Projet de loi pour une République numérique » est désormais en ligne. Quelques observations personnelles.

La plus importante est évidemment que le gouvernement organise une consultation sur le numérique après que toutes les lois importantes sur le numérique soient passées (et qu'il n'est pas question de les remettre en cause) : LCEN (qui posait le principe de la responsabilité de l'hébergeur, contrairement à ce que prétend son exposé des motifs, et qui imposait la conservation des données sur les activités des internautes), HADOPI (qui organise la défense des intérêts des ayant-trop-de-droits), le décret n° 2015-125 du 5 février 2015 mettant en place la censure administrative, la Loi Renseignement (le Patriot Act hexagonal) qui légalise notamment les fameuses boîtes noires, dispositifs d'espionnage installés dans le réseau... On note qu'il n'y a pas eu de consultation pour les lois présentées par des ministres importants (Cazeneuve ou Macron) mais qu'on en fait une lorsqu'il s'agit d'une loi essentiellement symbolique, portée par une ministre secondaire (Lemaire). On a fortement l'impression qu'une fois tous les grands sujets bouclés, quelqu'un au gouvernement s'est dit « il faudrait quand même laisser quelque chose à Lemaire, quelqu'un a une idée ? »

La provocation la plus claire est l'article sur le secret des correspondances, proposé quelques mois après avoir fait voter, en profitant cyniquement de l'attaque des intégristes contre Charlie Hebdo, la loi Renseignement, qui légalise justement l'écoute massive. Cet article semble avoir été écrit pour proclamer haut et fort « votre avis n'a aucune importance ». Bref, comme le note Jef Mathiot, cette loi aurait dû être baptisée « Loi Miettes » car c'est tout ce qui reste.

Pour participer à la consultation, il faut s'inscrire en ligne. Le site me propose de m'authentifier avec des fournisseurs d'identité, Facebook ou Google ou avec un compte créé localement sur le site (ce que j'ai fait). Les protocoles d'identification ouverts comme OpenID ne sont pas présents. On est loin de ce qui se fait en République tchèque. On apprécie ici l'hypocrisie qui prétend réguler « les plate-formes » (terme des ministères français pour désigner les GAFA, Google, Amazon, Facebook et Apple) alors qu'on encourage leur usage ! (Sans compter les mouchards Google Analytics dans le site Web.)

Une fois inscrit, je note qu'on peut voter sur tout, sauf sur les modalités de la consultation elle-même. Par exemple, aucun endroit pour discuter du fait que les arguments qu'on écrit doivent forcément être étiquetés Pour ou Contre le texte. Cela interdit, par exemple, de poser une question pour éclaircir un point. Ou tout simplement d'exprimer une position complexe. Cette consultation ressemble en effet pas mal à un plébiscite : soit on met un argument Pour et on est alors classé comme soutenant le gouvernement, soit on met un argument Contre et on risque alors de mettre en péril les progrès très modestes du projet de loi. Par exemple, dans l'article sur l'accès aux publications de la recherche publique, il est proposé de permettre cet accès après douze mois. Si c'est un progrès par rapport aux exigences exorbitantes des ayant-tous-les-droits (comme Elsevier) qui font actuellement la pluie et le beau temps au parlement et au gouvernement, c'est néanmoins très en retrait par rapport au respect de la volonté de l'auteur (qui devrait avoir le droit de rendre publics immédiatement ses propres articles !) et par rapport au bon sens (s'agissant de recherches financées sur fonds publics). Je n'ai donc pas envie de mettre un argument Pour ou Contre. « Progrès mais très insuffisant » serait une étiquette plus adaptée.

Parmi les sujets qui ne coûtent pas cher et sont donc souvent appréciés des ministres en mal de présence dans les médias, on trouve la défense de la langue française. Ici, elle a été oubliée et le nom de domaine est mal orthographié : republique-numerique.fr au lieu du correct république-numérique.fr qui a, comme d'habitude été enregistré par un internaute profitant de cette négligence. Cela a logiquement mené à des confusions, comme un article du Parisien qui suggérait aux internautes d'aller en http://république-numérique.fr/, bonne orthographe mais mauvais site.

Dans la série « souveraineté numérique », slogan souvent brandi dans les cercles gouvernementaux, on note que le site est hébergé par l'états-unien CloudFlare (qui a les serveurs DNS et le frontal HTTP, et signe le certificat). Les adresses IP utilisées sont donc celles de CloudFlare, attribuées par LACNIC à la filiale de CloudFlare au Costa Rica... Quant au courrier de confirmation de l'inscription, il est envoyé depuis la Georgie.

Je regrette aussi que certains articles n'aient pas été soigneusement relus. Par exemple, celui sur le domaine public affirme « [il existe] des pratiques abusives [qui] consistent à revendiquer des droits sur des choses qui appartiennent au domaine public. Par exemple : dans le domaine logiciel, certains codes sources libres sont réappropriés par des entreprises sans être repartagés avec la communauté. », confondant ainsi domaine public et logiciels libres (certaines licences libres permettent tout à fait de ne pas repartager). Cette confusion est classique, mais gênante dans un texte gouvernemental. Même chose pour l'affirmation incroyable comme quoi téléphone et SMS ne sont pas écoutés (dans l'article 22), affirmation qui sent très fort son protectionnisme franco-français (nos techniques à nous sont sûres, contrairement à l'Internet des méchants américains).

Pour finir, voici la liste des amendements sérieux proposés qui me paraissent mériter qu'on les soutienne (et n'ont donc aucune chance d'être repris par Lemaire et Valls) :

Ne vous émeuvez pas du message « Une erreur est survenue, veuillez réessayer », ce message est apparemment une erreur et n'empêche pas le vote d'être pris en compte.

Mon article a été repris sur Rue89. Parmi les nombreux articles publiés sur cette consultation, je vous recommande celui d'Antoine Amarilli.


L'article seul

RFC 7649: The Jabber Scribe Role at IETF Meetings

Date de publication du RFC : Septembre 2015
Auteur(s) du RFC : P. Saint-Andre (&yet), D. York (Internet Society)
Pour information
Première rédaction de cet article le 27 septembre 2015


Pendant les réunions physiques de l'IETF, il y a divers moyens de suivre la réunion en n'étant pas présent sur les lieux. Entre autres, il y a une pièce XMPP (protocole autrefois nommé Jabber, ce dernier nom restant très répandu) qui permet de poser des questions et de discuter. Une personne dont le rôle est important est le scribe : il ou elle est sur place et son travail est de relayer les remarques et commentaires dans les deux sens, par exemple en allant au micro lire les questions des participants distants.

Ce RFC décrit le travail de ce scribe, qu'on nomme en général en anglais le « Jabber scribe ». Le protocole XMPP (ex-Jabber) est décrit dans le RFC 6120 et le concept de pièces où peuvent être présents plusieurs utilisateurs est dans le XEP-0045. Le rôle du scribe nécessite surtout des compétences humaines (nul besoin d'être un expert XMPP, d'ailleurs l'IETF pourrait utiliser d'autres technologies de messagerie instantanée, cela ne changerait pas grand'chose à son travail).

Les autres techniques utilisées pour permettre aux participants éloignés de suivre (comme Meetecho) sont en général unidirectionnelles. La pièce XMPP est souvent le seul endroit où ces participants peuvent être actifs et pas seulement regarder et écouter. D'où l'importance du rôle du « scribe Jabber ». Il est présent dans les différentes sessions d'une réunion IETF, notamment lors des réunions des groupes de travail, et c'est une ou un volontaire, personne n'est payé et désigné pour être scribe Jabber. Ce RFC décrit cette activité, les qualités nécessaires et comment faire pour être un bon scribe.

Premièrement, le bon scribe doit connaitre son public, les gens pour qui elle ou il travaille (section 2 du RFC). Il y en a trois catégories :

  • Les participants distants dont j'ai déjà parlé. Ils regardent les planches qui sont montrées dans la salle, ils écoutent le flux audio, mais ils voudraient aussi pouvoir intervenir (au passage, il faut se rappeler que l'IETF est une organisation ouverte, donc permettre à des gens qui n'ont pas eu le temps ou l'argent de venir est important politiquement).
  • Les participants qui sont sur le site mais sont physiquement dans une autre salle. Cela fait partie du folklore IETF de voir quelqu'un dans la salle où se réunit le groupe de travail 1 tout en suivant sur son ordinateur portable les activités des groupes de travail 2 et 3... Comme ils écoutent la salle où ils sont, ils n'ont en général pas branché le flux audio et ont donc besoin d'une pièce XMPP plus bavarde.
  • Les participants qui sont dans la salle physique, mais apprécient le fait que, dans la pièce XMPP, on peut communiquer par écrit (cela peut être plus simple pour les non-anglophones) ou simplement qu'on peut discuter sans déranger les autres (du genre « il a bien dit qu'on pouvait raccourcir un changement de clé à une semaine ? Et la section 2.2 du RFC 5011, alors, il y a pensé ? »)

Cette dernière catégorie peut dans certains cas représenter la totalité des gens présents dans la pièce XMPP. Le scribe peut donc demander s'il y a des participants non physiquement présents. Si ce n'est pas le cas, son travail est simplifié puisque tout le monde peut suivre en direct et parler au micro soi-même.

Dans la pièce XMPP, les gens ont uniquement leur identificateur XMPP qui n'est pas forcément leur nom légal. Le scribe qui doit relayer les questions au micro peut leur demander de préciser quel est le nom à annoncer. Si le participant distant veut rester anonyme, il doit le dire explicitement (les présidents du groupe de travail peuvent refuser qu'il y ait des commentaires anonymes, pour des raisons qui sont entre autres liées aux RFC sur la propriété intellectuelle, cf. RFC 8179).

Le scribe Jabber doit aussi se connaitre lui-même (section 3 du RFC). Tout le monde n'est pas un roi de la dactylographie, tout le monde ne parle pas anglais couramment (et on en entend des accents différents dans les réunions IETF) et on n'exige pas du volontaire qu'il soit un professionnel capable de transcrire en temps réel l'intégralité des débats. Si vous êtes volontaire, ajustez donc votre style de scribe à vos capacités.

Les tâches du scribe sont (section 4 du RFC) avant tout de relayer les messages des participants distants. On n'attend pas du scribe qu'il transcrive toute la session sans erreurs sur le canal XMPP. La plupart des scribes se contentent de donner quelques repères (« Joe en est maintenant à la planche 8, sur les problèmes d'implémentation du protocole », « Daneesh demande comment ont été trouvés les paramètres numériques proposés »). Les tâches importantes sont :

  • Relayer au micro les commentaires des participants distants,
  • Compter les participants distants lors des demandes des présidents de la session du genre « qui a lu le draft ? » ou « qui est volontaire pour faire une revue du document ? » ou « pensez-vous qu'on doive continuer dans cette direction ? » (notez que, dans ce dernier cas, les participants à distance ne bénéficient pas du relatif anonymat de la procédure du hummmmm),

Traditionnellement, le scribe a priorité pour l'accès au micro. C'est notamment utile pour éviter d'aggraver le délai avec lequel les participants distants reçoivent le flux audio et tapent leur contribution.

Il y a aussi d'autres tâches du scribe, moins cruciales (section 5) :

  • Indiquer dans la pièce XMPP les noms des gens qui parlent au micro (en théorie, c'est sur le flux audio, mais c'est souvent marmonné en anglais avec un accent...),
  • Indiquer le numéro de la planche actuellement affichée sur l'écran (« Now slide 13, on the risks of the new protocol »),
  • Superviser via la pièce XMPP la qualité de la retransmission audio (« On n'entend plus rien », « Il y a un écho terrible »),
  • Fournir aux participants distants des liens vers les ressources utilisées (notamment les planches de support des exposés).

Certains scribes vont jusqu'à résumer l'essentiel des exposés et des interventions sur la pièce XMPP mais ce n'est pas obligatoire.

La section 6 fournit un certain nombre de conseils aux scribes potentiels, pour qu'ils puissent s'améliorer. D'abord, évidemment, il faut apprendre XMPP et le service XMPP/Jabber de l'IETF. Il faut ensuite, si ce n'est pas déjà fait, installer un client XMPP (une bonne liste est en ligne) et apprendre à s'en servir. Le serveur XMPP de l'IETF ne permet pas la création de compte : il faut avoir un compte existant chez un des innombrables fournisseurs XMPP (comme celui de la Quadrature du Net mais il en existe plein d'autres, XMPP n'étant pas un système centralisé). Vous pouvez tester la connexion aux pièces IETF, même en dehors des réunions, en se connectant à la pièce de bavardage et de test hallway@jabber.ietf.org.

Une fois prêt, le scribe devrait, avant la session, se coordonner avec les présidents de session, apprendre les dernières nouvelles, s'assurer qu'il y a bien une retransmission etc. Il faut aussi vérifier si ces présidents ont des desiderata particuliers pour le scribe, s'ils sont bien d'accord pour que le scribe ne fasse pas la queue pour s'emparer du micro, etc.

Le scribe doit ensuite s'asseoir près du micro. Même si lui ne s'en sert pas, cela lui permettra de voir les badges des intervenants et donc de lire leur nom (ce qui limiterait les innombrables rappels « state your name, please »). Ensuite, il ou elle doit se connecter en XMPP à NOM-DE-LA-SESSION@jabber.ietf.org. Il est recommandé d'avoir également un navigateur Web ouvert, avec plusieurs onglets, affichant l'agenda de la session, la liste des liens vers les documents présentés en session, la page décrivant la retransmission, etc.

Une fois que la session a démarré, le scribe doit :

  • Bien s'identifier pour que tout le monde soit au courant de son travail (et ne proteste pas quand elle ou il passe devant tout le monde pour accéder au micro),
  • Rappeler aux participants distants qu'il est recommandé de préfixer ses interventions par MIC si on veut les voir relayées au micro,
  • Lorsqu'on parle au micro, dire bien clairement qu'on est un relais, qu'on ne parle pas pour soi-même.

Et, à la fin de la session, le scribe met un message clair dans la pièce, indiquant bien que c'est fini et que cela ne sert plus d'envoyer des commentaires.

Le scribe ultra-pro peut bénéficier des conseils de la section 7, qui donne quelques trucs avancés mais utiles. Par exemple, il est intéressant d'avoir deux clients XMPP, connectés à des comptes sur des services différents, pour faire face à certaines pannes ou délais dans le réseau (expérience vécue par les auteurs du RFC). Si le scribe est fana de métrologie, il peut aussi mesurer le délai en écoutant lui-même le flux audio de retransmission, ou en travaillant avec un participant distant de confiance, de manière à communiquer sur la pièce XMPP une estimation de ce délai.

Tout ça, c'était pour quand tout va bien. Mais, dans le monde réel, il y a parfois des gens qui abusent, surtout dans la chaleur d'une vive discussion (IDN, par exemple...). Comment les gérer (section 8) ? Le scribe n'est pas censé tout relayer. Si un participant distant écrit dans la pièce XMPP « MIC: ce connard ne connait rien à la technique et devrait fermer sa gueule », le scribe n'est nullement obligé de répéter ce commentaire verbatim au micro. La meilleure solution est sans doute de demander à l'excité de refaire son commentaire de manière plus constructive.

Ceci dit, le scribe n'a aucune autorité ou pouvoir particulier. Il ou elle est juste un participant IETF parmi les autres. Cela veut dire qu'il n'est pas obligé de faire la police, c'est le rôle des présidents de session.

Retour aux problèmes techniques dans la section 9, qui rappelle les adresses de courrier électronique à utiliser pour signaler les ennuis (de WiFi, par exemple).

Dans le monde moderne, difficile d'échapper aux problèmes posés par l'appropriation intellectuelle. La section 10, consacrée aux IPR (Intellectual Property Rights) rassure le scribe : il n'est qu'un simple relais et les obligations IETF liées à ces IPR (RFC 5378 et RFC 8179) ne le concernent pas. Ce n'est pas lui le contributeur mais la personne dont il relaie le commentaire.

Enfin, la traditionnelle section sur la sécurité (ici, section 11), clôt ce RFC. À part l'hypothèse, théoriquement possible mais qui semble assez lointaine, d'une attaque DoS contre les serveurs XMPP pour empêcher le scribe de faire son travail, cette section note que l'IETF n'a pas actuellement déployé les mécanismes d'enregistrement des utilisateurs dans ses pièces XMPP et qu'il ne faut donc pas se fier aux noms annoncés. Si quelqu'un se prétend Jari Arkko (l'actuel président de l'IETF), rien ne prouve qu'il dit vrai. « Sur XMPP, personne ne sait que vous êtes un chien. »


Téléchargez le RFC 7649


L'article seul

RFC 7646: Definition and Use of DNSSEC Negative Trust Anchors

Date de publication du RFC : Septembre 2015
Auteur(s) du RFC : P. Ebersman (Comcast), C. Griffiths, W. Kumari (Google), J. Livingood (Comcast), R. Weber (Nominum)
Pour information
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 25 septembre 2015


Comme toutes les techniques de sécurité, DNSSEC, qui vise à assurer l'authenticité des réponses DNS, a ses inconvénients. De même qu'une serrure fermée à clé peut avoir pour conséquence de vous empêcher de rentrer chez vous, si vous avez oublié la clé, de même DNSSEC peut empêcher d'accéder à un domaine si le gérant de la zone a commis une erreur technique. Autant le DNS d'avant était très tolérant (il fallait vraiment insister pour « planter » une zone), autant DNSSEC est délicat : les erreurs ne pardonnent pas, puisque le but de DNSSEC est justement d'empêcher l'accès aux données si elles sont suspectes. Mais les outils et les compétences pour gérer DNSSEC ne sont pas encore parfaitement au point et ne sont pas utilisés partout. Il y a donc de temps en temps des plantages, qui ont pour conséquence la panne d'une zone DNS entière. Face à ce problème, les gérants des résolveurs DNS validants aimeraient bien temporairement suspendre les vérifications, après avoir vérifié qu'il s'agissait bien d'un problème et pas d'une attaque. Cette suspension temporaire et limitée se nomme NTA pour Negative Trust Anchor et est décrite dans ce RFC.

DNSSEC est normalisé dans les RFC 4033, RFC 4034 et RFC 4035. Il permet de valider des enregistrements DNS en les signant. Plusieurs points peuvent invalider accidentellement la signature. Par exemple, les signatures ont une durée de validité limitée (pour éviter les attaques par rejeu) : si le dispositif de re-signature périodique a une panne, les signatures expirent et la zone devient invalide. Ce genre de problèmes a été très fréquent au début du déploiement de DNSSEC et n'a pas complètement disparu. Lorsque cela frappe un domaine important, cela se remarque. (Rappel : toutes les techniques de sécurité ont ce genre de problème. Qu'on pense par exemple aux innombrables expirations de certificats X.509.)

Mettez-vous deux secondes à la place du responsable des serveurs DNS récursifs (les résolveurs) d'un gros FAI, ayant beaucoup de clients. Comcast, par exemple, puisque cette entreprise a beaucoup plaidé en faveur de ce nouveau RFC. L'administrateur d'un domaine important, mettons nasa.gov, a cafouillé, la zone est invalide. Mais seuls les résolveurs validants (ceux qui protègent leurs utilisateurs avec DNSSEC) voient cela. Les autres, les anciens résolveurs non sécurisés, ne testent pas DNSSEC et la zone, pour eux, marche normalement. Les utilisateurs des FAI qui n'ont pas déployé DNSSEC pourront donc accéder aux ressources de la zone en panne, mais pas les vôtres. Ils téléphonent au support en masse, et, sur les réseaux sociaux, disent « Comcast a bloqué l'accès à nasa.gov » (oui, c'est un cas réel et qui a été souvent mal présenté dans les forums publics). Le résultat de cette mauvaise interprétation par les utilisateurs risque d'être un recul de DNSSEC : les gérants de résolveurs DNS pourraient se dire « si les mesures de sécurité embêtent les utilisateurs, coupons les mesures de sécurité ».

La « solution » proposée dans ce RFC, la NTA (Negative Trust Anchor, ou « débrayage explicite de la validation ») est une option de configuration du résolveur qui dit « ne valide pas ces domaines, je sais qu'ils sont cassés, ce n'est pas une attaque ». Chaque gérant de résolveur devra donc prendre la décision unilatérale de configurer ou pas ces NTA. Il n'est pas prévu de protocole pour les distribuer. Les NTA sont un comportement, pas un objet sur le réseau. Il n'y a pas, par exemple, d'enregistrement DNS NTA.

Au passage, s'il y a des negative trust anchor, c'est qu'il en existe des positive, non ? Le concept de « point de départ de la confiance » (trust anchor) est décrit dans le RFC 5914. Le résolveur validant vérifie une zone à partir de sa parente, la parente à partir de la grand-parente et... Il faut bien un endroit où ancrer la vérification : c'est la trust anchor, en général la clé de la racine du DNS, qui sert récursivement à valider toutes les autres. Au contraire, la NTA arrête la validation et dit « tout ce qui est en dessous n'est pas vérifié ».

La section 1.2 de notre RFC décrit plus en détail les motivations pour le concept de NTA. En effet, l'idée de base est surprenante : on dépense beaucoup d'efforts et d'argent pour déployer DNSSEC, afin de vérifier les données DNS, puis on fournit un mécanisme qui permet de débrayer la validation. L'idée a en effet suscité beaucoup de remous à l'IETF et de longues discussions. Comme souvent, le débat opposait, non pas tant les pro contre les anti, que ceux qui disaient « cela existe dans la nature, il vaut mieux le documenter » à ceux qui affirmaient « en le documentant, on le légitimise ». Les premiers l'ont finalement emporté, d'où ce RFC 7646. Les raisons sont documentées dans cette section 1.2.

Aujourd'hui, où bien des administrateurs système sont encore débutants en DNSSEC, la majorité des problèmes de validation sont dus à des erreurs de l'administrateur, pas à une vraie attaque (notez que c'est sans doute également le cas en HTTPS...) Bien sûr, les administrateurs en question devraient lire le RFC 6781, et notamment sa section 4.2. Ils éviteraient ainsi bien des malheurs. Mais, en attendant, il est pratique d'avoir un moyen pour ignorer leurs erreurs. C'est l'un des buts des NTA.

Deuxième motivation, le problème de l'utilisateur. Le DNS est une technologie d'infrastructure. Il n'est pas visible à l'utilisateur final et les problèmes au niveau DNS ne peuvent donc pas être analysés par M. Toutlemonde. C'est délibéré : tout le rôle du DNS est justement d'isoler ce M. Toutlemonde de détails pratiques, comme le fait que seenthis.net a changé d'adresse IP. Il est donc cohérent avec ce rôle que l'utilisateur final ne soit pas informé qu'il y a un problème DNSSEC. Il ne peut donc pas savoir ce qui l'empêche d'aller sur son site Web favori et, dans son ignorance, il risque de ne pas attribuer les responsabilités correctement. Comme dans l'exemple plus haut, il pourrait dire « c'est la faute de mon FAI » au lieu de pointer du doigt, à juste titre, l'administrateur de la zone mal signée. Comme dans l'exemple Comcast/NASA cité plus haut, si un domaine important est signé, et fait une erreur déclenchant un problème DNSSEC, on risque de voir vite apparaitre des gazouillis désobligeants contre le FAI, qui n'y est pourtant pour rien. Cela risque de mener la direction du FAI à ordonner qu'on arrête de valider avec DNSSEC. « Le bruit de l'alarme dérange les utilisateurs : coupez l'alarme. » Mettre une NTA pour le domaine critique en question serait certes un recul de la sécurité, mais qui pourrait éviter des reculs encore pires. (C'est compliqué, la politique de sécurité.)

Cette décision stupide pourrait aussi être prise par l'utilisateur, qui passerait d'un résolveur validant à un résolveur non validant. Sur les réseaux sociaux, les conseils idiots se propagent plus vite que les bons, surtout en matière de sécurité « zyva, mets 192.0.2.1 comme résolveur et ça va marcher ». La NTA vise à ralentir cette fuite.

La section 2 de notre RFC décrit la bonne façon d'utiliser les NTA. D'abord, avant d'installer une Negative Trust Anchor, il faut une vérification manuelle, faite par un technicien compétent, de la situation (cf. section 7 sur les tests techniques). Est-ce bien une erreur de la part du gestionnaire de la zone ? On peut s'en assurer en testant la zone depuis différents points (en comptant qu'ils n'ont probablement pas tous été victimes d'une attaque par empoisonnement en même temps) ou tout simplement en prenant connaissance d'une annonce officielle du gestionnaire de la zone, s'il y en a une. Prendre contact avec le gestionnaire de la zone permettra aussi de s'assurer que le problème est bien involontaire (cf. section 6). En tout cas, il ne faut pas installer aveuglément une NTA à chaque fois qu'une validation DNSSEC échoue : cela annulerait complètement l'intérêt de DNSSEC. D'accord, une telle vérification par un humain coûte cher mais il n'y a pas non plus de problème de ce genre tous les mois, ou même tous les trimestres.

Lors de la discussion avec le gérant de la zone, l'administrateur du résolveur qui hésite à installer une NTA peut communiquer à son interlocuteur les enregistrements DNS qu'il voit (obtenus avec dig +cd, pour ignorer la validation), afin de pouvoir s'assurer que ces enregistrements sont bons, qu'il ne s'agit pas d'une attaque. Bien sûr, il faut être pragmatique : si un gros TLD a planté son DNSSEC, rendant ainsi de nombreuses zones invalides, et que ses employés ne répondent pas, il peut être raisonnable de placer unilatéralement la NTA, compte-tenu de l'urgence.

Les NTA sont censées être une mesure sale et temporaire. Il est donc important de faire en sorte qu'elles ne restent pas éternellement, par exemple en indiquant clairement la date dans le fichier de configuration ou dans le journal.

Comme la NTA est une action « anormale » (on ignore une alerte de sécurité), le RFC recommande d'informer clairement les utilisateurs du résolveur comme l'a fait Comcast. C'est d'autant plus important que les utilisateurs n'ont pas d'autre moyen de savoir qu'une NTA est en place (le protocole DNS ne fournit pas de mécanisme pour cela).

Mettre une NTA, c'est facile. Mais il ne faut pas la laisser éternellement, sinon cette zone n'est plus protégée par DNSSEC ! Le RFC demande donc (section 4) que les NTA soient, par défaut, supprimées automatiquement, par exemple au bout d'une semaine (si c'est vraiment une panne, elle ne dure jamais plus longtemps que quelques jours). Idéalement, il faudrait tester régulièrement la validité du domaine, et retirer la NTA s'il redevient valide. À cause de ces recommandations, une gestion entièrement manuelle des NTA, comme dans l'exemple ci-dessous avec la directive domain-insecure: d'Unbound, n'est pas forcément à recommander.

Et, évidemment, une fois la NTA retirée, il faut vider les caches DNS pour la zone.

La NTA revient à prendre une décision sur la gestion d'une zone alors qu'on n'est pas le gérant de la zone. Cela doit donc rester exceptionnel. Le problème, et la solution décrite dans ce RFC, sont très spécifiques à DNSSEC, ou plus exactement à son état actuel. La section 5 de notre RFC dit clairement qu'il ne faut pas envisager de telles solutions pour d'autres problèmes. Si un gérant de zone maladroit a mis le mauvais MX dans la zone, il ne faut pas « corriger » dans les résolveurs. Le principe du DNS doit rester que le gérant de la zone fait autorité sur le contenu de la zone.

Certaines zones, comme servfail.nl cité plus loin dans un exemple, ou comme dnssec-failed.org sont cassées exprès. Leur but est de permettre de tester les outils de diagnostic ou de mesurer le nombre de validateurs. Cette mesure se fait typiquement en incluant dans une page Web un objet (une image, par exemple) accessible via un nom de domaine ainsi invalide. Si le chargement de l'objet se fait, c'est que le navigateur Web n'utilisait pas de résolveur validant.

Il ne faut évidemment pas mettre de NTA sur ces domaines volontairement invalides (section 6 de notre RFC). J'utilise servfail.nl ci-dessous mais c'est juste un exemple.

On a dit plus haut qu'une NTA ne devait être ajouté qu'après qu'un technicien DNS ait évalué l'état de la zone et déterminé que c'était bien un accident. Pour l'aider à faire cette évaluation, il existe plusieurs outils. Par exemple, l'histoire compte : si l'enregistrement de type AAAA de example.net est invalide, mais qu'il vaut 2001:db8:67::ab et qu'il a cette valeur depuis deux ans, on peut être raisonnablement sûr que c'était une erreur DNSSEC et pas une attaque. Comment sait-on que la valeur n'a pas changé depuis deux ans ? On peut utiliser une base de passive DNS comme DNSDB. Un autre outil historique important est DNSviz, qui stocke le résultat des tests DNSSEC précédents (un domaine populaire a forcément été testé plusieurs fois).

Notre RFC liste plusieurs outils de débogage qui permettent d'analyser l'état actuel de la zone :

Les deux premiers sont des logiciels libres et peuvent être installés localement sur votre machine. (Une analyse du cas de nasa.gov a été faite avec ces outils.)

En effet, dans certains cas, le résultat peut dépendre de l'endroit où vous vous trouvez. Par exemple, certaines instances d'un nuage anycast peuvent servir des signatures expirées et d'autres pas. Il est donc utile d'avoir accès à des résolveurs DNSSEC distants. On peut utiliser les sondes Atlas, ou se connecter à des serveurs distants pour y lancer dig. Si tous les résolveurs validants de la planète voient SERVFAIL, il est beaucoup plus probable qu'on soit confronté à une erreur dans la gestion de la zone qu'à une attaque par empoisonnement.

Le RFC liste aussi, dans cette section 7, les causes les plus fréquentes de problème DNSSEC aujourd'hui :

  • Signatures expirées. Les clés DNSSEC n'ont pas de durée de validité mais les signatures, si (elle vaut en général de deux à huit semaines). Avant DNSSEC, une fois qu'une zone DNS était configurée et testée, elle restait correcte plus ou moins éternellement. Depuis DNSSEC, il faut re-signer la zone régulièrement puisque les signatures expirent, même si on n'a pas changé le contenu de la zone. Cette tâche doit évidemment être automatisée (par exemple, OpenDNSSEC ou BIND peuvent le faire sans intervention humaine) mais les logiciels ont des bogues. Si le programme de re-signature ne marche plus, les signatures vont expirer. Au début, c'était quasiment la seule cause de problème DNSSEC, menant au dicton « on peut déboguer DNSSEC avec deux commandes Unix, dig et date ». Aujourd'hui que les outils automatiques sont bien plus fréquents, cette erreur est plus rare.
  • Les autres causes de problème sont toutes liées à la chaîne de confiance, qui part en général de la racine et qui, via des signatures de zone parente en zone fille, permet de valider toute information stockée dans le DNS. Si cette chaîne casse (par exemple un enregistrement DS qui pointe vers une clé inexistante), la zone est invalide. Ici, DNSviz est vraiment l'outil idéal, grâce à la représentation graphique qu'il fait de cette chaîne de confiance. La chaîne de confiance peut être cassée à la suite d'une erreur en transmettant la clé à la zone parente, ou par suite d'un changement ultérieur de clés (key rollover) en oubliant de prévenir la parente.

Enfin, la section 8 de notre RFC couvre plusieurs points de sécurité qui n'étaient pas évidents. Politiquement, la NTA est une prise du pouvoir par le résolveur, qui se permet de contrarier les résultats. C'est un mal nécessaire mais, quand même, il faut être conscient de ce décalage des responsabilités. D'où l'importance d'informer le gérant de la zone signée et de discuter avec lui/elle.

Autre problème, la NTA transforme une zone signée en zone non signée. Cela évite les erreurs de validation mais cela pose un problème pour toutes les applications qui vérifient que le contenu des données est valide (par exemple lorsqu'on lit des clés cryptographiques dans le DNS). Cette vérification se fait typiquement en regardant le bit AD (Authentic Data) dans la réponse DNS. S'il est absent, c'est que la zone n'est pas signée, et les applications risquent alors d'ignorer les informations qu'elles ont trouvées dans le DNS, faute de validation positive. C'est par exemple un problème pour DANE (RFC 6698) : si une NTA est placée, les certificats mis par DANE seront tout à coup ignorés, ce qui pourra couper l'accès à certains serveurs TLS. Le RFC estime que les applications feront de plus en plus leur propre validation, ce qui diminuera le problème, mais ce pronostic me parait très contestable.

L'annexe A du RFC contient plein d'exemples de gestion des NTA sur différents logiciels. Je vais commencer par une méthode non décrite dans le RFC, avec Unbound. Voyons d'abord un domaine invalide avec une requête normale :


% dig A www.servfail.nl

; <<>> DiG 9.9.5-9+deb8u3-Debian <<>> A www.servfail.nl
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 26269
...

On récupère un SERVFAIL (Server Failure) ce qui est normal puisque ce domaine est (délibérement) invalide. Essayons avec l'option +cd (Checking Disabled) qui indique au résolveur de ne pas valider :

  
% dig +cd A www.servfail.nl

; <<>> DiG 9.9.5-9+deb8u3-Debian <<>> +cd A www.servfail.nl
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 53947
;; flags: qr rd ra cd; QUERY: 1, ANSWER: 6, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;www.servfail.nl.       IN A

;; ANSWER SECTION:
www.servfail.nl.        60 IN CNAME www.forfun.net.
...

Maintenant, modifions la configuration d'Unbound en ajoutant dans le unbound.conf la Negative Trust Anchor :

# Added on 2015-09-22, after confirmation from <foobar@forfun.net>
domain-insecure: "servfail.nl"

Notez l'importance de mettre la date dans le fichier de configuration : les NTA ne doivent pas être permanentes. On recharge la configuration :

% sudo unbound-control reload
ok

Et on réessaie :

    
% dig A www.servfail.nl

; <<>> DiG 9.9.5-9+deb8u3-Debian <<>> A www.servfail.nl
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 62157
;; flags: qr rd ra; QUERY: 1, ANSWER: 6, AUTHORITY: 4, ADDITIONAL: 13

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;www.servfail.nl.       IN A

;; ANSWER SECTION:
www.servfail.nl.        60 IN CNAME www.forfun.net.

Notez qu'on a eu la réponse mais que le bit AD (Authentic Data) n'est évidemment pas mis, comme discuté en section 8 du RFC.

Cette méthode a l'inconvénient d'être un peu trop manuelle et de ne pas être automatiquement réversible. À noter que l'annexe A du RFC cite également une méthode qui ne nécessite pas de changer le fichier de configuration, mais utilise l'outil de contrôle à distance d'Unbound (qu'il faut configurer préalablement) :

[Quels NTA sont installées ? ]
% sudo unbound-control list_insecure
%
[Aucun]

[On installe une NTA]
% sudo unbound-control insecure_add servfail.nl
ok
% sudo unbound-control list_insecure           
servfail.nl.

% dig A www.servfail.nl                        
...
www.servfail.nl.        60 IN CNAME www.forfun.net.
...

[On retire la NTA]
% sudo unbound-control insecure_remove servfail.nl
ok
% sudo unbound-control list_insecure              
%

BIND n'a pas d'équivalent de la directive domain-insecure:. C'est une de ses faiblesses. Mais il permet, à partir des récentes versions (non encore publiques, apparemment réservées aux clients payants), d'avoir des NTA plus conformes à ce que demande le RFC, notamment avec retrait automatique au bout d'un temps donné. Je n'ai pas testé donc voici les commandes que donne le RFC :

[Quels NTA sont installées ? ]
% sudo rndc nta -dump

[On installe une NTA pour une heure - la valeur par défaut]
% sudo rndc nta servfail.nl

[On retire explicitement la NTA (sinon, il est retiré automatiquement)]
% sudo rndc nta -remove servfail.nl

Téléchargez le RFC 7646


L'article seul

RFC 7594: A framework for Large-Scale Measurement of Broadband Performance (LMAP)

Date de publication du RFC : Septembre 2015
Auteur(s) du RFC : P. Eardley (BT), A. Morton (AT&T Labs), M. Bagnulo (UC3M), T. Burbridge (BT), P. Aitken (Brocade), A. Akhter (Consultant)
Pour information
Réalisé dans le cadre du groupe de travail IETF lmap
Première rédaction de cet article le 21 septembre 2015


Le groupe de travail LMAP de l'IETF travaille sur les mesures des performances des accès Internet « haut débit ». Des mesures comme celles que fait l'ARCEP en France. Ce RFC définit le cadre conceptuel de ces mesures et leur terminologie.

Donc, d'abord, les généralités (section 1 du RFC). On veut mesurer la qualité du réseau depuis un grand nombre de points de mesure. Sur chacun de ces points se trouve un MA (Measurement Agent, au passage, le vocabulaire spécifique de LMAP est en section 3 du RFC) qui peut être matériel (sondes de l'ARCEP, sondes RIPE Atlas, sondes Sam Knows, etc) ou logiciel (Grenouille, etc). Le matériel peut être un boîtier séparé ou bien être un composant dans un engin comme la box. Le but de LMAP est de travailler sur des mesures à grande échelle, avec des milliers, voire des millions de MA. À qui cela va-t-il servir ?

  • Aux opérateurs de réseau pour planifier les investissements et détecter des problèmes,
  • Aux régulateurs des télécommunications (comme l'ARCEP déjà citée) pour comparer les opérateurs et détecter des points où de la régulation pourrait être nécessaire (par exemple en cas de violation de la neutralité du réseau).

Ces buts sont décrits plus en détail dans le RFC 7536.

Outre les MA (Measurement Agents, installés chez M. Michu ou dans un point de mesure dédié, et qui exécutent les mesures), le système comprend les contrôleurs et les collecteurs. Le contrôleur est celui qui dit aux MA quelles mesures faire. Dans le cas de RIPE Atlas, le contrôleur est une machine au RIPE-NCC qui reçoit les demandes de mesures faites, par exemple, via l'API, et les transmet aux Atlas « pingue donc 192.0.2.34 avec un paquet ICMP ECHO par minute pendant dix minutes ». Le collecteur reçoit les résultats de ces mesures (« premier essai, RTT de 18 ms, deuxième essai time out, troisième essai, RTT de 23 ms... ») et les analyse et/ou les rend disponibles. Le collecteur doit donc gérer une belle base de donnéees (big data) avec un mécanisme d'accès aux données, comme SQL. Le protocole de communication entre le contrôleur et les MA se nomme le protocole de contrôle et celui entre les MA et le collecteur le protocole de collecte (report protocol). Certains systèmes (c'est le cas des Atlas) ne font pas de différence entre contrôleur et collecteur (et donc n'utilisent qu'un seul protocole pour le contrôle et la collecte).

On souhaite évidemment que l'ensemble du système :

  • Soit normalisé, afin qu'on puisse choisir indépendamment ses différents composants. Il ne s'agit pas seulement de normaliser les protocoles mais aussi le modèle de données et le format de celles-ci (description des tâches de mesure, et des données récoltées). Normaliser tout cela est le principal travail du groupe de travail LMAP. (Le modèle de données a été normalisé dans le RFC 8193.)
  • Passe à l'échelle comme indiqué plus haut (« des millions de MA »). Un contrôleur unique et centralisé, par exemple, pourrait avoir du mal à effectuer son travail, à devoir coordonner un million de MA bavards (cf. RFC 7398).
  • Accepte la diversité des réseaux (MA connectés à des capacités très variables, réseaux IPv4 et IPv6, tests par plusieurs moyens, par exemple traceroute avec ICMP ou UDP, de façon à maximiser les chances de passer outre les pare-feux).
  • Respecter la vie privée. Certaines informations récoltées peuvent être délicates.

La section 2 du RFC décrit à gros grains à quoi pourrait ressembler le système idéal. Le MA doit faire des mesures. Celles-ci peuvent être passives (le MA observe le trafic existant, sans interférer) ou actives (le MA envoie des paquets et observe leur effet). Notez que la plupart des systèmes existants sont purement actifs (une collecte passive soulève d'intéressants problèmes de vie privée...) mais que LMAP traite les deux cas.

Pour que les mesures soient anaysables et comparables, il vaut mieux qu'elles se réfèrent à des métriques standards et documentées (ce qui est rare, par exemple les mesures de l'ARCEP ne s'appuient pas sur les normes existantes, réinventant ainsi la roue).

Les canaux de communication (entre le MA et le contrôleur, ainsi qu'entre le MA et le collecteur) doivent évidemment être sécurisés, pour se prémunir contre des attaques comme celle d'un faux contrôleur qui essaierait d'utiliser les MA à son profit.

À noter que la configuration initiale du MA (par exemple, le nom de domaine pour contacter le contrôleur) n'est pas normalisée. Le MA peut arriver pré-configuré (c'est le cas des sondes RIPE Atlas) ou bien être configuré par un des protocoles existants comme NETCONF ou CWMP.

La section 4 de notre RFC est consacrée aux limites de LMAP. Le projet est assez ambitieux comme cela, il va donc se donner quelques restrictions (d'autres sont données en section 5.6) :

  • Une seule organisation gère les MA, le contrôleur et le collecteur. LMAP ne va pas essayer de traiter le cas très difficile de mesures complètement pair-à-pair. Un tel système sans chef bien identifié serait sans doute très dangereux (risque de détournement pour faire des attaques par déni de service, risque de manipulation des données, ou de fuite de données privées).
  • Chaque MA n'a qu'un seul contrôleur. Pour la résilience, il serait sans doute intéressant de pouvoir avoir plusieurs contrôleurs mais cela soulèverait le problème de quoi faire si un MA reçoit des instructions contradictoires.
  • Les MA ne se coordonnent pas entre eux, on est purement top->down.
  • La relation entre le contrôleur et le collecteur n'est pas au programme. Ils vont bien sûr coopérer mais ce sera d'une manière non définie dans LMAP.
  • Chaque système de mesures est indépendant des autres (pour éviter d'avoir à gérer des problèmes de coordination). Si un régulateur et un FAI ont chacun leur système LMAP, et que M. Michu a deux MA (Measurement Agent) chez lui, les deux MA s'ignorent et chacun considère le trafic de l'autre comme du trafic utilisateur ordinaire.
  • Il ne gère pas le problème de la triche. Si un régulateur fait des mesures, on peut imaginer que certains FAI chercheront à identifier les lignes où se fait la mesure, ce qui est facile, puis à favoriser ces lignes, pour obtenir un meilleur score. Le problème n'a pas de solution technique et n'est donc pas traité par LMAP. (Voir aussi la fin de la section 7.)

La section 5 du RFC décrit de manière abstraite le modèle des protocoles à élaborer. On y trouve notamment la liste des fonctions à mettre en œuvre comme par exemple un mécanisme de suppression des données si on découvre que certaines mesures étaient erronées (par exemple parce que l'amer visé n'était pas joignable à ce moment).

Mais les informaticiens préféreront peut-être lire la section 6, plus concrète, qui décrit les questions pratiques de mise en œuvre et de déploiement. Par exemple, que doit faire un MA qui redémarre après un long arrêt ? Les instructions du contrôleur qu'il avait reçues et stockées peuvent être dépassées. Il doit donc tenter de re-contacter le contrôleur avant de se lancer dans les mesures.

Autre exemple de discussion pratique, la section 6.2 étudie les différentes formes de MA, et l'endroit où les placer, chaque forme et chaque endroit ayant ses avantages et ses inconvénients. Ainsi, un MA embarqué dans la box du FAI aurait des avantages (il voit tout le trafic, donc les mesures passives sont triviales à effectuer et toujours exactes, et les mesures actives peuvent être faites uniquement lorsque le trafic utilisateur est faible, alors qu'une sonde séparée risque de faire ses mesures au moment où on utilise la ligne à fond) et des inconvénients (dans le modèle classique des box imposées, les fonctions de la box ne sont accessibles qu'au FAI, pas au régulateur ou à l'utilisateur).

Et si le MA est (malheureusement pour lui) coincé derrière un NAT ? La principale conséquence est que le contrôleur ne pourra pas le joindre à volonté, ce sera au MA de le contacter. Une autre solution est de mettre un client PCP (RFC 6887) dans le MA.

Autre cas intéressant à considérer, celui où le MA se trouve en plein dans le réseau du FAI, et non plus chez M. Michu. (Le cas est cité dans le RFC 7398.) Cela permet au MA d'être indépendant des lubies du réseau local et de son accès et de faire des mesures dans un environnement plus contrôlé, donc plus scientifiques. Évidemment, ces mesures seront alors moins représentatives du vécu de l'utilisateur.

La section 6 discute aussi le cas où on a besoin d'une aide sur le réseau. Par exemple, si on pingue un amer situé sur l'Internet, cet amer ne peut pas être purement passif. Ce doit être une machine allumée et qui répond aux paquets ICMP ECHO. Une telle aide est nommée MP pour Measurement Peer. Ce rôle n'est pas évident. Par exemple, un amer peut tout à coup se mettre à limiter le trafic ICMP car il en a assez d'être pingué en permanence, faussant alors toutes les mesures. C'est encore plus vrai si on fait des tests lourds, comme de charger en HTTP un fichier de grande taille. Si on fait cela sur une machine qui n'était pas au courant de son rôle de MP, on peut se retrouver dans les ACL rapidement. S'il y a un protocole de contrôle explicite avec le MP (comme ceux des RFC 4656 ou RFC 5357), tout est plus simple, le MA négocie avec le MP le bon déroulement de la mesure. Sinon, il faut s'assurer d'abord que le MP est d'accord pour être utilisé. Heureusement, il existe des machines qui sont dédiées à ce rôle de MP, comme les Ancres.

La section 6.4 décrit un certain nombre de déploiements typiques. Ça peut aller de cas simples (le MA fait du HTTP avec un MP qui est juste un serveur HTTP ordinaire), à des choses plus complexes, où le MP déploie un logiciel spécifique comme iperf.

Un peu de sécurité maintenant (section 7 du RFC). La sécurité de LMAP doit protéger aussi bien le système de mesures, que le réseau mesuré (des mesures actives trop agressives pourraient sérieusement ralentir ce réseau, par exemple, voir la section 6 du RFC 4656). Plusieurs points sont donc à sécuriser. Par exemple, la mise à jour du logiciel du MA doit se faire de manière sécurisée. Imaginez des sondes dont le firmware serait mis à jour en HTTP (pas HTTPS avec vérification du certificat) : un méchant pourrait se glisser sur le trajet, leur envoyer du logiciel malveillant et se constituer ainsi un botnet. Par exemple, si les MA peuvent faire des mesures passives, un tel botnet pourrait servir à faire de la surveillance massive (RFC 7258).

De la même façon, le MA ne doit pas obéir aveuglément à toute machine qui prétend être le contrôleur : il doit l'authentifier, tester l'intégrité des requêtes du contrôleur et empêcher les rejeux, qui pourraient facilement être utilisés pour des attaques par déni de service. La communication entre MA et contrôleur doit également être chiffrée : elle peut révéler des choses à un attaquant. Idem pour la communication du MA avec le collecteur : elle doit être authentifiée (imaginez un faux MA envoyant des mesures mensongères pour fausser une étude comparée sur les différents FAI) et confidentielle (les MA peuvent faire des mesures privées). À noter que, lorsque le MA est situé chez un utilisateur, on ne peut jamais être totalement sûr de son intégrité : il a pu être ouvert et modifié par l'utilisateur. (C'est encore plus vrai pour un MA logiciel.)

LMAP est prévu pour des grands systèmes de mesure. En outre, des malveillants pourraient tenter des attaques par déni de service contre le système de mesure. Notre RFC précise donc également que le collecteur doit se protéger en limitant le nombre de MA qui se connectent à lui simultanément, en limitant le débit d'envoi des données, et la taille totale des données.

Reste la question de la vie privée (section 8), qui fut le gros sujet de discussion au sein du groupe de travail à l'IETF. La vie privée de qui ? Eh bien, on cherche à protéger aussi bien les utilisateurs, que les FAI et les régulateurs. En cas de mesures passives, l'information sur le trafic Internet des utilisateurs est certainement très sensible et on ne veut pas qu'elle soit diffusée partout. Tout MA qui observe le trafic va donc accéder à ces informations qui peuvent menacer la vie privée. (Le RFC note qu'IPFIX a le même problème, cf. section 11.8 du RFC 7011.) Ainsi, même si la sonde Sam Knows ne fait que des mesures actives, a priori moins sensibles, sa documentation recommande de brancher la sonde en coupure du réseau local, de manière à voir passer tout le trafic de l'utilisateur. C'est pour pouvoir ne déclencher les mesures actives que lorsque le trafic utilisateur est faible ou nul. Mais brancher un engin dont on n'a pas le source de manière à ce qu'il puisse voir tout le trafic est assez dérangeant. En outre, quelqu'un qui observerait les communications de la Sam Knows avec son contrôleur, même sans les comprendre, pourrait savoir quand l'utilisateur est en train d'utiliser son réseau : le MA n'a rien à communiquer dans ce cas (section 8.5.1 de notre RFC).

Même en l'absence de mesures passives du trafic, les MA peuvent avoir accès à des informations confidentielles : SSID du WiFi local, adresses MAC repérées lors des requêtes ARP, etc. Certaines informations sont rentrées explicitement par l'utilisateur et peuvent être sensibles : le contrôleur des sondes Atlas connait ainsi la longitude et latitude de la sonde donc la position de la maison (la précision est volontairement réduite lors de la saisie, précisément pour cette raison).

Quand aux données du FAI, qui peuvent être révélées indirectement via les systèmes de mesure, elles sont nombreuses : topologie exacte du réseau, trafic effectif dans les tuyaux, informations commerciales (type d'abonnements souscrits), etc.

Et le régulateur ? Oui, lui aussi a de la vie privée à défendre car il possède des infos confidentielles aussi bien sur les utilisateurs que sur les FAI, et n'a typiquement pas le droit de les diffuser.

Parmi les méchants qui seraient intéressés par cette information, on peut trouver les concurrents (le chiffrement est alors la protection minimale), l'organisation qui fait tourner les mesures (il est donc souhaitable de réduire la confiance qu'il faut lui faire, par exemple en mettant le MA derrière le port d'un commutateur, ce qui le rend difficilement capable de faire des mesures passives), ou bien sûr les organes de surveillance (RFC 6973, notamment section 5.1.1).

Outre le chiffrement des communications entre le MA et ses contrôleurs et collecteurs, solution déjà citée, il va être préférable de minimiser les données récoltées et transmises. Le chiffrement n'est pas une solution parfaite (notamment, il ne protège pas contre l'organisation qui fait fonctionner le collecteur), et il doit être complété par la minimisation, composante cruciale de tout projet de protection de la vie privée (RFC 6973, section 6.1, et notre RFC 7594, section 8.6.1). Les données doivent être agrégées, résumées, réduites à ce qui est strictement nécessaire pour la tâche en cours.

Les organisations qui collectent et traitent des grandes quantités de données essaient souvent de rassurer les utilisateurs en promettant que les données sont « anonymisées ». La section 8.6.2 de notre RFC rappelle que l'anonymisation est très difficile à faire correctement et que les techniques modernes d'analyse de données peuvent souvent dé-anonymiser et donc retrouver les individus dans la masse des données (cf. RFC 6235 et l'étude de Burkhart, M., Schatzmann, D., Trammell, B., et E. Boschi, « The Role of Network Trace anonymisation Under Attack » en 2010).

L'anonymat ne doit pas être réduit au simple pseudonymat, (section 6.1.2 du RFC 6973) où il y a un identificateur stable des activités, même s'il n'est pas relié à une identité du monde extérieur. Dans le vrai anonymat (très difficile à obtenir, malgré les promesses des commerciaux du big data), il n'y a pas de traçabilité.

D'ou la conclusion de cette section, qu'un accord explicite d'un utilisateur informé et conscient est nécessaire, si on fait des mesures chez lui. (Cela peut d'ailleurs être un argument pour des points de mesures créés spécialement pour la mesure, comme dans les tests ARCEP. Il n'y a alors pas de problème de vie privée.)


Téléchargez le RFC 7594


L'article seul

Un exemple de contrat Ethereum

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


J'ai déjà parlé d'Ethereum dans un précédent article, avec une description de ses possibilités. Je suis passé plutôt vite sur la notion de contrat alors qu'elle est essentielle dans Ethereum, et qu'elle est sa principale innovation par rapport à Bitcoin et tous ses dérivés. Je comptais me mettre à l'écriture de contrats mais je manque de temps donc, en attendant que j'apprenne sérieusement, je vais décrire un exemple que je n'ai pas réalisé moi-même mais qui a l'avantage pédagogique d'être assez simple à comprendre et assez compliqué pour faire quelque chose de réel : la Pyramide.

Le nom fait référence à une accusation stupide, mais récurrente, faite contre Bitcoin et ses dérivés, qui seraient soi-disant une pyramide de Ponzi. Mais avant de décrire ce que fait la Pyramide Ethereum, revenons aux contrats.

Un contrat est un programme informatique, stocké sous forme de code pour une machine virtuelle, l'EVM (Ethereum Virtual Machine). Il va s'exécuter sur les machines du réseau qui minent, c'est-à-dire qui vérifient les transactions. Le langage de l'EVM (qu'on appelle parfois, lui aussi, EVM) est un langage de Turing, ce qui, en français, veut dire que tout ce qui peut être programmé dans un autre langage de Turing (C, PHP, Haskell, Go...) peut être programmé pour l'EVM. Un contrat est aussi une entité stockée dans le livre des opérations (la blockchain) et a donc une adresse : on peut lui écrire, plus précisement lui envoyer des ethers (l'unité de compte Ethereum) pour lui faire exécuter son code. (Ethereum n'a pas de code tournant en permanence et n'a pas l'équivalent de cron : il faut explicitement appeler le contrat depuis l'extérieur.)

Les contrats sont stockés sous forme de code de bas niveau mais on les écrit en général dans un langage de plus haut niveau, le plus répandu étant Solidity.

Ces préliminaires étant posés, que fait le contrat « Pyramide » ? Eh bien, il mérite son nom, c'est une vraie pyramide de Ponzi. On envoie un ether (environ un euro au cours actuel) au contrat, et on est ajouté à la pyramide. Quand le niveau où on a été ajouté est plein, un niveau inférieur est ajouté (la pyramide grandit) et on reçoit des ethers. Comme tout bon schéma de Ponzi, cela ne marche que lorsque de nouveaux entrants arrivent en permanence. Quand ils cessent d'affluer, le schéma ne marche plus et les derniers arrivés n'ont plus qu'à pleurer.

Le code écrit en Solidity est disponible en ligne. Les programmeurs familiers avec des langages comme C ou comme JavaScript ne devraient pas avoir trop de mal à le lire. Les points importants :

struct Participant {
        PayoutType payoutType;
        bytes desc;
        address etherAddress;
        bytes bitcoinAddress;
    }

Participant[] public participants;

Cette variable participants est l'état de la pyramide. Les transactions Ethereum peuvent en effet modifier l'état du système. (Ethereum, comme Bitcoin, est donc aussi un système de stockage.)

function() {
        enter(msg.data);
    }

Cette fonction anonyme est celle qui est appelée lorsque des ethers sont envoyés au contrat, le « réveillant ». La fonction enter, qu'elle appelle, fait l'essentiel du travail (je l'ai un peu simplifiée ici) :


function enter(bytes desc) {
        if (msg.value < 1 ether) {
            msg.sender.send(msg.value);
            return;
        }

        if (desc.length > 16) {
            msg.sender.send(msg.value);
            return;
        }

        if (msg.value > 1 ether) {
            msg.sender.send(msg.value - 1 ether);
         }

Ces trois tests vérifient certaines pré-conditions : que le paiement était bien de un ether pile, et que le message envoyé par l'utilisateur (msg.data) fait bien moins de seize octets. Si un des deux premiers tests échoue, on est remboursé (attention donc en testant : vous aurez l'impression que rien ne s'est passé, alors qu'en fait vous avez été silencieusement remboursé). Si vous envoyez plus d'un ether, vous serez remboursé du surplus mais le contrat continuera.


uint idx = participants.length;
participants.length += 1;
participants[idx].desc = desc;
// for every three new participants we can
// pay out to an earlier participant
if (idx != 0 && idx % 3 == 0) {
        // payout is triple, minus 10 % fee
        uint amount = 3 ether - 300 finney;
        participants[payoutIdx].etherAddress.send(amount);
        payoutIdx += 1;
	}

  

Ce code paie (avec intérêts) un ancien participant lorsque de nouveaux participants sont arrivés.

J'ai moi-même envoyé mon ether (sous le nom "Stephane B.") ainsi, depuis la console de geth (cf. mon premier article) :

> eth.sendTransaction({from: eth.accounts[0], value: web3.toWei(1, 'ether'),
    to: '0x7011f3edc7fa43c81440f9f43a6458174113b162', gas: 500000,
    data: web3.fromAscii('Stephane B.')})

Ethereum étant transparent, on peut voir sur un explorateur public du livre des transactions tous les paiements reçus par la pyramide, en donnant son adresse (0x7011f3edc7fa43c81440f9f43a6458174113b162) : https://etherchain.org/account/0x7011f3edc7fa43c81440f9f43a6458174113b162#txreceived. L'argent envoyé est bien débité du compte utilisé (eth.accounts[0]) :

> eth.getBalance(eth.accounts[0])
2980411500000000000

[Minage de la transaction]

> eth.getBalance(eth.accounts[0])
1975400100000000000

Et hop, je suis ajouté à la pyramide, en attendant un profit (quand d'autres gogos viennent, suite à cet article). C'est ainsi que, deux mois après, j'ai bien touché mes ethers. De l'argent facilement gagné ! Le code JavaScript de la page Web du projet affiche alors la pyramide modifiée. (Le programmeur aurait pu interroger dynamiquement en JSON-RPC un nœud Ethereum pour récupérer les données mais, apparemment, cette récupération est faite entièrement côté serveur et ce code n'est pas publié. Mais vous pouvez faire pareil. Comment récupère-t-on des données d'un contrat ? On note (dans le source) que le contrat a des méthodes publiques comme getNumberOfParticipants. Il suffit de créer un objet JavaScript dans la console ayant la bonne ABI et l'adresse du contrat. On pourrait faire l'ABI à la main à partir du source mais c'est plus facile de demander au compilateur Solidity de le faire :

%  solc --json-abi file pyramid.sol

Et l'ABI en JSON est dans le fichier Pyramid.abi. Plus qu'à y ajouter un peu de code Javascript au début et à la fin (déclaration au début et adresse du contrat à la fin) et on a :

var pyramid = eth.contract(
[{"constant":false,"inputs":[{"name":"_owner","type":"address"}],"name":"setOwner","outputs":[],"type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"participants","outputs":[{"name":"payoutType","type":"uint8"},{"name":"desc","type":"bytes"},{"name":"etherAddress","type":"address"},{"name":"bitcoinAddress","type":"bytes"}],"type":"function"},{"constant":false,"inputs":[{"name":"_bitcoinBridge","type":"address"}],"name":"setBitcoinBridge","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"desc","type":"bytes"},{"name":"bitcoinAddress","type":"bytes"}],"name":"enter","outputs":[],"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":true,"inputs":[],"name":"collectedFees","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"recipient","type":"address"}],"name":"collectFees","outputs":[],"type":"function"},{"constant":true,"inputs":[],"name":"payoutIdx","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[],"name":"bitcoinBridge","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":true,"inputs":[],"name":"getNumberOfParticipants","outputs":[{"name":"n","type":"uint256"}],"type":"function"},{"inputs":[{"name":"_bitcoinBridge","type":"address"}],"type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"idx","type":"uint256"}],"name":"NewParticipant","type":"event"}]
).at('0x7011f3edc7fa43c81440f9f43a6458174113b162');

On demande à geth de charger tout ça :

> loadScript("load-abi.js");
true

Et on a un objet JavaScript dont on peut appeler les méthodes, récupérant ainsi les données du contrat :

> pyramid
{
  address: "0x7011f3edc7fa43c81440f9f43a6458174113b162",
  ...
  getNumberOfParticipants: function(),
  ...
}

>  pyramid.getNumberOfParticipants()
65

On voit dans cet exemple qu'il est très simple d'écrire un contrat, et de faire donc calculer ses programmes par les machines d'Ethereum.

Le code machine du contrat est également public et visible, à l'adresse du contrat : https://etherchain.org/account/0x7011f3edc7fa43c81440f9f43a6458174113b162#codeDisasm.


L'article seul

Ethereum, la prochaine étape des systèmes transparents

Première rédaction de cet article le 12 septembre 2015


Je viens de me lancer dans Ethereum et j'ai envie de partager avec vous (partager mon expérience, pas mon argent virtuel, faut pas rêver).

Ethereum est souvent présenté par rapport à Bitcoin : « Bitcoin 2.0 », « the next Bitcoin », « Bitcoin on steroids », etc. Il est vrai qu'il s'inspire très fortement de Bitcoin mais, en le présentant ainsi, on peut le confondre avec tous les autres machins qui ont été faits à partir de Bitcoin comme Dogecoin, Litecoin ou encore Namecoin. À part ce dernier, ces comparaisons peuvent amener à conclure qu'Ethereum n'est qu'« une nouvelle monnaie virtuelle et cryptographique (alt coin) ». Alors qu'il est bien plus que cela.

Ceci dit, c'est vrai que, pour expliquer Ethereum, partir de Bitcoin est pratique. Avant Bitcoin, on considérait que, pour établir et exécuter des contrats (oui, une monnaie est une forme de contrat : je te donne des billets en échange de quelque chose), il n'y avait que deux solutions :

  • Une toute petite communauté, composée uniquement de gens honnêtes qui se connaissent,
  • Ou bien un organisme de confiance, à qui tout le monde délègue la responsabilité de surveillance : banque centrale dans le cas de la monnaie, registre de noms de domaines pour les noms, etc.

Bitcoin a montré qu'il existait une troisième solution : une structure de données publique, le livre des opérations ou blockchain, que tout le monde peut voir et vérifier. Cette structure liste toutes les transactions et est protégée par la magie de la cryptographie, de façon à ce qu'elle soit validable. C'est le grand mérite de Bitcoin, et l'invention géniale de Satoshi Nakamoto : prouver théoriquement et expérimentalement qu'un système complètement pair à pair pouvait fonctionner, ce qui était loin d'être évident (par exemple, j'étais personnellement persuadé que c'était impossible).

Bitcoin est spécialisé : on ne peut s'en servir que pour la monnaie. Si on veut, par exemple, enregistrer des noms et non pas échanger de l'argent, il faut copier le code de Bitcoin (il est libre), faire des modifications et créer sa propre infrastructure (sa blockchain à soi, ses mineurs, ses explorateurs de blockchain, etc). Ce choix n'est pas un oubli ou une erreur des concepteurs de Bitcoin : c'est parce que faire un système équivalent, mais généraliste, est non trivial, notamment du point de vue de la sécurité.

Ethereum reprend plusieurs concepts importants de Bitcoin, notamment la blockchain et la preuve de travail (il n'est donc pas plus écologiste que Bitcoin). Mais le code est radicalement différent, réécrit de zéro (contrairement à la plupart des alt coins). Il existe en outre plusieurs implémentations, avec une spécification commune (contrairement à Bitcoin où le code est la spécification, le papier original de Nakamoto ne descendant pas dans les détails). Mais le gros changement par rapport à Bitcoin est que les transactions stockées dans la blockchain ne sont pas limitées à envoyer et recevoir de l'argent. Ethereum dispose d'un quasi-langage de Turing et est donc un système de calcul réparti : les pairs dans le réseau Ethereum ne se contentent pas de vérifier l'intégrité de la blockchain et d'ajouter de la monnaie, ils exécutent du code arbitraire, celui des applications que vous ou moi développons et envoyons sur le réseau.

Cela permet d'écrire des contrats (appelés, dans le style marketing fréquent dans le monde Ethereum, des smart contracts) qui sont la description, dans un langage de programmation, des règles qui s'imposent aux parties contractantes. Un prêt d'argent, par exemple, peut se programmer dans un contrat et s'exécuter automatiquement, sans intervention humaine, et donc sans possibilité de triche. (Question philosophique : quel est le pourcentage des contrats entre humains qui peuvent s'automatiser, c'est-à-dire ne plus accepter d'arrangement, de cas particuliers, etc ?) Les applications d'Ethereum ne sont donc limitées que par votre imagination.

Ces contrats sont la nouveauté importante d'Ethereum. Comme leur exécution peut potentiellement consommer des ressources importantes (imaginez une boucle sans fin dans un contrat...), il faut payer pour leur exécution, ce qu'Ethereum nomme l'essence (gas). Cette essence est payée avec la monnaie de base d'Ethereum, l'ether. (D'ailleurs, si vous voulez m'envoyer des ethers, mon adresse actuelle est 0xbe1f2ac71a9703275a4d3ea01a340f378c931740.) Si vous tombez à court d'essence, l'application s'arrête. C'est cette limite qui fait qu'Ethereum n'est pas une vraie machine de Turing : celle-ci a des ressources infinies.

Bon, vous trouverez des articles généraux et théoriques sur Ethereum un peu partout. Passons plutôt à la pratique. D'abord, un sérieux avertissement, Ethereum est encore vraiment expérimental. Le premier bloc de la blockchain, la genèse, n'a été générée que fin juillet 2015. Le code ne marche pas toujours, les compétences humaines sont encore rares et, surtout, tout évolue vite et les documentations qu'on trouve en ligne sont presque toujours fausses ou dépassées (ou les deux à la fois). Les interfaces utilisateurs d'accès facile manquent (il n'existe pas encore d'équivalent des nombreux portefeuilles Bitcoin, par exemple). Contrairement à Bitcoin, on n'est donc pas encore en production. Ne vous plaignez pas qu'on ne vous a pas prévenus ! Et, comme avec Bitcoin, vous êtes entièrement responsable de votre sécurité. Un bon exemple d'erreur de sécurité faite par un utilisateur et de ses conséquences a été raconté sur Reddit.

Donc, installons un nœud Ethereum pour commencer. J'ai dit que, contrairement à Bitcoin, Ethereum n'est heureusement pas défini par une seule implémentation. Deux sont souvent citées pour l'usage pratique d'Ethereum, eth (écrit en C++) et geth (écrit en Go). Essayons avec geth (je dirais plus loin pourquoi eth ne m'a pas satisfait). La voie officielle pour installer un exécutable binaire de geth sur une Debian est :

% curl https://install-geth.ethereum.org -L > install-geth.sh
% sudo bash install-geth.sh
    

Cela ne fonctionne pas (rappelez-vous ce que j'ai dit sur le côté expérimental de la chose). Contrairement à ce que prétend la documentation, le code ne marche que sur Ubuntu et il faut, pour Debian, modifier la liste des sources apt. J'édite donc /etc/apt/sources.list.d/ethereum-ethereum-jessie.list et je remplace « jessie » (Debian) par « vivid » (Ubuntu). Après, cela fonctionne. Si vous n'aimez pas installer du binaire sans comprendre, le source est disponible en ligne.

Une fois geth installé, on le lance :

% geth console
...
I0912 15:05:24.430701    6306 chain_manager.go:237] Last block (#223283) f374ff2948430d05acc4a14684924d78d6ade385116c9541eec6e40994785dd7 TD=899026925409268704
...
I0912 15:05:25.966841    6306 backend.go:557] Server started
...
instance: Geth/v1.1.3/linux/go1.5
>
    

(Le dernier caractère, le > est l'invite de la console Ethereum.) La console est, par défaut, très bavarde. Le moyen le plus simple de travailler tranquillement est de lancer un autre terminal :

% geth attach

(Vous pouvez avoir toutes les options de geth en tapant geth --help ou bien en ligne.) Au premier lancement (WARNING: No etherbase set and no accounts found as default et WARNING: Wrote default ethereum genesis block), vous en aurez pour plusieurs heures (en septembre 2015) avant que votre nœud Ethereum soit synchronisé avec la blockchain. (eth est bien plus long que geth pour cette tâche, et il passe en outre du temps à nous prévenir qu'il construit un énorme DAG, nécessaire pour le minage.) À noter que la chaîne de blocs ne fait que s'allonger et, en mars 2016, ce temps était passé à 36 h, sur le même PC... En attendant cette synchronisation, vos transactions ne seront pas visibles localement, puisque votre nœud sera encore dans le passé de la blockchain. Pour voir où en est cette synchronisation :

> eth.blockNumber
223298

Et vous allez voir sur un explorateur public de la blockchain si vous vous en approchez. Par exemple, si EtherChain ou Eth status me disent sur leur page d'accueil qu'on vient de faire le bloc 223299, j'en déduis que je suis quasi-synchronisé (un seul bloc de retard).

La syntaxe de la ligne de commandes de geth peut paraître bizarre mais elle vient du fait qu'elle s'inspire de l'API JavaScript accessible aux programmes Ethereum (et cette API est documentée, c'est ainsi que vous pouvez apprendre à utiliser la console). Vous pouvez donc, non seulement taper des commandes, mais aussi écrire du JavaScript dans la console. Une documentation plus complète (mais pas toujours correcte) est disponible sous le nom d'« Ethereum Frontier Guide ». Il y a aussi une bonne documentation de la console interactive (pensez juste à remplacer web3.eth. par eth.).

Bien, maintenant que geth est lancé et a fini par se synchroniser (rappelez-vous, plusieurs heures, la première fois), on peut se créer un compte, pour envoyer et recevoir des ethers :

> personal.newAccount("Tu ne sauras pas mon mot de passe")
"0xbe1f2ac71a9703275a4d3ea01a340f378c931740"

> eth.getBalance(eth.accounts[0])
0

Il peut y avoir plusieurs comptes et eth.accounts[0] est le premier créé. Son adresse est 0xbe1f2ac71a9703275a4d3ea01a340f378c931740. C'est là où vous pouvez m'envoyer des ethers. Puisqu'Ethereum, comme Bitcoin, est transparent, vous pouvez regardez sur un explorateur public toute l'activité de ce compte.

La commande getBalance indiquait mon niveau de pauvreté. Aucun ether disponible. Je pourrais en miner en faisant tourner mon CPU (et donc mes ventilateurs) à fond mais j'ai préféré en acheter des tout faits, chez Kraken où on peut désormais acheter et vendre des ethers. Menu Trade / New order, j'ai acheté deux ethers. Attention, les interfaces Ethereum comptent parfois en ethers mais parfois aussi dans leurs subdivisions, portant des noms pittoresque comme « szabo » (un millionième d'ether) ou « lovelace » (un millionième de milliardième d'ether). Une fois mes ethers obtenus, je les envoie depuis Kraken vers mon compte, en indiquant l'adresse de celui-ci (menu Funding / Withdraw). Attention, si vous utilisez Kraken pour d'autres monnaies que l'ether, la fonction permettant d'enregistrer une adresse est par compte Kraken et pas par monnaie. Si vous avez enregistré une adresse Bitcoin sous le nom « Maison », vous ne pourrez pas nommer l'adresse Ethereum de la même façon (« duplicate withdrawal information » est le peu utile message d'erreur de Kraken).

Rapidement, les ethers se retrouvent sur votre compte :

> eth.getBalance(eth.accounts[0])
1995000000000000000

(Le montant est indiqué en weis, voir plus haut l'avertissement sur les subdivisions de l'ether. Ici, cela fait 1,995 ethers soit même pas deux euros au cours actuel.) Notez bien qu'Ethereum est aussi transparent que Bitcoin : tout le monde peut voir les retraits effectués depuis Kraken (essayez avec un autre explorateur public, Blockchain).

Jusqu'à présent, rien d'extraordinaire, on a fait exactement la même chose qu'avec Bitcoin. Quel intérêt d'utiliser Ethereum ? Le client est plus perfectionné et permet de faire du JavaScript pour automatiser certaines tâches. Par exemple, ce code :

function cab() { 
    var i =0;
    eth.accounts.forEach(function(e){
    	console.log("  eth.accounts["+i+"]: " +  e + " \tbalance: " + web3.fromWei(eth.getBalance(e), "ether") + " ether"); 
	i++; 
    })
};

va itérer sur tous vos comptes et afficher le nombre d'ethers :

> cab()
  eth.accounts[0]: 0xbe1f2ac71a9703275a4d3ea01a340f378c931740 	balance: 1.9833824 ether
undefined

Mais la vraie puissance d'Ethereum n'est pas là. Elle est dans les contrats. Ceux-ci sont des programmes exécutés par la machine Ethereum. Celle-ci exécute un langage machine nommé EVM. Il est de trop bas niveau pour le programmeur normal, qui écrit en général ses contrats dans un langage de plus haut niveau qu'il compilera. Le plus répandu de ces langages est Solidity (qui ressemble à JavaScript) mais on trouve aussi Serpent (inspiré de Python) ou LLL (dont la syntaxe ressemble à Lisp mais qui est en fait un langage de bas niveau, très proche du langage machine, Serpent peut d'ailleurs produire du LLL). Comme je suis paresseux, je vais utiliser un contrat en Solidity que j'ai récupéré chez Ethereum.org. C'est le Hello, World des contrats. Voyons d'abord si on a bien un compilateur Solidity :

> eth.getCompilers()
[""]

Non, rien. Installons-le (le script d'installation a mis la bonne source dans ma configuration d'apt) :

% sudo apt-get install solc

... (Retour à geth)

> admin.setSolc("/usr/bin/solc")
"solc v0.1.1\nSolidity Compiler: /usr/bin/solc\n"

> eth.getCompilers()
["Solidity"]

On peut alors rédiger le contrat (je ne le recopie pas ici, il est en ligne) :

...
(Appel à greeterContract.new()...)
...
Unlock account be1f2ac71a9703275a4d3ea01a340f378c931740
Passphrase: 
Contract transaction send: TransactionHash: 0x07dc92c133a433ad58946a7acf8a6f3ccf0352f34882158cc4745c17636ee81e waiting to be mined...
undefined

La demande de phrase de passe est due au fait que la création du contrat et son exécution nécessitent de l'essence. Cette transaction a nécessité plus de 200 000 unités d'essence et m'a couté en tout 0,0116 ethers, ce que reflète mon portefeuille :

> eth.getBalance(eth.accounts[0])
1983382400000000000

Une fois validée par les mineurs, le contrat a une adresse :

> Contract mined! Address: 0xf0b64c321e9db6bf9164eae8be44443e1e2834a5
[object Object]

On peut voir le contrat en ligne, récupérer le code compilé :

> greeter.address;
"0xf0b64c321e9db6bf9164eae8be44443e1e2834a5"

> eth.getCode(greeter.address)
"0x60606040526000357c0100000..."

Et, bien sûr, l'exécuter :

> greeter.greet();
"Mon contrat à moi"

La méthode créée par le code est visible dans la définition de l'ABI, ce que les autres utilisateurs devront connaître pour interagir avec « mes » contrats :

> greeterCompiled.greeter.info.abiDefinition;
[ ...
{
    constant: true,
    inputs: [],
    name: "greet",
    outputs: [{
        name: "",
        type: "string"
    }],
    type: "function"
    ...

C'est évidemment un tout petit contrat, sans grand intérêt. Au fur et à mesure que je progresse en programmation, j'espère en faire des meilleurs. En attendant, il existe plein d'exemples en ligne, comme le DAO qui prétend outrageusement implémenter... la démocratie en Solidity et clame même « This is exactly how a democracy should work. ». Ce contrat met en œuvre un mécanisme de vote entre « actionnaires » sur l'allocation de ressources. Ce vote est censitaire « The rules of your organization are very simple: anyone with at least one token [la monnaie du DAO] can create proposals to send funds from the country's account. After a week of debate and votes, if it has received votes worth a total of 100 tokens or more and has more approvals than rejections, the funds will be sent. If the quorum hasn't been met or it ends on a tie, then voting is kept until it's resolved. Otherwise, the proposal is locked and kept for historical purposes. ». Cela peut être une façon intéressante de gérer certaines organisations mais appeler ça « démocratie » est franchement fort de café. Inutile de dire que je ne partage pas leur délire libertarien.

Un exemple plus simple de contrat, facile à étudier mais illustrant la plupart des possibilités d'Ethereum, est la Pyramide, décrite dans mon article suivant.

Revenons à l'autre mise en œuvre d'Ethereum, eth, écrite en C++. C'est en fait par celle là que j'avais commencé mais j'ai arrêté car je n'arrivais pas à lui faire accepter mes contrats. L'installation ressemble beaucoup à celle de geth :

% curl https://install-eth.ethereum.org -L > install-eth.txt
%  sudo bash -x install-eth.txt

On lance eth, par exemple, ainsi :

%  eth -j --frontier -i --verbosity 2

Et sa console n'a pas l'air de comprendre le Contrôle-D de fin de session, il faut faire web3.admin.eth.exit(). Pour de l'aide, on peut faire eth --help (ou bien voir la doc en ligne) et juste taper web3 dans la console.

J'ai créé plusieurs comptes avec eth (l'objet de référence est web3.eth, et pas eth comme c'était le cas avec geth) :

> web3.eth.accounts
['0x003653c3b972ede82f621ac322c6e430493eeb8c', '0x0007ca35a2680425974312233a59a74c00d3c040', '0x00740378b6046b199f7197fabe21484787648d24']

> web3.eth.getBalance(web3.eth.accounts[1])
1995000000000000000'

J'avais ensuite essayé de créer un contrat depuis eth mais sans succès. eth a tous les compilateurs :

> web3.eth.getCompilers()
['lll', 'solidity', 'serpent']

J'ai utilisé le même contrat qu'avec geth, une transaction était bien générée (0xffc8450fd29e6dc26b7df84328913df16dad4b29b3fbd1df9df2a5d12dabc251) mais apparemment jamais validée :

20:51:34|eth  New transaction ffc8450f…{[CREATE]/788$0+300000@50000000000<-0007ca35… #0}

'Contract transaction send: TransactionHash: 0xffc8450fd29e6dc26b7df84328913df16dad4b29b3fbd1df9df2a5d12dabc251 waiting to be mined...'

Cela illustre bien qu'Ethereum n'est pas encore prêt pour un usage généralisé. C'est une technique expérimentale mais très prometteuse techniquement et très intéressante politiquement.

Quelques lectures supplémentaires :

  • Le Livre Blanc, la meilleure introduction technique à Ethereum.
  • L'article de Gavin Wood, un des concepteurs d'Ethereum, si vous voulez vraiment plonger dans les détails techniques. Aspirine de compétition nécessaire.
  • Un dépôt de tas de contrats tout faits, pour les réutiliser ou bien pour apprendre.
  • Un texte plus politique, pour un vaste public, de Vinay Gupta.
  • Le Wiki de geth contient plein de bonnes informations.

L'article seul

RFC 7622: Extensible Messaging and Presence Protocol (XMPP): Address Format

Date de publication du RFC : Septembre 2015
Auteur(s) du RFC : P. Saint-Andre (&yet)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF xmpp
Première rédaction de cet article le 10 septembre 2015


Ce RFC normalise le format des adresses du protocole de messagerie instantanée XMPP, protocole également connu sous son ancien nom de Jabber. Il remplace l'ancien RFC 6122 avec notamment un changement important sur l'internationalisation de ces adresses, le passage au nouveau système PRECIS (décrit dans le RFC 7564), qui remplace stringprep. Les adresses XMPP peuvent en effet être entièrement en Unicode.

Le protocole XMPP est le standard actuel de messagerie instantanée de l'IETF (il est normalisé dans le RFC 6120). Les utilisateurs sont identifiés par une adresse également connue, pour des raisons historiques, sous le nom de JID (Jabber IDentifier). Ces adresses ont une forme qui ressemble aux adresses de courrier électronique mais elles sont en fait complètement différentes. Ainsi, j'ai personnellement deux adresses XMPP, bortzmeyer@gmail.com (le service de messagerie Google Talk utilise en effet la norme XMPP), qui me sert surtout pour la distraction, et bortzmeyer@dns-oarc.net qui me sert pour le travail (j'utilise aussi le service XMPP de la Quadrature du Net mais plus rarement). Mais rien ne dit qu'un courrier envoyé à ces adresses fonctionnera : adresses XMPP et de courrier vivent dans des mondes différents.

Le format des adresses XMPP était spécifié à l'origine dans le document XEP-0029. Puis il a été normalisé dans la section 3 du RFC 3920. La norme XMPP ayant subi une refonte complète, qui a mené entre autres à un nouveau RFC, le RFC 6120, se posait la question du format d'adresses, dont l'internationalisation, compte tenu de la nouvelle norme IDN, suscitait des débats. Ces débats n'étant pas terminés, la décision a été prise de sortir le format d'adresses du RFC principal, et d'en faire le RFC 6122, jusqu'à ce qu'un consensus apparaisse sur le format « définitif ». Ce format final est celui de notre RFC 7622, qui utilise pour Unicode le cadre PRECIS, normalisé dans le RFC 8264.

Donc, quels sont les points essentiels des adresses XMPP (section 3) ? Une adresse (ou JID) identifie une entité (un humain mais peut-être aussi un programme automatique). Elle comprend trois parties (dont une seule, le domaine, est obligatoire), la partie locale, le domaine et une ressource. Ainsi, dans bortzmeyer@gmail.com/Home, bortzmeyer est la partie locale, gmail.com le domaine et Home la ressource. Le @ et le / servent de séparateurs. Chacune des trois parties peut être composée de caractères Unicode, qui doivent être encodés en UTF-8. La partie locale doit être canonicalisée avec PRECIS et son profil UsernameCaseMapped (voir RFC 8265), le domaine avec les méthodes IDN des RFC 5890 et RFC 5892. Seul le domaine est obligatoire et bot.example.org est donc un JID valide.

Les adresses XMPP (ou JID) sont souvent représentées sous forme d'un IRI, selon le RFC 5122. En gros, un IRI XMPP est un JID préfixé par xmpp:. Mais ces IRI ne sont pas utilisés par le protocole XMPP. Dans les champs to et from des strophes (stanzas) XMPP, on ne trouve que des JID (sans le xmpp: devant). Les IRI ne servent que dans les liens dans les pages Web, comme xmpp:bortzmeyer@gmail.com (attention, ce lien ne marchera pas avec tous les navigateurs).

Le RFC détaille ensuite chaque partie. Le domaine, seule partie obligatoire, est dans la section 3.2. On peut le voir comme une identification du service auquel on se connecte (gmail.com = Google Talk), et la création de comptes et l'authentification se font typiquement en fonction de ce service. En théorie, une adresse IP est acceptable pour cette partie mais, en pratique, c'est toujours un FQDN. Ce nom de domaine peut être un IDN donc instantanée.nœud.example est un nom acceptable pour former un JID. Auquel cas, ce doit être un IDN légal (ce qui veut dire que toute chaîne de caractères Unicode n'est pas forcément un nom légal pour la partie domaine d'un JID). À noter que XMPP n'utilise pas l'encodage en ASCII des IDN (le Punycode).

Et la partie locale, celle avant le @ ? La section 3.3 la couvre. Elle est optionnelle et identifie en général une personne (mais peut aussi indiquer un programme ou bien un salon de conversation à plusieurs). Si elle est en Unicode, elle doit être canonicalisée avec le profil UsernameCaseMapped de PRECIS, profil décrit dans le RFC 8265. Cette partie locale est donc insensible à la casse. Certains caractères normalement autorisés par ce profil sont explicitement interdits en XMPP comme les séparateurs / ou @ mais aussi comme " ou <. (Voir XEP-0106 pour un mécanisme d'échappement permettant de mettre quand même ces caractères.)

Quant à la ressource, troisième partie du JID (après le /), également optionnelle, elle sert à distinguer plusieurs sessions par le même utilisateur (par exemple /Home et /Office). La section 3.4 la décrit en détail. Également en Unicode, elle est canonicalisée par le profil OpaqueString de la classe FreeformClass de PRECIS (RFC 8264, section 4.3). Elle n'a pas de structure officielle. Un / dans une ressource (par exemple example.com/foo/bar) n'implique donc pas une hiérarchie. De même, si on y trouve quelque chose ressemblant à une adresse (par exemple joe@example.net/nic@host), cette ressource nic@host doit être traitée comme un identificateur opaque (et pas être analysée en « nom (at) machine »).

La section 3.5 contient quelques exemples de JID. Si certains sont « ordinaires » (le classique juliet@example.com/foobar, reprenant la tradition XMPP des noms tirés de Roméo et Juliette), d'autres sont plus déroutants à première vue comme juliet@example.com/foo@bar (le domaine est example.com, la ressource foo@bar), foo\20bar@example.com (avec un échappement pour l'espace), π@example.com (partie locale en Unicode), king@example.com/♚ (ressource en Unicode), example.com (juste le nom de domaine)...

Il y a aussi des exemples de JID illégaux, qu'il ne faut pas utiliser, comme "juliet"@example.com (les guillemets), foo bar@example.com (l'espace), henriⅣ@example.com (le caractère Unicode à la fin de la partie locale a un équivalent canonique et n'est donc pas autorisé), ♚@example.com (la partie locale doit obéir aux règles restrictives du RFC 8265, qui n'autorise pas les symboles dans les identificateurs, seulement les lettres et chiffres), juliet@ (domaine absent)...

En parlant d'adresses illégales, qui doit vérifier qu'elles sont légales ? Évidemment, l'émetteur devrait le faire. Mais notre RFC va plus loin en recommandant (section 4) que le récepteur jette les messages XMPP (les strophes, stanzas en anglais) contenant de telles adresses. C'est donc plus strict que le traditionnel principe de robustesse.

Quelles sont les conséquences de sécurité de ces adresses ? Il n'y en a guère mais, bon, il y a toujours des inquiets donc la section 7 examine en détail tous les risques, même très théoriques. Bien sûr, les adresses XMPP héritent des questions de sécurité de PRECIS mais le RFC mentionne surtout les risques de triche sur les adresses. Il y en a de deux sortes, les usurpations et les imitations. Les usurpations (section 7.3.1) sont les cas où un méchant arrive à envoyer un message XMPP en trichant sur l'origine, par exemple si jean@example.net, une fois authentifié auprès de son propre serveur, arrive à transmettre un message prétendant venir de jeanne@jabber.example. Normalement, le protocole XMPP empêche cela, par l'authentification mutuelle des serveurs (sauf attaques un peu sophistiquées, par exemple sur le DNS). Cela dit, cette authentification n'empêche pas un serveur d'annoncer une autre partie locale (jeanne@example.net au lieu jean@example.net).

L'autre risque est celui d'imitation (section 7.3.2). Cette fois, il s'agit d'utiliser des JID légitimes et authentiques mais qui ressemblent à celui de la victime, par exemple fric@paypa1.com au lieu de fric@paypal.com (si vous ne voyez pas la différence, regardez mieux). Cette technique est souvent connue sous le nom de typejacking. Comme le montre l'exemple du RFC ou bien celui cité plus haut, le problème arrive même en se limitant à ASCII. Si vous voulez un joli exemple avec Unicode (mais le résultat dépend de l'environnement avec lequel vous lisez cet article), regardez ᏚᎢᎵᎬᎢᎬᏒ qui ressemble à STPETER mais est écrit en Cherokee. Comme un JID peut contenir à peu près n'importe quel caractère Unicode, il n'y a pas vraiment de prévention technique possible contre ce problème. Il est peu probable que cela ait des conséquences en pratique.

La liste complète des changements par rapport au RFC 6122 figure en annexe A. Rappelons que le RFC 6122 s'appuyait, pour les parties en Unicode, sur des profils Stringprep (RFC 3454) comme Nameprep. Ce Nameprep, décrit dans le RFC 3491, ayant été supprimé à l'occasion de la réforme IDNA bis, le grand changement dans ce nouveau RFC est l'abandon complet de stringprep et l'utilisation de PRECIS pour les identificateurs (comme la partie locale d'un JID) et d'IDN pour le nom de domaine.

Vu les changements entre stringprep et PRECIS, on ne peut pas garantir à 100 % que les JID autrefois valides le seront toujours. Mais, dans la plupart des cas, les anciens JID Unicode resteront légaux et utilisables.


Téléchargez le RFC 7622


L'article seul

RFC 7610: DHCPv6-Shield: Protecting Against Rogue DHCPv6 Servers

Date de publication du RFC : Août 2015
Auteur(s) du RFC : F. Gont (SI6 Networks / UTN-FRH), W. Liu (Huawei Technologies), G. Van de Velde (Alcatel-Lucent)
Réalisé dans le cadre du groupe de travail IETF opsec
Première rédaction de cet article le 7 septembre 2015


Un peu de sécurité IPv6 sur le réseau local : comment protéger les pauvres machines IPv6 contre un méchant serveur DHCP, qui répond à la place du serveur légitime, et plus rapidement que lui ? Pas de surprise, la solution est la même qu'en IPv4 (DHCP snooping) et est détaillée dans ce RFC : le commutateur bloque les réponses DHCP qui viennent d'un port où aucun serveur DHCP n'est censé être présent.

Le mécanisme porte le doux nom de DHCP Shield. DHCP, normalisé dans le RFC 8415, est très proche en IPv6 et en IPv4 et, dans les deux cas, n'offre quasiment aucune sécurité. Sur un réseau sans serveur DHCP officiel, une machine peut prétendre être serveur DHCP et tout le monde va la croire et accepter ses annonces. C'est une des plaies des réseaux locaux, d'autant plus qu'authentifier le serveur DHCP est très difficile puisqu'on utilise justement DHCP pour ne rien avoir à configurer sur les machines clientes. Sur un réseau avec serveur DHCP légitime, un faux serveur peut parfois se faire écouter, par exemple s'il répond plus vite. Et, même quand il n'y a qu'un seul serveur DHCP, rien ne garantit que les machines utiliseront uniquement les adresses IP qui leur ont été allouées officiellement.

Pour DHCP Shield, le mode de fonctionnement normal est que l'administrateur réseaux configure le commutateur en lui disant sur quels ports du commutateur se trouve le serveur DHCP légitime. Le commutateur examine alors tous les messages et rejette les réponses DHCP qui viendraient d'un autre port. Le problème d'un serveur DHCP pirate est très proche de celui d'un routeur IPv6 pirate qui envoie des Router Advertisement (RFC 4861, section 4.2) trompeurs et la solution est donc très proche (pour les RAcailles, les RA illégitimes, le problème était exposé dans le RFC 6104 et la solution, RA Guard, dans les RFC 6105 et RFC 7113).

Voilà pour le principe, les détails maintenant. Un commutateur ordinaire ne protège pas contre les serveurs DHCP pirates. Il faut un DHCPv6 Shield Device (section 3 du RFC), commutateur « intelligent » capable de mettre en œuvre la technique décrite dans ce RFC. Demandez à votre vendeur avant d'acheter, s'il y a bien les fonctions de DHCP Shield.

Il faut ensuite le configurer explicitement (le commutateur pourrait apprendre seul, en regardant les réponses mais c'est risqué : si le serveur pirate est déjà en service au moment où le commutateur démarre, ce dernier pourrait prendre le pirate pour le serveur légitime). Cette configuration est faite par l'administrateur réseaux, qui désigne le ou les ports du commutateur qui peuvent légitimement voir arriver des réponses DHCPv6, car un serveur légitime se trouve derrière (section 4 du RFC).

Dit comme cela, ça a l'air simple. Mais, dans les réseaux réels, plein de complications peuvent survenir et la section 5 du RFC, sur les problèmes possibles, est beaucoup plus longue que la section 4 qui décrit l'algorithme. Premier gag possible, les en-têtes d'extension IPv6 qui sont très difficiles à analyser. Notre RFC impose donc aux mises en œuvre de DHCP shield d'analyser tout le paquet, de ne pas se limiter arbitrairement aux N premiers octets, car la liste des en-têtes peut être longue. (La section 6 note que cela peut être difficile sur le fast path - mis en oeuvre dans le matériel - des commutateurs et suggère de jeter le paquet si on ne peut pas l'analyser complètement, mais avec une liste de protocoles de transport qui soit configurable, pour éviter de bloquer les nouveaux protocoles apparus après la vente du commutateur.)

Pour aider un peu les pauvres commutateurs, le RFC 7112 impose que, dans un paquet fragmenté, la totalité des en-têtes soit dans le premier fragment (autrement, un serveur DHCPv6 pirate pourrait « tricher » en « cachant » la réponse IPv6 dans le deuxième fragment et en espérant qu'il ne soit pas analysé). Le commutateur doit donc jeter les paquets fragmentés dont le premier fragment ne contient pas toute la chaîne des en-têtes. (Interdire que les réponses DHCP soient fragmentées aurait été encore plus efficace mais pouvait être gênant dans certains cas, où il y a un besoin légitime d'envoyer de grandes réponses.) Cette politique peut sembler violente mais, de toute façon, un paquet fragmenté n'incluant pas la totalité des en-têtes n'a déjà quasiment aucune chance de passer les pare-feux actuels.

Il faut aussi prêter attenion aux fragments qui se recouvrent (RFC 5722). Ils peuvent permettre d'échapper à la détection par le commutateur.

Plus contestable, la décision en cas d'en-têtes dont le champ Next Header est inconnu. Malheureusement, en IPv6, il n'y a pas de moyen garanti de sauter par dessus un tel en-tête (c'est un peu mieux depuis le RFC 6564). Notre RFC 7610 prend donc une décision radicale : par défaut, les paquets IPv6 ayant un tel en-tête doivent être jetés sans merci. Une option du commutateur doit permettre, si l'administrateur le demande, de les accepter (cf. RFC 7045 pour un point de vue plus général sur la question).

Si le paquet est protégé par IPsec/ESP, le commutateur ne peut évidemment pas savoir si c'est du DHCP ou pas, le but d'ESP (RFC 4303) étant bien d'empêcher les intermédiaires d'être indiscrets. Dans ces conditions, le commutateur doit transmettre le paquet. Les machines clientes qui acceptent des réponses DHCP sur IPsec (ça doit être très rare !) doivent donc les authentifier elles-mêmes, ce qui est dans la logique d'IPsec.

Une fois ces précautions prises, le DHCPv6 Shield Device peut déterminer si le paquet est une réponses DHCPv6 et, si oui, et si elle ne vient pas par le bon port, la jeter, protégeant ainsi les clients DHCP innocents.

La section 6 résume certains problèmes de sécurité du DHCP Shield. Elle rappelle que celui-ci ne protège pas contre les attaques non-DHCP (évidemment) ni même contre certaines attaques DHCP (comme les dénis de service).

Elle rappelle également que DHCP Shield devrait être présent sur tous les commutateurs du réseau : autrement, un attaquant relié à un commutateur bête, qui ne filtre pas, verra ses paquets acceptés s'il y a au moins un serveur légitime sur ce commutateur (puisqu'il aura fallu, en aval, autoriser le port où est relié ce commutateur.)

Notez que notre RFC ne propose pas de solution à l'usurpation d'adresses IP (une machine utilisant une adresse qui ne lui a pas été allouée en DHCP, cas mentionné au début de mon article) mais que ces solutions sont dans le RFC 7513.

À l'heure actuelle, au moins certains commutateurs Cisco ont cette fonction de DHCP Shield.


Téléchargez le RFC 7610


L'article seul

RFC 7601: Message Header Field for Indicating Message Authentication Status

Date de publication du RFC : Août 2015
Auteur(s) du RFC : M. Kucherawy
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF appsawg
Première rédaction de cet article le 5 septembre 2015


Il existe désormais plusieurs techniques pour authentifier les courriers électroniques. Certaines peuvent nécessiter des calculs un peu compliqués et on voudrait souvent les centraliser sur une machine de puissance raisonnable, dotée de tous les logiciels nécessaires. Dans cette hypothèse, le MUA ne recevra qu'une synthèse (« Ce message vient bien de example.com ») et pourra alors prendre une décision, basée sur cette synthèse. C'est le but de l'en-tête Authentication-Results:, normalisé originellement dans le RFC 5451 six ans plus tôt, auquel a succédé le RFC 7001, que ce nouveau RFC met légèrement à jour (il y a peu de changements, le principal étant la correction de l'erreur #4201). Depuis, notre RFC a lui-même été remplacé par le RFC 8601.

Avec des techniques d'authentification comme DKIM (RFC 6376) ou SPF (RFC 7208), les calculs à faire pour déterminer si un message est authentique peuvent être complexes (DKIM utilise la cryptographie) et nécessiter la présence de bibliothèques non-standard. Les installer et les maintenir à jour sur chaque machine, surtout en présence d'éventuelles failles de sécurité qu'il faudra boucher en urgence, peut être trop pénible pour l'administrateur système. L'idée de ce RFC est donc de séparer l'opération en deux : l'authentification est faite sur un serveur, typiquement le premier MTA du site (cf. annexe C pour une discussion de ce choix), celui-ci ajoute au message un en-tête indiquant le résultat de ladite authentification et le MUA (ou bien le MDA, voir la section 1.5.3 pour un bon rappel sur ces concepts) peut ensuite, par exemple par un langage de filtrage comme procmail ou Sieve, agir sur la base de ce résultat. L'idée n'est donc pas de montrer la valeur de cet en-tête à M. Michu (voir la section 4.1 pour quelques risques que cela poserait), mais d'en faire une donnée pour un programme. Cet en-tête marche pour tous les protocoles d'authentification et surpasse donc les en-têtes spécifiques comme le Received-SPF: de SPF (section 1 du RFC). Le filtrage des messages non authentifiés n'est pas obligatoire (section 1.4) : agir - ou pas - sur la base de l'en-tête Authentication-Results: est une décision politique locale.

J'ai utilisé le terme de « site » pour désigner un ensemble de machines gérées par la même organisation mais le RFC a un terme plus rigoureux, ADMD (ADministrative Management Domain). La frontière d'un ADMD est la « frontière de confiance » (trust boundary), définie en section 1.2. Un domaine administratif de gestion est un groupe de machines entre lesquelles il existe une relation de confiance, notamment du fait que, à l'intérieur de l'ADMD, l'en-tête Authentication-Results: ne sera pas modifié ou ajouté à tort (section 1.6 : l'en-tête n'est pas protégé, notamment il n'est pas signé). Il existe de nombreuses variantes organisationnelles du concept d'ADMD. Un ADMD inclus typiquement une organisation (ou un département de celle-ci) et d'éventuels sous-traitants. Il a un nom, l'authserv-id, défini en section 2.2.

L'en-tête Authentication-Results: lui-même est formellement défini en section 2. Il appartient à la catégorie des en-têtes de « trace » (RFC 5322, section 3.6.7 et RFC 5321, section 4.4) comme Received: qui doivent être ajoutés en haut des en-têtes et jamais modifiés. La syntaxe de Authentication-Results: est en section 2.2. L'en-tête est composé du authserv-id, le nom de l'ADMD et d'une série de doublets (méthode, résultat), chacun indiquant une méthode d'authentification et le résultat obtenu. L'annexe B fournit une série d'exemples. Elle commence (annexe B.1) par un message sans Authentication-Results: (eh oui, il n'est pas obligatoire). Puis (tiré de l'annexe B.3), une authentification SPF réussie, au sein de l'ADMD example.com, donnera :

        Authentication-Results: example.com;
                  spf=pass smtp.mailfrom=example.net
        Received: from dialup-1-2-3-4.example.net
                      (dialup-1-2-3-4.example.net [192.0.2.200])
                  by mail-router.example.com (8.11.6/8.11.6)
                      with ESMTP id g1G0r1kA003489;
                  Wed, Mar 14 2009 17:19:07 -0800
        From: sender@example.net
        Date: Wed, Mar 14 2009 16:54:30 -0800
        To: receiver@example.com

Rappelez-vous qu'il peut y avoir plusieurs authentifications. Voici un cas (annexe B.4) avec SPF et l'authentification SMTP du RFC 4954 :

       Authentication-Results: example.com;
                  auth=pass (cram-md5) smtp.auth=sender@example.net;
                  spf=pass smtp.mailfrom=example.net
        Received: from dialup-1-2-3-4.example.net (8.11.6/8.11.6)
                      (dialup-1-2-3-4.example.net [192.0.2.200])
                  by mail-router.example.com (8.11.6/8.11.6)
                      with ESMTP id g1G0r1kA003489;
                  Fri, Feb 15 2002 17:19:07 -0800
        Date: Fri, Feb 15 2002 16:54:30 -0800
        To: receiver@example.com
        From: sender@example.net

L'une des authentifications peut réussir et l'autre échouer. Un exemple (annexe B.6) avec deux signatures DKIM, une bonne et une qui était correcte au départ (regardez le premier Authentication-Results:) mais plus à l'arrivée, peut-être parce qu'un gestionnaire de liste de diffusion a modifié le message :

       Authentication-Results: example.com;
              dkim=pass reason="good signature"
                header.i=@mail-router.example.net;
              dkim=fail reason="bad signature"
                header.i=@newyork.example.com
        Received: from mail-router.example.net
                  (mail-router.example.net [192.0.2.250])
              by chicago.example.com (8.11.6/8.11.6)
                  for <recipient@chicago.example.com>
                  with ESMTP id i7PK0sH7021929;
              Fri, Feb 15 2002 17:19:22 -0800
        DKIM-Signature: v=1; a=rsa-sha256; s=furble;
              d=mail-router.example.net; t=1188964198; c=relaxed/simple;
              h=From:Date:To:Message-Id:Subject:Authentication-Results;
              bh=ftA9J6GtX8OpwUECzHnCkRzKw1uk6FNiLfJl5Nmv49E=;
              b=oINEO8hgn/gnunsg ... 9n9ODSNFSDij3=
        Authentication-Results: example.net;
              dkim=pass (good signature) header.i=@newyork.example.com
        Received: from smtp.newyork.example.com
                  (smtp.newyork.example.com [192.0.2.220])
              by mail-router.example.net (8.11.6/8.11.6)
                  with ESMTP id g1G0r1kA003489;
              Fri, Feb 15 2002 17:19:07 -0800
        DKIM-Signature: v=1; a=rsa-sha256; s=gatsby;
              d=newyork.example.com;
              t=1188964191; c=simple/simple;
              h=From:Date:To:Message-Id:Subject;
              bh=sEu28nfs9fuZGD/pSr7ANysbY3jtdaQ3Xv9xPQtS0m7=;
              b=EToRSuvUfQVP3Bkz ... rTB0t0gYnBVCM=
        From: sender@newyork.example.com
        Date: Fri, Feb 15 2002 16:54:30 -0800
        To: meetings@example.net

La liste complète des méthodes figure dans un registre IANA (section 6). De nouvelles méthodes peuvent être enregistrées en utilisant la procédure « Examen par un expert » du RFC 5226.

La section 2.3 détaille l'authserv-id. C'est un texte qui identifie le domaine, l'ADMD. Il doit donc être unique dans tout l'Internet. En général, c'est un nom de domaine comme laposte.net. (Il est possible d'être plus spécifique et d'indiquer le nom d'une machine particulière mais cette même section du RFC explique pourquoi c'est en général une mauvaise idée : comme les MUA du domaine n'agissent que sur les Authentication-Results: dont ils reconnaissent l'authserv-id, avoir un tel identificateur qui soit lié au nom d'une machine, et qui change donc trop souvent, complique l'administration système.)

La section 2.7 explique les résultats possibles pour les méthodes d'authentification (en rappelant que la liste à jour des méthodes et des résultats est dans le registre IANA). Ainsi, DKIM (section 2.7.1) permet des résultats comme pass (authentification réussie) ou temperror (erreur temporaire au cours de l'authentification, par exemple liée au DNS). Des résultats similaires sont possibles pour SPF (section 2.7.3).

Notons la normalisation d'une méthode traditionnelle d'authentification faible, le test DNS du chemin « adresse IP du serveur -> nom » et retour. Baptisée iprev, cette méthode, bien que bâtie sur la pure superstition (cf. section 7.11) est utilisée couramment. Très injuste (car les arbres des résolutions inverses du DNS, in-addr.arpa et ip6.arpa, ne sont pas sous le contrôle du domaine qui envoie le courrier), cette méthode discrimine les petits FAI, ce qui est sans doute un avantage pour les gros, comme AOL qui l'utilisent. Attention aux implémenteurs : aussi bien la résolution inverse d'adresse IP en nom que la résolution droite de nom en adresse IP peuvent renvoyer plusieurs résultats et il faut donc comparer des ensembles. (Cette méthode qui, contrairement aux autres, n'avait jamais été exposée dans un RFC avant le RFC 5451, est décrite en détail dans la section 3, avec ses sérieuses limites.)

Autre méthode mentionnée, auth (section 2.7.4) qui repose sur l'authentification SMTP du RFC 4954. Si un MTA (ou plutôt MSA) a authentifié un utilisateur, il peut le noter ici.

Une fois le code d'authentification exécuté, où mettre le Authentication-Results: ? La section 4 fournit tous les détails, indiquant notamment que le MTA doit placer l'en-tête en haut du message, ce qui facilite le repérage des Authentication-Results: à qui on peut faire confiance (en examinant les en-têtes Received: ; en l'absence de signature, un Authentication-Results: très ancien, situé au début du trajet, donc en bas des en-têtes, ne signifie pas grand'chose). On se fie a priori aux en-têtes mis par les MTA de l'ADMD, du domaine de confiance. L'ordre est donc important. (La section 7 revient en détail sur les en-têtes Authentication-Results: usurpés.)

Ce n'est pas tout de mettre un Authentication-Results:, encore faut-il l'utiliser. La section 4.1 s'attaque à ce problème. Principe essentiel pour le MUA : ne pas agir sur la base d'un Authentication-Results:, même si ce n'est que pour l'afficher, sans l'avoir validé un minimum. Comme le Authentication-Results: n'est pas signé, n'importe qui a pu en insérer un sur le trajet. Le RFC précise donc que les MUA doivent, par défaut, ne rien faire. Et qu'ils doivent ne regarder les Authentication-Results: qu'après que cela ait été activé par l'administrateur de la machine, qui indiquera quel authserv-id est acceptable.

Naturellement, le MTA d'entrée du domaine devrait supprimer les Authentication-Results: portant son propre authserv-id qu'il trouve dans les messages entrants : ils sont forcément frauduleux (section 5). (Le RFC accepte aussi une solution plus simpliste, qui est de supprimer tous les Authentication-Results: des messages entrants, quel que soit leur authserv-id.)

Arrivé à ce stade de cet article, le lecteur doit normalement se poser bien des questions sur la valeur du Authentication-Results:. Quel poids lui accorder alors que n'importe quel méchant sur le trajet a pu ajouter des Authentication-Results: bidons ? La section 7, consacrée à l'analyse générale de la sécurité, répond à ces inquiétudes. 7.1 détaille le cas des en-têtes usurpés. Les principales lignes de défense ici sont le fait que le MUA ne doit faire confiance aux Authentication-Results: que s'ils portent le authserv-id de son ADMD et le fait que le MTA entrant doit filtrer les Authentication-Results: avec son authserv-id. Comme l'intérieur de l'ADMD, par définition, est sûr, cela garantit en théorie contre les Authentication-Results: usurpés. Le RFC liste néanmoins d'autres méthodes possibles comme le fait de ne faire confiance qu'au premier Authentication-Results: (le plus récent), si on sait que le MTA en ajoute systématiquement un (les éventuels Authentication-Results: usurpés apparaîtront après ; mais certains serveurs les réordonnent, cf. section 7.3). Pour l'instant, il n'y a pas de méthode unique et universelle de vérification du Authentication-Results:, le RFC propose des pistes mais ne tranche pas.

Comme toujours en sécurité, il faut bien faire la différence entre authentification et autorisation. Un spammeur a pu insérer un Authentication-Results: légitime pour son authserv-id. Même authentifié, il ne doit pas être considéré comme une autorisation (section 7.2).

Plusieurs mises en œuvre de ce système existent déjà comme dans MDaemon, sendmail (via sid-milter), Courier, OpenDKIM, etc. Si on veut analyser les en-têtes Authentication-Results: en Python, on a le module authres. Parmi les grosses usines à courrier centralisées, Gmail met systématiquement cet en-tête, par exemple :

Authentication-Results: mx.google.com; spf=pass \
           (google.com: domain of stephane@sources.org designates 217.70.190.232 \
               as permitted sender) smtp.mail=stephane@sources.org

Outre Gmail, à la date de publication du RFC, Yahoo et Hotmail ajoutaient cet en-tête.

Les changements depuis le RFC 7001 sont peu nombreux (annexe D pour une liste complète). Le RFC 7410, qui créait le registre des types d'information possibles sur l'authentification a été intégré et est donc remplacé par notre nouveau RFC. Autrement, l'un des principaux changements concerne la bogue #4201. Le texte du précédent RFC disait que la source de l'authentification devait être un en-tête du message alors que cela peut être un champ particulier d'un en-tête (le cas du champ i dans les signatures DKIM d'exemple dans cet article, cf. 2.3 et 2.7.1). Autrement, les changements par rapport au RFC 7001 sont surtout des détails et les mises en œuvre actuelles devraient continuer sans trop d'histoires. Je rappelle que ce RFC 7601 n'est plus d'actualité, ayant été remplacé par le RFC 8601.


Téléchargez le RFC 7601


L'article seul

RFC 7620: Scenarios with Host Identification Complications

Date de publication du RFC : Août 2015
Auteur(s) du RFC : M. Boucadair, D. Binet, S. Durel, B. Chatras (France Telecom), T. Reddy (Cisco), B. Williams (Akamai), B. Sarikaya, L. Xue (Huawei), R. Wheeldon
Pour information
Première rédaction de cet article le 4 septembre 2015


Un problème intéressant de l'Internet d'aujourd'hui est l'identification d'une machine (Host Identification, ou Host-ID, en anglais). Il s'agit de détecter si une machine A avec qui on communique est la même que la machine B avec qui on échange également. (Rappel : identification n'est pas authentification.) Évidemment, l'adresse IP ne convient plus depuis longtemps : les techniques de partage d'adresses IP, comme le CGN, sont trop répandues. Comment faire, alors ? Ce nouveau RFC ne propose pas de solutions mais il fait le tour d'horizon de ce problème complexe, plus complexe qu'on pouvait croire en lisant les solutions qui avaient été proposées par le RFC 6967.

En effet, TCP/IP n'a pas de notion d'identité d'une machine. Au début, les adresses IP, stables et uniques, pouvaient remplir tant bien que mal ce rôle. Mais c'est fini depuis longtemps, surtout en IPv4. (IPv6 n'est pas forcément la solution : je connais des sites qui font du NAT IPv6 en sortie. Voir la section 3 de notre RFC.) Le RFC 6269 décrit en détail ce partage d'adresses IP et ses conséquences (en général néfastes pour l'identification). Notez que NAT et CGN ne sont pas les seules techniques qui amènent à un tel partage (par exemple, un relais applicatif a les mêmes conséquences : plusieurs machines derrière une seule adresse IP, cf. section 5 du RFC.). Et, en plus du partage d'adresses, les tunnels compliquent également les choses, puisqu'une machine aura une adresse très éloignée de son point d'attachement physique.

Outre les points mentionnés dans le RFC 6269, l'absence d'identification facile rend difficile :

  • D'appliquer une politique spécifique à chaque machine (comme une limitation de trafic),
  • De retrouver une machine interne quand on ne connait que l'adresse vue à l'extérieur,
  • D'appeler un serveur de localisation, qui donne la position physique d'une machine, ce qui serait bien utile pour les appels d'urgence en VoIP (section 9 de notre RFC, et RFC 6443).

Évidemment, le partage d'adresses a aussi des avantages, comme une certaine dissimulation, utile pour la protection de la vie privée (cf. section 12 du RFC). Les solutions d'identification d'une machine peuvent potentiellement annuler certains efforts de protection de la vie privée. Le RFC qui proposait des solutions, le RFC 6967 avait un principe: ne pas transmettre davantage d'informations que celles qui étaient dans le paquet IP original émis par la machine. Notre nouveau RFC se demande (section 2) si ce principe n'est pas trop strict.

La suite du RFC est constituée d'études de cas pour différents environnements. Par exemple, la section 3 étudie le classique CGN (RFC 6888). Certains cas seront résolus par IPv6 (par exemple le NAT IPv4 courant aujourd'hui) mais d'autres vont rester comme la traduction d'adresses IPv6 mentionnée plus haut (RFC 6296). La section 5 regarde les relais applicatifs : comme le CGN, ils « cachent » plusieurs machines derrière une même adresse IP. Comme pour le CGN, cela empêche certains usages comme une identification de l'abonné individuel, ou comme l'attribution d'une attaque, par exemple un commentaire menaçant sur un forum. On peut noter que des solutions spécifiques à tel ou tel protocole applicatif ont été développées et que, si le relais les utilise, le problème disparait. C'est le cas de l'en-tête Received: de SMTP (RFC 5321, sections 3.7.2 et 4.4), largement déployé. Dans le monde HTTP, il y a l'en-tête Forwarded:, du RFC 7239, moins fréquemment rencontré. Ces solutions sont souvent discutées dans le contexte de la protection de la vie privée car leur caractère indiscret est assez évident.

Autre étude de cas, en section 7, les overlays. Ils ont beaucoup d'usages comme par exemple dans certaines architectures pair à pair (RFC 5694). Les manipulations qu'ils utilisent peuvent également aboutir à masquer les adresses IP d'origine. Le RFC contient également des études de cas sur d'autres architectures, le tout étant synthétisé dans la section 11 sous forme d'un joli tableau qui indique notamment, pour chaque architecture, si les problèmes qu'elle pose à l'identification d'une machine disparaitront ou pas avec IPv6.

Terminons en revenant sur la question de la protection de la vie privée car, évidemment, les mécanismes d'identification de la machine visent à envoyer des informations, là où la vie privée exigerait qu'on en envoie le moins possible. La section 12 du RFC expose le problème et renvoie à la section 3 du RFC 6967. Elle note aussi qu'il existe des « solutions » non-standard à la question de l'identification et que ces solutions sont souvent discutables en termes de vie privée (par exemple les en-têtes HTTP non-standards HTTP_MSISDN, HTTP_X_MSISDN, HTTP_X_UP_CALLING_LINE_ID, HTTP_X_NOKIA_MSISDN..) L'IESG a en outre ajouté une note au RFC, rappelant que, si on considère en effet les « problèmes » cités par ce RFC 7620 comme des problèmes à résoudre, les solutions ont de fortes chances de piétiner d'autres RFC et d'être contradictoires avec les principes de confidentialité des RFC 6280 et RFC 7258. Bref, identifier les machines ou protéger la vie privée des utilisateurs, il faudra sans doute choisir.


Téléchargez le RFC 7620


L'article seul

RFC 7603: Energy Management (EMAN) Applicability Statement

Date de publication du RFC : Août 2015
Auteur(s) du RFC : Brad Schoening (Independent Consultant), Mouli Chandramouli (Cisco Systems), Bruce Nordman (Lawrence Berkeley National Laboratory)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF eman
Première rédaction de cet article le 4 septembre 2015


Le but du projet EMAN (Energy MANagement) à l'IETF est de développer un ensemble de normes techniques sur la gestion de l'énergie par les équipements informatiques en réseau. Ce RFC explique le projet et décrit des scénarios d'utilisation. C'est un pas de plus (très modeste encore) vers un Internet plus « vert ».

Le cadre général pour la gestion de l'énergie des équipements Internet figure dans le RFC 7326 (et le cahier des charges dans le RFC 6988). L'idée est de d'abord de pouvoir superviser à distance tout engin connecté à l'Internet, et de connaitre par ce moyen sa consommation d'énergie (le préalable à toute action). Puis, le cadre EMAN (défini par le groupe de travail du même nom) doit permettre l'action sur ces engins, par exemple ralentir le processeur pour diminuer la consommation, ou carrément arrêter certaines machines pour économiser l'énergie. Il existe bien sûr déjà des méthodes pour cela mais elles ne sont pas encore normalisées ou bien utilisent des protocoles pré-Internet. EMAN doit permettre la supervision et l'action sur des engins très différents, et ne sortant pas de chez le même fournisseur. Le but n'est pas seulement d'économiser l'argent (l'électricité coûte cher) mais aussi de tenir compte de la finitude des ressources de la planète (c'est, à ma connaissance, la première fois que ce point est mentionné dans un RFC : bien des acteurs de l'Internet vivaient jusqu'à présent dans l'illusion qu'on trouverait toujours « une autre ressource énergétique »).

Bref, deux tâches pour EMAN, la supervision (mesurer la consommation) et l'action (éteindre si nécessaire). Pour permettre cette supervision et cette action, EMAN (RFC 7326) a défini un modèle de données, et utilisera le protocole SNMP, et des MIB dont certaines sont déjà développées (voir par exemple les RFC 7460 sur la MIB générale, RFC 7461 et le RFC 7577 sur la MIB de gestion des batteries). EMAN n'est donc pas une nouvelle pile protocolaire complète (cf. section 5), il s'appuie sur TCP/IP et sur les protocoles de gestion de réseaux standard (cf. RFC 6632).

Et les scénarios d'usage promis ? Ils figurent en section 2 de notre RFC. Je ne vais pas tous les reprendre ici mais certains sont rigolos. On trouve des routeurs dont on veut mesurer la consommation, des commutateurs qui sont eux-même distributeurs d'énergie (PSE Power Sourcing Equipment, par exemple via PoE, cf. RFC 3621), etc. Dans ce dernier cas, celui où des machines sont alimentées via un équipement réseau, il y a deux sous-cas : soit la machine est elle-même capable de faire du EMAN, donc d'informer sur sa consommation électrique elle-même (elle est un « Energy Object »), soit elle ne l'est pas et le PSE va alors devoir le faire pour elle. Et si la machine tire du courant d'une prise au mur ? Là encore, deux sous-cas, l'alimentation électrique peut être un PDU (Power Distribution Unit) « intelligent », capable de transmettre les informations lui-même, soit ce n'est pas le cas et il faudra alors que la machine alimentée soit capable de transmettre les informations à la gestion de réseau (un PC n'aura pas de mal, un objet plus simple si). Voir aussi la section 2.5 sur cette notion d'intermédiaire de mesure, le Mid-level Manager.

Il y a déjà partout des compteurs électriques, soit intégrés aux PDU, soit autonomes, et qui mesurent la consommation. Un des enjeux d'EMAN est de les rendre interrogeables à distance (section 2.4).

Prenons maintenant le cas d'un immeuble de bureaux ou d'une usine, doté d'une grosse alimentation électrique, gérée par des professionnels. De tels systèmes (BMS, Building Management System) sont évidemment gérés centralement depuis longtemps, bien avant EMAN, mais en général par des mécanismes non-standards. La liaison physique avec les équipements se fait souvent en RS-232 ou RS-485, les protocoles sont BACnet, Modbus ou ZigBee.

Plus modeste, la supervision de la consommation électrique à la maison. On peut vouloir savoir combien son frigo consomme (le fameux frigo connecté, de préférence en IPv6, un grand classique du discours marketing sur l'Internet des Objets). Beaucoup des équipements à superviser seront sans doute bon marché, et n'ayant donc pas toutes les capacités EMAN, et devront donc être interrogés via un relais (le mid-level manager dont j'ai parlé plus haut).

Au contraire, dans un centre de données, on a à la fois un enjeu bien plus important (la facture d'électricité de ces centres est énorme) et davantage de moyens (plein de machines connectés qui ne demandent pas mieux que d'être gérées à distance depuis un gestionnaire central). On veut en général une granularité de mesure très fine (pas juste « ce que consomme cette armoire » mais « ce que consomme ce serveur ») donc on va gérer d'importantes quantités de données.

Il ne faut pas oublier les équipements de stockage de l'énergie eux-mêmes, de la batterie traditionnelle à la pile à hydrogène. Ces équipements sont souvent distants (une batterie dans une tour de télécommunications ou en haut d'un château d'eau).

Et pour terminer cette liste très variée, n'oublions pas les humbles imprimantes. En raison de leur consommation électrique élevée, les imprimantes ont souvent des dispositifs d'économie d'énergie (mode « veille »). La consommation varie donc énormément (pensez au chauffage des éléments thermo-mécaniques comme le cylindre lorsque l'imprimante démarre) et des interrogations périodiques risquent donc de rater les moments de haute consommation. Les imprimantes haut de gamme connaissent déjà la gestion à distance et ont souvent SNMP.

Je l'ai indiqué plus haut, EMAN n'arrive pas dans un vide complet. Il y a de nombreuses années que la consommation électrique des équipements informatiques est mesurée et que les machines sont éteintes à distance pour économiser des joules. La section 4 de notre RFC couvre les normes et spécifications techniques existantes (je ne les reprends pas toutes ici, il y en a beaucoup). Ainsi, la CEI a toute une série de normes sur la gestion de l'électricité, avec notamment un modèle décrit dans IEC 61850. C'est un modèle qui embrasse largement, avec une centaine de classes. La norme IEC 62053 est également importante et ces normes ont déjà été utilisées dans EMAN. Proche de IEC 62053, l'ANSI a sa norme C12 sur les compteurs électriques. DMTF a aussi son modèle, DMTF DSP1027.

Il existe aussi des normes plus spécifiques, par exemple le PWG a des normes pour les imprimantes. À noter que la MIB « imprimante », dans le RFC 3805, ne couvre pas la gestion d'énergie. Il y a onze ans, c'était jugé moins important et peu de travail avait été fait en ce sens à l'IETF.

Parmi les autres spécifications existantes, on peut aussi citer ZigBee, élaboré par une organisation privée et pas une SDO ouverte.

Et, bien sûr, il y a Smart grid (section 4.3.3), le projet coordonné par le NIST. Smart grid est plus vaste qu'EMAN (il inclut la distribution de l'énergie) mais moins normatif car c'est plus un projet de coordination que de normalisation.

Un projet important car souvent vu par le consommateur final est Energy Star, lancé par le gouvernement états-unien. Il ne s'agit pas d'une norme technique ou d'un protocole de communication mais d'un ensemble de bonnes pratiques que devraient suivre les équipements électriques, notamment en terme d'efficacité énergétique. Aujourd'hui, EMAN et EnergyStar sont deux efforts séparés mais, dans le futur, EnergyStar pourrait référencer EMAN pour inciter les fabricants à doter leurs systèmes de capacité de mesure.

La section 5 de notre RFC rappelle quelques limites volontaires d'EMAN : EMAN ne cherche pas à résoudre tous les problèmes de l'électricité. Par exemple, EMAN ne couvre pas la production et le transport de l'électricité, seulement sa consommation chez les utilisateurs finaux.

Enfin, pour terminer ce RFC, n'oublions évidemment pas la sécurité, avec la section 6, qui rappelle notamment que la mesure de la consommation électrique peut poser de sérieux problèmes de protection de la vie privée. (On pourra déterminer à distance vos habitudes à la maison, par exemple. La NSA saura quand vous avez des insomnies et allumez la lumière en pleine nuit.) Le RFC 7460, dans sa section 10, détaille ce risque.


Téléchargez le RFC 7603


L'article seul

RFC 7624: Confidentiality in the Face of Pervasive Surveillance: A Threat Model and Problem Statement

Date de publication du RFC : Août 2015
Auteur(s) du RFC : R. Barnes, B. Schneier, C. Jennings, T. Hardie, B. Trammell, C. Huitema, D. Borkmann
Pour information
Première rédaction de cet article le 3 septembre 2015


La publication, grâce à Edward Snowden, d'affreux PowerPoint® de la NSA montrant l'ampleur de la surveillance permanente et généralisée a suscité une prise de conscience chez tous les acteurs de l'Internet. (D'autant plus que d'autres pays en font autant, comme la France, surtout depuis la Loi Renseignement.) Ces PowerPoint® sont souvent d'interprétation difficile et il est donc nécessaire, lorsqu'on travaille aux contre-mesures, d'avoir un modèle clair de la menace contre laquelle on tente de défendre les citoyens internautes. Ce nouveau RFC est l'une des étapes dans ce travail à l'IETF : décrire clairement les risques de la surveillance généralisée.

Ce RFC est écrit par l'IAB, et on note parmi les auteurs Bruce Schneier. Il ne s'agit pas de revenir sur le problème bien connu de l'espionnage des communications (qui est aussi ancien que les réseaux), mais sur les nouveautés qui résultent de la prise de conscience d'un espionnage illimité et indiscriminé (cf. RFC 7258 pour la décision politique de considérer cet espionnage comme une attaque contre l'Internet). Les programmes de la NSA, avec leurs noms rigolos, n'utilisent pas de vulnérabilités inconnues. Aucune science-fiction derrière PRISM, TEMPORA ou BULLRUN. Ces programmes exploitent uniquement des risques connus, mais de manière massive, avec un budget très élevé et une absence totale de scrupules.

Notre nouveau RFC commence donc logiquement par un peu de terminologie (section 2). Il réutilise d'autre part les précédents RFC analogues notamment celui de terminologie de la sécurité (RFC 4949) et celui d'analyse de la protection de la vie privée (RFC 6973). Notons deux choses importantes : d'abord la distinction entre attaques passives et actives. La différence ne vient pas de l'effort de l'attaquant (monter une attaque passive peut être beaucoup de travail) mais du fait que, dans le premier cas, l'attaquant n'écrit rien sur le réseau, n'envoie aucun paquet, ne stoppe aucune communication et ne modifie aucun bit. Il espionne, c'est tout. Au contraire, dans une attaque active comme QUANTUM, le surveillant se permet d'interférer avec les communications, changeant le contenu d'un paquet, envoyant des paquets (pour de l'ARP spoofing par exemple, ou de l'empoisonnement de cache DNS), bloquant certains paquets (par exemple pour faire une attaque par repli contre TLS).

Et la deuxième chose importante est le terme relativement nouveau d'attaque généralisée (pervasive attack), qui désigne les attaques menées, non pas par le lycéen dans son garage, mais par un organisme puissant, pouvant observer (et peut-être intervenir) en de très nombreux points du réseau, avec des capacités big data.

Commençons par décrire l'attaquant, étape indispensable pour élaborer un modèle de menace (section 3). D'abord, un modèle d'un attaquant purement passif (et donc moins puissant que la NSA). S'il est purement passif, cet attaquant « idéal » (idéal du point de vue du modèle, pas du point de vue légal ou moral) a quand même de grandes possibilités, notamment quantitatives. Il voit tout, partout. Le RFC note à juste titre qu'avant les révélations de Snowden (qu'on ne remerciera jamais assez pour ce qu'il a fait), un tel attaquant aurait été considéré comme le produit d'un esprit à la limite de la paranoïa, à part chez les experts en sécurité (qui se doutaient bien, même avant Snowden, de la réalité de la surveillance massive). Cet attaquant peut notamment :

  • Observer tous les paquets, où qu'ils passent,
  • Observer les données stockées dans les différentes machines (comme le permet PRISM),
  • Collaborer avec d'autres attaquants (comme le font les Five Eyes),
  • Mais ne peut pas bloquer, modifier, injecter, il est purement passif.

L'attaquant doit donc se débrouiller avec ce qu'il observe directement, puisqu'il ne peut pas le modifier, et ce qu'il en déduit (inférence, c'est-à-dire dériver des informations de celles qu'on a déjà).

Le chiffrement, même sans authentification, protège largement contre un tel attaquant, en réduisant sérieusement les observations qu'il peut faire. (À condition que ce chiffrement soit bien réalisé, par exemple que les générateurs aléatoires soient de qualité. Cette condition est, en pratique, très difficile à remplir.) Le chiffrement est par contre moins efficace contre l'inférence. Par exemple, les fameuses métadonnées laissées en clair (en-têtes IP et TCP lorsqu'on utilise TLS) peuvent donner plein d'information. Un autre exemple est la taille des paquets (qui permet de savoir si on a envoyé ou reçu un fichier), une information que TLS (ou SSH) ne brouille pas. Même IPsec/ESP, s'il chiffre l'en-tête de couche 4, laisse la couche 3 (IP) en clair.

L'idéal bien sûr pour notre attaquant modèle est quand il n'y a pas de chiffrement. Quand tout est en clair, le contenu des communications est accessible trivialement. Voilà pourquoi le RFC 3365 (en 2002 ! Ça ne nous rajeunit pas.) disait déjà que tout protocole IETF susceptible d'envoyer des données en clair doit avoir une version sécurisée qui chiffre. C'est le cas de presque tous les protocoles aujourd'hui. Le RFC note qu'il y a une exception avec le DNS mais elle est en train d'être comblée par le groupe de travail DPRIVE, (cf. le RFC 7626).

L'inférence peut aussi utiliser des informations qui se trouvent dans des bases de données extérieures à la communication elle-même. Par exemple, comme l'ICANN impose de publier les coordonnées des titulaires des noms de domaine dans les TLD qu'elle contrôle, ces informations peuvent nourrir l'inférence. Même chose avec les bases géoIP ou, encore mieux, avec la quantité d'informations disponibles dans des réseaux sociaux comme Facebook. Ces dernières sources sont très riches, avec de l'information déjà structurée et envoyée « volontairement » par les utilisateurs. Cela met une sérieuse limite à ce que l'IETF peut faire pour améliorer la vie privée sur l'Internet : améliorer les protocoles n'est pas suffisant.

Notre RFC détaille comment inférer à partir des observations directes. Par exemple, pour corréler des adresses IP avec des utilisateurs, on a plusieurs outils : une requête DNS « inverse » (type PTR) suffit parfois. Ces requêtes marchent bien pour les serveurs, peu nombreux et stables (donc une copie locale peut être facilement faite, pour accélerer le processus). Elles sont moins efficaces pour les clients (on obtient parfois des trucs sans trop d'intérêt comme ARouen-655-1-102-140.w90-23.abo.wanadoo.fr). Notez que le RFC étudie les possibilités de surveillance massive. La technique (légale dans de nombreux pays démocratiques) qui consiste pour la police à demander au FAI le nom de l'utilisateur correspond à telle adresse IP ne marche pas ici, elle ne passe pas à l'échelle. C'est un exemple de la différence entre enquêtes ciblées et surveillance généralisée, style Big Brother.

Même si le FAI ne coopère pas dans la mission de surveillance, il existe d'autres moyens de relier une adresse IP à des identités de l'utilisateur. Par exemple, s'il utilise IMAP, on a facilement son identificateur, sauf si la session est chiffrée (ce qui n'est pas encore fait partout). Le problème n'est pas spécifique à IMAP et se trouve aussi dans SIP et dans bien d'autres protocoles. Chiffrer la session n'est donc pas uniquement utile lorsqu'on a « quelque chose à cacher » mais aussi simplement lorsqu'on veut éviter d'être suivi à la trace. Un autre exemple amusant est décrit en section 3.3.4 : l'utilisation des en-têtes Received: du courrier. Même si tout le courrier est chiffré, l'attaquant peut toujours s'abonner à des listes de discussion publiques comme perpass. Il reçoit alors des messages avec ce genre d'en-têtes :

Received: from 192-000-002-044.zone13.example.org (HELO ?192.168.1.100?) (xxx.xxx.xxx.xxx) by lvps192-000-002-219.example.net
   with ESMTPSA (DHE-RSA-AES256-SHA encrypted, authenticated); 27 Oct 2013 21:47:14 +0100
Message-ID: <526D7BD2.7070908@example.org>
Date: Sun, 27 Oct 2013 20:47:14 +0000
From: Some One <some.one@example.org>
    

Collectionner ces en-têtes va lui permettre de compiler une base des émetteurs et des adresses IP qu'ils utilisent. Au bout d'un moment, l'attaquant saura que, si un paquet IP vient de 192.0.2.44, il y a de fortes chances que ce soit l'utilisateur Some One.

Parmi les techniques d'inférence, il y a aussi celles fondées sur les graphes de relations. Si une adresse IP envoie X % de ses paquets à l'IETF, Y % au MIT et Z % à YouPorn, l'observation ultérieure d'une toute autre adresse IP qui a le même graphe de relations peut permettre de conclure que la même personne est derrière les deux adresses.

Il y a aussi les adresses MAC. Celles-ci sont uniques au niveau mondial et sont en général très stables (peu de gens utilisent macchanger). Si le réseau est publiquement accessible (ce qui est typiquement le cas des hotspots WiFi), l'attaquant peut facilement regarder « qui est là » et mettre à jour sa base de données. Notez que certaines techniques, comme les SSID cachés aggravent le risque : la machine de l'utilisateur va diffuser les SSID qu'elle cherche, donnant ainsi davantage d'informations à l'attaquant. Des bases de données des hotspots existent déjà (constituées, par exemple, par les utilisateurs d'Android, dont le smartphone transmet à Google et à la NSA plein d'informations sur les SSID détectés). C'est évidemment encore plus facile pour l'attaquant si le réseau WiFi n'utilise pas WPA ou équivalent (tapez sur votre fournisseur WiFi si ce n'est pas le cas).

Ce très intéressant exposé des techniques d'espionnage existantes est évidemment incomplet : nul doute que la NSA ou la DGSI ont plein d'autres idées. Et il y a certainement des différences entre la théorie de la section 3 et la réalité de la surveillance massive effectuée par ces organisations. Il est bien sûr impossible de savoir exactement ce que la NSA sait faire. Tout au plus peut-on faire quelques suppositions raisonnables (section 4 de notre RFC). D'abord, les révélations Snowden ne laissent pas de doute sur l'existence de cette surveillance généralisée effectuée par la NSA et le GCHQ (notez que notre RFC ne fait pas dans la fausse pudeur, et cite les noms de ces organisations, alors qu'avant on ne parlait que de « certaines agences gouvernementales »). Ensuite, ces mêmes révélations donnent une première idée des méthodes utilisées. Et il n'y a pas que la NSA et ses collaborateurs : nul doute que les services secrets français, chinois, russes ou israéliens espionnent également massivement, dans la mesure de leurs moyens matériels et de leurs compétences. Mais on n'a pas encore les détails, on attend un héros comme Snowden dans ces pays moins imbibés de culture démocratique.

Donc, reality check, à la lumière des révélations Snowden, que fait effectivement la NSA, par rapport à l'attaquant passif idéalisé de la section 3 ? D'abord, cette organisation d'espionnage a effectivement une activité massive de collecte passive :

  • Son système XKEYSCORE surveille l'Internet depuis un très grand nombre de points de mesure, à la recherche d'élements indiquant une cible (comme une adresse de courrier particulière),
  • Le programme TEMPORA du GCHQ espionne les câbles sous-marins (environ 1 500 d'entre eux),
  • Et on peut aussi citer MUSCULAR, qui se branche sur les câbles reliant les différents centres de données de gros acteurs Internet, pour capturer leur trafic interne.

Ce n'est pas tout de capturer, il faut aussi décoder, et une partie du trafic est chiffré. La NSA ne renonce pas devant le chiffrement et, par exemple, son programme BULLRUN met en œuvre divers moyens pour affaiblir la protection qu'offre la cryptographie, par exemple par des modifications du code.

Et, surtout, la NSA ne se contente pas d'attaques passives, comme le faisait l'attaquant modélisé en section 3. Elle a aussi des mécanismes actifs :

Si les révélations Snowden ne portent que sur la NSA et le GCHQ, le RFC rappelle que d'autres États n'hésitent certainement pas à recourir aux mêmes méthodes, et le cas évident de la Chine est cité, avec les techniques de modification de données utilisées par le GFW, techniques qui rappellent fortement le QUANTUM états-unien. Par exemple, le réseau chinois n'hésite pas à modifier les réponses DNS. De l'espionnage actif à l'attaque par déni de service, il n'y a qu'un pas, que le gouvernement chinois a franchi avec le Grand Canon et peut-être avec l'attaque « Poivre du Sichuan ».

La section 5 de notre RFC synthétise la menace à laquelle nous devons désormais faire face. Les attaquants comme la NSA ou la DGSE peuvent :

  • Effectuer passivement des observations (cf. la section 3),
  • Inférer, à partir des observations,
  • Contrairement à l'attaquant passif de la section 3, ces organisations peuvent aussi faire des attaques actives,
  • La cryptographie ne protège pas dans 100 % des cas : entre autres contre-mesures, ces organisations peuvent obtenir des clés privées, soit ponctuellement (piratage d'un ordinateur, fausse manœuvre de l'utilisateur), soit systématiquement (faille de sécurité délibérement introduite dans le logiciel via BULLRUN, piratage d'un fournisseur),
  • Et, enfin, obtenir les données stockées, ce que le chiffrement de la communication n'empêche pas (programme PRISM, où des collaborateurs de la NSA comme Google lui donnent accès à leurs données).

La traditionnelle opposition attaquant passif / attaquant actif des analyses de sécurité est sans doute insuffisante dans le cas de la surveillance systématique. Les trois dernières possibilités citées plus haut (obtention ponctuelle des clés, obtention systématique des clés et accès aux données stockées) étaient ainsi absentes ou très sous-estimées, avant Snowden. En outre, comme ces trois possibilités se situent en dehors des protocoles réseau, l'IETF tendait à les négliger, les considérant comme hors de son domaine.

Autrefois, on considérait que les attaquants actifs étaient forcément situés en bordure du réseau : sur un hotspot WiFi non protégé par WPA, une attaque active est triviale, pour toute personne connectée à ce hotspot. Mais les organisations comme la NSA peuvent également agir au cœur de l'Internet, ce qui augmente sérieusement leurs possibilités. J'avais entendu lors d'une conférence de sécurité un expert affirmer qu'il ne fallait jamais utiliser la WiFi mais toujours la 3G pour des raisons de sécurité. Ce conseil peut avoir un sens face à un attaquant lycéen dans son garage mais certainement pas face à des organisations importantes, pour qui le réseau de l'opérateur 3G est terrain de chasse libre.

La différence quantitative entre le cracker de base dans son garage et une organisation étatique ou para-étatique devient en outre une différence qualitative. Le fait de pouvoir tout observer rend l'inférence beaucoup plus efficace, même en cas de chiffrement. Ainsi, un observateur présent en beaucoup d'endroits peut corréler des flux réseau entre eux, même s'ils sont chiffrés. Un observateur présent en un seul point du réseau n'a pas cette possibilité. Un simple VPN chiffré peut le rendre aveugle, alors que l'observateur présent partout peut trouver les serveurs où on se connecte uniquement en corrélant le trafic du VPN avec le trafic simultané en un autre point de l'Internet (XKEYSCORE fait apparemment cela.)

En prime, les attaquants susceptibles de monter un système de surveillance massive, comme la DGSE, sont également souvent capables de subvertir l'authentification. Chiffrer, en effet, ne sert pas beaucoup si on chiffre, non pas pour le vrai destinataire mais pour l'homme du milieu. La protection habituelle contre ces attaques de l'homme du milieu est l'authentification. Par exemple, on vérifie l'identité du correspondant via un certificat X.509. Mais une organisation puissante peut contraindre les autorités de certification à émettre de vrais/faux certificats. Comme il suffit d'une seule autorité de certification contrainte (ou piratée, ce qui revient au même) pour faire un certificat pour n'importe quel serveur, on voit que la NSA n'a que l'embarras du choix.

Tout cela ne veut pas forcément dire qu'un attaquant puissant comme la NSA ou le FSB a table ouverte. Ces attaques ont des coûts et l'analyse de ces coûts est une branche relativement récente de la sécurité (elle est bien illustrée dans un excellent dessin de XKCD). On ne peut évidemment pas espérer aveugler les agences d'espionnage mais on peut augmenter le prix de leurs activités, jusqu'à les forcer à réduire ces activités. La section 5.2 de notre RFC discute ces coûts.

Tous ne sont pas forcément monétaires. Par exemple, comme les espions, à l'égal des cloportes, n'aiment pas la lumière, le risque d'être pris la main dans le sac, représente un coût. Cela suppose évidemment que l'espion soit détecté et identifié. Si c'est fait, les conséquences peuvent aller de la fermeture d'une voie d'accès aux données, à des poursuites judiciaires, ou à la démission d'un ministre bouc émissaire.

Par exemple, une attaque passive offre à priori moins de chance de se faire attraper puisqu'on ne modifie pas le trafic. Sauf qu'un branchement physique sur des câbles va laisser des traces (les plombiers du Watergate ou du Canard Enchainé en savent quelque chose). Si l'opérateur réseau n'est pas complice de l'attaquant (il semble que, dans le cas de TEMPORA, il l'était), la « bretelle » peut être découverte à l'occasion d'une opération de maintenance, comme ce fut le cas dans l'affaire de Tarnac. Même si l'écoute se faisait de manière purement logicielle, un employé zélé peut la détecter un jour (« mais pourquoi ce port du commutateur est-il en mode miroir ? »). Les techniques sans-fil ne nécessitent pas de branchement physique mais, souvent, la portée utile est faible et l'attaquant doit se rapprocher, ce qui peut mener à sa détection. Bref, la vie d'un espion n'est pas toujours facile. Si l'opérateur collabore, c'est plus facile pour l'espion mais, s'il y a un Snowden parmi les employés de l'opérateur, patatras, la belle opération secrète d'écoute finit en une du Monde ou du New York Times. Si l'attaquant est un État, il peut forcer les employés d'un opérateur national à collaborer mais c'est plus difficile avec les étrangers.

C'est encore pire (du point de vue de l'attaquant) avec les méthodes actives. Elles laissent forcément davantage de traces. Par exemple, un vrai/faux certificat X.509 peut être détecté par des mesures comme les « certificats au grand jour » du RFC 9162.

Les attaques actives représentent aussi souvent un défi technique plus important. Là où les attaques passives nécessitent surtout des gros disques durs, les attaques actives peuvent demander, par exemple, qu'un injecteur de paquets frauduleux gagne la course contre la source légitime afin que ses paquets arrivent avant. À un térabit/s, ce n'est pas évident et cela ne se fait pas avec un PC ordinaire !

Voilà, on a fait un tour partiel des attaquants et de leurs capacités. Les solutions à ces attaques seront développées plus tard (mais cela ne sera pas facile).


Téléchargez le RFC 7624


L'article seul

RFC 7613: Preparation, Enforcement, and Comparison of Internationalized Strings Representing Usernames and Passwords

Date de publication du RFC : Août 2015
Auteur(s) du RFC : P. Saint-Andre (&yet), A. Melnikov (Isode)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF precis
Première rédaction de cet article le 29 août 2015


Ah, les plaisirs de l'internationalisation du logiciel... Quand l'informatique ne concernait que les États-Unis, tout était simple. Un utilisateur ne pouvait avoir un nom (un login) que composé des lettres de l'alphabet latin (et même chose pour son mot de passe). Mais de nos jours, il n'est pas acceptable de se limiter au RFC 20. Il faut que Пу́тин ou 艾未未 puissent écrire leur nom dans leur écriture et l'informatique doit suivre. La première tentative de normaliser ces noms d'utilisateur en Unicode, dans le RFC 4013 n'avait pas été un immense succès et elle est désormais remplacée par une approche un peu différente, décrite dans ce nouveau RFC, qui a depuis été remplacé par le RFC 8265.

Mais pourquoi faut-il standardiser quelque chose ? Pourquoi ne pas dire simplement « les noms d'utilisateur sont en Unicode » et basta ? Parce que les logiciels qui gèrent noms d'utilisateurs et mots de passe ont besoin de les manipuler, notamment de les comparer. Si ПУ́ТИН essaie de se loguer, et que la base de données contient un utilisateur пу́тин, il faut bien déterminer si c'est le même utilisateur (ici, oui, à part la casse). C'est en général assez simple dans l'alphabet latin (ou dans le cyrillique utilisé pour les exemples) mais il y a d'autres cas plus vicieux qui nécessitent quelques règles supplémentaires.

Le RFC 4013, qui était fondé sur le cadre du RFC 3454 visait à décrire ces règles. Mais l'approche utilisée n'a pas accroché (en partie parce qu'elle était liée à une version d'Unicode particulière) et le défunt stringprep du RFC 3454 a été remplacé par un nouveau cadre, celui du RFC 7564. Notre nouveau RFC 7613 est l'adaptation de ce RFC 7564 au cas spécifique des noms d'utilisateur et des mots de passe.

Ces noms et ces mots de passe (aujourd'hui, il faudrait plutôt dire phrases de passe) sont largement utilisés pour l'authentification, soit directement (SASL PLAIN du RFC 4616, authentification de base de HTTP du RFC 7617), ou bien comme entrée d'une fonction de condensation cryptographique (SASL SCRAM du RFC 5802 ou bien authentification HTTP digest du RFC 7616). L'idée est que les opérations de base sur ces noms (et sur les mots de passe) ne surprennent pas excessivement l'utilisateur, quel que soit son pays, sa langue, sa culture. Un Français ou un Belge ne sera probablement pas trop étonné que Dupont soit accepté comme synonyme de dupont mais il le serait davantage si dupond l'était. Évidemment, la tâche est impossible (les utilisateurs sont tous différents) mais l'idée est de ne pas faire un système parfait mais un système qui marche la plupart du temps.

C'est là qu'intervient le cadre PRECIS (PReparation, Enforcement, and Comparison of Internationalized Strings) du RFC 7564. Il évite que chaque développeur d'un système d'authentification doive lire et comprendre toutes les conséquences d'Unicode, et lui permet de s'appuyer sur une analyse déjà faite. Un exemple de piège d'Unicode (et qui montre pourquoi « on va juste dire que les noms d'utilisateur peuvent être n'importe quel caractère Unicode » est sans doute une mauvaise politique) est le chiffre 1 en exposant, U+00B9 (comme ça : « ¹ » Si vous ne voyez rien, c'est parce que votre logiciel ne sait pas afficher ce caractère. Vous pouvez toujours regarder le source HTML pour comprendre l'exemple.). Doit-on l'autoriser ? Le mettre en correspondance avec le 1 traditionnel de façon à ce que user¹ et user1 soient le même nom ? Imaginez un client XMPP qui vous dise « user¹@example.com veut être votre copain. Je l'autorise ? » et que vous acceptiez en croyant que c'était user1@example.com. Bien sûr, on ne peut pas réellement parler d'« attaque » dans ce cas, une telle erreur permettrait juste de faire quelques farces mais, pour le logiciel qui vérifie une identité, des confusions seraient plus gênantes. Si les « attaques » exploitant la similitude de caractères Unicode sont surtout un fantasme d'informaticien anglophone n'ayant jamais réellement accepté l'internationalisation (plutôt qu'une réalité du terrain), il est quand même plus prudent de supprimer quelques causes de cafouillage le plus tôt possible.

Je l'ai dit plus haut, ce nouveau RFC met fin au profil SASLprep du RFC 4013 mais les protocoles qui l'utilisaient ne sont pas mis à jour automatiquement, ils devront publier une nouvelle version de leur norme (comme le RFC 7622 pour XMPP).

Notre RFC compte deux sections importantes, décrivant le profil PRECIS pour les noms d'utilisateur (section 3) et les mots de passe (section 4). Commençons par les noms d'utilisateur. Un nom est une chaîne de caractères Unicode composée de parties séparées par des espaces. Chaque partie doit être une instance de IdentifierClass et est normalisée en NFC. L'encodage doit être UTF-8. Pourquoi cette notion de « parties séparées par des espaces » ? Parce que la classe IdentifierClass du RFC 7564 ne permet pas les espaces, ce qui est gênant pour certains identificateurs (« Prénom Nom » par exemple, cf. section 3.5). D'où la grammaire de la section 3.1 :

      username   = userpart *(1*SP userpart)
    

qui dit « un nom d'utilisateur est composé d'au moins une partie, les parties étant séparées par un nombre quelconque d'espaces ». Une des conséquences de cette grammaire étant que le nombre d'espaces n'est pas significatif : Jean Dupont et Jean Dupont sont le même identificateur.

Chaque partie étant une instance de l'IdentifierClass du RFC 7564, les caractères interdits par cette classe sont donc interdits pour les noms d'utilisateurs. Une application donnée peut restreindre (mais pas étendre) ce profil. Ces noms d'utilisateurs sont-ils sensibles à la casse ? Ce fut l'un des deux gros débats dans le groupe de travail PRECIS, puisque certains protocoles ont fait un choix et d'autres le choix opposé (l'autre gros débat concernait - bien à tort - un problème subtil et peu important sur les conséquences des changements dans les nouvelles versions d'Unicode). Eh bien, il y a désormais deux sous-profils, un sensible et un insensible. Les protocoles et applications utilisant ce RFC 7613 devront annoncer clairement lequel ils utilisent. Et les bibliothèques logicielles manipulant ces utilisateurs auront probablement une option pour indiquer le sous-profil à utiliser.

Le sous-profil UsernameCaseMapped rajoute donc une règle de préparation des chaînes de caractères : tout passer en minuscules (avant les comparaisons, les condensations cryptographiques, etc), en utilisant l'algorithme Case Folding d'Unicode (oui, changer la casse est bien plus compliqué en Unicode qu'en ASCII). Une fois la préparation faite, on peut comparer octet par octet (rappelez-vous que la chaîne doit être en UTF-8).

L'autre sous-profil, UsernameCasePreserved ne change pas la casse, comme son nom l'indique. ПУ́ТИН et пу́тин y sont donc deux identificateurs différents. C'est la seule différence entre les deux sous-profils. Notre RFC recommande le profil insensible à la casse, UsernameCaseMapped, pour éviter des surprises comme celles décrites dans le RFC 6943 (cf. section 8.2 de notre RFC).

Bon, tout ça est bien nébuleux et vous préféreriez des exemples ? Le RFC nous en fournit. D'abord, des identificateurs peut-être surprenants mais légaux (légaux par rapport à PRECIS : certains protocoles peuvent mettre des restrictions supplémentaires). Attention, pour bien les voir, il vous faut un navigateur Unicode, avec toutes les polices nécessaires :

  • juliet@example.com : le @ est autorisé donc un JID (identificateur XMPP) est légal.
  • fussball : un nom d'utilisateur traditionnel, purement ASCII, qui passera partout, même sur les systèmes les plus antédiluviens.
  • fußball : presque le même mais avec un peu d'Unicode. Bien qu'en allemand, on traite en général ces deux identificateurs comme identiques, pour PRECIS, ils sont différents. Si on veut éviter de la confusion aux germanophones, on peut interdire la création d'un des deux identificateurs si l'autre existe déjà : PRECIS ne donne que des règles miminales, on a toujours droit à sa propre politique derrière.
  • π : entièrement en Unicode, une lettre.
  • Σ : une lettre majuscule.
  • σ : la même en minuscule. Cet identificateur et le précédent seront identiques si on utilise le profil UsernameCaseMapped et différents si on utilise le profil UsernameCasePreserved.
  • ς : la même, lorsqu'elle est en fin de mot. Le cas de ce sigma final est compliqué, PRECIS ne tente pas de le résoudre. Comme pour le eszett plus haut, vous pouvez toujours ajouter des règles locales.

Par contre, ces noms d'utilisateurs ne sont pas valides :

  • Une chaîne de caractères vide.
  • HenriⅣ : le chiffre romain 4 à la fin est illégal (car il a ce qu'Unicode appelle « un équivalent en compatibilité », la chaîne « IV »).
  •  : seules les lettres sont acceptées, pas les symboles (même règle que pour les noms de domaine).

Continuons avec les mots de passe (section 4). Comme les noms, le mot de passe est une chaîne de caractères Unicode. Il doit être une instance de FreeformClass. Cette classe autorise bien plus de caractères que pour les noms d'utilisateur, ce qui est logique : un mot de passe doit avoir beaucoup d'entropie. Peu de caractères sont donc interdits (parmi eux, les caractères de contrôle, voir l'exemple plus bas). Les mots de passe sont sensibles à la casse. L'encodage doit être UTF-8.

Des exemples ? Légaux, d'abord :

  • correct horse battery staple : vous avez reconnu un fameux dessin de XKCD.
  • Correct Horse Battery Staple : les mots de passe sont sensibles à la casse, donc c'est un mot de passe différent du précédent.
  • πßå : un mot de passe en Unicode ne pose pas de problème.
  • Jack of ♦s : et les symboles sont acceptés, contrairement à ce qui se passe pour les noms d'utilisateur.
  • foo bar : le truc qui ressemble à un trait est l'espace de l'Ogham, qui doit normalement être normalisé en un espace ordinaire, donc ce mot de passe est équivalent à foo bar.

Par contre, ce mot de passe n'est pas valide :

Rappelez-vous que ces profils PRECIS ne spécifient que des règles minimales. Un protocole utilisant ce RFC peut ajouter d'autres restrictions (section 5). Par exemple, il peut imposer une longueur minimale à un mot de passe (la grammaire de la section 4.1 n'autorise pas les mots de passe vides mais elle autorise ceux d'un seul caractère, ce qui serait évidemment insuffisant pour la sécurité), une longueur maximale à un nom d'utilisateur, interdire certains caractères qui sont spéciaux pour ce protocole, etc.

Certains profils de PRECIS suggèrent d'être laxiste en acceptant certains caractères ou certaines variantes dans la façon d'écrire un mot (accepter strasse pour straße ? C'est ce qu'on nomme le principe de robustesse.) Mais notre RFC dit que c'est une mauvaise idée pour des mots utilisés dans la sécurité, comme ici (voir RFC 6943).

Comme toutes les fois qu'on change les règles, il faut se préoccuper de la migration depuis l'ancien système (c'est la section 6 du RFC). Si vous aviez déjà des noms d'utilisateur en Unicode en suivant l'ancien système SASLprep, celui du RFC 4013, il va falloir examiner votre base de données et peut-être faire des conversions. Pour les noms, il y a notamment le fait que SASLprep utilisait la normalisation Unicode NFKC alors que PRECIS se sert de NFC. Ce n'est pas forcément si grave que ça car PRECIS interdit les lettres ayant un équivalent de compatibilité, les seules qui sont traitées différemment par NFKC et NFC. Il est donc recommandé d'examiner la base et de repérer des noms ayant un de ces équivalents.

Pour les mots de passe, c'est plus compliqué puisque, si vous êtes sérieux, vous ne les stockez pas en clair, et vous ne pouvez donc pas les examiner. Disons que si un utilisateur qui a utilisé toutes les possibilités rigolotes d'Unicode n'arrive pas à s'authentifier après la migration, il faudra penser à ce problème.

Les profils PRECIS ont été ajoutés au registre IANA (section 7 de notre RFC).

Un petit mot sur la sécurité et on a fini. La section 8 de notre RFC revient sur quelques points difficiles. Notamment, est-ce une bonne idée d'utiliser Unicode pour les mots de passe ? Ça se discute. D'un côté, cela augmente les possibilités (en simplifiant les hypothèses, avec un mot de passe de 8 caractères, on passe de 10^15 à 10^39 possibilités en permettant Unicode et plus seulement ASCII), donc l'entropie. D'un autre, cela rend plus compliqué la saisie du mot de passe, surtout sur un clavier avec lequel l'utilisateur n'est pas familier. Le monde est imparfait et il faut choisir le moindre mal...

Enfin, un résumé des changements depuis l'ancienne technique, celle du RFC 4013, figure dans l'annexe A. Il rappelle que l'ancien stringprep/SASLprep est remplacé par une approche vraiment différente, même si, dans les cas « normaux », le résultat sera le même. Par exemple, stringprep (RFC 3454) autorisait tous les caractères sauf ceux qui étaient interdits alors que PRECIS, comme le fait IDN depuis la nouvelle norme RFC 5891, fait l'inverse (tout ce qui n'est pas autorisé est interdit). Pour résumer les autres principaux changements :

  • Il n'y avait qu'un seul algorithme de préparation et de comparaison dans SASLprep, il y en a désormais trois (noms sensibles à la casse, noms insensibles à la casse, mots de passe).
  • Indépendance vis-à-vis de la version d'Unicode.
  • Normalisation NFC et plus NFKC.

Téléchargez le RFC 7613


L'article seul

RFC 7606: Revised Error Handling for BGP UPDATE Messages

Date de publication du RFC : Août 2015
Auteur(s) du RFC : E. Chen (Cisco Systems), J. Scudder (Juniper Networks), P. Mohapatra (Sproute Networks), K. Patel (Cisco Systems)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF idr
Première rédaction de cet article le 28 août 2015


Que doit faire un routeur BGP lorsqu'il reçoit un message de type UPDATE avec un attribut incorrect ? La norme était claire : le routeur doit fermer la session BGP en cours (et donc perdre toutes les routes associées). Cela partait du bon sens (si l'attribut est corrompu, on ne peut pas se fier au routeur qui l'a envoyé) mais cela avait des conséquences sérieuses : on supprimait toutes les routes, pas seulement celle dans l'annonce UPDATE. Ce court RFC modifie donc BGP sur un point : on ne coupe plus forcément toute la session, on retire uniquement la route qui figurait dans l'annonce incorrecte.

L'ancienne norme figurait dans le RFC 4271, section 6 : « When any of the conditions described here are detected, a NOTIFICATION message, with the indicated Error Code, Error Subcode, and Data fields, is sent, and the BGP connection is closed ». En pratique, cela voulait dire que les routeurs coupaient des sessions simplement à cause d'un attribut mal formé. Cela pose un problème de sécurité : comme certains routeurs ne vérifient pas les attributs des annonces, l'annonce avec l'attribut invalide peut être propagée et planter des sessions situées bien après l'origine de l'annonce, rendant le débogage et l'attribution des responsabilités très difficiles. En outre, l'annonce a pu être dupliquée par ces routeurs qui ne vérifient pas, et une seule annonce peut donc planter plusieurs sessions. Cela s'était produit, par exemple, dans le cas du fameux attribut 99.

Que peut faire un routeur BGP lorsque il reçoit une annonce invalide ? La section 2 du RFC liste les possibilités, de la plus violente à la plus modérée :

  • Réinitialiser la session (« dans le doute, reboote »). C'était l'approche officielle avant ce RFC.
  • Ne réinitialiser qu'une seule famille d'adresses (AFI, Address Family Identifier, comme seulement IPv4 ou seulement IPv6), comme documenté dans le RFC 4760.
  • Considérer que l'annonce invalide est équivalente à un retrait des routes qu'elle contient (treat-as-withdraw). C'est une nouveauté de ce RFC, qui n'existait pas dans BGP avant. Cela évite de perdre toutes les routes de la session, comme c'était le cas avec la première approche.
  • Ignorer l'attribut invalide mais garder l'annonce, ce que notre RFC déconseille formellement (sauf si l'attribut n'avait aucune conséquence sur la sélection et l'installation des routes).

L'approche « ignorer l'annonce invalide » n'est pas citée : dans un protocole où les mises à jour sont incrémentales, comme BGP (qui n'envoie pas la table de routage complète, seulement les changements), elle pourrait mener à des routes impossibles à détruire (cf. section 6).

C'est la section 3 qui contient les nouvelles règles exactes, après moultes discussions à l'IETF. Pour résumer : c'est la troisième option (treat-as-withdraw) qui est désormais recommandée dans la plupart des cas.

Le reste du RFC est consacré à des détails pratiques. Par exemple, en section 5, on trouve des règles d'encodage qui permettront d'accéder aux routes annoncées (NLRI, Network Layer Reachability Information) malgré la présence d'attributs mal formés. En effet, c'est très joli de dire qu'on doit traiter une annonce invalide comme un retrait mais il faut pour cela savoir quelles routes retirer (réinitialiser toute la session est bien plus simple à mettre en œuvre). Quand l'annonce est invalide, l'analyser n'est pas trivial. Notre RFC demande donc de faciliter la tâche du routeur de réception de l'annonce, par exemple en encodant les attributs MP_REACH_NLRI et MP_UNREACH_NLRI au tout début de la liste des attributs (pour pouvoir les comprendre même si l'annonce est invalide). Évidemment, les routeurs anciens ne suivent pas forcément ces règles et les récepteurs doivent donc rester prêts à tout.

Bien sûr, rien n'est parfait. L'ancienne règle de couper toute la session n'était pas due au désir des auteurs de BGP de perturber le plus possible l'Internet. Il y avait de bonnes raisons à cette décision, notamment de garantir la cohérence du routage. Avec la nouvelle règle, ce n'est plus aussi simple et on risque donc des tables de routage incohérentes (un routeur ayant accepté l'annonce et un autre l'ayant traité comme un retrait...), avec leurs conséquences, comme des boucles de routage. Cela explique la très longue gestation de ce RFC, due à de nombreuses discussions à l'IETF. Il faut dire que toucher à BGP est toujours délicat : une erreur peut potentiellement planter tout l'Internet.

La section 7 du RFC décrit en détail ce que veut dire « malformé » pour un attribut BGP. Par exemple, l'attribut ORIGIN (RFC 4271, section 4.3, et qui indique la source de l'information contenue dans l'annonce) a normalement une longueur de 1 (les attributs BGP sont encodés en TLV) et toute autre longueur indique un attribut ORIGIN mal formé : autrefois, cela aurait coupé la session, depuis notre RFC, cela doit entrainer un retrait de la route contenue dans l'annonce. Pour l'attribut ORIGIN, même chose si la valeur de l'attribut n'est pas une des valeurs spécifiées (IGP, EGP ou INCOMPLETE).

Autre exemple, l'attribut COMMUNITIES (RFC 1997) doit avoir une longueur qui est un multiple de 4. Si ce n'est pas le cas => attribut mal formé => annonce traitée comme étant un retrait de routes.

Conséquence de ce nouveau RFC : tout nouvel attribut spécifié doit indiquer le traitement à appliquer en cas de malformation (section 8). Ce sera en général treat-as-withdraw mais cela doit être marqué explicitement dans la norme décrivant le nouvel attribut.

Un avantage du long délai avant la sortie de ce RFC, est que ce nouveau comportement a déjà été mis en œuvre dans la plupart des routeurs (Alcatel-Lucent SR OS, Cisco IOS, Cisco IOS XR, Juniper JUNOS, Quagga).


Téléchargez le RFC 7606


L'article seul

RFC 7607: Codification of AS 0 processing

Date de publication du RFC : Août 2015
Auteur(s) du RFC : W. Kumari (Google), R. Bush (Internet Initiative Japan), H. Schiller (Verizon), K. Patel (Cisco)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF idr
Première rédaction de cet article le 28 août 2015


Petit quizz BGP : sans relire le RFC 4271, pouvez-vous dire si 0 est acceptable comme numéro de système autonome dans un message BGP ? Si vous ne pouvez pas, ce n'est pas grave, vous n'êtes pas le seul, ce point n'avait jamais été clairement précisé. Ce très court RFC règle le problème : 0 est désormais officiellement interdit.

Pourtant, cela fait longtemps que l'AS 0 (zéro, pas O) est spécial : il est indiqué dans le registre IANA comme non routable. En outre, les ROA (Route Origin Authorizations) IANA du RFC 6491 utilisent l'AS 0 pour indiquer qu'un préfixe IP ne peut pas être annoncé sur l'Internet. Mais cela veut-il dire qu'un message BGP, par exemple une annonce de route, n'a pas le droit de contenir l'AS 0 dans son chemin d'AS (AS_PATH) ? La plupart des mises en œuvre de BGP avaient choisi cette voie et rejetaient ces annonces. Ce comportement est désormais officiel.

Donc, en deux mots, la nouvelle règle : il est défendu d'utiliser l'AS 0 dans les attributs BGP AS_PATH, AS4_PATH, AGGREGATOR et AS4_AGGREGATOR qu'on émet. Si un pair BGP le fait, et vous envoie de tels attributs, ses messages doivent être considérés comme malformés et rejetés selon les procédures du RFC 7606.

Si jamais un pair ouvre une session en indiquant que son AS est zéro, on doit avorter ladite session avec le message d'erreur n° 2, Bad peer AS (RFC 4271, section 6.2).


Téléchargez le RFC 7607


L'article seul

RFC 7626: DNS privacy considerations

Date de publication du RFC : Août 2015
Auteur(s) du RFC : S. Bortzmeyer (AFNIC)
Pour information
Réalisé dans le cadre du groupe de travail IETF dprive
Première rédaction de cet article le 27 août 2015


Les révélations d'Edward Snowden en juin 2013 ont fait comprendre à tous, même aux plus obtus qui s'obstinaient à nier l'ampleur et la gravité de la surveillance généralisée, que les problèmes de vie privée ne sont pas un simple détail. Au contraire, il est maintenant établi que l'Internet, et les technologies numériques en général, sont utilisés comme arme de surveillance massive par le gouvernement des États-Unis et, quasi-certainement, par plusieurs autres, dans la mesure de leurs moyens. Cela a mené l'IETF, qui avait parfois tendance à relativiser l'intensité du problème, à se pencher sérieusement sur la question. Plusieurs travaux ont été lancés. L'un d'eux concerne la protection de la vie privée lors de l'utilisation du DNS et ce nouveau RFC, écrit par votre serviteur, est son premier résultat.

Ce RFC est en fait à la croisée de deux activités. L'une d'elles consiste à documenter les problèmes de vie privée, souvent ignorés jusqu'à présent dans les RFC. Cette activité est symbolisée par le RFC 6973, dont la section 8 contient une excellente analyse de ces problèmes, pour un service particulier (la présence en ligne). L'idée est que, même si on ne peut pas résoudre complètement le problème, on peut au moins le documenter, pour que les utilisateurs soient conscients des risques. Et la seconde activité qui a donné naissance à ce RFC est le projet d'améliorer effectivement la protection de la vie privée des utilisateurs du DNS, en marchant sur deux jambes : minimiser les données envoyées (c'est le sous-projet qname minimization) et les rendre plus résistantes à l'écoute, via le chiffrement. La diminution des données est étudiée dans le groupe de travail IETF dnsop (le principal document est DNS query name minimisation to improve privacy) et le chiffrement dans le groupe de travail IETF dprive (le principal document est TLS for DNS: Initiation and Performance Considerations, qui propose de faire circuler les requêtes DNS sur TLS). Le groupe dprive (le nom, contraction de DNS privacy, suit la tradition des noms de groupes humoristiques, ce qui est fréquent à l'IETF, et est dû à Alexander Mayrhofer) est également l'enceinte où a été développé le RFC 7626, objet principal de cet article.

Donc, pourquoi un RFC sur les questions de vie privée dans le DNS ? Ce dernier est un très ancien protocole, dont l'une des particularités est d'être mal spécifié : aux deux RFC originaux, les RFC 1034 et RFC 1035, il faut ajouter dix ou vingt autres RFC dont la lecture est nécessaire pour tout comprendre du DNS. Et aucun travail de consolidation n'a jamais été fait, contrairement à ce qui a eu lieu pour XMPP, HTTP ou SMTP. Or, le DNS est crucial, car quasiment toutes les transactions Internet mettent en jeu au moins une requête DNS (ne me dites pas des bêtises du genre « moi, je télécharge avec BitTorrent, je n'utilise pas le DNS » : comment allez-vous sur thepiratebay.am ?) Mais, alors que les questions de vie privée liées à HTTP ont fait l'objet d'innombrables articles et études, celles liées au DNS étaient largement ignorées (voir la bibliographie du RFC pour un état de l'art). Pourtant, on peut découvrir bien des choses sur votre activité Internet uniquement en regardant le trafic DNS.

Une des raisons du manque d'intérêt pour le thème « DNS et vie privée » est le peu de compétences concernant le DNS : le protocole est souvent ignoré ou mal compris. C'est pourquoi le RFC doit commencer par un rappel (section 1) du fonctionnement du DNS.

Je ne vais pas reprendre tout le RFC ici. Juste quelques rappels des points essentiels du DNS : il existe deux sortes de serveurs DNS, qui n'ont pratiquement aucun rapport. Il y a les serveurs faisant autorité et les résolveurs. Les premiers sont ceux qui connaissent de première main l'information pour une zone DNS donnée (comme fr ou wikipedia.org). Ils sont gérés par le titulaire de la zone ou bien sous-traités à un hébergeur DNS. Les seconds, les résolveurs, ne connaissent rien (à part l'adresse IP des serveurs de la racine). Ils interrogent donc les serveurs faisant autorité, en partant de la racine. Les résolveurs sont gérés par le FAI ou le service informatique qui s'occupe du réseau local de l'organisation. Ils peuvent aussi être individuels, ou bien au contraire être de gros serveurs publics comme Google Public DNS, gros fournisseur de la NSA. Pour prendre un exemple concret (et en simplifiant un peu), si M. Michu veut visiter le site Web http://thepiratebay.am/, son navigateur va utiliser les services du système d'exploitation sous-jacent pour demander l'adresse IP de thepiratebay.am. Le système d'exploitation va envoyer une requête DNS au résolveur (sur Unix, les adresses IP des résolveurs sont dans /etc/resolv.conf). Celui-ci va demander aux serveurs de la racine s'ils connaissent thepiratebay.am, il se fera rediriger vers les serveurs faisant autorité pour am, puis vers ceux faisant autorité pour thepiratebay.am. Le résolveur aura alors une réponse qu'il pourra transmettre au navigateur de M. Michu.

Principal point où j'ai simplifié : le DNS s'appuie beaucoup sur la mise en cache des données, c'est-à-dire sur leur mémorisation pour gagner du temps la fois suivante. Ainsi, si le même M. Michu, cinq minutes après, veut aller en http://armenpress.am/, son résolveur ne demandera rien aux serveurs de la racine : il sait déjà quels sont les serveurs faisant autorité pour am.

Le trafic DNS est un trafic TCP/IP ordinaire, typiquement porté par UDP. Il peut être écouté, et comme il n'est aujourd'hui pas chiffré, un indiscret peut tout suivre. Voici un exemple pris avec tcpdump sur un serveur racine (pas la racine officielle, mais, techniquement, cela ne change rien) :

15:29:24.409283 IP6 2001:67c:1348:8002::7:107.10127 > \
    2001:4b98:dc2:45:216:3eff:fe4b:8c5b.53: 32715+ [1au] \
    AAAA? www.armenpress.am. (46)

On y voit que le client 2001:67c:1348:8002::7:107 a demandé l'adresse IPv6 de www.armenpress.am.

Pour compléter le tableau, on peut aussi noter que les logiciels génèrent un grand nombre de requêtes DNS, bien supérieur à ce que voit l'utilisateur. Ainsi, lors de la visite d'une page Web, le résolveur va envoyer la requête primaire (le nom du site visité, comme thepiratebay.am), des requêtes secondaires dues aux objets contenus dans la page Web (JavaScript, CSS, divers traqueurs et autres outils de cyberflicage ou de cyberpub) et même des requêtes tertiaires, lorsque le fonctionnement du DNS lui-même nécessitera des requêtes. Par exemple, si abc.xyz est hébergé sur des serveurs dans google.com, une visite de http://abc.xyz/ nécessitera de résoudre les noms comme ns1.google.com, donc de faire des requêtes DNS vers les serveurs de google.com.

Bien sûr, pour un espion qui veut analyser tout cela, le trafic DNS représente beaucoup de données, souvent incomplètes en raison de la mise en cache, et dont l'interprétation peut être difficile (comme dans l'exemple ci-dessus). Mais les organisations qui pratiquent l'espionnage massif, comme la NSA, s'y connaissent en matière de big data et savent trouver les aiguilles dans les bottes de foin.

La section 2 du RFC détaille les risques pour la vie privée dans les différents composants du DNS. Notez que la confidentialité du contenu du DNS n'est pas prise en compte (elle l'est dans les RFC 5936 et RFC 5155). Il est important de noter qu'il y a une énorme différence entre la confidentialité du contenu et la confidentialité des requêtes. L'adresse IP de www.charliehebdo.fr n'est pas un secret : les données DNS sont publiques, dès qu'on connait le nom de domaine, et tout le monde peut faire une requête DNS pour la connaitre. Mais le fait que vous fassiez une requête pour ce nom ne devrait pas être public. Vous n'avez pas forcément envie que tout le monde le sache.

Pour comprendre les risques, il faut aussi revenir un peu au protocole DNS. Les deux informations les plus sensibles dans une requête DNS sont l'adresse IP source et le nom de domaine demandé (qname, pour Query Name, cf. RFC 1034, section 3.7.1). L'adresse IP source est celle de votre machine, lorsque vous parlez au résolveur, et celle du résolveur lorsqu'il parle aux serveurs faisant autorité. Elle peut indiquer d'où vient la demande. Lorsque on utilise un gros résolveur, celui-ci vous masque vis-à-vis des serveurs faisant autorité (par contre, ce gros résolveur va avoir davantage d'informations).

Quant au qname, il peut être très révélateur : il indique les sites Web que vous visitez, voire, dans certains cas, les logiciels utilisés. Au moins un client BitTorrent fait des requêtes DNS pour _bittorrent-tracker._tcp.domain.example, indiquant ainsi à beaucoup de monde que vous utilisez un protocole qui ne plait pas aux ayant-droits. Et si vous utilisez le RFC 4255, pas mal de serveurs verront à quelles machines vous vous connectez en SSH...

Donc où un méchant qui veut écouter votre trafic DNS peut-il se placer ? D'abord, évidemment, il suffit qu'il écoute le trafic réseau. On l'a dit, le trafic DNS aujourd'hui est presque toujours en clair donc tout sniffer peut le décoder. Même si vous utilisez HTTPS pour vous connecter à un site Web, le trafic DNS, lui, ne sera pas chiffré. (Les experts pointus de TLS noteront qu'il existe d'autres faiblesses de confidentialité, comme le SNI du RFC 6066.) À noter une particularité du DNS : le trafic DNS peut passer par un autre endroit que le trafic applicatif. Alice peut naïvement croire que, lorsqu'elle se connecte au serveur de Bob, seul un attaquant situé physiquement entre sa machine et celle de Bob représente une menace. Alors que son trafic DNS peut être propagé très loin, et accessible à d'autres acteurs. Si vous utilisez, par exemple, le résolveur DNS public de FDN, toute la portion de l'Internet entre vous et FDN peut facilement lire votre trafic DNS.

Donc, l'éventuel espion peut être près du câble, à écouter. Mais il peut être aussi dans les serveurs. Bercé par la musique du cloud, on oublie souvent cet aspect de la sécurité : les serveurs DNS voient passer le trafic et peuvent le copier. Pour reprendre les termes du RFC 6973, ces serveurs sont des assistants : ils ne sont pas directement entre Alice et Bob mais ils peuvent néanmoins apprendre des choses à propos de leur conversation. Et l'observation est très instructive. Elle est utilisée à de justes fins dans des systèmes comme DNSDB (section 3 du RFC) mais il n'est pas difficile d'imaginer des usages moins sympathiques comme dans le cas du programme NSA MORECOWBELL.

Les résolveurs voient tout le trafic puisqu'il y a peu de mise en cache en amont de ces serveurs. Il faut donc réfléchir à deux fois avant de choisir d'utiliser tel ou tel résolveur ! Il est déplorable qu'à chaque problème DNS (ou supposé tel), des ignorants bondissent sur les réseaux sociaux pour dire « zyva, mets 8.8.8.8 [Google Public DNS] comme serveur DNS et ça ira plus vite » sans penser à toutes les données qu'ils envoient à la NSA ainsi.

Les serveurs faisant autorité voient passer moins de trafic (à cause des caches des résolveurs) mais, contrairement aux résolveurs, ils n'ont pas été choisis délibérement par l'utilisateur. Celui-ci peut ne pas être conscient que ses requêtes DNS seront envoyées à plusieurs acteurs du monde du DNS, à commencer par la racine. Le problème est d'autant plus sérieux que, comme le montre une étude, la concentration dans l'hébergement DNS est élevée : dix gros hébergeurs hébergent le tiers des domaines des 100 000 sites Web les plus fréquentés (listés par Alexa).

Au passage, le lecteur attentif aura noté qu'un résolveur personnel (sur sa machine ou dans son réseau local) a l'avantage de ne pas envoyer vos requêtes à un résolveur peut-être indiscret mais l'inconvénient de vous démasquer vis-à-vis des serveurs faisant autorité, puisque ceux-ci voient alors votre adresse IP. Une bonne solution (qui serait également la plus économe des ressources de l'Internet) serait d'avoir son résolveur local et de faire suivre les requêtes non résolues au résolveur du FAI. Du point de vue de la vie privée, ce serait sans doute la meilleure solution mais cela ne résout hélas pas un autre problème, celui des DNS menteurs, contre lesquels la seule protection est d'utiliser uniquement un résolveur de confiance.

Enfin, il y a aussi les serveurs DNS « pirates » (installés, par exemple, via un serveur DHCP lui-même pirate) qui détournent le trafic DNS, par exemple à des fins de surveillance. Voir par exemple l'exposé de Karrenberg à JCSA 2012 disponible en ligne (transparents 27 et 28, Unknown et Other qui montrent l'existence de clones pirates du serveur racine K.root-servers.net).

Pour mes lecteurs français férus de droit, une question intéressante : le trafic DNS est-il une « donnée personnelle » au sens de la loi Informatique & Libertés ? Je vous laisse plancher sur la question, qui a été peu étudiée.

Quelques élements d'histoire de ce RFC pour finir, puisque j'ai vécu tout son cycle de vie (c'est mon premier RFC publié). Sa première version a été entièrement écrite, dans un avion de la KLM entre Amsterdam et Vancouver, où j'allais à une réunion IETF en novembre 2013. Long vol sans connexion Internet, donc sans distractions, sièges de la classe affaires et présence de plusieurs collègues qui vous stimulent et avec qui discuter (merci au passage à Olaf Kolkman pour avoir insisté « il faut que tu publies cela »), cela fait d'excellentes conditions de travail.

Le RFC venant d'être publié, on voit qu'il aura fallu moins de deux ans en tout, alors qu'on raconte souvent que l'IETF est lente (sur le fonctionnement de l'IETF, voir mon exposé à JRES). Pour avoir une idée des changements entre le premier « draft KLM » et l'actuel RFC, vous pouvez voir un calcul automatique des différences.

Quelques autres lectures utiles :


Téléchargez le RFC 7626


L'article seul

RFC 7605: Recommendations on Using Assigned Transport Port Numbers

Date de publication du RFC : Août 2015
Auteur(s) du RFC : J. Touch (USC/ISI)
Réalisé dans le cadre du groupe de travail IETF tsvwg
Première rédaction de cet article le 8 août 2015


Vous développez une application Internet et vous utilisez des ports enregistrés à l'IANA ? Ou bien aucun port ne convient et vous voulez en enregistrer un nouveau ? Ce RFC est fait pour vous en expliquant, du point de vue du créateur de nouveaux services Internet, comment utiliser les ports ou bien en demander un nouveau.

La procédure complète figure dans le RFC 6335. Ce nouveau RFC 7605 ne le remplace pas mais fournit une vision moins bureaucratique du processus, plus orientée vers le développeur, avec des recommandations concrètes.

Donc, c'est quoi, un port ? C'est un entier de 16 bits qui :

  • Sert à démultiplexer les paquets entrants dans une machine (à les délivrer au bon processus),
  • Sert à identifier un service (25 = SMTP).

Seule la deuxième utilisation nécessite un registre central.

Pour se connecter à une autre machine, il faut connaître le port de destination. Le cas le plus connu est celui des URL. Si l'URL n'indique pas de numéro de port, le port par défaut est 80 (RFC 7230, section 2.7.1). Donc, avec http://www.example.com/, le client HTTP se connectera au port 80 de la machine www.example.com. Mais on peut indiquer un port dans un URL (RFC 3986, section 3.2.3). Si l'URL est http://www.example.com:9081/, le client HTTP se connectera au port 9 081 de la machine www.example.com.

Bien sûr, rien n'oblige à faire tourner un service sur le port officiellement affecté. On peut mettre un serveur DNS sur le port 80 ou au contraire un serveur HTTP sur le port 53, normalement prévu pour le DNS. C'est ainsi que bien des serveurs SSH écoutent sur le port 443, de manière à ce qu'on puisse se connecter même depuis les points d'accès WiFi les plus pourris qui filtrent tous les ports que leur concepteur ne connait pas. Attention toutefois, si des équipements situés sur le trajet font du DPI, cela peut ne pas leur plaire de voir du trafic non-DNS sur le port 53 et cela peut les amener à couper la communication. Comme le note notre section 5, supposer que le trafic sur le port 53 est forcément du DNS est une erreur : l'interprétation des numéros de ports doit être laissé aux deux machines qui communiquent. Le registre des ports est juste là pour leur faciliter la tâche, pas pour ajouter des contraintes inutiles.

Bien sûr, ce principe n'est pas forcément suivi et des tas de logiciels utilisent le registre des ports en supposant que les services correspondent aux numéros de ports (cf. aussi la section 6.2). C'est fréquent sur les pare-feux, par exemple. On veut couper le DNS, pour forcer l'usage des DNS menteurs, on bloque le port 53, ce qui sera contourné en envoyant le trafic DNS sur un autre port et ainsi de suite. Autre cas où un logiciel utilise le registre des ports pour se faciliter la vie, mais parfois à tort, celui des logiciels d'analyse du trafic réseau, comme tcpdump. Le trafic est avec le port 53, tcpdump l'analyse comme si c'était du DNS. Cela peut mener à des résultats amusants. Ici, tcpdump décode du trafic HTTP en croyant que c'est du DNS :

18:34:03.263985 IP 127.0.0.1.46680 > 127.0.0.1.53: \
        Flags [P.], seq 1:111, ack 1, win 342, \
        options [nop,nop,TS val 240543975 ecr 240543975], \
        length 11021536 update+ [b2&3=0x2f20] \
           [21584a] [18516q] [12081n] [11825au][|domain]

Ce qui le mène à des résultats absurdes comme de croire que la section « Question » du message DNS comprend 18 516 questions... À noter que Wireshark, lui, permet de choisir le décodeur, pour ne pas utiliser celui par défaut d'un port donné (menu Analyze/Analyser, puis Decode as/Decoder[sic]).

Aujourd'hui, au moment de la publication de notre RFC 7605, quelle est l'utilisation de l'espace des ports ? Cet espace est divisé (cf. RFC 6335) en trois catégories, « Système » (sur une machine Unix, il faut être root pour écouter sur ces ports), de 0 à 1 023, « Utilisateur », de 1 024 à 49 151, et « Dynamique » (aussi appelé « Privé », les ports locaux, non enregistrés à l'IANA, contrairement aux deux premières catégories), de 49 152 à 65 535.

Donc, un problème à garder en tête avant de réclamer son port, la nécessite de préserver une ressource finie. L'espace des numéros de ports est partagé par tous les utilisateurs de l'Internet et cet espace est petit, moins de 2^16. Sur les 49 151 numéros ouverts à l'enregistrement (à l'exception, donc, de la catégorie « Dynamique »), 5 850 ont été enregistrés pour TCP. Les enregistrements sont en théorie annulables (RFC 6335, section 8.4) mais permanents en pratique (la procédure du RFC 6335 semble parfaitement irréaliste, cf. aussi la section 7.9 de notre RFC). Il faut donc y aller mollo (cette question du conservatisme dans l'allocation a été une des plus disputées au sein du groupe de travail IETF). Par exemple, chaque service ne devrait avoir qu'un seul numéro de port (outre l'économie des numéros de port, cela évite des problèmes de débogages pénibles au cas où certains ports soient bloqués par un pare-feu et pas d'autres). La section 7.2 détaille cette question des ports multiples.

Donc, plutôt que de demander plusieurs ports pour votre service :

  • Prenez un seul port bien connu et indiquez les éventuels autres ports dynamiquement, comme le passive FTP (RFC 959),
  • Utilisez un service externe pour indiquer un port dynamique, comme le permet le portmapper (RFC 1833),
  • Utilisez une fonction de signalisation du protocole, comme le champ Host: de HTTP, qui évite d'avoir un port (ou une adresse IP) par site Web.

Les ports sont censés permettre de séparer des services différents, pas juste des variations d'un même service.

La section 7 du RFC couvre toutes les questions qu'il faut se poser avant l'enregistrement d'un nouveau port. D'abord, est-il vraiment nécessaire, compte tenu des exigences de conservation indiquées plus haut ?

  • Est-ce vraiment un nouveau service ? Si c'est une variante d'un service existant, il peut réutiliser le port de ce service. Notamment, le port ne devrait pas indiquer la version du service, cette version doit être marquée dans le protocole (notez que POP est une exception à cette règle).
  • Si ce service est expérimental (RFC 3692), pourquoi ne pas utiliser les ports réservés à ces usages expérimentaux (RFC 2780) ?
  • A-t-il vraiment besoin d'un port bien connu, statique ? Ne pourrait-il pas utiliser un port dynamique, indiqué dans la configuration, ou dans le DNS (par exemple avec les SRV) ou dans l'identificateur (comme avec les URL cités plus haut), ou échangé via le protocole (comme fait SIP), ou avec un protocole dédié comme le portmapper cité plus haut ?

OK, on a déterminé qu'on avait vraiment besoin d'un numéro de port, on s'apprête à la demander à l'IANA. Mais quel numéro choisir ? Ce n'est pas une obligation. On peut ne pas indiquer de numéro particulier, et laisser l'IANA en choisir un. En revanche, il faut indiquer si le port doit être dans la plage Système ou dans la plage Utilisateur. La distinction est nettement moins importante aujourd'hui. Autrefois, quand l'Internet ne connectait que des grosses machines gérées professionnellement, la distinction servait à isoler les services critiques des autres. Sur ces grosses machines, l'utilisateur ordinaire ne pouvait pas écouter sur les ports de numéro inférieurs à 1 024 (par exemple, sur Unix, il faut être root pour cela) et cela garantissait que le service sur ces ports était « sérieux ». Aujourd'hui où certains systèmes ne font plus la différence et où, de toute façon, tout le monde est super-utilisateur de son Raspberry Pi, la différence a beaucoup moins de sens. Et cette distinction ne doit pas être utilisé pour la sécurité (cf. section 7.4) comme le faisait malheureusement rlogin. Néanmoins, la différence demeure, au moins comme un marqueur de la criticité du service. La plage Système étant petite et très demandée, les chances d'y obtenir un numéro de port sont plus faibles (il faut un examen par l'IETF ou bien une approbation par l'IESG, RFC 6335, section 8.1, et aussi le RFC 5226, sur la définition des politiques d'enregistrement).

Comme toute ressource limitée dans un espace commun, les numéros de port peuvent susciter des frictions. Une fois le logiciel déployé, il peut être difficile de changer le numéro de port de manière coordonné. D'où les deux règles :

  • Ne pas déployer de code avec un numéro de port statique tant que celui-ci n'a pas été enregistré par l'IANA, afin d'éviter le squat (cf. plus loin),
  • Si on utilise les ports expérimentaux du RFC 4727 (1 021 et 1 022), il ne faut le faire que dans un environnement qu'on contrôle bien, pour garantir qu'on pourra migrer ensuite vers le port final, sans bloquer éternellement ces numéros de port expérimentaux.

Et c'est quoi, ce risque de squat ? C'est l'utilisation d'un port statique sans l'avoir obtenu par les procédures normales. Cela peut être dû à un développeur pressé ou négligent qui écrit son code sans tenir compte des procédures, et le publie. Cela peut être aussi délibéré de la part de gens qui s'estiment au-dessus des règles et qui se réservent sans vergogne une part de la ressource commune. Dans les deux cas, c'est très gênant car, une fois le code largement déployé sur l'Internet, il sera vraiment difficile de le changer, ou même de savoir si le port est encore utilisé (voir aussi la section 7.9). Le squat est donc nettement condamné. Un exemple fameux de squat est l'enregistrement de CARP.

La section 8 de notre RFC couvre les questions de sécurité liées aux ports. D'abord, il ne faut pas se fier au numéro de port. Rien ne garantit que ce qui circule sur le port 53 soit du DNS, et encore moins que ce soit du DNS correct (voir l'exemple plus haut avec tcpdump). Rien ne garantit qu'un paquet où le port source est inférieur à 1 024 a vraiment été émis par une personne de confiance, et ainsi de suite. Les mesures classique d'authentification sont donc nécessaires si on veut vraiment se protéger.

Ensuite, un mot sur la vie privée. Le système des ports bien connus est l'antithèse de la vie privée puisqu'un simple coup d'œil à l'en-tête de couche 4, sans aller examiner le contenu applicatif, indique quel service on utilise. Bien sûr, ce n'est pas une garantie (paragraphe précédent...) mais cela donne déjà une indication. Autre indiscrétion liée aux ports : en envoyant des demandes de connexion TCP à une machine, vers les différents ports (comme ce que fait nmap), on peut savoir quels services elle offre, sans avoir besoin d'analyser les applications. C'est un problème, mais qui est fondamentalement lié à l'architecture de TCP/IP et qui est difficile à corriger (on peut toujours recourir à des trucs comme le port knocking).

Moins directement utile mais passionnante, l'histoire des ports était présentée dans la section 3. Le terme est apparu pour la première fois dans le RFC 33, en 1970 (« We assume here that a process has several input-output paths which we will call ports. »). À l'époque, les couches 3 et 4 étaient encore mêlées, dans le protocole NCP. L'adresse désignant une machine, le port devait désigner une voie de communication d'un processus sur cette machine. (Notez qu'avec des adresses IP suffisamment longues et abondantes, comme ce que fournit IPv6 aujourd'hui, on pourrait se débarrasser complètement de la distinction adresse/port, un préfixe IP pourrait désigner une machine et chaque adresse une prise ou un processus. La séparation adresse/port est le souvenir d'une époque révolue.) Le RFC 37 et le RFC 38 ont ensuite précisé et modifié l'idée (« The destintation [sic] socket must be added to the header of each message on the data link. Presumably this would consist of 32 bits [ce sera finalement 16 bits] immediately after the header and before the marking. »). Puis le RFC 48, toujours en 1970, introduit l'idée d'« écoute » sur un port, lorsqu'un processus est en attente d'une requête. Et le RFC 61 est le premier à se demander comment on est censé connaître le port de destination d'un message, et à introduire le concept de « port bien connu » (well-known port) comme le futur port 80 pour HTTP. Le RFC 76 s'attaque à la question posée, mais non résolue, par le RFC 61 et propose un annuaire permettant d'associer des noms de services à des numéros de port (le /etc/services de votre machine Unix en est le lointain descendant). « most permanently assigned devices and/or processes are known by standard mnemonic labels such as DSK (disk), LP (line printer), CR (card reader), TECO (PDP-10 text editor), etc. »

Une importante étape est ensuite franchie avec le RFC 333 en 1972, qui est le premier à suggérer que les ports de source et de destination servent (avec les adresses IP) à identifier une connexion, ce qui sera le choix final de TCP (RFC 793, en 1981, mais décrit deux ans avant avant dans le document IEN 112). Le RFC 717 est le premier à indiquer des numéros de port officiellement affectés mais c'est le RFC 739, en 1977, qui avait généralisé l'idée (sous le nom de socket number). Dans ce RFC, telnet avait déjà le port 23, qu'il a gardé jusqu'à aujourd'hui, comme bien des protocoles depuis oubliés. Les procédures de l'époque étaient plus simples qu'aujourd'hui (« please contact Jon [Postel] to receive a number assignment »).

Quant au RFC 758, il était le premier à étendre le concept de port à TCP (les RFC précédents ne parlaient que de NCP). Certaines plages de numéros de ports étaient réservées à des usages spécifiques, mais son successeur, le RFC 820, n'a pas retenu cette distinction (en prime, le RFC 820 a étendu l'usage des ports à UDP). Avec le RFC 900 disparait la notation octale, avec le RFC 1340 (en 1992), la liste des « ports bien connus » va désormais de 0 à 1 023 et plus seulement jusq'à 255 (on y note l'apparition de 80, pour HTTP). Cette liste sera encore révisée dans le RFC 1700 puis remplacée en 2002 par un registre en ligne à l'IANA, registre décrit par le RFC 3232. (Le RFC listant les ports était toujours en retard sur l'allocation réelle.)


Téléchargez le RFC 7605


L'article seul

Un exemple de problème dans BGP

Première rédaction de cet article le 24 juillet 2015


« On » me demande parfois quels outils utiliser pour analyser un problème BGP quand on n'a pas accès à un routeur de la DFZ (d'ailleurs, certaines techniques ici peuvent servir même dans ce cas). Voici un exemple avec la panne de plus de deux heures de Swift hier 22 juillet.

Point de départ, la machine 204.13.164.192 n'est plus joignable. Bête panne d'un serveur, comme cela arrive tout le temps sur l'Internet ? Non, cette fois, c'est plus rigolo, le préfixe IP 204.13.164.0/24 qui l'englobe a disparu de la table de routage mondiale. De même que d'autres préfixes du même opérateur, comme 204.8.32.0/24 (qui héberge notamment les serveurs DNS de swiftco.net, rendant ce nom de domaine inutilisable ; on ne le répétera jamais assez, il faut mettre ses serveurs DNS dans plusieurs réseaux différents).

Comment voir ce que contient cette table de routage ? Si on a accès à un routeur qui a une table complète, on peut le faire soi-même mais, si ce n'est pas le cas, on peut utiliser un des innombrables looking glasses qui vous donnent un accès indirect à ces routeurs. Par exemple, voici ce que donne celui de Hurricane Electric une fois la panne réparée (on voit les routes pour le 204.8.32.0/24, pendant la panne, on avait « None of the BGP4 routes match the display condition ») : swift-he-lg.png

Qu'on utilise ce looking glass ou bien qu'on passe par un de ses routeurs à soi, on n'a qu'une vision immédiate. Il serait intéressant de pouvoir regarder le passé, notamment si on a été prévenu trop tard et qu'on veut investiguer a posteriori. C'est ce que permet RIPEstat qui fournit tout un tas d'outils d'analyse (qui ne sont pas toujours d'un abord facile). L'un des plus simples est le BGP Update activity. Voici ce qu'il affichait juste après la réparation : swift-ripestat.png

On y voit une grosse activité BGP vers 0810 UTC au moment où le préfixe, pour une raison inconnue, était retiré. Cette activité comporte des retraits (withdraw) mais aussi des annonces (announce). C'est normal, les routeurs BGP réagissent au retrait en annonçant des routes alternatives pendant une minute ou deux, le temps que tous réalisent que le préfixe est bien retiré, qu'il n'y a pas d'alternative. Puis on voit une autre période d'activité vers 1045 UTC au moment où ça repart. Celle-ci ne comporte que des annonces.


L'article seul

RFC 7608: IPv6 Prefix Length Recommendation for Forwarding

Date de publication du RFC : Juillet 2015
Auteur(s) du RFC : M. Boucadair (France Telecom), A. Petrescu (CEA, LIST), F. Baker (Cisco Systems)
Réalisé dans le cadre du groupe de travail IETF v6ops
Première rédaction de cet article le 23 juillet 2015


Comme IPv4, IPv6 route les paquets en fonction d'un préfixe d'adresses, préfixe qui a une longueur comprise entre 0 (tout l'Internet) et 128 bits (une seule machine). Ce très court RFC a juste pour but de rappeler cette règle : la longueur d'un préfixe est quelconque, les mises en œuvres de IPv6, logicielles ou matérielles, ne doivent pas imposer ou favoriser une longueur de préfixe particulière (même pas 64, souvent considéré, à tort, comme spécial). Le routage se fait exclusivement sur le plus long préfixe, quelle que soit sa longueur.

Il est normal qu'IPv6 et IPv4 fassent pareil, ce sont après tout deux versions du même protocole. IPv4 utilisait autrefois un système différent mais, depuis CIDR, il suit les mêmes règles qu'IPv6 : le routage se fait sur la base d'un préfixe d'adresses de longueur quelconque. C'est le préfixe le plus long qui est choisi. Ainsi, pour prendre un exemple IPv4, si la destination est 203.0.113.51 et qu'il existe deux routes possibles, une vers le préfixe 203.0.113.0/26 (longueur 26 bits) et l'autre vers le préfixe 203.0.0.0/18, c'est la première, la plus spécifique (le préfixe le plus long) qui gagne. En IPv6, si on veut envoyer un paquet à 2001:db8:440:fe::25a:9ff et qu'il existe deux routes possibles, 2001:db8:440:fe::/80 (longueur 80 bits) et 2001:db8:440::/48, c'est la première qui est choisie. Le routage sur la base du préfixe le plus long, un concept fondamental d'IP, c'est juste ça. (Le terme de CIDR, introduit par le RFC 1380 et décrit dans le RFC 4632, terme très spécifique à IPv4 et aujourd'hui dépassé techniquement depuis l'abandon de l'ancien système des classes, n'est pas utilisé pour IPv6.)

Mais pas mal de gens qui ne connaissent pas bien IPv6 ont des idées fausses à ce sujet et croient, par exemple, que les préfixes de longueur 64 bits ont un rôle particulier pour le routage, voire que les préfixes comme le /80 donné en exemple plus haut sont illégaux. Le RFC 4291, qui normalise l'adressage IPv6, dit bien (dans sa section 2.5) que n'importe quelle longueur de préfixe (« arbitrary bit-length ») est possible. Mais c'est vrai que la confusion peut venir du rôle particulier de certaines longueurs, notamment 64, dans d'autres utilisations que le routage. Ainsi, le RFC 7421 note que les préfixes plus longs que 64 bits ont des problèmes pour certaines utilisations, comme le SLAAC. Mais il s'agit là de questions liées à l'adressage : cela ne devrait pas affecter le routage, si on veut que les changements futurs de l'adressage n'empêchent pas les routeurs de fonctionner (deux exemples de changement d'adressage : au début d'IPv6, il était envisagé que ce soit /80 plutôt que /64 qui soit la longueur de préfixe « de référence » et, autre exemple, la recommandation pour les liens point à point a varié de /64 à /127, cf. RFC 6164).

Donc, pour résumer, l'adressage est une chose (et les recommandations du RFC 7421, indiquant les avantages à utiliser du /64 pour un lien local, continuent à s'appliquer), le routage en est une autre : le routage IPv6 doit suivre l'algorithme du préfixe le plus long, et ne doit pas avoir de longueurs de préfixes privilégiées ou spéciales.

Cette exigence est formalisée dans la section 2 de notre RFC :

  • Les routeurs IPv6 doivent suivre les règles de la section 5.1 du RFC 4632.
  • La transmission d'un paquet doit se faire sur la base du préfixe le plus long et toutes les longueurs sont également acceptables, même 128, même des valeurs qui ne sont pas un multiple de 8.

Ces règles s'appliquent au code des routeurs : l'administrateur d'un routeur donné peut toujours avoir sa propre politique (par exemple, en BGP, ne pas accepter de préfixes plus longs que 48 bits) mais cela ne doit pas se retrouver dans le logiciel, autrement, les futures évolutions seraient sérieusement compliquées.


Téléchargez le RFC 7608


L'article seul

Thunderbird contre Logjam

Première rédaction de cet article le 22 juillet 2015


La sécurité informatique, c'est compliqué. Voilà qu'un utilisateur d'un serveur de messagerie que je gère me signale qu'il ne peut plus lire son courrier avec Thunderbird. Et je découvre que le problème était en fait dû au zèle que mettait Thunderbird à protéger ses utilisateurs de la faille Logjam.

Avant de revenir sur cette faille et sur la solution, voici les symptômes : Thunderbird était configuré pour récupérer le courrier avec POP. Récemment mis à jour automatiquement, il ne récupère plus de courrier. Apparemment pas de messages d'erreurs côté client, mais pas de courrier non plus. Côté serveur (un Courier), on trouve juste dans le journal :

pop3d-ssl: couriertls: accept: error:14094417:SSL routines:SSL3_READ_BYTES:sslv3 alert illegal parameter

Message sybillin, non, d'autant plus que ce serveur refuse évidemment SSLv3, comme le dit le RFC 7568. C'est ça, les messages d'erreur d'OpenSSL...

Bon, je n'ai pas eu trop à chercher, des tas de gens avaient le même problème (par exemple chez CentOS). Deux bogues enregistrées chez Mozilla (la fondation qui développe Thunderbird) donnaient les détails : #1183650 et #1184488. L'explication est simple : la mise à jour de Thunderbird (ou plus exactement celle de la bibliothèque TLS NSS dont il dépend), introduit un refus des paramètres Diffie-Hellman trop faibles.

De quoi s'agit-il encore ? La faille de sécurité Logjam, contre le protocole TLS, concerne les échanges de clés Diffie-Hellman. TLS peut fonctionner sans Diffie-Hellman (et c'est pour cela que certaines utilisateurs n'ont pas eu de problèmes) mais, si on l'utilise, l'échange de clé peut être deviné par un attaquant car les groupes Diffie-Hellman ont pu être pré-calculés, surtout s'ils sont trop petits (768 bits par exemple, taille souvent utilisée par défaut, cf. la bogue Debian #787579). Outre le site officiel de Logjam, on peut consulter sur cette faille une excellente explication chez Cloudflare. Donc, Thunderbird (ou plutôt NSS) refuse désormais les paramètres Diffie-Hellman trop faibles. Testons notre serveur (le problème initial concernait aussi bien POP que IMAP, ici, je teste le serveur IMAP) :

% openssl s_client -connect server.bortzmeyer.org:993
CONNECTED(00000003)
...
No client certificate CA names sent
Peer signing digest: SHA512
Server Temp Key: DH, 768 bits
...
* OK [CAPABILITY IMAP4rev1 UIDPLUS CHILDREN NAMESPACE THREAD=ORDEREDSUBJECT THREAD=REFERENCES SORT QUOTA IDLE AUTH=PLAIN ACL ACL2=UNION] Courier-IMAP ready. Copyright 1998-2011 Double Precision, Inc.  See COPYING for distribution information.

En effet, avec ses 768 bits (DH = Diffie-Hellman), le serveur ne suit pas les bonnes pratiques et c'est pour cela que Thunderbird coupe la communication.

Quelle est la solution ? Le site officiel de Logjam a une bonne page d'explications pour les administrateurs système mais, ici, j'ai simplement utilisé le commentaire 13 dans la bogue Mozilla #1184488. Il faut regénérer des paramètres Diffie-Hellman. Le serveur est une machine Debian, les paramètres sont en /etc/courier/dhparams.pem, et le script à utiliser, mkdhparams, est fourni avec Courier. À noter que sa documentation est inexacte sur la méthode à utiliser pour augmenter le nombre de bits (bogue Debian #793184). J'ai choisi une taille de 3 072 bits (plutôt exagérée aujourd'hui mais c'est ce qui est recommandé par le RGS) et j'ai donc fait :

server# export DH_BITS=3072

server# mkdhparams                  
512 semi-random bytes loaded
Generating DH parameters, 3072 bit long safe prime, generator 2
This is going to take a long time
................................................+....... 
...
server# /etc/init.d/courier-imap-ssl restart
[ ok ] Restarting courier-imap-ssl (via systemctl): courier-imap-ssl.service.
server# 

Testons le résultat :

% openssl s_client -connect server.bortzmeyer.org:993
CONNECTED(00000003)
...
No client certificate CA names sent
Peer signing digest: SHA512
Server Temp Key: DH, 3072 bits
...
* OK [CAPABILITY IMAP4rev1 UIDPLUS CHILDREN NAMESPACE THREAD=ORDEREDSUBJECT THREAD=REFERENCES SORT QUOTA IDLE AUTH=PLAIN ACL ACL2=UNION] Courier-IMAP ready. Copyright 1998-2011 Double Precision, Inc.  See COPYING for distribution information.
closed

Parfait, cette fois, ça marche, et Thunderbird est content, il peut récupérer le courrier de manière sécurisée.

Amusante coïncidence, le lendemain de cet article, à la réunion IETF de Prague, Aaron Zauner faisait un excellent exposé sur des tests de la sécurité des serveurs de courrier (SMTP, POP et IMAP) qu'il avait réalisés dans l'Internet. Beaucoup d'entre eux sont encore vunérables à Logjam.


L'article seul

RFC 7558: Requirements for Scalable DNS-SD/mDNS Extensions

Date de publication du RFC : Juillet 2015
Auteur(s) du RFC : K. Lynn (Verizon), S. Cheshire (Apple), M. Blanchet (Viagenie), D. Migault (Ericsson)
Pour information
Réalisé dans le cadre du groupe de travail IETF dnssd
Première rédaction de cet article le 17 juillet 2015


Pour résoudre des noms de domaine en informations (comme l'adresse IP) sur le réseau local, sans configurer de serveur DNS, nous avons mDNS (RFC 6762). Pour découvrir des services (par exemples les imprimantes) avec ce mDNS, nous avons DNS-SD (RFC 6763). Mais ces deux techniques, mDNS et DNS-SD, ne fonctionnent que sur un seul segment du réseau, à l'intérieur d'un domaine de diffusion. Il serait bien pratique de pouvoir les utiliser dans un réseau étendu (comme l'Internet...). Ce RFC décrit le problème, les souhaits et établit une liste d'exigences pour cette extension de mDNS et DNS-SD « au-delà du lien local ». (À l'heure actuelle, on n'a pas encore de solution satisfaisant ces exigences.)

C'est par conception que mDNS (RFC 6762) ne passe pas les routeurs IP. Ce protocole marche par diffusion. On crie à la cantonade « qui connait iPhone-de-Jean-Bernard ? » et la machine qui se reconnait répond. mDNS s'appuie donc sur un service de couche 2, la diffusion, et ne fonctionne donc pas sur un réseau composé de plusieurs segments L2 reliés par des routeurs.

Or, il y a évidemment des cas où on voudrait des services comme ceux fournis par mDNS et DNS-SD au-delà du lien local. Parce que le campus ou l'entreprise où on travaille a plusieurs segments L2 (par exemple un pour le filaire et un pour le WiFi), ou bien parce qu'on travaille avec une association située à des centaines de kilomètres, mais joignable par l'Internet. Il n'existe pas actuellement de solutions standard pour cela. Et pas encore de consensus sur la façon la plus propre de le faire.

Autre cas où on se retrouve facilement coincé, celui de réseaux ad hoc comme les 6LowPAN (RFC 6568) où chaque machine ou presque peut devenir routeur (RFC 4903).

D'ailleurs, même en l'absence de ce problème multi-segments, la technique de mDNS, la diffusion (globale, ou bien restreinte) n'est pas idéale dans tous les cas. Sur de l'Ethernet filaire, la diffusion consomme relativement peu de ressources. Mais, sur certains segments, la diffusion coûte cher. En WiFi, elle peut vite mener à consommer une bonne partie de la capacité, d'autant plus qu'il faut ralentir au niveau du récepteur le plus lent (cf. section 2.2). Au passage, autre problème de 802.11 : il n'y a pas d'accusé de réception des trames diffusées et donc des pertes peuvent se produire.

La section 2 de notre RFC décrit le problème qu'on veut résoudre. D'abord, on voudrait pouvoir découvrir des ressources distantes (comme des imprimantes ou des serveurs de fichier) même si elles ne sont pas sur le même segment L2. Actuellement, la seule solution standard est le DNS classique. Cela nécessite soit une configuration manuelle par l'administrateur système, ce qui fait du travail, surtout en cas de changement (on modifie l'adresse IP de l'imprimante mais on oublie de changer la base DNS : tous les sites n'ont pas forcément un IPAM intégré qui prend en charge tout cela et tous les réseaux ne sont pas centralement gérés). Autre solution avec le DNS classique, autoriser les mises à jour dynamiques du DNS, ce qui implique qu'on configure les imprimantes pour faire ces mises à jour.

Et la solution à ce problème doit marcher pour des cas où on a des centaines ou des milliers de machines, et à un coût raisonnable (y compris le coût pour le réseau en terme de trafic).

Les réseaux contraints (LLN pour Low power and Lossy Networks, cf. RFC 7102) posent des défis particuliers. Ils sont souvent multi-segments, avec des nœuds devenant routeurs pour prolonger la portée des ondes radio, et ne peuvent donc pas se contenter des actuels mDNS et DNS-SD. Mais ils connectent souvent des machines peu dotées en ressources. Celles-ci sont parfois injoignables (hibernation ou déconnexion) et on ne peut donc pas compter sur leur présence permanente. Ainsi, mDNS assure l'unicité des noms par la vérification, par une nouvelle machine, que le nom n'était pas déjà présent sur le réseau. Si le possesseur de ce nom hiberne, il ne pourra pas « défendre » son nom.

La section 3 du RFC présente ensuite quelques scénarios d'usage concrets, pour qu'on se fasse une meilleure idée de cas où mDNS et DNS-SD ne suffisent pas. D'abord, un cas de base, le PAN (Personal Area Network, qui regroupe les machines d'un seul utilisateur, par exemple, dans un cas trivial, son PC portable et son imprimante). Pas de routeur présent, mDNS et DNS-SD suffisent bien et résolvent tous les problèmes. On passe ensuite à un cas un peu plus riche : une maison, avec un routeur qui connecte à un FAI et un réseau local d'un seul segment (il peut y avor plusieurs segments physiques, par exemple filaire et WiFi, mais le routeur, qui fait également point d'accès WiFi, les présente comme un seul réseau L2. C'est le réseau de M. Michu aujourd'hui et, là encore, mDNS et DNS-SD marchent bien.

On passe ensuite au réseau SOHO ou bien à la maison « avancée ». Cette fois, on introduit plusieurs routeurs (RFC 7368). Un tel réseau peut s'auto-organiser (il n'y a typiquement pas d'administrateur réseaux professionnel) mais la résolution de noms devient difficile, mDNS ne fonctionnant plus (il ne passe pas les routeurs).

Ensuite viennent les réseaux d'« entreprise » (en fait, de n'importe quelle grande organisation, entreprise à but lucratif ou pas). Plusieurs routeurs, des réseaux compliqués mais, cette fois, on a des administrateurs réseaux professionnels pour s'en occuper. À noter que les grands réseaux des conférences (comme le réseau WiFi des réunions IETF) rentrent dans cette catégorie. mDNS ne marche plus mais on peut désormais avoir des serveurs DNS administrés sérieusement.

Le RFC cite un cas encore plus élaboré, avec les NREN, qui mèlent administration centrale du réseau national, avec des équipes qui gèrent des réseaux régionaux ou de campus.

Et les réseaux « mesh » ? Ils sont multi-segments mais en général pas administrés, ils posent donc le plus de problèmes.

Bon, assez de préliminaires, les exigences maintenant, le vrai cahier des charges. Il figure en section 4. Les exigences sont notées REQn où N est un numéro de 1 à 15. REQ1, par exemple, dit qu'il faut un mode d'auto-configuration permettant à la future solution de marcher toute seule, pour le cas des réseaux non administrés. Mais attention, le RFC précise aussi que les objectifs de sécurité, de passage à l'échelle, de facilité et de déployabilité sont souvent contradictoires et qu'il ne faut pas prendre les exigences isolément mais en groupe (il faudra parfois en sacrifier une pour atteindre l'autre).

REQ2, complémentaire de REQ1, dit que pour les réseaux administrés, il faut pouvoir configurer le mécanisme de manière à partitionner le réseau, pour éviter qu'une requête ne voyage partout (voir aussi REQ15). REQ3 demande que cette possibilité de partition ne se fasse pas sur des critères topologiques (si on a deux segments dans un même bâtiment et un troisième dans un autre bâtiment, il faut pouvoir faire une partition regroupant un des segments du bâtiment et le segment de l'autre bâtiment, voir aussi REQ7).

Parmi les autres exigences, le fait (REQ5) de réutiliser les protocoles existants, notamment mDNS (RFC 6762) et DNS-SD (RFC 6763), l'obligation de fonctionner sur des réseaux où la consommation électrique est un facteur crucial (REQ10, qui dit en gros que le protocole ne doit pas réveiller toutes les machines toutes les cinq minutes), la nécessité de marcher correctement sur des réseaux de plusieurs milliers de machines (REQ11), l'importance de fournir aux utilisateurs un vécu identique que les ressources qu'ils cherchent soient locales au lien ou au contraire distantes (REQ12), le souhait que l'information présentée audit utilisateur ne soit pas dépassée (pas question de lui montrer les services tels qu'ils étaient il y a deux heures, ou même simplement deux minutes, REQ13), etc.

Après cette liste d'exigences, la section 5 de notre RFC se penche sur un problème délicat, la coexistence de plusieurs espaces de noms. En effet, si on utilise le DNS « normal », les noms sont uniques, et c'est une des propriétés les plus essentielles du DNS (RFC 2826). Mais si on utilise mDNS, chaque segment réseau a ses propres noms, sous le TLD .local. On peut parfaitement avoir une Imprimante-Couleur.local dans un bâtiment et voir une toute autre imprimante sous le même nom dans un autre bâtiment. Les noms ne sont plus mondialement uniques. Comme beaucoup d'engins seront livrés avec des noms par défaut identiques, ces « collisions » seront fréquentes. Le problème reste ouvert (voir aussi la section 6.2).

Enfin, la section 6 du RFC se préoccupe de la sécurité. Bien sûr, l'exigence d'un service automatique et efficace ne va pas forcément dans le sens de la sécurité (difficile d'authentifier sans ennuyer les utilisateurs, par exemple). Mais il y a aussi d'autres pièges. Par exemple, avec le mDNS traditionnel, les requêtes et les réponses ont une portée limitée (au seul segment de réseau local). Si on donne un nom à sa machine, le nom ne sera vu que localement et l'utilisateur peut donc donner un nom ridicule ou grossier sans trop de risques. Avec le projet d'étendre cette résolution de noms plus loin que le réseau local, le nom donné aura davantage de conséquences. Sans même parler du cas de noms à problèmes, une extension de la découverte de services peut faciliter la tâche d'un attaquant (imaginez ce que Shodan ferait d'un tel service) et/ou permettre/faciliter l'accès à des ressources qu'on pensait privées (une imprimante, par exemple). Bien sûr, la découverte d'un service n'implique pas son accessibilité mais le risque est quand même là.

Autre problème, la vie privée. Déjà, aujourd'hui, une technologie comme Bonjour est très bavarde. Un Mac ou un iPhone diffusent à tout le réseau local en donnant le nom de l'utilisateur ("l'iPhone de Jean Durand"). Mais le problème ne peut que s'aggraver si on va plus loin que le réseau local. Ce n'est sans doute pas une bonne idée qu'une machine arrivant dans un réseau inconnu annonce le nom de son propriétaire immédiatement. À noter que, en juillet 2015, une expérience de collecte du trafic diffusé à la réunion IETF de Prague a suscité de nombreuses discussions.


Téléchargez le RFC 7558


L'article seul

RFC 7578: Returning Values from Forms: multipart/form-data

Date de publication du RFC : Juillet 2015
Auteur(s) du RFC : L. Masinter (Adobe)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF appsawg
Première rédaction de cet article le 15 juillet 2015


Voici la nouvelle définition du type de données Internet multipart/form-data, qui est notamment envoyé par les navigateurs Web une fois qu'on a rempli un formulaire. Elle remplace la définition du RFC 2388.

Il y a plusieurs façons de représenter les données d'un formulaire rempli (cf. annexe B de notre RFC). (Et il faut aussi se rappeler qu'il n'y a pas que les formulaires en HTML : le format décrit dans ce RFC peut servir à d'autres types de formulaires.) Les deux plus fréquentes sont le format par défaut des formulaires Web, application/x-www-form-urlencoded, et le multipart/form-data qui fait l'objet de notre RFC. La sagesse générale des développeurs Web (citée par exemple dans la norme HTML 4) est d'utiliser application/x-www-form-urlencoded sauf s'il faut transmettre des fichiers ou des données binaires, auquel cas on préfère multipart/form-data. En HTML, cela se choisit par l'attribut enctype. Voici un exemple de formulaire HTML pour envoyer un fichier :

  
<form action="http://www.example.com/register"
       enctype="multipart/form-data"
       method="post">
   <p>
   What is your name? <input type="text" name="submit-name"/>
   What files are you sending? <input type="file" name="thefile"/>
   <input type="submit" value="Send"/> 
 </form>
  

Si l'utilisateur « Larry » envoie ainsi le fichier fi1e1.txt, le navigateur encodera les données du formulaire ainsi :

Content-Type: multipart/form-data; boundary=---------------------------14768918103265920051546586892
Content-Length: 359

-----------------------------14768918103265920051546586892
Content-Disposition: form-data; name="submit-name"

Larry
-----------------------------14768918103265920051546586892
Content-Disposition: form-data; name="thefile"; filename="file1.txt"
Content-Type: text/plain

   ... contents of file1.txt ...

-----------------------------14768918103265920051546586892--

Alors que l'encodage pour du application/x-www-form-urlencoded aurait été submit-name=Larry&thefile=file1.txt (ce qui ne convient pas pour le fichier). Cette différence entre les formats des données des formulaires est bien expliquée dans cette réponse sur StackOverflow. Et si vous voulez expérimenter vous-même avec netcat, voyez cette autre réponse.

Vu de l'utilisateur, les choses se passent comme cela (section 1 de notre RFC) : on présente à l'utilisateur un formulaire theform.png L'utilisateur le remplit, il sélectionne (par exemple en cliquant) le contrôle qui sert à dire « j'ai fini, traite-moi ce formulaire ». Le contenu est envoyé à une application sur le serveur. (Petit souvenir personnel : les formulaires sont apparus avec la version 2 de Mosaic et, pendant un certain temps, il était difficile de compter dessus car tout le monde n'avait pas encore mis à jour. Mais ça semblait formidable d'avoir un formulaire en Motif développé avec juste trois lignes d'HTML.)

Quel est le format de ce contenu qu'on envoie ? Il faut se rappeler que les formulaires ne sont pas spécifiques au Web, à HTML et à HTTP : le format peut être utilisé dans toute application qui a une notion de formulaire. Notre RFC ne spécifie pas le formulaire, ni le traitement sur le serveur de réception, mais uniquement le format de transport du formulaire rempli.

Il travaille donc sur une vision abstraite d'un formulaire, composé d'une séquence de champs, chaque champ ayant une valeur, fournie par l'utilisateur (certains champs peuvent avoir une valeur par défaut). Les champs ont un nom, qui est une chaîne de caractères Unicode (mais il est conseillé de se limiter à ASCII si on veut maximiser les chances d'interopérabilité). Il est également conseillé que les noms des champs soient uniques.

La section 4 de notre RFC détaille le format complet. Un message multipart/form-data suit de près le format des autres multipart/ MIME (RFC 2046, section 5.1). Comme son nom l'indique, il est composé de plusieurs parties séparées par une frontière, une ligne commençant par deux tirets. La valeur complète de cette ligne-frontière est donnée dans le champ Content-Type:. Il ne faut évidemment pas que cette ligne apparaisse dans les données envoyées.

Pour chaque partie, il est obligatoire d'avoir un champ Content-Disposition: (RFC 2183) avec un paramètre name qui indique le nom original du champ. Si la partie concerne un fichier qui a été envoyé, le RFC recommande que le champ Content-Disposition: contienne un paramètre filename, suggérant au serveur un nom pour le fichier. (« Suggérant » car, pour des raisons de sécurité, le serveur ne doit pas utiliser ce nom aveuglément, cf. aussi la section 7.)

Problème toujours intéressant, le jeu de caractères utilisé, et son encodage. On peut mettre un paramètre charset au Content-Type: de chaque partie MIME. Mais il est plus fréquent d'avoir un tel paramètre qui soit global. En HTML, la convention est qu'un champ caché du formulaire, nommé _charset_, fixe l'encodage par défaut. (Rappelez-vous que, dans les protocoles IETF et W3C, charset est mal nommé : c'est un encodage, plus qu'un jeu de caractères.) D'autre part, lorsque le transport du multipart/form-data est « 8-bit clean », ce qui est le cas de HTTP, l'utilisation du Content-Transfer-Encoding: est déconseillée.

La section 5 rassemble un ensemble de conseils pratiques pour la bonne transmission et interprétation des données des formulaires. D'abord, il est fortement déconseillé (même si, légalement parlant, ce n'est pas systématiquement interdit) d'éviter les caractères autres que ceux d'ASCII pour les noms des champs dans un formulaire. Ce n'est pas grave en pratique puisque ces noms, contrairement aux étiquettes affichées dans le formulaire, ne sont pas visibles à l'utilisateur. Voici un exemple en HTML :


<p>Envoyez une copie de votre carte d'identité 
<input type="file" name="idscan"/></p>

Le texte d'accompagnement comprend des caractères non-ASCII mais pas le paramètre name.

Toujours d'un point de vue pratique, quelques conseils de sécurité en section 7 :

  • Les données envoyées peuvent être des données personnelles, voire sensibles. C'est d'autant plus vrai que certains navigateurs Web ont une fonction d'auto-remplissage qui met automatiquement des informations personnelles dans les formulaires, ce qui fait qu'un utilisateur distrait peut envoyer davantage d'informations qu'il ne le voulait. L'auteur du formulaire et de son traitement doit donc faire attention à ces données.
  • Le contenu du fichier peut être dangereux (malware).

Le type multipart/form-data est, comme les autres types MIME, enregistré à l'IANA.

Quels sont les changements depuis le RFC 2388 ? Le format a été spécifié à l'origine dans le RFC 1867 puis dans la norme HTML 3.2. L'annexe A de notre RFC détaille les changements, parmi lesquels :

  • Les noms des champs non-ASCII doivent désormais être en UTF-8 et non plus encodés selon la méthode du RFC 2047 (mais, de toute façon, il est recommandé de les éviter). Cf. la section 5.1
  • Lorsque plusieurs fichiers sont envoyés (pour un même champ du formulaire), l'ancienne recommandation (RFC 2388) était d'utiliser un multipart/mixed, la nouvelle est de mettre chaque fichier dans une partie MIME spécifique (en utilisant le même nom de champ).
  • La convention du champ _charset_ (encodage par défaut) est désormais documentée.

Téléchargez le RFC 7578


L'article seul

RFC 7574: Peer-to-Peer Streaming Peer Protocol (PPSPP)

Date de publication du RFC : Juillet 2015
Auteur(s) du RFC : A. Bakker (Vrije Universiteit Amsterdam), R. Petrocco, V. Grishchenko (Technische Universiteit Delft)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF ppsp
Première rédaction de cet article le 14 juillet 2015


Le pair-à-pair est un succès énorme de l'Internet et du contenu en quantités impressionnantes est échangé tous les jours avec des techniques fondées sur ce principe. Toutefois, il s'agit surtout de téléchargement (obtenir un contenu statique) alors qu'on voudrait pouvoir utiliser le même concept, le pair-à-pair, pour du ruissellement (streaming), afin de distribuer du contenu dynamique, comme un évenement en train de se produire et qu'on filme. C'est ce que permet le nouveau protocole PPSPP (Peer-to-Peer Streaming Peer Protocol), que normalise ce RFC. Son but est de fournir l'équivalent de BitTorrent pour du contenu dynamique, et beaucoup de concepts de PPSPP sont très proches de BitTorrent (cf. son cahier des charges, dans le RFC 6972).

Dans PPSPP, le contenu est « auto-certifié ». L'identificateur d'un contenu permet sa vérification. Contrairement au contenu statique, on ne peut pas utiliser un simple condensat cryptographique (méthode de BitTorrent) puisqu'on ne connait pas tous les octets à l'avance. PPSPP se sert donc d'un arbre de Merkle calculé récursivement au fur et à mesure que le contenu est disponible (comme cela avait été proposé pour BitTorrent, voir aussi la section 5.5). L'identificateur du contenu est le condensat cryptographique de la racine de cet arbre de Merkle. Grâce à cette auto-certification, un pair malveillant ne pourra pas modifier le contenu (il reste à s'assurer de l'authenticité de l'identificateur mais c'est une autre histoire... BitTorrent a le même problème.)

PPSPP est un protocole applicatif qui peut tourner sur plusieurs protocoles de transport. À l'heure actuelle, le seul normalisé est LEDBAT (RFC 6817), le protocole « durable », qui n'envoie des octets que lorsque le tuyau est libre. Ainsi, l'usage de PPSPP ne va pas perturber les autres applications. (La section 8 détaille l'usage de LEDBAT sur UDP.)

PPSPP peut découvrir la liste des pairs de plusieurs façons : via un tracker centralisé, ou via une DHT. Ce nouveau RFC suppose la liste des pairs déjà connue et ne décrit que le protocole pour récupérer le contenu. L'obtention de la liste fera l'objet d'autres travaux.

La section 2 de notre RFC présente le protocole, à travers trois exemples. D'abord, un pair qui rejoint un essaim (swarm). Un utilisateur humain regarde une page Web contenant un élément <video>. Son navigateur Web lui a présenté une image avec les contrôles habituels comme un bouton Play. L'utilisateur clique sur ce bouton. L'URL derrière la vidéo indique du PPSPP. Le navigateur va alors récupérer la liste des pairs (rappelez-vous que ce point n'est pas couvert dans ce RFC). Supposons qu'on utilise un tracker centralisé. Le logiciel PPSPP va s'enregistrer auprès de ce tracker. Il a une liste de pairs, il peut commencer à parler le protocole PPSPP avec eux. D'abord, le message HANDSHAKE (section 3.1 de notre RFC). Ensuite, il recevra des messages HAVE (section 3.2) indiquant quels sont les parties du flux de données que ses pairs connaissent déjà et peuvent donc fournir à leurs pairs. Il est maintenant un membre de l'essaim.

Deuxième exemple, on veut échanger des données. Notre logiciel PPSPP va envoyer des messages REQUEST (section 3.7) indiquant ce qui l'intéresse, en tenant compte des HAVE reçus. Les pairs envoient des messages DATA (section 3.3) contenant les octets de la vidéo, ainsi que des messages INTEGRITY (section 3.5) contenant les éléments de l'arbre de Merkle et permettant de vérifier que des intermédiaires n'ont pas modifié la vidéo (les détails sur cette vérification sont dans la section 5).

Une fois que notre logiciel a des données, il peut téléverser (to upload). Il va à son tour envoyer des messages HAVE aux pairs, et répondre à des requêtes REQUEST.

Le départ « propre » de l'essaim se fait en envoyant un message HANDSHAKE (et en se désincrivant du tracker, s'il y en a un). Mais, évidemment, dans un réseau pair-à-pair, il est fréquent que des machines ne partent pas proprement : coupure du réseau, plantage de la machine ou du logiciel, etc. Les pairs doivent donc être prêts à gérer le cas de pairs qui ne répondent plus.

La section 3 de notre RFC présente tous les messages qui peuvent être échangés (rassurez-vous : je n'en couvre qu'une partie mais ils ne sont pas si nombreux, seulement douze types). Les messages ne demandent pas de réponse : une absence de nouvelles de la part du pair indique qu'il y a un problème. Par exemple, si on envoie un message HANDSHAKE à des pairs qui ne veulent pas de nous, ils ne répondront pas avec un message d'erreur, ils s'abstiendront simplement de répondre. Il y a donc deux sortes de pairs : ceux qui répondent vite et bien et ceux qui répondent peu ou pas, et qu'on va donc petit à petit décider d'ignorer. On n'insiste pas avec les pairs non répondants.

À noter que PPSPP ignore le format des données envoyées : il transmet des octets, sans savoir si c'est du MPEG nu, ou bien un container rassemblant plusieurs fichiers, comme le permettent des formats comme AVI. PPSPP est un protocole de transfert de données, pas une solution complète de télé-diffusion.

Parmi les points à noter dans les messages : chaque essaim transmet un flot d'octets et un seul (cf. l'avertissement ci-dessus sur les containers). Un essaim a un identificateur (swarm ID), échangé dans les messages HANDSHAKE. Ces messages contiennent également d'autres paramètres (cf. section 7) comme la taille des morceaux (chunks) ou comme la fonction exacte utilisée pour l'arbre de Merkle. Le flot d'octets est en effet découpé en morceaux, chacun ayant un identificateur (chunk ID). Cet identificateur est un paramètre des messages HAVE, REQUEST et DATA. Ainsi, un message DATA contient un morceau, et l'identificateur de ce morceau. Cela permet au pair de savoir où il en est et s'il lui manque quelque chose.

J'ai parlé plus haut du message INTEGRITY qui contient un condensat cryptographique d'un sous-arbre de l'arbre de Merkle correspondant au contenu transmis. Les messages INTEGRITY ne sont pas signés donc ils ne protègent que contre les accidents, pas contre un pair malveillant. Il existe des messages SIGNED_INTEGRITY qui, eux, sont signés (cf. sections 5 et 6.1). À noter que, dans ce cas, la clé publique est dans l'identificateur de l'essaim, encodée en suivant le format des DNSKEY de DNSSEC.

Les messages REQUEST, mentionnés plus haut, servent à demander une partie du flot de données. Contrairement à BitTorrent, ils ne sont pas indispensables : un pair peut vous envoyer des morceaux que vous n'avez pas explicitement demandé. C'est logique pour PPSPP, qui est prévu pour le ruissellement : PPSPP est plus push que pull.

La section 4 explique le mécanisme d'adressage des morceaux. On n'est en effet pas obligé de les désigner un par un. On peut utiliser des intervalles (« du morceau N1 au morceau N2 »), des octets (« tous les morceaux qui composent le premier million d'octets ») ou bien des bin numbers. Un bin number est un mécanisme très astucieux permettant de désigner un intervalle d'octets presque quelconque avec un seul nombre. Je vous laisse lire la section 4.2 du RFC pour une explication complète. (Si quelqu'un de courageux peut ensuite en faire un article sur les bin numbers pour Wikipédia... Actuellement, il n'y en a pas.)

La section 12 de notre RFC intéressera tout particulièrement les administrateurs système et réseau. Elle couvre les problèmes opérationnels avec PPSPP. Par exemple, comme avec tout protocole pair-à-pair, un pair PPSPP a intérêt à choisir des pairs « proches » (entre guillemets car il n'est pas évident de définir « proche »). Le protocole ALTO du RFC 7285 peut aider à mieux choisir ses pairs. Mais il faut bien dire que, l'expérience concrète avec PPSPP manquant encore, on est un peu ici dans des zones inexplorées.

La section 13 du RFC, elle, se consacre aux questions de sécurité. D'abord, la vie privée : comme BitTorrent, PPSPP expose à chaque pair l'adresse IP des autres pairs (sauf si on utilise Tor, ce qui ne sera pas forcément simple) et on ne peut donc pas tellement cacher à ses pairs son intérêt pour tel ou tel contenu. À noter que PPSPP ne fournit pas de mécanisme pour protéger la confidentialité du contenu. Si on veut distribuer du contenu à accès restreint, on le chiffre avant, ou bien on utilise IPsec ou DTLS.

Ensuite, le risque d'attaques par réflexion, puisque PPSPP tournera typiquement sur UDP. Si un attaquant ment sur son adresse IP, peut-il déclencher l'envoi de données massives vers un innocent ? A priori, non, en raison de l'usage d'un mécanisme analogue aux ISN (Initial Sequence Number) de TCP. La communication nécessite la connaissance de nombres nommés channel ID et ils sont choisis aléatoirement (RFC 4960). Un attaquant ne peut donc pas les connaitre (cf. section 5.1.3) s'il a triché sur son adresse IP (puisqu'il ne recevra pas le message lui communiquant le channel ID à utiliser : en d'autres termes, PPSPP teste la « routabilité »).

Une version, apparemment assez expérimentale, de ce protocole a été mise en œuvre en logiciel libre, dans libswift. Une autre, écrite en Erlang est le projet Swirl.


Téléchargez le RFC 7574


L'article seul

RFC 7567: IETF Recommendations Regarding Active Queue Management

Date de publication du RFC : Juillet 2015
Auteur(s) du RFC : F. Baker (Cisco Systems), G. Fairhurst (University of Aberdeen)
Réalisé dans le cadre du groupe de travail IETF aqm
Première rédaction de cet article le 12 juillet 2015


L'AQM (Active Queue Management) désigne l'ensemble des techniques utilisées par un routeur pour gérer les files d'attente de paquets attendant de partir. La technique triviale est de faire passer les paquets en FIFO et de refuser de nouveaux paquets quand la file d'attente est pleine. Mais il existe plein d'autres techniques possibles, qui forment l'AQM. Ce nouveau RFC résume les recommandations de l'IETF sur l'AQM. Notamment, il n'y a plus de méthode privilégiée, comme l'était RED précédemment (dans l'ancien RFC 2309).

Petit rappel sur IP d'abord (section 1 du RFC) : IP (RFC 791 ou RFC 2460) est un protocole sans état (chaque paquet est routé indépendamment des autres) et donc sans connexion. Cela rend les routeurs bien plus efficaces (ils n'ont pas besoin d'avoir de mémoire), cela permet de changer de route facilement, cela permet de survivre à la perte ou au redémarrage d'un routeur. L'extrême robustesse de l'Internet le montre tous les jours. En revanche, une des faiblesses de ce mécanisme sans connexion est sa sensibilité aux fortes charges : si un routeur congestionné commence à perdre des paquets car ses liens de sortie sont saturés, les machines vont réémettre, envoyant davantage de paquets, aggravant la situation et ainsi de suite jusqu'à la fusion du réseau (le fameux Internet meltdown, cf. RFC 896 et RFC 970). Ce phénomène a été plusieurs fois observés dans les années 1980 sur le cœur de l'Internet. Il est depuis confiné aux marges de l'Internet, par l'applications de meilleures techniques dans les routeurs, mais il menace en permanence de réapparaitre.

Le RFC 2309, publié en 1998, est le dernier qui fasse le point sur le problème de la congestion et ses conséquences. Sa principale recommandation concrète était de déployer massivement une technique de gestion des files d'attente, RED (« Internet routers should implement some active queue management [...] The default mechanism for managing queue lengths to meet these goals in FIFO queues is Random Early Detection (RED). Unless a developer has reasons to provide another equivalent mechanism, we recommend that RED be used. ») Mais, depuis 1998, l'Internet a évolué, notamment par la demande plus forte de limitation de la latence. La recommandation du RFC 2309 ne semble plus aussi opportune. (Et RED s'est avéré difficile à configurer en pratique.)

Tout le travail n'est pas à faire du côté des routeurs. Le problème de la congestion et le risque de fusion sont tellement sérieux, surtout depuis les grandes pannes des années 1980, que beaucoup d'efforts ont été dépensés pour les traiter. C'est ainsi que Van Jacobson a développé les règles (« Congestion Avoidance and Control » dans le SIGCOMM Symposium proceedings on Communications architectures and protocols en 1988) que doit suivre TCP pour éviter que ce dernier n'aggrave la congestion : en cas de perte de paquets, TCP ne doit pas réémettre bêtement comme un porc mais au contraire se calmer, arrêter d'envoyer des paquets à la vitesse maximale, pour donner une chance aux files d'attente des routeurs de se vider. Ces règles sont aujourd'hui documentées dans le RFC 5681. Elles s'appliquent aux machines terminales de l'Internet, alors que notre RFC 7567 concerne les routeurs, qui ont aussi leur rôle à jouer. Les machines terminales ne peuvent pas tout, d'autant plus que toutes ne sont pas bien élevées : il y a des programmes mal écrits ou malveillants qui sont connectés au réseau, cf. la section 5. Des travaux sont en cours pour gérer le cas de machines qui ne réagissent pas à la congestion et continuent à émettre au maximum (cf. RFC 6789).

Mais le risque d'écroulement du réseau sous l'effet de la congestion n'est pas le seul. Il faut aussi penser à la latence. Si on augmente la taille des files d'attente dans les routeurs, pour diminuer le risque d'avoir à jeter des paquets, on augmente aussi la latence, car vider ces files prendra du temps. (L'augmentation excessive de la taille des files d'attentes est connue sous le nom de bufferbloat, voir aussi la section 2.3, et le RFC 8033.)

La section 2 décrit en détail le problème de la gestion des files d'attente dans un routeur de l'Internet. La méthode traditionnelle, la plus simple, est connue sous le nom de tail drop : la queue a une taille finie, lorsqu'elle est pleine, on arrête d'accepter des paquets, point. Cela veut dire que les premiers paquets jetés sont les derniers arrivés. Cette méthode est simple à programmer mais elle a plusieurs inconvénients :

  • Tail drop ne signale la congestion aux machines terminales (en jetant les paquets) que lorsque la file d'attente est pleine. Si la file reste en permanence à 50-80 % pleine, aucun paquet ne sera jeté, les machines terminales continueront à émettre au même rythme, alors que le fait que la file soit plus qu'à moité pleine aura un effet négatif sur la latence.
  • Cette technique ne garantit pas l'égalité des différents flots de communication : dans certains cas, un seul flot peut monopoliser la queue.
  • Elle a aussi la propriété qu'elle tend à synchroniser les différentes machines qui partagent le même goulet d'étranglement (Floyd, S. et V. Jacobsen, « The Synchronization of Periodic Routing Messages »).

On pourrait réduire certains de ces problèmes (notamment le premier) en réduisant la taille de la file d'attente. Mais celle-ci est indispensable dans le cas d'augmentation brusque de trafic : le rythme d'arrivée des paquets n'est pas constant, il y a des moments où tout le monde parle en même temps (Leland, W., Taqqu, M., Willinger, W., et D. Wilson, « On the Self-Similar Nature of Ethernet Traffic (Extended Version) », IEEE/ACM Transactions on Networking), et les files d'attente sont là pour lisser ces soubresauts. Idéalement, on voudrait une queue vide en temps normal, qui ne se remplisse que pendant les pics de trafic. L'algorithme tail drop a l'inconvénient de créer souvent des queues pleines en permanence, au détriment de la latence.

Mais il y a d'autres algorithmes. Le random drop on full jette, lorsque la file est pleine, non pas le dernier paquet mais un paquet au hasard. Cela évite la monopolisation de la file par un seul flot de données mais cela ne résout pas le problème des files toujours pleines. Même chose pour le head drop qui consiste à jeter le premier paquet et non pas le dernier. La bonne solution est donc de ne pas attendre que la file soit pleine pour agir. C'est cette idée qui est à la base de l'AQM. En jetant des paquets avant que la file ne soit remplie (ou bien en les marquant avec ECN, cf. RFC 3168), on va dire indirectement aux machines terminales de ralentir, et on évitera ainsi les files complètement pleines, sauf en cas de brusque pic de trafic.

AQM est donc un concept proactif. Il permet de :

  • Jeter moins de paquets,
  • Réduire l'occupation des files d'attente, et donc la latence, pour le plus grand plaisir des applications interactives,
  • Éviter la monopolisation par un seul flot,
  • Réduire la synchronisation (par l'usage de choix aléatoires).

Tout cela est très bien si les applications utilisent toutes TCP, protocole habitué à réagir à la congestion (en diminuant son débit), et qui protège l'Internet contre les abus. Tant qu'il n'y a que TCP, avec des algorithmes conformes aux recommandations du RFC 5681, tout le monde partage le réseau en bonne intelligence et sans catastrophe, et chacun obtient une part égale de la capacité.

Mais il n'y a pas que TCP dans l'Internet, certains applications utilisent, par exemple, UDP (conseil personnel au passage : le programmeur débutant qui ne connait pas bien les problèmes de congestion devrait n'utiliser que TCP ou un équivalent comme SCTP, afin d'éviter d'écrouler le réseau). On peut classer les flots de données non-TCP en trois catégories :

  • Flots amicaux avec TCP : ce sont ceux qui utilisent des algorithmes de contrôle de la congestion qui, en pratique, leur donnent un débit proche de celui d'un flot TCP (RFC 5348). Par exemple, ce sont des flots UDP envoyés par des applications dont les auteurs ont lu et appliqué le RFC 8085.
  • Flots qui ne réagissent pas à la congestion : ce sont ceux qui continuent à envoyer des paquets sans tenir compte des pertes ou des signalements ECN. Ce sont les « méchants ». Certaines applications de transport de la voix ou de la vidéo sont dans cette catégorie. Jusqu'à présent, la solution anti-congestion à l'IETF avait toujours été d'améliorer les applications. Comme on ne peut pas espérer que 100 % des applications soient bien élevées, il faudra un jour développer des solutions pour gérer ceux qui abusent.
  • Flots qui réagissent, mais pas aussi bien que TCP : ils ont un mécanisme de réaction à la congestion mais ce mécanisme est trop peu réactif, et ces flots prennent donc une part disproportionnée du trafic. Cela peut être le résultat d'une maladresse du programmeur (voir mon conseil plus haut : utilisez TCP, sauf si vous êtes vraiment très fort en contrôle de congestion). Mais cela peut être aussi délibéré, pour s'assurer une plus grosse part du gâteau. Par exemple, certaines mises en œuvre de TCP étaient plus agressives que la normale, peut-être pour que le vendeur puisse proclamer que son TCP était « plus rapide ». On est dans une problématique très proche de celle de nombreux problèmes écologiques : si peu de gens trichent, les tricheurs et les égoïstes ont un gros avantage. Mais s'ils entrainent les autres, une spirale de la triche se développe, jusqu'au point où c'est l'enfer pour tout le monde. Pour l'Internet, une telle spirale pourrait aller jusqu'au cas où il n'y aurait plus de réaction à la congestion du tout, chacun poussant ses octets au maximum, sans tenir compte de l'intérêt collectif.

La section 4 de notre RFC résume les recommandations actuelles :

  • Il faut faire de l'AQM,
  • Ce serait bien de ne pas seulement jeter les paquets mais aussi de pouvoir faire de l'ECN,
  • L'administrateur système ou réseaux ne devrait pas avoir à faire de réglages manuels (tuning), tout devrait s'ajuster automatiquement,
  • L'AQM doit répondre à la congestion effective, pas à ce que le routeur croit savoir sur l'application ou sur le protocole de transport (c'est également impératif pour la neutralité de l'Internet),
  • Le problème des flots délibérement égoïstes est très important, et nécessite davantage de recherche.

Le reste de la section 4 détaille chacune de ces recommandations.

Par exemple, la seconde vient du fait qu'il n'y avait au début qu'un seul moyen pour un routeur de signaler la congestion : jeter des paquets (ce qui était de toute façon nécessaire : quand il n'y a plus de place, il n'y a plus de place). L'ajout d'ECN, dans le RFC 3168, et les spécifications de son usage (voir par exemple le RFC 6679) ont ajouté un deuxième moyen, qui permet de réagir avant qu'on perde des paquets. (Le RFC note que retarder les paquets, ce que fait la file d'attente, peut aussi être vu comme un signal : l'augmentation du RTT va mener TCP à ajuster son débit.)

La recommandation comme quoi le tuning (par le biais de paramètres numériques qu'il faudrait ajuster pour obtenir l'effet idéal) ne doit pas être obligatoire est discutée en section 4.3. Elle vient de l'expérience ce certaines mises en œuvre d'AQM où le pauvre administrateur du routeur devait absolument fixer certains paramètres, alors qu'il manque de temps et qu'il n'est pas forcément expert en congestion. En environnement de production, il n'est pas réaliste d'espérer que le dit administrateur passe ses nuits à faire du tuning ; l'algorithme doit avoir des paramètres par défaut raisonnables et, pour le reste, doit s'ajuster tout seul, en tenant compte d'informations comme la capacité des interfaces du routeur, et de variables mesurées en cours de route comme la durée moyenne de séjour des paquets dans la file d'attente ou le pourcentage de paquets jetés. (Un des problèmes de RED est justement la difficulté à s'ajuster automatiquement.)

Cela n'interdit pas au programmeur de fournir des mécanismes permettant le tuning manuel (ainsi que des outils pour aider l'administrateur à prendre ses décisions) mais ces mécanismes ne doivent pas être indispensables.

Pour la recommandation d'objectivité (décider en fonction de ce qu'on observe, pas de ce qu'on suppose), il est utile de relire le RFC 7141. Par exemple, il ne faut pas tenir compte de la taille des paquets. De même, il ne faut pas supposer que toutes les applications utilisent TCP.

Enfin, sur la recommendation de continuer les recherches, la section 4.7 fournit un programme aux chercheurs qui se demandent sur quel sujet travailler : il reste encore beaucoup de travail.

La section 1.4 de notre RFC décrit les changements depuis le RFC 2309. Les deux plus importants sont :

  • La taille d'une file d'attente n'est plus forcément évaluée uniquement en octets. Elle peut l'être en temps passé par le paquet dans la queue.
  • L'algorithme RED n'est plus le seul recommandé pour gérer les files d'attente.

Téléchargez le RFC 7567


L'article seul

RFC 7562: Transport Layer Security (TLS) Authorization Using DTCP Certificate

Date de publication du RFC : Juillet 2015
Auteur(s) du RFC : D. Thakore (CableLabs)
Pour information
Première rédaction de cet article le 10 juillet 2015


Le protocole de sécurité TLS permet différents types d'autorisation et ce RFC en ajoute un nouveau, par la présentation d'un certificat DTCP. DTCP est un mécanisme de menottes numériques, et cette extension à TLS permet désormais « TLS pour les ayant-droits ».

DTCP, également connu sous le nom de 5C, est un système fermé. À l'heure actuelle, une version apparemment à jour de la spécification est disponible. Ce système DTCP est assez répandu dans des télévisions, des tablettes, des consoles de jeu... Les certificats DTCP (qui ne sont pas des certificats X.509) sont émis par DTLA (section 2.1 du RFC).

Le RFC 5878 spécifie l'extension de TLS à d'autres mécanismes d'autorisation. Et le RFC 4680 décrit l'ajout de données supplémentaires (le certificat) dans le message Handshake de TLS.

Le type d'autorisation IANA dtcp_authorization est désormais enregistré à l'IANA.


Téléchargez le RFC 7562


L'article seul

RFC 7504: SMTP 521 and 556 Reply Codes

Date de publication du RFC : Juin 2015
Auteur(s) du RFC : J. Klensin
Chemin des normes
Première rédaction de cet article le 1 juillet 2015


Ce RFC enregistre officiellement deux nouveaux codes de retour SMTP (qui étaient déjà largement utilisés), 521 (« I do not accept mail ») et 556 (« The remote domain does not accept mail »). Tous les deux sont prévus pour le cas où un serveur ou un domaine n'acceptent jamais de courrier, en aucune circonstance (par opposition aux codes de rejet plus généraux comme 554).

Petit rappel au passage : les codes de retour SMTP, spécifiés dans la section 4.2 du RFC 5321, ont un premier chiffre qui indique notamment si l'erreur est temporaire (si le premier chiffre est un 4) ou permanente (si le premier chiffre est un 5). Dans le second cas, pas la peine de réessayer plus tard. Ici, le 521 dit bien « ne t'embête pas à revenir, demain, ce sera comme aujourd'hui, je n'accepterai jamais ton message »).

SMTP avait été prévu au début dans un monde où tout le monde acceptait du courrier. Dans les années 1980, toute station de travail Unix venait avec un sendmail activé qui pouvait recevoir des messages. Le paysage aujourd'hui est très différent (section 2 de notre RFC) avec un grand nombre de machines qui ne reçoivent pas de courrier. De même, certains domaines ne sont pas utilisés pour le courrier et il serait pratique de pouvoir indiquer cela à l'avance (RFC 7505).

Dans le premier cas (machine qui ne veut pas recevoir de courrier), le plus simple semble être de ne pas avoir de serveur SMTP du tout. Mais l'impossibilité de se connecter (réponse TCP RST, ou bien timeout, si le pare-feu jette les requêtes TCP) va être interprétée par le client SMTP comme temporaire, et celui-ci va alors réessayer pendant des jours. Si, par la suite d'une erreur de configuration, un client SMTP tente de se connecter à une machine sans serveur, il faudra donc attendre avant de détecter le problème. Avoir un simple serveur SMTP qui ne fait rien d'autre que dire tout de suite « arrête d'insister, ça ne sert à rien » pourrait être plus efficace.

Pour le second cas, le domaine qui n'a pas du tout de service de courrier, le RFC 7505 fournit un moyen simple de l'indiquer dans le DNS, avec le « MX nul ». Il ne manquait qu'un code de retour adapté, pour que le premier relais SMTP de l'utilisateur puisse dire « je ne peux pas envoyer de courrier à ce domaine, ils ne veulent pas ».

Le code 521 est décrit dans la section 3 du RFC. Il est renvoyé au début de la connexion puisqu'il décrit un refus général (pas d'exceptions). Si le refus du courrier est dû à certaines caractéristiques du courrier (par exemple l'emploi de tel émetteur), il ne faut pas utiliser 521 mais plutôt 554. Voici à quoi pourrait ressembler l'accueil d'un serveur SMTP simple, qui ne fait que rejeter imédiatement :

% telnet mail.example.net smtp
Trying 2001:db8:666::1...
Connected to mail.example.net.
Escape character is '^]'.
521 I hate everybody, do not come back
[Connexion fermée]

Le serveur peut clore la connexion immédiatement, ou bien la laisser ouverte et renvoyer des 521 systématiquement. Un message moins pittoresque pourrait être « Server does not accept mail ».

À noter que le code 521 avait déjà été décrit dans le RFC 1846 mais pas normalisé.

La section 4 décrit l'autre code, 556. Le premier code était prévu pour un serveur qui refusait le courrier, le second pour un relais qui essaie d'envoyer au serveur suivant mais découvre que le domaine de destination n'a pas l'intention d'accepter du courrier. Cette découverte se fait typiquement en voyant le « MX nul » du domaine en question (RFC 7505). En faisant une requête MX pour connaître le serveur suivant, le relais peut découvrir que le domaine n'accepte pas de courrier, et il renvoie alors un 556 à son client.

Les deux codes sont désormais enregistrés à l'IANA.


Téléchargez le RFC 7504


L'article seul

RFC 7505: A "Null MX" No Service Resource Record for Domains that Accept No Mail

Date de publication du RFC : Juin 2015
Auteur(s) du RFC : J. Levine (Taughannock Networks), M. Delany (Apple)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF appsawg
Première rédaction de cet article le 1 juillet 2015


Comment indiquer qu'un domaine ne reçoit jamais de courrier ? Jusqu'à présent, il n'existait pas de mécanisme standard, permettant d'indiquer aux clients de ne pas perdre de temps à essayer d'écrire. Ce nouveau RFC indique une méthode, le « MX nul » qui consiste à mettre un point en partie droite de l'enregistrement MX.

Normalement, un logiciel de messagerie qui veut envoyer du courrier à bob@example.net va chercher dans le DNS l'enregistrement MX du domaine example.net. (Le processus exact est décrit dans le RFC 5321, section 5.1.) A priori, si on ne veut pas recevoir de courrier, il suffit de ne pas mettre d'enregistrement MX, non ? Malheureusement, ce n'est pas le cas : le RFC 5321 précise que, s'il n'y aucun MX, on essaie alors les adresses IP associées au nom (règle dite du « MX implicite »).

Or, il existe des domaines qui ne reçoivent pas de courrier, parce qu'ils sont seulement réservés sans intention d'être utilisés, ou bien parce qu'ils ne servent que pour le Web ou bien encore pour toute autre raison. Si un message tente de parvenir à ces domaines, la machine émettrice va perdre du temps à essayer des MX délibérement invalides (avant la norme de notre RFC 7505, des gens mettaient un MX pointant vers localhost) ou bien des adresses où aucun serveur SMTP n'écoute. Ce n'est pas joli. Et cela peut prendre du temps (lorsque la délivrance échoue, l'émetteur met en attente et réessaie) donc l'utilisateur qui s'est trompé de domaine ne sera prévenu que plusieurs jours plus tard, lorsque le serveur émetteur renoncera enfin.

Au contraire, avec le nouveau « MX nul », dit officiellement No Service MX, le rejet sera immédiat et l'utilisateur, notifié tout de suite, pourra corriger son erreur.

La syntaxe exacte du MX nul figure en section 3. On utilise l'enregistrement MX (RFC 1035, section 3.3.9), avec une partie droite comprenant une préférence égale à zéro et un nom de domaine (exchange, dans la terminologie du RFC 1035) vide (de longueur nulle), ce qui se note, en représentation texte, par un simple point. Voici un exemple :

% dig +short MX  internautique.fr 
0 .

Ce nom ne pouvait pas être un nom de machine légal, il n'y a pas de risque de confusion avec les MX actuels. (Les enregistrements SRV du RFC 2782 utilisent le même truc pour dire qu'il n'y a pas de service disponible à ce nom : « A Target of "." means that the service is decidedly not available at this domain. ».)

La section 4 liste les effets de l'utilisation du MX nul. Comme indiqué plus haut, il permet une réponse immédiate à l'utilisateur, lorsque celui-ci s'est trompé d'adresse (bob@example.net alors qu'il voulait écrire à bob@example.com). L'erreur SMTP à utiliser dans ce cas est 556 (Server does not accept mail, RFC 7504) avec comme code amélioré (codes définis dans le RFC 3643) le nouveau 5.1.10 Domain has null MX.

Le MX nul sert aussi si, par erreur ou par usurpation, un serveur tente d'envoyer du courrier avec une adresse d'émission qui est un domaine à MX nul : le récepteur peut rejeter tout de suite ce message, pour la raison qu'il ne pourrait de toute façon pas lui répondre (ou pas lui envoyer de DSN). C'est ainsi que procèdent beaucoup de serveurs de messagerie avec les adresse d'émission dont le domaine n'existe pas. Dans ce cas, les codes d'erreurs à utiliser sont 550 (mailbox unavailable) avec le code étendu 5.7.27 (Sender address has null MX). (Les nouveaux codes sont dans le registre IANA.) Par exemple, Postfix signale, pour le domaine example.com, une erreur 5.1.0 et le message « <foobar@example.com>: Domain example.com does not accept mail (nullMX) ».

Notez enfin que ce RFC concerne le cas où on ne reçoit pas de courrier. Si on veut dire qu'on n'en envoie pas, le plus simple est un enregistrement SPF -all.

Tous les hébergeurs DNS ne permettent pas encore de mettre un MX nul. Par exemple, l'un d'eux m'envoie promener « La valeur et/ou la priorité MX est incorrecte ».


Téléchargez le RFC 7505


L'article seul

RFC 7586: Scaling the Address Resolution Protocol for Large Data Centers (SARP)

Date de publication du RFC : Juin 2015
Auteur(s) du RFC : Youval Nachum (Ixia), Linda Dunbar (Huawei), Ilan Yerushalmi, Tal Mizrahi (Marvell)
Expérimental
Première rédaction de cet article le 28 juin 2015


Le problème de passage à l'échelle de protocoles de recherche d'adresse MAC des voisins, les protocoles comme ARP, sont connus depuis un certain temps, et documentés dans le RFC 6820. Résumé en deux mots, dans un grand centre de données non partitionné en sous-réseaux IP, le trafic ARP peut représenter une partie significative du travail à effectuer par les machines. Ce nouveau RFC expose une des solutions pour faire face à ce problème : SARP (Scaling the Address Resolution Protocol) fait appel à des relais ARP qui peuvent générer localement la plupart des réponses.

Si le centre de données est rigoureusement découpé en sous-réseaux IP (par exemple un sous-réseau, et donc un routeur par baie), il n'y a pas de problème ARP : le trafic ARP reste local. Mais si on veut profiter de la souplesse que permet la virtualisation, par exemple en déplaçant des machines virtuelles d'un bout à l'autre du centre de données en gardant leur adresse IP, on doit alors propager les requêtes ARP sur une bien plus grande distance et les problèmes de passage à l'échelle apparaissent (RFC 6820). La mémoire consommée par la FDB (Filtering Data Base, la table des adresses MAC connues) augmente, ainsi que le temps de traitement de tous ces paquets ARP diffusés.

Les premières versions des brouillons ayant mené à ce RFC ne mentionnaient qu'ARP (RFC 826), protocole de résolution IP->MAC pour IPv4. Mais la version finale considère que le protocole marche aussi bien pour ND (RFC 4861), son équivalent pour IPv6. Seul le nom de la solution garde trace de cette préférence pour ARP. Dans le reste de cet article, je parlerais de ARP/ND.

L'idée de base de SARP est que chaque domaine d'accès (un groupe de machines proches, par exemple dans la même baie ou dans la même rangée) ait un relais (SARP proxy) qui connaisse les adresses MAC de tout le domaine, et réponde aux requêtes ARP/ND pour les autres domaines avec sa propre adresse MAC. Ainsi, la taille de la table ARP des machines du domaine reste proportionnelle à la taille du domaine d'accès, pas au nombre total de machines (comme ce serait le cas avec un réseau « plat » classique, entièrement en couche 2, et sans SARP).

Le relais SARP peut être l'hyperviseur d'un groupe de machines virtuelles (commutateur virtuel) ou bien il peut être dans un commutateur physique, ToR (Top of Rack) ou bien EoR (End of Row). En gros, le relais SARP est là où un domaine d'accès se connecte au cœur du réseau interne du centre de données. Ce doit être une grosse machine car elle va devoir stocker les adresses MAC de toutes les machines qui communiquent avec une machine d'un autre domaine d'accès. Et il peut aussi faire l'objet d'attaques délibérées (cf. section 4).

La section 3 de notre RFC décrit plus en détail le fonctionnement de SARP. Si la machine source et la destination sont dans le même domaine d'accès (même baie, ou même rangée, selon l'endroit où se trouve le commutateur), ARP/ND fonctionne comme d'habitude et SARP n'intervient pas. Si la machine de destination est dans un autre sous-réseau IP, on passe alors par le routeur, selon le mécanisme normal de la couche 3. Mais si la destination est dans le même sous-réseau IP, mais dans un domaine d'accès différent ? Le relais SARP voit alors passer la requête ARP/ND. Si la réponse est dans son cache (qui associe des adresses IP à des adresses MAC), il répond avec sa propre adresse MAC (ainsi, les machines du domaine d'accès local ne sont pas noyées par des milliers d'adresses MAC de tout le centre de données). Sinon, il transmet à tous les domaines d'accès qui peuvent avoir cette adresse IP puis relaie la réponse. Seuls les relais SARP ont un cache qui contient des adresses MAC de tout le centre de données. Les machines ordinaires n'ont que les adresses MAC de leur propre domaine d'accès.

Et pour transmettre un paquet de données ? La machine source, ayant reçu l'adresse MAC du relais SARP en réponse à sa requête ARP/ND va donc mettre sur le câble un paquet ayant pour adresse Ethernet de destination le relais SARP. Le relais SARP, utilisant son propre cache (qui, lui, est complet), remplace l'adresse MAC de destination par la « vraie », et l'adresse MAC source par la sienne (pour qu'une réponse puisse revenir), et remet le paquet sur le câble.

Un tel mécanisme fait que des opérations comme la migration d'une VM d'un bout à l'autre du centre de données sont complètement invisibles. Les mécanismes normaux de résolution feront tout le travail. Cela suppose toutefois que la machine qui se déplace (ou plutôt son hyperviseur qui, contrairement à la VM, est conscient du déplacement) émette tout de suite un paquet ARP gratuit ou un paquet ND non sollicité, pour que les caches soient mis à jour (autrement, la machine migrée restera injoignable le temps que l'entrée dans le cache expire).

Une conséquence de cette technique est que le relais SARP est absolument vital : s'il est en panne, plus rien ne marche, à part les communications locales à un domaine d'accès. Il vaut donc mieux en avoir plusieurs, pour chaque domaine d'accès.

Ce RFC n'a que le statut « Expérimental » car l'IESG n'est pas convaincue que ce soit la seule méthode. Le RFC 7342 liste un certain nombre d'autres techniques (pas forcément directement comparables à SARP). À noter que les approches de type overlay (RFC 7364) résolvent une partie du problème mais pas la question de la taille de la table des adresses MAC. Mais il y a les RFC 4664, RFC 925, RFC 4389 (ces deux derniers sont, à mon avis, proches de SARP), RFC 4541 et RFC 6575...


Téléchargez le RFC 7586


L'article seul

Dépanner un Raspberry Pi utilisé comme serveur

Première rédaction de cet article le 27 juin 2015


Parmi les joies de l'administration système, il y a le dépannage d'un serveur headless (sans console physique, ni écran ni clavier), lorsque ce dernier ne veut pas redémarrer. Comment faire sur un Raspberry Pi ?

(Si vous ne connaissez pas le Pi, il y a aussi un de mes articles.) Si le Pi est habituellement connecté à une télévision et à un clavier, on voit le processus de démarrage du système et on peut intervenir. Mais c'est plus facile à dire qu'à faire, car un Pi qui ne démarre pas et qui dit juste :

Requested init /bin/systemd failed (error -2)
kbd>

a de quoi laisser perplexe même l'administrateur système Unix expérimenté. Ce problème m'est arrivé avant-hier après une mise à jour d'Arch Linux. Ce système, en raison de ses rolling releases est évidemment plus vulnérable à ce genre de problèmes qu'un système très stable comme Debian, mais aucun système n'est 100 % à l'abri. Un jour ou l'autre, on se retrouve avec uniquement la diode rouge et le Pi qui n'est plus joignable en SSH.

Les gros serveurs dans les centres de données ont des cartes d'accès à distance comme les DRAC de Dell. Mais le Pi, très bon marché, n'a rien de tel. Brancher une télé, avec le câble HDMI, permet d'avoir au moins le message d'erreur. Curieusement, la plupart des articles qu'on trouve avec DuckDuckGo indiquent des méthodes compliquées pour réparer, avec des commandes tapées au clavier du Pi défaillant. Mais je trouve qu'il y a bien plus simple.

La méthode que j'ai utilisé la plupart du temps est simplement d'éteindre le Pi, de prendre la carte SD et de la mettre dans un PC Linux où on pourra réparer tranquillement. Bien sûr, cela nécessite d'avoir un PC sous la main mais je suppose que peu de gens ont un Pi sans aucun autre ordinateur.

Une fois la carte SD montée sur la machine Linux, on a alors un environnement Unix complet pour investiguer, et réparer. Cela va bien plus vite.

Et quel était le problème dans le cas cité plus haut ? Au cours de la mise à jour, Arch Linux avait mis dans les instructions de démarrage init=/bin/systemd alors que systemd était dans /lib/systemd. init est le premier programme en mode utilisateur qui est lancé par le noyau Linux du Pi, et l'erreur -2 voulait simplement dire qu'il n'était pas trouvé. Sur la carte SD montée sur un PC de secours, un ln -s /lib/systemd/systemd /bin a suffit à réparer, en mettant un lien symbolique depuis le nom utilisé vers le « vrai » nom. Une autre solution aurait évidemment été d'éditer le cmdline.txt (qui se trouve dans l'autre partition de la carte SD, la première, celle formatée en VFAT), et de remplacer init=/bin/systemd par init=/lib/systemd/systemd.


L'article seul

Fiche de lecture : La boîte à outils de la créativité

Auteur(s) du livre : Edward de Bono
Éditeur : Eyrolles
978-2-212-55658-2
Publié en 2004
Première rédaction de cet article le 27 juin 2015


C'est l'année dernière à Paris-Web que j'avais reçu ce livre. Après chaque conférence, l'orateur choisissait une personne du public qui avait posé une question particulièrement pertinente, et c'était moi (je suis désolé, j'ai oublié la question que j'avais posé). Mais je ne suis pas sûr que le choix des livres ait toujours été pertinent...

Ceci dit, sans Paris-Web, je n'aurais jamais pensé à lire ce livre. C'est un de ces ouvrages de consultant, écrit par un gourou qui passe son temps à expliquer à des gens comment être plus... efficace, productif, créatif, même. Je suis toujours surpris qu'on se moque des peuples premiers qui ont des sorciers pour faire venir la pluie ou faire en sorte que la chasse soit favorable, mais que des entreprises par ailleurs souvent sérieuses dépensent des sommes importantes pour payer ces gourous dont la seule compétence est le talent à faire croire qu'ils servent à quelque chose. À chaque fois, ils me font penser au sorcier Shadok à qui un sceptique reprochait de ne pas faire de miracles et qui répondait « 25 ans que je fais se lever le soleil tous les matins : pas un échec ». De nos jours, dans les pays riches du monde, on ne croit plus aux sorciers ou aux prêtres mais on n'est pas devenu plus intelligent pour autant : on croit aux gourous.

Pourtant, celui-ci fait des efforts pour qu'on évite de le prendre au sérieux. Il utilise plein d'exemples enfantins et j'ai du mal à croire qu'une assemblée de cadres supérieurs et de dirigeants, dans un grand hôtel international, ait pu suivre sans rire ses exercices de pseudo-psychologie avec les chapeaux jaunes et les chapeaux noirs...

Ce gourou est tellement convaincu de son importance qu'il n'a pas peur de lasser la patience de ses lecteurs avec ses diatribes contre les méchants plagiaires qui lui piquent ses remarquables idées (il y a vraiment des gourous secondaires, qui utilisent les chapeaux jaunes et les chapeaux noirs sans payer de droits d'auteurs ?) Pas une seconde, il ne se demande si celui qui a acheté (ou, dans mon cas, reçu) son livre n'a pas autre chose à faire que de lire ses plaintes.

Et, puisqu'on parle de fric et de droits, il est également significatif que de Bono parle pendant 450 pages de méthodes pour augmenter la « créativité » sans jamais s'interroger sur le but, sur le pourquoi. On rassemble des gens devant le gourou, il les fait travailler avec des exercices de l'école maternelle, mais jamais il ne les laisse ébrécher le tabou : on peut discuter des moyens pour atteindre le but (vendre plus de voitures, ou plus de hamburgers) mais jamais du but lui-même...

Preuve de son efficacité de vendeur, la page du Wikipédia francophone qui lui est consacrée est un article publicitaire « Ses techniques sont relativement simples d'usage et d'une bonne efficacité pratique » (le Wikipédia anglophone est plus prudent). Bref, une brochure commerciale pour ses activités de consultant, mais certainement pas un livre.


L'article seul

RFC 7568: Deprecating Secure Sockets Layer Version 3.0

Date de publication du RFC : Juin 2015
Auteur(s) du RFC : R. Barnes, M. Thomson (Mozilla), A. Pironti (INRIA), A. Langley (Google)
Réalisé dans le cadre du groupe de travail IETF tls
Première rédaction de cet article le 26 juin 2015


Ce nouveau RFC formalise un point déjà bien connu des experts en sécurité : le dernier survivant de la famille SSL, SSL version 3, a de graves failles et ne doit pas être utilisé.

Il y a bien longtemps que SSL est dépassé, remplacé par TLS (même si des ignorants continuent de parler de SSL dès qu'ils voient un petit cadenas sur leur navigateur Web). Mais les vieux protocoles ne meurent pas facilement sur l'Internet. Manque de ressources humaines qualifiées, absence d'intérêt pour la sécurité, blocage par la direction financière qui demande quel est le ROI, des tas de raisons font que pas mal de serveurs acceptent encore le SSL v3. Celui-ci, décrit dans le RFC 6101 (mais qui avait été défini et déployé bien avant, en 1996, le RFC 6101 ne faisant que documenter longtemps après), devrait pourtant être abandonné définitivement, ne laissant que TLS (dont la version actuelle est la 1.2, en RFC 5246).

La première fin de SSL v3 était en 1999, avec la sortie de TLS, dans le RFC 2246. Le fait que SSL v3 soit toujours bien vivant aujourd'hui, plus de quinze ans après, donne une idée de l'ossification de l'Internet et du manque de réactivité des techniciens.

La section 3 de notre RFC résume la bonne pratique actuelle : NE PAS UTILISER SSL v3. Les clients ne doivent pas le proposer dans le ClientHello, ni les serveurs dans leur ServerHello.

Bien plus longue, la section 4 décrit pourquoi SSL v3 est cassé sans espoir de réparation. Première raison, qui a permis la faille POODLE (cf. un bon article d'explication pour tous), c'est que le remplissage en mode CBC n'est pas spécifié (et donc pas vérifiable par le pair). Autre faille, SSL v3 fait forcément du MAC-then-encrypt, ce qui est aujourd'hui considéré comme dangereux. TLS fait aussi du MAC-then-encrypt par défaut mais on peut le changer (RFC 7366) grâce aux extensions. Or, SSL v3 n'a pas la notion d'extensions.

Les algorithmes de chiffrement stream de SSL v3 ont tous des défauts sérieux, par exemple RC4 est désormais officiellement abandonné (RFC 7465). Question condensation, ce n'est pas mieux, certaines opérations de SSL v3 imposant MD5 (RFC 1321, abandonné par le RFC 6151).

L'échange de clés dans SSL v3 a aussi des failles permettant à un homme du milieu de se placer. Corrigées dans TLS par des extensions, elles ne sont pas corrigeables en SSL v3.

Toujours en raison de son manque d'extensibilité, SSL v3 ne peut pas avoir certaines des nouvelles fonctions développées depuis sa naissance. Pas d'algorithmes dans les modes AEAD (RFC 5246, section 6), pas de courbes elliptiques (RFC 8422), pas de reprise d'une session existante sans état sur le serveur (RFC 5077), pas de mode datagramme pour UDP (RFC 6347), pas de négociation de l'application utilisée (RFC 7301).

Comme le notait le texte d'accompagnement à l'IESG, où on doit indiquer les mises en œuvre du protocole, « Are there existing implementations of the protocol? Yes, and that's the problem;-) ». Ceci dit, une bonne partie des déploiements de TLS ont commencé à supprimer SSL v3. Logiquement, il devrait être retiré du code des bibliothèques TLS (alors que, encore aujourd'hui, la page d'accueil de GnuTLS se vante de gérer SSL v3). Espérons que ce RFC, qui n'apporte aucune information technique nouvelle, par son côté « officiel », contribue à faire bouger les choses.

Pour déterminer si un serveur accepte SSL v3, on peut utiliser le client d'OpenSSL :

% openssl s_client -connect www.bortzmeyer.org:443 -ssl3 
CONNECTED(00000003)
depth=0 CN = www.bortzmeyer.org
...
SSL handshake has read 2276 bytes and written 470 bytes
...
SSL-Session:
    Protocol  : SSLv3
    Cipher    : DHE-RSA-AES256-SHA
    Session-ID: 8B815B79611AB6FB105E84AA3159A0E57D50BA61BEE33478BB5DFEAFD5E4979B

Ici, le serveur a accepté SSL v3 (handshake terminé, algorithme de chiffrement - DHE-RSA-AES256-SHA - sélectionné alors qu'on a forcé SSL v3). Si vous voulez savoir pourquoi ce serveur particulier accepte malheureusement SSL v3, voir à la fin de cet article.

Avec un qui n'a pas SSL v3, on voit :

% openssl s_client -connect www.example.net:443 -ssl3
CONNECTED(00000003)
3073382076:error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number:s3_pkt.c:348:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 5 bytes and written 7 bytes
---
...
SSL-Session:
    Protocol  : SSLv3
    Cipher    : 0000
    Session-ID: 

Les messages d'OpenSSL, comme toujours, sont peu clairs, mais on peut voir que le handshake n'a pas abouti (très peu de données transmises), qu'aucun algorithme de chiffrement n'a été choisi et qu'aucune session n'a commencé (ID vide). Ce serveur est donc correct.

Notez que l'administrateur système est dépendant des logiciels utilisés et qu'il ne peut pas tout reprogrammer lui-même. Ainsi, GnuTLS a un module Apache, mod_gnutls, qui a une très sérieuse bogue (ancienne et jamais réparée) qui fait que SSLv3 n'est pas interdit, même quand la configuration le demande. Personnellement, je vais arrêter d'utiliser GnuTLS sur mes sites Web, pas à cause de la bibliothèque elle-même, qui est excellente, mais à cause de ce module Apache pas maintenu.


Téléchargez le RFC 7568


L'article seul

RFC 7590: Use of Transport Layer Security (TLS) in the Extensible Messaging and Presence Protocol (XMPP)

Date de publication du RFC : Juin 2015
Auteur(s) du RFC : P. Saint-Andre (&yet), T. Alkemade
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF uta
Première rédaction de cet article le 25 juin 2015


Le groupe de travail UTA de l'IETF produit des recommandations pour un usage correct de TLS par les applications. En effet, indépendamment des forces et faiblesses propres de TLS, plusieurs problèmes de sécurité sont survenues en raison d'une mauvaise utilisation. Ce nouveau RFC traite le cas spécifique de l'utilisation de TLS par le protocole XMPP.

Les problèmes généraux identifiés par le groupe UTA avaient été documentés dans le RFC 7457 et les solutions généralistes, applicables à toutes les applications, dans le RFC 7525. Et pour le protocole XMPP, normalisé dans le RFC 6120 ? XMPP utilise TLS depuis au moins 1999. Les sections 5, 9 et 13 du RFC 6120 expliquent déjà comment faire du TLS avec XMPP. Mais notre nouveau RFC va plus loin et, dans l'esprit du manifeste XMPP/TLS , décide que XMPP doit suivre les recommandations plus strictes du RFC 7525, notamment concernant le choix des algorithmes de chiffrement.

La section 3 du RFC répète les recommandations du RFC 7525, que doivent désormais suivre les mises en œuvre de XMPP, notamment :

  • Toute mise en œuvre de XMPP doit avoir l'option <starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/> qui indique qu'elle est prête à démarrer TLS (RFC 6120, section 5.4.1 et quelques autres). Mais, comme cette option n'est pas elle-même protégée par TLS, elle peut être supprimée par un homme du milieu (attaque dite de stripping, RFC 7457, section 2.1). XMPP doit donc tenter de faire du TLS avec son partenaire, que cette option soit présente ou pas (le manifeste cité plus haut impose TLS, de toute façon).
  • La compression TLS étant désormais rejetée (RFC 7525, section 3.3), XMPP peut se rabattre sur la compression XMPP du XEP-0138.
  • XMPP a un mécanisme de reprise rapide des sessions (XEP-0198), on peut encore l'améliorer en le couplant avec la reprise de sessions de TLS.
  • En théorie (RFC 6125), un client XMPP devrait authentifier le serveur (et, de préférence, le serveur authentifier les autres serveurs). En pratique, ce n'est pas toujours le cas (avec Pidgin, un certificat à problèmes est signalé mais un seul clic suffit à l'accepter). Une des raisons pour lesquelles on ne peut pas imposer immédiatement une authentification généralisée est que les serveurs XMPP sont souvent hébergés dans un environnement multi-clients, chaque client hébergé ayant son propre nom de domaine et qu'un tel serveur devrait donc avoir un certificat pour chaque client, ou un certificat couvrant tous les clients. DANE résoudra peut-être le problème. En attendant, le RFC recommande fortement de préférer une connexion chiffrée et non authentifiée à une connexion en clair (se replier sur du trafic en clair parce que le certificat est invalide est absurde, mais courant). C'est par exemple ce que recommande le RFC 5386 pour le cas d'IPsec. Bref, « TLS tout le temps, authentification si possible » est le principe.
  • SNI (Server Name Indication, RFC 6066, section 3) est inutile en XMPP, l'attribut to suffit à indiquer le domaine concerné (l'attribut to envoyé avant TLS n'indique que le domaine, pas le destinataire).
  • En sécurité, il est bien connu que le point faible est l'utilisateur humain. La section 3.6 fait donc des recommandations pour les développeurs d'interface utilisateur : indiquer si la connexion avec le serveur est chiffrée par TLS, indiquer si l'authentification a réussi et, si oui, comment, permettre d'afficher l'algorithme de chiffrement utilisé et le certificat présenté, être averti si un certificat change (ce qu'on nomme parfois l'épinglage - pinning). Je viens de tester avec un Pidgin 2.10.10 et la seule de ces recommandations qui semble mise en œuvre est la possibilité d'afficher les certificats (menu Tools -> Certificates).

La section 5 rappelle que XMPP sur TLS chiffre aussi les informations de routage (contrairement à SMTP) et limite donc les fuites de métadonnées. Elle revient aussi sur quelques limites de TLS : XMPP passe par plusieurs serveurs et, si ceux-ci sont piratés ou indiscrets, le chiffrement TLS, qui n'est pas de bout en bout, ne protège pas contre ceux qui ont le contrôle des serveurs. En termes moins gentils, si vous utilisez Google Talk, le chiffrement TLS avec Google Talk (qui marche bien) ne vous protège pas de PRISM. (À noter que notre RFC ne cite pas la solution de bout-en-bout OTR, qui existe mais est mal intégrée à XMPP.)

Je n'ai pas trouvé de liste de toutes les implémentations XMPP, avec leur degré de conformité à ce RFC.


Téléchargez le RFC 7590


L'article seul

RFC 7595: Guidelines and Registration Procedures for URI Schemes

Date de publication du RFC : Juin 2015
Auteur(s) du RFC : D. Thaler (Microsoft), T. Hansen (AT&T Laboratories), T. Hardie (Google), L. Masinter (Adobe)
Réalisé dans le cadre du groupe de travail IETF appsawg
Première rédaction de cet article le 24 juin 2015


Ce n'est pas tous les jours qu'on enregistre un plan d'URI (le plan - scheme en anglais - est le premier composant d'un URI, la partie avant le premier deux-points). Ils sont peu nombreux et on voit rarement autre chose que le fameux http:. Mais, si jamais vous voulez ajouter un plan à la liste existante, ce RFC vous explique les règles d'enregistrement. Il remplace le RFC 4395.

Les plans d'URI sont normalisés dans le RFC 3986, section 3.1. Le plan est souvent appelé à tort « protocole » alors que, dans la grande majorité des cas, il n'a aucun rapport avec un protocole (voir la section 3.8 de notre RFC), et, même quand le nom du plan est celui d'un protocole (comme http:), il n'implique pas l'utilisation de ce protocole (un URI ne sert pas forcément à accéder à une ressource). Il existe de nombreux plans, du très connu http: au moins fréquent tag: (RFC 4151) en passant par bien d'autres, souvent assez confidentiels comme le acct: du RFC 7565 ou le dict: du RFC 2229. La liste des plans enregistrés se trouve à l'IANA. Le RFC 3986 décrit seulement la syntaxe générique des URI, celle commune à tous les URI et qui se limite largement à « un plan, deux points, puis du texte » (par exemple, http://www.bortzmeyer.org/608.html ou tag:bortzmeyer.org,2006-02:Blog/608). La grande majorité du contenu de l'URI a une syntaxe et une signification qui dépendent du plan et un logiciel d'usage très général doit donc connaître ces plans et leurs particularités.

Il existe un registre des plans, qui permet aux développeurs de ces applications de trouver tous les plans en un endroit, et de limiter le risque de collision. La politique d'enregistrement est déliberement assez libérale pour éviter la prolifération de plans non-enregistrés.

Petite note d'internationalisation au passage : les plans sont les mêmes pour les URI (qui doivent s'écrire uniquement en ASCII) et les IRI du RFC 3987, qui peuvent utiliser Unicode (ce n'était pas clair dans le RFC précédent, le RFC 4395).

En section 3 de notre RFC, les règles à suivre. D'abord, la syntaxe générale des URI doit être respectée (ce qui est facile, elle est très générale). Par exemple, l'identificateur de fragment (ce qui suit le croisillon, cf. RFC 3986, section 3.5), garde la même sémantique (notamment le fait qu'il n'est utilisé que par le client, pas par le serveur Web), un nouveau plan d'URI ne peut pas utiliser cette syntaxe pour exprimer autre chose.

Est-ce que le nouveau plan d'URI est une bonne idée ? Pour que son enregistrement soit accepté, le plan doit présenter une utilité à long terme, répond la section 3.1. Cette restriction est justifiée par le fait que tout nouveau plan peut nécessiter une modification de tous les logiciels qui traitent des URI et agissent différemment selon le plan. Et le Web contient autre chose que des clients et serveurs, il y a les relais, les caches, etc. (Le RFC note également que, bien que l'espace de nommage des plans soit infini, en pratique, il pourrait y avoir une concurrence trop forte pour les noms courts et facilement mémorisables et que cela justifie donc de ne pas accepter toutes les candidatures.)

Il y a aussi des contraintes plus techniques. La définition d'un nouveau plan doit décrire la syntaxe de l'URI (rappelez-vous que la syntaxe générale des URI ne couvre qu'une petite partie des règles). La section 3.2 impose que le nouveau plan respecte les règles syntaxiques existantes. Par exemple le // a une signification bien précise dans un URI, il précède le nom de la machine qui sert d'autorité de nommage, pour attribuer le reste de l'URI (section 3.2 du RFC 3986). En l'absence d'une telle machine de référence, le // ne doit donc pas être utilisé. (c'est pour cela que dict://dict.example.org/d:chocolate: a un //, car il contient le nom d'un serveur, ici dict.example.org alors que mailto:echo@generic-nic.net n'en a pas, car les adresses de courrier sont globales, elles ne dépendent pas d'un serveur particulier). D'une manière générale, notre RFC déconseille l'utilisation de la barre oblique, sauf si on accepte des URI relatifs, pour éviter qu'un logiciel trop zélé n'ajoute en prime un traitement spécial pour . ou .. (souvent interprétés pour dire « ce niveau » ou « le niveau supérieur »).

Il faut bien sûr que le plan soit correctement et complètement défini (sections 3.3 à 3.5). Par exemple, si l'URI est résolvable, sa description doit expliquer comment. Autre exemple, la description doit expliquer ce qu'on peut faire de l'URI. Accéder (et parfois modifier) à une ressource (cas du http:) ? À une machine (cas de telnet:, où le modèle « accès à une ressource » ne s'applique pas) ? S'il existe une opération par défaut (« je lance mon navigateur Web sur example:foo-bar-42, que fait-il ? », elle doit être sûre, au sens où elle ne doit pas avoir d'effets de bord. Enfin, le cas des URI qui servent juste à faire correspondre à un identificateur non-URI est normalement plus simple, avec une définition assez évidente. C'est le cas par exemple des mid: du RFC 2392, qui transforment un Message-ID: du courrier électronique en URI.

On a parlé plus haut des IRI. La section 3.6 nous rappelle les principes d'internationalisation des URI, et donne des bons conseils (faire bien attention à ne pas autoriser plusieurs représentations d'un même caractère, cf. RFC 3986, section 2.5). Le RFC donne aussi de mauvais conseils comme de prétendre (sans donner un seul exemple) qu'il faut restreindre le plus possible le jeu de caractères autorisé, certains caractères étant « dangereux ».

Pendant qu'on parle de danger, la section 3.7 rappelle la nécessité de bien documenter les questions de sécurité et de vie privée liées au nouveau plan. C'est une des nouveautés par rapport à l'ancien RFC 4395 que cette mention de la vie privée. Cela reflète l'importance croissante accordée à ce problème à l'IETF : de nombreux RFC mentionnent désormais la vie privée et pas seulement la sécurité informatique traditionnelle.

Enfin, le plan doit recevoir un nom (section 3.8), qui soit à la fois assez court pour être pratique et assez long pour être descriptif (et ce nom doit suivre la syntaxe de la section 3.1 du RFC 3986 qui limite notamment à ASCII, même pour des IRI). Pire, comme ces plans sont visibles (des URI sont souvent affichés dans les publications, sur les cartes de visite, sur les publicités), le nom du plan ne doit pas interférer avec des marques déposées défendues par des bataillons d'avocats. Il vaut donc mieux ne pas essayer de normaliser le plan coca-cola: (qui permettrait d'écrire des choses utiles comme coca-cola:light)... Le RFC recommande aussi d'éviter des noms trop marketing comme tout ce qui contient « universal » ou « standard ».

Pour les plans privés, spécifiques à une organisation et non enregistrés, notre RFC recommande d'utiliser un nom de domaine inversé comme préfixe, afin de limiter les risques de collisions (sections 3.8 et 6). Si la société Example, titulaire du domaine example.com, veut un plan pour son système Foobar, elle utilisera donc com.example.foobar: comme plan d'URI. Cela évite toute collision avec une autre société qui aurait un Foobar. (Le RFC 4395 recommandait un tiret au lieu d'un point dans ce nom inversé.)

Ces règles de la section 3 sont obligatoires pour les plans enregistrés de manière permanente. Mais le registre contient aussi des plans enregistrés à titre provisoire et les règles en question ne sont qu'indicatives pour eux (section 4). Les enregistrements provisoires sont soumis à une politique plus libérale, « premier arrivé, premier servi ». Cela permet de demander que les plans privés soient, s'ils ne sont pas fabriqués à partir d'un nom de domaine comme l'exemple précédent, enregistrés de manière provisoire. Parmi les plans provisoires, au moment de cet article, bitcoin:, dtn: (cf. RFC 5050), etc.

Notez que, dans le registre des plans d'URI, outre les caractéristiques « permanent » et « provisoire », il y a aussi « historique » qui désigne les plans abandonnés (comme le fax: du RFC 2806).

Bref, une fois qu'on a bien lu toutes ces considérations, on peut passer à l'enregistrement proprement dit. Pour cela, il faut suivre la procédure exposée en section 7 (qui utilise les termes du RFC 5226 comme « examen par un expert » ou « premier arrivé, premier servi »). On remplit un formulaire (section 7.4 pour un formulaire vierge), il est examiné (dans la plupart des cas) sur une liste de diffusion comme uri-review@ietf.org, puis par un expert (section 7.2).

Une éventuelle mise à jour d'un enregistrement se fait par le même mécanisme (section 7.3).

Une des nouveautés de notre RFC, par rapport à son prédécesseur RFC 4395, est la création d'un plan d'URI qui sert à la documentation (dans l'esprit du RFC 5398 pour les numéros d'AS et RFC 2606 pour les noms de domaine). Si vous voyez un URI qui commence par example:, c'est... un exemple. Imaginons une base de données qui stocke des URI et qu'on montre un exemple d'export de cette base en JSON, on est sûr de ne pas entrer en conflit avec un vrai URI, et on n'a pas trop à se soucier de la syntaxe (le plan example: autorise tout), en utilisant ce plan :

{"uris":
   {"date": "2014-09-02 09:58:23+00:00",
    "uri": "example:do-some-thing#test"},
   {"date": "2015-06-24 16:11:09+00:00",
    "uri": "example:foo.bar"},
   ...
}

Le formulaire d'enregistrement de ce plan figure dans la section 8 de notre RFC, si vous envisagez d'enregistrer un plan et que vous voulez un exemple. Si vous voulez un vrai exemple récent, vous pouvez regarder la section 7 du RFC 7565, qui enregistrait acct:. (Pour les enregistrements provisoires, la demande est indiquée à partir du registre IANA.)

L'annexe A de notre RFC liste les changements qui se sont produits depuis le RFC 4395. Les plus importants, à mon avis, sont :

  • Fusion des registres permanent et provisoire en un seul registre, avec une colonne Status,
  • Libéralisation de l'enregistrement des plans provisoires (cf. RFC 5226), de « Examen par un expert » à « Premier arrivé, premier servi » (les plans permanents restent à « Examen par un expert »),
  • Ajout du plan example:,
  • Changement des conventions pour les préfixes des plans privés non enregistrés (point au lieu du tiret entre les composants du nom de domaine),
  • Diverses clarifications, par exemple sur le fait que tout plan d'URI s'aapplique aux IRI aussi bien qu'aux URI,
  • Ajout de la vie privée aux considérations sur la sécurité.

Il y avait eu d'autres idées pendant le développement de ce RFC, mais toutes n'ont pas été retenues. Par exemple, à l'IETF 90, nous avions discuté de faire des plans avec préfixes (coap+ws:, coap+sms:, etc, au lieu du simple coap: du RFC 7252), par analogie avec les types MIME structurés du RFC 6839.


Téléchargez le RFC 7595


L'article seul

Version 8 d'Unicode

Première rédaction de cet article le 19 juin 2015


Le 17 juin a vu la sortie d'une nouvelle version du jeu de caractères Unicode, la 8.0, pile un an après la précédente. On peut trouver une description des principaux changements en http://www.unicode.org/versions/Unicode8.0.0/ mais voici ceux qui m'ont intéressé particulièrement. (Il n'y a pas de changement radical.)

Pour explorer plus facilement la grande base Unicode, j'utilise un programme qui la convertit en SQL et permet ensuite de faire des analyses variées. Faisons quelques requêtes SQL :

ucd=> SELECT count(*) AS Total FROM Characters;
 total  
--------
 120737

Plus de 120 000 caractères. Lesquels ont été apportés par la version 8 ?


ucd=> SELECT version,count(version) FROM Characters GROUP BY version ORDER BY version;
...
 7.0     |  2834
 8.0     |  7716

7 716 nouveaux. Lesquels ?

ucd=> SELECT To_U(codepoint) AS Codepoint, name FROM Characters WHERE version='8.0';
 codepoint |                                    name                                    
-----------+----------------------------------------------------------------------------
...
 U+8B4     | ARABIC LETTER KAF WITH DOT BELOW
...
 U+13FB    | CHEROKEE SMALL LETTER YU
...
 U+11294   | MULTANI LETTER DDHA
...
 U+12488   | CUNEIFORM SIGN DA TIMES TAK4
...
 U+1D96D   | SIGNWRITING MOVEMENT-FLOORPLANE DOUBLE ALTERNATING WRIST FLEX
...
 U+1F32F   | BURRITO
 ...
 U+1F3FF   | EMOJI MODIFIER FITZPATRICK TYPE-6
 ...
 U+1F54C   | MOSQUE
 U+1F54D   | SYNAGOGUE
...

Comme on le voit, c'est varié. On trouve des écritures entièrement nouvelles comme le multani ou le système Sutton pour la langue des signes, des nouvelles lettres pour des écritures existantes (le « ARABIC LETTER KAF WITH DOT BELOW » est ajouté à l'alphabet arabe pour écrire des langues de l'Asie du Sud-Est), des nouveaux emojis (comme le burrito)... L'alphabet cherokee a connu un grand changement, il est désormais bicaméral et les minuscules du Cherokee viennent donc s'ajouter à Unicode (comme la U+13FB ci-dessus). Par contre, comme il ne s'est écrit qu'en majuscules pendant longtemps, l'algorithme d'uniformimisation de casse d'Unicode met le Cherokee en majuscules, et pas en minuscules comme pour toutes les autres écritures.

Si vous avez les bonnes polices de caractères, voici les caractères pris en exemple plus haut : ࢴ, ᏻ, 𑊔 𒒈, 𝥭, 🌯, (U+1F3FF a été omis, voir à la fin), 🕌, 🕍 ... (UniView n'a apparemment pas encore été mis à jour avec les données de la version 8).

Comme toujours depuis quelques versions d'Unicode, tout le monde s'excite sur les nouveaux emojis (si vous ne les avez pas encore sur votre ordinateur, voyez les jolis dessins sur ce site). Plutôt que de donner des listes pittoresques, avec des glyphes rigolos, je suggère fortement à mes lecteurs de lire l'excellent Unicode Technical Report #51 sur la gestion des emojis dans Unicode. Vous y apprendrez le pourquoi de ces caractères, et les règles qu'ils suivent dans Unicode, et comment enregister un nouvel emoji. À la lecture de ce rapport, vous saurez pourquoi le policier tue le crocodile (et pas le contraire), pourquoi un emoji dont le nom inclut BLACK n'est pas forcément noir, quelles sont toutes les formes possibles du shortcake...

Une nouveauté importante des emojis dans cette version 8 est la gestion de la couleur de peau. Traditionnellement, les personnages humains dans des emojis sont représentés avec une peau jaune vif. C'est considéré comme « neutre » (notez que les emojis sont nés au Japon...) Cela ne convient pas forcément à tout le monde et il y a une demande depuis longtemps pour permettre de représenter des gens à la peau rose ou noire. C'est possible avec la nouveauté des modificateurs d'emojis. Ce sont des caractères Unicode qui se placent après l'emoji et modifient la couleur de la peau du personnage. Ils sont cinq, correspondant aux cinq degrés de l'échelle de Fitzpatrick. Par exemple, si votre navigateur gère ces récents modificateurs, en mettant les deux caractères U+1F477 (CONSTRUCTION WORKER) et U+1F3FE (EMOJI MODIFIER FITZPATRICK TYPE-5), vous devriez voir un ouvrier à la peau sombre (mais pas complètement noire). Essayons d'abord sans le modificateur : 👷 et avec : 👷 🏾. (Au passage, ce caractère U+1F477 est cité dans le rapport #51 pour une autre raison politique : il est neutre du point de vue du genre et peut donc être représenté par un homme ou une femme.)

À noter deux limites des modificateurs : ils ne peuvent pas s'appliquer à chaque membre d'un groupe. Donc, dans U+1F46C TWO MEN HOLDING HANDS, les deux hommes ont forcément la même couleur de peau. Et, autre limite, les modificateurs ne peuvent changer que la couleur de la peau, pas d'autres caractéristiques comme la minceur.


L'article seul

RFC 7575: Autonomic Networking - Definitions and Design Goals

Date de publication du RFC : Juin 2015
Auteur(s) du RFC : M. Behringer, M. Pritikin, S. Bjarnason, A. Clemm (Cisco Systems), B. Carpenter (Univ. of Auckland), S. Jiang (Huawei Technologies), L. Ciavaglia (Alcatel Lucent)
Pour information
Réalisé dans le cadre du groupe de recherche IRTF nmrg
Première rédaction de cet article le 19 juin 2015


Ce nouveau RFC, issu de l'IRTF et donc assez futuriste, se penche sur les « réseaux autonomes » (autonomic networking), c'est-à-dire sur les réseaux qui se débrouillent tout seuls, sans administrateur réseaux, sans DSI, sans ICANN, etc. Un réseau autonome doit se configurer, s'optimiser, guérir des pannes et se protéger des attaques sans intervention humaine. Ce RFC n'explique pas comment les réaliser (c'est le début d'un programme de recherche) mais définit la terminologie et les buts à atteindre. Il a été publié en même temps que le RFC 7576, qui analysait les techniques existantes et leurs limites. (Le groupe de travail IETF ANIMA travaille sur les aspects plus concrets de ce sujet.)

La première description de tels réseaux autonomes date de 2001 (l'article de Kephart et Chess). L'idée est que toutes les boucles de régulation du système doivent être fermées, sans interaction avec l'extérieur (d'où l'adjectif « autonome »). IP lui-même a éte partiellement conçu pour fonctionner ainsi (la fameuse demi-légende de l'Internet prévu pour résister à une attaque nucléaire). Un protocole comme OSPF est autonome dans la mesure où il s'adapte tout seul aux changements de topologie. Toutefois, IP n'a jamais été complètement autonome et les évolutions qu'il a subi allaient plutôt dans le sens de mettre plus d'intelligence dans la configuration externe que dans le réseau lui-même. Est-ce grave ? Pour un grand réseau d'un Tier 1, on peut penser que son propriétaire préfère que le réseau n'ait pas trop d'autonomie (Skynet ?) et suive plutôt la politique configurée. Mais les réseaux autonomes sont tentants pour l'Internet des objets, quand on a un grand nombre de petites machines très simples, ensemble qui serait très difficile ou impossible à configurer avec les outils existants. Notre RFC estime que les deux approches (configuration extérieure centralisée, et fonctionnement réparti autonome) ont leurs avantages et inconvénients, et que pas mal de réseaux utiliseront une de ces deux approches pour certaines fonctions et la seconde pour les autres fonctions. Ne cherchez donc pas de réseau complètement autonome tout de suite.

De toute façon, l'approche autonome ne peut pas tout faire. Elle nécessite de découvrir tout seul un certain nombre de choses et la politique de gestion du réseau (qui peut s'en servir, pour quoi...) est un bon exemple de quelque chose qui ne peut pas être découvert, qui doit être configuré explicitement.

Les réseaux autonomes ont fait l'objet d'un très grand nombre d'études scientifiques et de publications (la section 7 du RFC contient des lectures, pour les gourmands, notamment trois synthèses de l'existant). Attention, on dit « autonome » et pas « automatique ». Il faut se gérer seul, pas juste dérouler automatiquement un script pré-établi par un humain (voir la section 2 sur les définitions). Par exemple, un système automatique doit être reprogrammé lorsque l'environnement change alors qu'on attend d'un réseau autonome qu'il s'adapte seul.

Donc, que veut-on d'un réseau autonome ? La section 3 décrit les buts. Le réseau doit être auto-géré ce qui se décline en :

  • Se configure tout seul. Les machines démarrent, se découvrent, trouvent les liens qui les relient et se mettent à les utiliser. Pas d'admin' pour avoir tapé des default_router=fe80::1.
  • Se guérit tout seul. Une pelleteuse arrache un câble ? Le réseau contourne le problème automatiquement (ceci marche dans l'Internet actuel : rappelez-vous qu'on a déjà certaines fonctions qui peuvent marcher de manière autonome).
  • S'optimise tout seul en trouvant la meilleure façon d'accomplir les tâches définies.
  • Se protège tout seul car le monde est hostile et cruel et des hackers chinois islamistes à cagoule vont attaquer le réseau.

Évidemment, en trichant, on peut définir tout réseau comme « autonome » si on élargit la définition pour inclure, par exemple, un contrôleur central (comme avec le SDN). Le RFC est donc plus spécifique : « tout seul » veut dire « en n'utilisant que des fonctions qui sont sur les machines terminales ». Comme dit l'Internationale, le réseau autonome n'a « ni Dieu, ni César, ni tribun[, ni contrôleur SDN] ».

Comme on ne peut pas envisager un Internet complètement autonome, ces réseaux autonomes vont devoir coexister avec les méthodes de gestion traditionnelles (comme Netconf). Cela peut nécessiter un mécanisme d'arbitrage si les deux méthodes sont en désaccord. Le RFC utilise un exemple tiré de l'aviation : un avion où le pilote automatique se coupe automatiquement si le vol sort d'une certaine plage de paramètres (par exemple si l'angle d'incidence est trop élevé). Toutefois, on peut aussi se dire qu'une crise n'est pas le meilleur moment pour passer brutalement le contrôle au pilote stressé et le RFC demande donc que les mécanismes autonomes ne se coupent pas tout seuls, même dans des situations non prévues.

Autre but de nos réseaux autonomes : qu'ils soient sûrs. On doit pouvoir, par exemple, empêcher un intrus de rejoindre le réseau, ce qui implique un certain mécanisme d'authentification, qui ne sera pas forcément totalement autonome (par exemple un certificat émis par une AC, une base d'utilisateurs centralisée, etc). Bref, il faudra sans doute de la cryptographie.

« Autonome » ne veut pas dire « isolé et sourd-muet » (sinon, ce ne serait pas un réseau). La machine doit communiquer avec des pairs mais aussi avec des autorités, comme cela qui lui communique le travail à faire, à qui la machine terminale transmet des rapports, des statistiques, etc. C'est ce qu'on nomme l'interface Nord (car placée en haut sur les schémas et tant pis pour l'Australie).

On a vu que le réseau n'est pas créé pour satisfaire les machines mais pour accomplir un certain travail. Il faudra donc un mécanisme pour informer les machines de ce travail, et des changements dans les définitions de ce travail. Ce mécanisme doit être de haut niveau, sinon, ce ne sera plus un réseau autonome, on retournerait à la configuration centralisée traditionnelle. Par exemple, le RFC demande que ce mécanisme n'expose pas la version d'IP utilisée (IPv4 ou IPv6) : cela doit rester un détail technique interne au réseau.

J'ai parlé plus haut de transmettre des rapports à l'autorité centrale. Il est évidemment nécessaire de prévenir les humains qui ont acheté et déployé ces machines de l'efficacité de celles-ci : le travail a-t-il été fait ? Mais, pour respecter le principe d'un réseau autonome, les rapports ne doivent pas porter sur des détails d'implémentation que le réseau doit résoudre lui-même (comme « le lien entre la machine X et la machine Y ne marche plus »). Il faut au contraire un mécanisme de communication abstraite, synthétisant l'information, pour ne pas écrouler l'autorité centrale sous les détails. Imaginons que l'autorité ait envoyé le but de haut niveau « économise l'énergie », le rapport devrait être du genre « 30 % de réduction de la consommation, obtenu en éteignant 40 % des ports réseau ». Pour résumer : les rapports devraient décrire le réseau globalement, pas machine par machine ou lien par lien.

Le RFC 7576 montre qu'il existe déjà un certain nombre de protocoles et de fonctions autonomes dans la famille IP. Mais le but du projet « réseaux autonomes » n'est pas uniquement d'empiler des solutions mais de les intégrer dans un cadre commun, qui reste à développer.

Enfin, « autonome » est un adjectif qu'on peut appliquer à toutes les couches. Par exemple, les commutateurs typiques aujourd'hui sont autonomes au niveau 2 (on les branche n'importe comment et ils font une topologie qui marche). Les routeurs peuvent en faire autant au niveau 3, comme vu avec l'exemple OSPF.

Un bon cahier des charges doit aussi avoir des non-buts : ce qu'on ne cherche pas à atteindre. C'est le rôle de la section 4 du RFC. Les non-buts sont :

  • Supprimer complètement tout opérateur humain (Skynet, encore). Les humains vont rester, mais en se concentrant sur des fonctions de haut niveau, comme la définition et la vérification des politiques.
  • Résoudre tous les problèmes. De temps en temps, il se produira un évènement dont le réseau ne saura pas se dépêtrer seul. Là encore, des humains devront intervenir. Ce sera au moins le cas pour les pannes matérielles, tant que les ordinateurs n'auront pas de périphériques leur permettant d'aller à la casse eux-même...
  • Supprimer tout contrôle central. Comme le note le RFC, la Direction Générale ne serait sans doute pas d'accord.

Enfin, notre RFC se termine par une description, en section 5, d'un modèle de référence des réseaux autonomes, reprenant les points vus précédemment.


Téléchargez le RFC 7575


L'article seul

RFC 7572: Interworking between the Session Initiation Protocol (SIP) and the Extensible Messaging and Presence Protocol (XMPP): Instant Messaging

Date de publication du RFC : Juin 2015
Auteur(s) du RFC : P. Saint-Andre (&yet), A. Houri (IBM), J. Hildebrand (Cisco Systems)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF stox
Première rédaction de cet article le 17 juin 2015


Ce court RFC décrit une correspondance entre deux protocoles standards de messagerie instantanée, SIP et XMPP. Cela permet de développer proprement des passerelles connectant ces deux mondes, autorisant ainsi Juliette, utilisatrice de XMPP, à parler avec son Roméo, qui utilise SIP. C'est aussi un exercice intellectuel rigolo, mais parfois difficile, comment faire se parler deux protocoles différents, qui n'ont pas exactement les mêmes sémantiques.

C'est vrai qu'on ne sait pas forcément que SIP (RFC 3261) est aussi un protocole de messagerie instantanée. On le voit plutôt uniquement comme un protocole de signalisation pour la téléphonie sur IP. Mais SIP sait bel et bien échanger de courts messages textes, grâce à l'extension MESSAGE du RFC 3428. Quant à XMPP (RFC 6120), ses capacités de messagerie instantanée sont spécifiées dans le RFC 6121. C'est pour des raisons historiques variées que l'IETF a deux protocoles standard de messagerie instantanée, sans compter l'ancêtre IRC.

Le concept de messagerie instantanée, à l'IETF, est décrit dans le RFC 2779. Le but est de communiquer, donc il serait ennuyeux que Roméo et Juliette ne puissent pas échanger simplement parce qu'ils ont fait des choix technologiques différents. Spécifier un mécanisme de passerelle entre ces deux protocoles peut se faire en développant une sémantique abstraite (elle existe déjà, dans le RFC 3860), puis en définissant une correspondance entre cette abstraction et chaque protocole (ce qui a été fait pour XMPP : RFC 3922). En pratique, c'est bien compliqué et notre nouveau RFC 7572 choisit une autre approche, définir une correspondance entre SIP et XMPP, sans intermédiaire. L'inconvénient est que cela ne se généralise pas à davantage de protocoles, l'avantage est que c'est simple à comprendre et à programmer. En pratique, cette approche est donc bien plus répandue.

Notre RFC repose sur un modèle simple, l'envoi de courts textes, les messages, de manière synchrone, entre deux entités (Roméo et Juliette dans les exemples du RFC), ce qui se nomme page mode. Il existe d'autres modèles comme celui de conversations stables sur une certaine durée (session mode) ou comme celui de communications à plus de deux participants. Le groupe de travail STOX de l'IETF est penché dessus et produira d'autres RFC sur ces modèles, comme le RFC 7573 sur les sessions. Notre RFC s'appuie sur le RFC 7247, qui définissait une architecture pour l'interconnexion de SIP et XMPP.

Donc, commençons par XMPP vers SIP (section 4). Un message XMPP est une strophe (stanza) XML <message/> de type normal (le type par défaut). Voici l'exemple envoyé par Juliette :


<message from='juliet@example.com/yn0cl4bnw0yr3vym'
         to='romeo@example.net'>
   <body>Art thou not Romeo, and a Montague?</body>
</message>

Si le domaine dans l'attribut to est un domaine SIP (section 5 du RFC 7247), le serveur XMPP que Juliette utilise va transmettre le message à une passerelle XMPP->SIP qui va traduire en SIP :


MESSAGE sip:romeo@example.net SIP/2.0
Via: SIP/2.0/TCP x2s.example.com;branch=z9hG4bK776sgdkse
Max-Forwards: 70
To: sip:romeo@example.net
From: <sip:juliet@example.com;gr=yn0cl4bnw0yr3vym>;tag=12345
Call-ID: D9AA95FD-2BD5-46E2-AF0F-6CFAA96BDDFA
CSeq: 1 MESSAGE
Content-Type: text/plain
Content-Length: 35

Art thou not Romeo, and a Montague?

Notez que l'identificateur de ressource dans le JID (le JID nu est juliet@example.com, la ressource est yn0cl4bnw0yr3vym, cf. RFC 6120, section 1.4) a été traduit en GRUU (Globally Routable User Agent URIs, cf. RFC 5627) SIP.

Le serveur SIP de Roméo répondra automatiquement avec le code 200 (tout va bien) :

SIP/2.0 200 OK
Via: SIP/2.0/TCP x2s.example.com;branch=z9hG4bK776sgdkse
From: sip:juliet@example.com;tag=12345
To: sip:romeo@example.net;tag=vwxyz
Call-ID: D9AA95FD-2BD5-46E2-AF0F-6CFAA96BDDFA
CSeq: 1 MESSAGE
Content-Length: 0

La correspondance entre les termes utilisés figure dans le tableau 1 dans cette section 4. Ainsi, le <body/> de XMPP est transformé en corps du message SIP, l'attribut to de XMPP qui indique le destinataire devient le champ To: de SIP, l'attribut xml:lang de XMPP (absent dans cet exemple) devient un champ Content-Language:, etc. Certaines valeurs n'ont pas de correspondance (comme l'attribut type de XMPP, inutilisé dans l'exemple).

En sens inverse, lorsque Roméo répond, il va utiliser SIP (avec l'extension du RFC 3428) et il va donc falloir traduire le SIP en XMPP. Sa réponse était (section 5 de notre RFC) :


MESSAGE sip:juliet@example.com SIP/2.0
Via: SIP/2.0/TCP s2x.example.net;branch=z9hG4bKeskdgs677
Max-Forwards: 70
To: sip:juliet@example.com
From: sip:romeo@example.net;tag=vwxyz
Call-ID: 9E97FB43-85F4-4A00-8751-1124FD4C7B2E
CSeq: 1 MESSAGE
Content-Type: text/plain
Content-Length: 44

Neither, fair saint, if either thee dislike.

Et la passerelle SIP->XMPP qu'utilisera le serveur SIP de Roméo traduira en :


<message from='romeo@example.net/dr4hcr0st3lup4c'
         to='juliet@example.com'>
  <body>Neither, fair saint, if either thee dislike.</body>
</message>

La correspondance entre les termes (tableau 2) est la même, mais inversée. Le champ To: est traduit en attribut to, le corps du message devient un élément XMPP <body>, etc. Notez que la passerelle connaissait le GRUU SIP (par un moyen non spécifié, peut-être parce qu'elle fait partie du serveur SIP) et l'a utilisé pour générer un JID complet avec identificateur de ressource (romeo@example.net/dr4hcr0st3lup4c).

Faire des passerelles entre deux protocoles indépendants, conçus de manière différente et sans coordination a toujours été délicat. Par exemple, la section 6 fait remarquer qu'il y a un problème... de taille. SIP met une limite de 1 300 octets aux messages (RFC 3428, section 8) alors que les RFC sur XMPP ne spécifient pas de limite. En pratique, les messages XMPP dépassent rarement cette taille et, de toute façon, les mises en œuvre effectives de XMPP ont souvent une limite (RFC 6120, section 13.12), mais plus élevée (au moins 10 000 octets doivent être acceptés, dit le RFC 6120). Si Juliette, qui utilise XMPP, essaie d'envoyer un message de 1 500 octets à son Roméo, la passerelle XMPP->SIP n'aura pas d'autre choix que de le rejeter, avec une erreur <policy-violation/>. (Des solutions plus sophistiquées existent, comme de passer en session mode mais notre RFC ne les spécifie pas.)

Autre cause d'incompatibilités possibles, mais en sens inverse, cette fois, les questions de format des données (section 7). Un message SIP peut contenir des données de n'importe quel type (dans les exemples ci-dessus, c'était toujours du text/plain mais ce n'est pas obligatoire). XMPP traitant le contenu de manière très différente, notre RFC impose aux passerelles SIP->XMPP de :

  • Accepter le contenu text/plain, comme dans les exemples ci-dessus, en le mettant dans le <body/> XMPP,
  • Accepter le contenu text/html en le transformant en XHTML qu'on met dans le <body/> XMPP (comme décrit dans le XEP-0071),
  • Faire ce qu'elle veut avec les autres types, aucune règle n'est spécifiée pour eux.

Et si on veut le dire autrement qu'en anglais ? Pas de problème, les deux protocoles permettent d'étiqueter le message avec la langue utilisée, et tous les deux permettent de transporter des caractères Unicode (en général en UTF-8). Si Roméo décide de parler tchèque :


MESSAGE sip:juliet@example.com SIP/2.0
Via: SIP/2.0/TCP s2x.example.net;branch=z9hG4bKeskdgs677
Max-Forwards: 70
To: sip:juliet@example.com
From: sip:romeo@example.net;tag=vwxyz
Call-ID: 5A37A65D-304B-470A-B718-3F3E6770ACAF
CSeq: 1 MESSAGE
Content-Type: text/plain
Content-Length: 45
Content-Language: cs

Nic z obého, má děvo spanilá, nenávidíš-li jedno nebo druhé. 

La passerelle le traduira sans problème (j'ai utilisé ici les notations commençant par &#x mais ce n'est pas obligatoire, XMPP utilise XML et peut donc se servir d'UTF-8) :


<message from='romeo@example.net'
         to='juliet@example.com'
         xml:lang='cs'>
	 <body>
           Nic z ob&#x00E9;ho, m&#x00E1; d&#x011B;vo spanil&#x00E1;, nen&#x00E1;vid&#x00ED;&#x0161;-li jedno nebo druh&#x00E9;.
       </body>
</message>

Un mot sur la sécurité pour finir. L'introduction de la passerelle entre les deux protocoles ajoute évidemment quelques risques. Notamment, il est plus difficile de garantir une sécurité de bout en bout. Il existe des solutions standard peu déployées (RFC 3862 et RFC 3923) ou une solution non standard, OTR.

Parmi les serveurs qui mettent déjà en œuvre cette passerelle, on peut apparemment citer Cisco, Kamailio, ou AG Projects (dans Silk Server).


Téléchargez le RFC 7572


L'article seul

RFC 7556: Multiple Provisioning Domain Architecture

Date de publication du RFC : Juin 2015
Auteur(s) du RFC : D. Anipko
Pour information
Réalisé dans le cadre du groupe de travail IETF mif
Première rédaction de cet article le 16 juin 2015


Ce RFC décrit une architecture nouvelle permettant de mieux gérer les machines ayant plusieurs connexions à l'Internet. On ne parle pas ici de gros routeurs ou serveurs connectés à plusieurs réseaux, non, un simple smartphone qui a à la fois le WiFi et la 4G est un exemple d'une machine qui a plusieurs interfaces. Et cela pose des sérieux problèmes avec l'Internet d'aujourd'hui, car, parfois, chaque interface va nécessiter des réglages différents. Notre nouvelle architecture aborde ce problème en définissant le PvD (ProVisioning Domain ou domaine d'avitaillement), un ensemble cohérent de réglages, qui sera attaché à chaque interface.

Pourquoi est-ce un problème d'avoir plusieurs interfaces actives ? Car certains réglages ne sont valables que pour une seule interface, alors que TCP/IP considérait au début que toutes les interfaces se valaient et pouvaient être utilisées. Par exemple, l'adresse IP obtenue sur une interface ne doit pas être utilisée comme adresse IP source sur une autre interface, de peur de se faire mordre par le RFC 2827. Le résolveur DNS obtenu sur une interface ne doit pas être utilisé pour une autre car il refusera probablement de répondre (RFC 5358). Et, même si les résolveurs DNS acceptaient tous les clients, il arrive qu'ils renvoient des données qui ne sont pas les mêmes pour tout le monde (par exemple pour un serveur qui n'est accessible que depuis un certain réseau). Le RFC 6418 décrit plus en détail le problème des interfaces multiples, et le RFC 6419 proposait déjà quelques solutions, chacune spécifique à une plate-forme donnée. Pour résumer (à l'extrême) le RFC 6418, les risques sont :

  • Incohérence entre les informations obtenues depuis les différentes interfaces (comme dans l'exemple DNS ci-dessus),
  • Risque de mélanger les informations obtenues sur différentes interfaces (tenter de résoudre le nom d'un relais avec le serveur DNS d'un autre opérateur...),
  • Usage non conforme à la politique d'un des réseaux (par exemple, téléchargement d'un jeu via le VPN de l'entreprise...)

Donc, pour résoudre ce genre de problème, on introduit le concept de PvD. Mais c'est quoi, un PvD (section 2) ? Un ProVisioning Domain est simplement un ensemble cohérent d'informations de configuration d'un réseau, pour une interface donnée. Cela comprend par exemple l'adresse IP à utiliser (ou le préfixe IP), les adresses IP des résolveurs DNS, le routeur par défaut, le proxy Web à utiliser, etc. Une machine PvD-aware sait gérer cette information (notamment en l'association à une interface et en gardant en mémoire que, par exemple, ce résolveur DNS est fait pour cette interface). Une application PvD-aware a du code pour gérer la coexistence de différents PvD.

Aujourd'hui, les PvD sont implicites. La machine connectée reçoit de l'information de configuration sur chaque interface, via des processus divers (DHCP, mais pas seulement), et cette information n'est pas groupée, sous l'étiquette d'un PvD donné. C'est à la machine PvD-aware de gérer une table de PvD en les nommant et en les associant à chaque interface. Par défaut, avec les PvD implicites, une interface = un PvD.

Mais il y aura plus tard des PvD explicites. Cette distinction entre PvD implicites et explicites est essentielle. L'idée est de développer via l'IETF des mécanismes (comme celui du RFC 8801) pour communiquer à la machine des PvD explicites, regroupant sous un nom donné un jeu d'informations de configuration cohérentes. Par exemple, on peut imaginer une option DHCP qui indique le nom du PvD correspondant aux options de configuration contenues dans cette réponse DHCP (ce n'est qu'une hypothèse : le RFC liste d'autres possibilités, cf. section 3). Avec les PvD explicites, il n'y aura plus forcément une interface = un PvD. On pourra avoir plusieurs interfaces utilisant le même PvD (si elles sont gérées par la même organisation).

Cela impliquera un système (non encore défini) de nommage des PvD. Le « PvD ID » devra être unique (puisque le but est de différencier les informations de configuration de réseaux différents), par exemple en le tirant au hasard dans un espace de grande taille. Le PvD ID ne sera donc pas forcément lisible par un humain ; si on veut une telle lisibilité, il faudra développer une solution, par exemple de métadonnées associées au PvD.

Un PvD peut être commun à plusieurs familles IP (par exemple IPv4 et IPv6) et comporter donc plusieurs adresses. C'est utile si certaines options ont un sens pour plusieurs familles (c'est le cas de la politique de sélection de l'adresse du RFC 7078). Pour les PvD implicites, utiliser un seul PvD pour toutes les familles présentes sur l'interface est la politique recommandée.

La section 3 examine quelques protocoles existants pour voir comment ils pourraient être modifiés pour transporter de l'information explicite sur les PvD. Aujourd'hui, la configuration des machines terminales est faite en général par DHCP (RFC 8415) ou RA (RFC 3971). Notons qu'elles ne sont pas sécurisées par défaut. Des solutions existent pour authentifier la machine qui émet la réponse DHCP ou RA mais authentification n'est pas autorisation : elle ne nous dit pas si cette machine est autorisée à annoncer explicitement tel PvD. Pour cela, il faudrait un moyen de signer les PvD.

Évidemment, si on ajoute des mécanismes de PvD à ces protocoles, cela devra être fait d'une manière compatible avec les machines existantes, qui ne sont pas PvD-aware. Pendant la phase de coexistence, il faudra peut-être dupliquer de l'information dans les réponses DHCP ou RA, pour satisfaire tout le monde.

La section 4 du RFC présente trois études de cas concrètes. La première est celle d'une machine mobile, un smartphone, par exemple. Il a une interface avec un réseau mobile, mettons 3G, et une interface WiFi. S'il est dehors, loin de tout hotspot, il n'aura qu'une interface active et donc un seul PvD : pas de difficultés. S'il s'approche d'un point d'accès WiFi et s'y connecte, le dilemme commence : quelle interface utiliser ? Android, par exemple, ne peut en utiliser qu'une à la fois et va donc cesser d'utiliser la 3G. Cela simplifie le modèle de connexion pour les développeurs mais n'est pas satisfaisant pour l'utilisateur. Il serait plus satisfaisant de pouvoir utiliser les deux, mais en respectant à chaque fois le PvD (qui peut être différent) de chaque interface.

Autre étude de cas, un VPN, qui peut être considéré comme une interface supplémentaire, quoique virtuelle, et un réseau à la maison, connecté à la fois à un FAI généraliste classique et à un service de VoD, avec une interface séparée qu'on n'utilise que pour la vidéo, et qui est donc décrite par un PvD différent.

La section 5 de notre RFC étudie plus en détail certains points spécifiques qui doivent être traités par un nœud PvD-aware. Par exemple, la résolution de noms, déjà citée plus haut, qui dépend fortement du PvD : un résolveur DNS n'est typiquement utilisable que par certains clients, et pas par le monde entier. En outre, les résultats d'une résolution de noms peuvent varier selon le résolveur interrogé (cas d'un service spécifique à un FAI, par exemple le MMS). La machine doit donc savoir quel PvD utiliser pour chaque nom, avec des règles du genre « pour tous les noms se terminant en ma-boîte.example, se servir du résolveur DNS du PvD du VPN de ma boîte ». Si plusieurs PvD correspondent à des FAI généralistes, pouvant servir pour tout accès à un serveur public, la machine PvD-aware peut faire les résolutions de noms en parallèle, et prendre le plus rapide, selon un approche identique à celle des globes oculaires heureux du RFC 6555.

Et puisqu'on parle de sélectionner le « meilleur » PvD, il faut rappeler que la connectivité au réseau local, tel qu'elle s'obtient lorsqu'une requête DHCP ou RA a réussi, ne garantit pas un bon accès à tout l'Internet. Le signal local peut être fort, le serveur DHCP très réactif... et la connexion ultérieure échouer. Il est donc prudent de tester les connexions obtenues, par exemple en essayant de se connecter à un amer bien connu.

On a vu qu'une application pouvait être PvD-aware si elle sait utiliser l'information sur les PvD pour prendre des décisions. La section 6 décrit les propriétés attendues de l'API qui permettra de développer ces applications. Dans le cas le plus simple, une application PvD-aware peut se limiter à n'utiliser qu'un seul PvD. C'est le cas d'une application MMS qui dépend d'un opérateur particulier et qui devra donc passer par l'interface correspondante. Un peu plus complexe serait une application qui exprime des exigences et des préférences, du genre « il me faut IPv6 » ou « je fais de la vidéo-conférence, je veux une faible latence » ou bien « je suis paranoïaque, je ne veux passer que par un PvD cité dans telle liste » ou encore « je ne suis pas pressé, il vaut mieux utiliser la connexion la moins chère ». Le système pourrait alors choisir, en regardant les informations obtenues pour chaque PvD, quel PvD utiliser. Dans le dernier cas (une application qui télécharge beaucoup, comme la mise à jour du système d'exploitation, ou comme une application pair-à-pair d'accès à la culture), un mécanisme de sélection automatique via le PvD simplifierait nettement la tâche de l'utilisateur en le dispensant d'options comme la « n'utiliser qu'avec la WiFi » qu'on trouve souvent sur les applications Android, qui veulent éviter de faire exploser le forfait de téléphonie mobile.

Enfin, les applications les plus avancées pourraient simplement obtenir la liste des PvD et leurs caractéristiques et faire leurs choix elles-mêmes. Ces choix ne seront pas forcément respectés par le système, qui peut avoir ses propres exigences (par exemple forcer la passage par le VPN de l'entreprise pour les connexions aux services de la dite entreprise).

Puisqu'on a parlé de sécurité (« je suis paranoïaque, je ne veux passer que par un PvD cité dans telle liste »), un mot sur les PvD de confiance ou pas (section 7). Par défaut, un PvD n'est pas « de confiance ». Si je me promène dans la rue et que je me connecte à un hotspot inconnu, le PvD associé ne sera pas considéré comme de confiance. Certains systèmes ou applications ne voudront se connecter à tel service que via un PvD de confiance. Mais attention : supposons qu'on ait une telle liste (le PvD du VPN de la boîte, le PvD d'un opérateur à qui on fait confiance, le réseau local à la maison...), il ne faut pas pour autant considérer que le PvD est ce qu'il annonce. Si le PvD de l'entreprise est 6a97f31e-34ec-4ef9-ba75-b1e3addd8222 (ce n'est pas la vraie syntaxe des PvD ID, qui n'est pas encore décidée), et que le serveur DHCP du hotspot annonce ce PvD ID, il ne faut pas pour autant lui faire confiance (voir aussi la section 8). Un PvD de confiance nécessite deux choses : une relation de confiance avec son opérateur, et un moyen de vérifier qu'il s'agit bien du PvD attendu. Ce moyen d'authentification peut passer par une signature du PvD ID, ou bien simplement par le mécanisme d'attachement au réseau : on peut décider que, si on est connecté à un réseau physique stable et sûr, l'annonce du PvD ID sur ce réseau peut être crue. À noter que le RFC fournit un autre exemple, où on fait confiance au réseau d'un opérateur mobile, ce qui ignore le risque des IMSI-catchers.

La section 8 revient d'ailleurs sur les problèmes de sécurité. Par exemple, même si le serveur DHCP ou RA est sûr, un attaquant a pu modifier les données en cours de route. On peut utiliser les techniques (très peu déployées en pratique) de l'option AUTH du RFC 3315 (abandonnée depuis, dans le RFC 8415), section 22.11, ou le SEND du RFC 3971.


Téléchargez le RFC 7556


L'article seul

RFC 7553: The Uniform Resource Identifier (URI) DNS Resource Record

Date de publication du RFC : Juin 2015
Auteur(s) du RFC : P. Faltstrom (Netnod), O. Kolkman (ISOC)
Pour information
Première rédaction de cet article le 14 juin 2015


Ce RFC est la documentation d'un nouveau type d'enregistrement DNS, le type URI qui permet de publier des URI et donc d'avoir un mécanisme pour faire correspondre un nom de domaine à un URI.

Petit rappel, les URI sont normalisés dans le RFC 3986 et permettent sous une forme simple et compacte d'identifier une ressource sur le Web et, très fréquemment, fournissent les moyens d'y accéder. Traditionnellement, quand on voulait mettre des URI dans le DNS et permettre de les retrouver, on utilisait les NAPTR des RFC 3401 et RFC 3404. Notre nouveau RFC critique cette solution en notant qu'une requête NAPTR récupère tous les NAPTR qu'il faut trier ensuite, pas uniquement ceux liés à un seul service (le triage est d'autant plus compliqué qu'il n'existe toujours aucune bibliothèque en logiciel libre pour manipuler des NAPTR). En effet, le nom du service fait partie des données du NAPTR, pas du nom de domaine (le seul critère de sélection dans une requête DNS, avec le type). La solution de notre RFC 7553 permet cette sélection en mettant le type de service souhaité dans le nom de domaine. En outre, l'URI est trivial à extraire, il est le dernier composant des données de l'enregistrement, et ne nécessite pas de traitement ultérieur (on est loin de la complexité des NAPTR, même si les S-NAPTR du RFC 3958 l'ont un tout petit peu simplifiée).

Donc, dès que vous avez besoin d'une correspondance simple entre un nom de domaine et un URL, allez-y, ce type d'enregistrement est fait pour vous. À quoi ressemble-t-il (section 4 du RFC) ? Le format de présentation en texte met dans les données (la partie droite de l'enregistrement) une priorité, suivie d'un poids et de l'URI (nommé Target). Cela donne comme exemple :

_ftp._tcp.example.net.    IN URI 10 1 "ftp://ftp1.example.com/public"

Priorité et poids ont la même sémantique que dans le RFC 2782 (voir plus loin).

Le nom de domaine suit certaines conventions (section 4.1), notamment d'indiquer le service demandé (pris dans le registre IANA qu'avait créé le RFC 6335) et le protocole utilisé, précédés d'un tiret bas.

L'enregistrement URI a le type 256 et figure à ce titre dans le registre IANA des types DNS.

On peut avoir plusieurs URI pour un même nom de domaine (donc un même service). La sélection se fait en examinant d'abord la priorité, puis le poids. La priorité est absolue. On contacte d'abord les URI ayant la priorité la meilleure (c'est le chiffre le plus bas, attention), et, seulement si cela échoue, on tente les autres. Par contre, à priorité équivalente, la sélection selon le poids est probabiliste. Cela permet de faire de la répartition de charge dans le DNS. Si j'écris deux URI avec la même priorité mais des poids différents :

_ftp._tcp.example.net.    IN URI 10 2 "ftp://ftp1.example.net/public"
                          IN URI 10 1 "ftp://ftp4.example.com/mirrors/example.net/"

Alors, l'URI ftp://ftp1.example.net/public a deux fois plus de chances d'être sélectionné, il recevra donc les deux tiers des requêtes. Si j'avais mis des priorités différentes :

_ftp._tcp.example.net.    IN URI 10 1 "ftp://ftp1.example.net/public"
                          IN URI 20 1 "ftp://ftp4.example.com/mirrors/example.net/"

Alors, ftp://ftp4.example.com/mirrors/example.net/ ne sera sélectionné que s'il n'y a pas le choix, uniquement si ftp1.example.net est en panne.

Et sur le réseau, comment est encodé ce nouveau type (section 4.5) ? C'est simple, deux octets pour la priorité, deux pour le poids et l'URI lui-même, sous forme de texte.

Les enregistrements URI permettent d'indiquer la même chose qu'un SRV (RFC 2782), à savoir un nom de serveur et un port, mais ils permettent en outre d'exprimer d'autres choses (comme le répertoire dans les exemples FTP plus haut). En contre partie, il faut pouvoir traiter les URI, les analyser, mais c'est aujourd'hui une tâche bien connue, pour laquelle on a déjà du code. Ainsi, ces deux informations sont presque équivalentes (si on sait que le protocole à utiliser est HTTP) :

_http._tcp    IN  SRV   0  1 8081  www.example.net.
_http._tcp    IN  URI   0  1 "http://www.example.net:8081"

Mais les enregistrements URI sont plus puissants, ceci ne pourrait pas être exprimé en SRV :

_http._tcp    IN  URI   0  1 "http://www.example.net:8081/actu/2015"

Les futurs protocoles pourraient donc n'utiliser que URI, et plus du tout SRV. (À l'heure actuelle, certains protocoles utilisent une combinaison de SRV + un enregistrement TXT, pour résoudre ce problème : l'enregistrement URI est plus élégant.)

Je ne peux pas m'empêcher de noter que bien des problèmes du Web auraient été évités si, dès le début, Tim Berners-Lee avait pensé à découpler le nom de domaine et le serveur, en utilisant les SRV. Actuellement, le nom dans l'URL doit être un nom de machine (il doit obéir aux règles syntaxiques restrictives sur les noms de machine, et il doit avoir une adresse IP). Cela oblige à mettre une adresse à l'apex (le sommet) de la zone DNS (si on veut que http://example.com/ marche, il faut une adresse IP mise au nom example.com, ce qui est compliqué à réaliser proprement). Si le Web utilisait les SRV ou, aujourd'hui, les enregistrements URI, on ne serait pas obligé de polluer l'apex de la zone avec des adresses IP, on aurait séparé le nom court (example.com), dans l'URL, et celui du serveur (qui ne serait pas visible à l'utilisateur ordinaire).

Bien que ce type d'enregistrement ait déjà plusieurs années (le RFC 6895 permet d'enregistrer un type d'enregistrement DNS sans avoir de RFC), certains logiciels ne le gèrent pas encore. Voici une version un peu ancienne d'OpenDNSSEC (je n'ai pas testé avec les versions plus récentes) :

ods-signerd: [adapter] error parsing RR at line 28 (Syntax error, could not parse the RR's rdata):   IN URI 0 1 "http://www.bortzmeyer.org/"

Aïe. Et pareil avec le signeur DNSSEC d'une version un peu vieille de BIND :

dnssec-signzone: warning: sources.org:23: unknown RR type 'URI'
dnssec-signzone: fatal: failed loading zone from 'sources.org': unknown class/type

Idem pour les formulaires Web qui permettent de créer des enregistrements DNS dans une zone gérée par son hébergeur DNS. Tous n'ont pas encore ce type, loin de là.

Pour une vision optimiste, voici le commit qui a ajouté le type URI à PowerDNS.

Un exemple d'utilisation des enregistrements URI est le service des codes postaux dans le DNS, où un URI pointe vers OpenStreetMap. Ici, la commune de Luchon :

% dig +short +nodnssec URI 31110.cp.bortzmeyer.fr
10 1 "http://www.openstreetmap.org/?mlat=42.781913&mlon=0.564010&zoom=12"

Téléchargez le RFC 7553


L'article seul

Alerte en Malaisie, une nouvelle fuite BGP

Première rédaction de cet article le 12 juin 2015
Dernière mise à jour le 14 juin 2015


C'est un accident qui, à cette ampleur, se produit tous les... quoi... trois ou quatre ans sur l'Internet. Un opérateur, en l'occurrence Telekom Malaysia, a laissé fuiter des centaines de milliers de routes Internet, attirant ainsi une quantité de trafic qu'il n'a pas su gérer. Le problème a duré environ deux heures. Du classique, à quelques exceptions près.

Merci à Buck Danny pour la référence :alerte-malaisie.jpg

D'abord, les observations brutes : les premières observations publiques qu'il y avait un problème ont été divers tweets comme celui de Nathalie Rosenberg à 0855 UTC. Une bonne partie de l'Internet semblait injoignable, et des gens ont commencé à accuser Free ou CloudFlare. En fait, on pouvait voir à plusieurs endroits que la source du problème était dans une crise BGP. Par exemple, les fichiers stockant les annonces BGP à RouteViews augmentaient brusquement de taille, montrant une forte activité BGP, ce qui n'est pas en général bon signe. De fichiers de moins d'un Mo en temps normal, on est passé à 2,2 Mo à 0845 puis à 14 Mo à 0900 et 19 Mo à 0915. L'examen du contenu de ces fichiers montre la cause du problème : l'AS 4788 (Telekom Malaysia) a laissé fuiter dans les 200 000 routes BGP (au lieu de 1 300 en temps normal, ce qui est déjà beaucoup)... Voici la première annonce erronnée :

TIME: 06/12/15 08:43:29
TYPE: BGP4MP/MESSAGE/Update
FROM: 208.51.134.246 AS3549
TO: 128.223.51.102 AS6447
ORIGIN: IGP
ASPATH: 3549 4788 3491 4651 9737 23969
NEXT_HOP: 208.51.134.246
MULTI_EXIT_DISC: 24968
COMMUNITY: 3549:4992 3549:7000 3549:7003 3549:7004 354
9:32344 4788:400 4788:410 4788:415
ANNOUNCE
  1.0.208.0/22
  1.0.212.0/23
  1.1.176.0/22
  ...

Aucune de ces préfixes n'est géré par Telekom Malaysia ou ne devrait être annoncé par eux. C'est à tort que leur transitaire Level 3/GlobalCrossing (AS 3549) a accepté ces annonces. (Rappelez-vous qu'un chemin d'AS se lit de droite à gauche, ici 23969 est l'origine.) Normalement, on filtre les annonces de ses clients ou de ses pairs BGP, à partir des IRR. Même si on ne filtre pas sur les données des IRR (souvent mal maintenues), on devrait, au minimum, mettre un nombre maximal de préfixes annoncé et couper la session autrement (si Free l'avait fait, ses clients auraient eu moins de problèmes, voir plus loin). Mais personne ne veut prendre le risque de mécontenter un client. Et puis filtrer demande davantage de travail, alors que la sécurité ne rapporte rien.

Level 3 relayant ce grand nombre de routes, bien des routeurs qui avaient configuré un nombre maximum de préfixes BGP annoncés ont coupé leur session. Ainsi, au RING, on voyait :

id	timestamp	raised_by	short
2413	2015-06-12 09:33:52	linode01	linode01.ring.nlnog.net: raising ipv4 alarm - 17 new nodes down
2412	2015-06-12 09:32:46	ovh04	ovh04.ring.nlnog.net: raising ipv4 alarm - 43 new nodes down
2411	2015-06-12 09:31:56	ovh03	ovh03.ring.nlnog.net: raising ipv4 alarm - 29 new nodes down
2410	2015-06-12 09:27:49	adix01	adix01.ring.nlnog.net: raising ipv4 alarm - 1 new nodes down
2409	2015-06-12 09:27:46	octopuce01	octopuce01.ring.nlnog.net: raising ipv4 alarm - 20 new nodes down
2408	2015-06-12 09:20:51	berkeley01  berkeley01.ring.nlnog.net: raising ipv4 alarm - 3 new nodes down

Notons que tout n'est pas passé par Level 3. Les gens qui peeraient avec Telekom Malaysia et qui, bien à tort, ne filtraient pas les annonces, ont également reçu les annonces fausses. C'est le cas de Free, ce qui explique l'ampleur de la crise pour les abonnés de Free. Voici un traceroute actuel, montrant le peering entre Free et Telekom Malaysia :

% traceroute www.tm.com.my
traceroute to www.tm.com.my (58.27.84.129), 30 hops max, 60 byte packets
 1  freebox (192.168.2.254)  12.533 ms  12.510 ms  12.498 ms
...
 7  bzn-crs16-1-be1024.intf.routers.proxad.net (212.27.56.149)  25.686 ms  14.741 ms  14.706 ms
 8  th2-9k-1-be1003.intf.routers.proxad.net (78.254.249.97)  12.186 ms  31.208 ms  31.177 ms
 9  yankee-6k-1-po1.intf.routers.proxad.net (212.27.57.14)  115.595 ms  117.136 ms  117.129 ms
10  ash-bo02.tm.net.my (206.126.236.176)  106.776 ms  106.789 ms  115.466 ms
11  10.55.36.116 (10.55.36.116)  366.449 ms  366.450 ms  367.967 ms
12  58.27.84.6 (58.27.84.6)  375.796 ms  375.787 ms  382.950 ms
...

Résultat de ces annonces, le trafic filait effectivement en Malaisie comme le montre ce test :

$ mtr -4rwc100 cloudflare.com
Start: Fri Jun 12 11:06:26 2015
HOST: laptop Loss% Snt Last Avg Best Wrst StDev
1.|-- box 0.0% 100 3.4 3.7 3.3 10.5 0.8
2.|-- 129.120.16.109.rev.sfr.net 0.0% 100 28.2 27.7 26.0 39.6 1.4
3.|-- 193.45.66.86.rev.sfr.net 0.0% 100 27.0 27.8 26.0 32.6 0.8
4.|-- 181.45.66.86.rev.sfr.net 0.0% 100 28.6 32.3 26.4 225.8 26.1
5.|-- v3790.poi1-co-1.gaoland.net 0.0% 100 30.6 30.7 27.6 46.4 2.4
6.|-- 54.247.5.109.rev.sfr.net 0.0% 100 38.4 36.2 33.1 42.6 1.5
7.|-- ae1.parigi32.par.seabone.net 2.0% 100 33.8 34.5 32.4 49.1 2.1
8.|-- xe-5-1-2.parigi52.par.seabone.net 0.0% 100 35.1 35.1 33.1 48.0 1.7
9.|-- global-crossing.parigi52.par.seabone.net 72.0% 100 378.4 612.6 378.4 3819. 796.8
10.|-- telekom-malaysia-berhad.xe-0-2-0.ar2.clk1.gblx.net 74.0% 100 399.2 399.3 397.4 412.8 2.8
11.|-- ??? 100.0 100 0.0 0.0 0.0 0.0 0.0
12.|-- 13335.sgw.equinix.com 83.0% 100 460.9 462.5 459.8 480.8 5.1
13.|-- 198.41.214.163 84.0% 100 460.3 460.2 459.0 462.3 0.9

Notez que Telekom Malaysia n'a annoncé que 200 000 routes, sur les environ 600 000 qu'on trouve dans l'Internet donc environ les deux tiers des sites connectés n'ont pas eu de problème. On voit ici, via DNSmon, l'effet sur les serveurs DNS de .fr : deux des serveurs perdent environ 1 % des paquets au plus fort de la crise, c'est tout dnsmon-june-2015.png

Les annonces erronnées ont été supprimées vers 1030 UTC mais le trafic BGP n'est complètement revenu à la normale que vers 1200 UTC. karotte-bgp-malaysia.png (Attention, ce graphique affiche les heures en UTC+2, alors qu'une supervision de l'Internet devrait toujours utiliser UTC.)

Une des originalités de cette fuite est que l'origine du chemin d'AS n'était pas le fuiteur, Telekom Malaysia. La plupart du temps, le fuiteur émet les routes comme s'il en était l'origine et des techniques comme RPKI+ROA détectent l'usurpation. Ici, au contraire, l'origine... originelle a été préservée et RPKI+ROA n'auraient donc rien vu. On voit ici une annonce Telekom Malaysia sur un routeur qui valide et on note qu'il a validé l'annonce :

193.0.0.0/21
                      [BGP/170] 00:20:29, MED 1000, localpref 150
                      AS path: 3549 4788 12859 3333 I, validation-state: valid
                    > to 64.210.69.85 via xe-1/1/0.0

Alors, BGP mérite-t-il le surnom de « Bordel Gateway Protocol » que Nathalie Rosenberg lui avait donné ? Il est vrai que l'acceptation sans discussions d'annonces par les autres opérateurs est une source de fragilité. Mais les ingénieurs réagissent rapidement et s'adaptent et la panne, finalement, n'aura pas duré longtemps.

D'autres articles sur ce sujet :


L'article seul

RFC 7557: Extension Mechanism for the Babel Routing Protocol

Date de publication du RFC : Mai 2015
Auteur(s) du RFC : J. Chroboczek (PPS, University of Paris-Diderot)
Expérimental
Première rédaction de cet article le 11 juin 2015


Le protocole de routage Babel, spécifié dans le RFC 6126, est désormais doté d'un mécanisme d'extension documenté. Il a depuis été intégré dans la norme Babel, dans le RFC 8966.

Un paquet Babel comprend un en-tête fixe, suivi d'une série de TLV. Babel prévoyait des mécanismes d'extension en réservant certaines valeurs et en précisant le comportement d'un routeur Babel lors de la réception de valeurs inconnues. Ainsi :

  • Un paquet Babel avec un numéro de version différent de 2 doit être ignoré, ce qui permet de déployer une nouvelle future version de Babel sans que ses paquets ne cassent les implémentations existantes,
  • Un TLV de type inconnu doit être ignoré (RFC 6126, section 4.3), ce qui permet d'introduire de nouveaux types de TLV en étant sûr qu'ils ne vont pas perturber les anciens routeurs,
  • Les données contenues dans un TLV au-delà de sa longueur indiquée, ou bien les données présentes après le dernier TLV, doivent également être silencieusement ignorées (au lieu de déclencher une erreur). Ainsi, une autre voie d'extension est possible, où on pourra glisser des données supplémentaires.

Bien sûr, ces règles ne garantissent pas à elles seules que les extensions cohabiteront bien. D'où ce nouveau RFC, qui décrit comment utiliser ces possibilités, sans conflit entre deux extensions différentes.

La section 2 décrit toutes les possibilités d'extensions propres. Cela commence par une nouvelle version du protocole (l'actuelle version est la 2), qui utiliserait des numéros 3, puis 4...

Moins radicale, une extension de la version 2 peut introduire de nouveaux TLV (qui seront ignorés par les mises en œuvre anciennes de la version 2). Ces nouveaux TLV doivent suivre le format de la section 4.3 du RFC 6126.

Si on veut ajouter des données dans un TLV existant, en s'assurant qu'il restera correctement analysé par les anciennes mises en œuvre, il faut jouer sur la différence entre la taille explicite (explicit length) et la taille effective (natural length) du TLV. La taille explicite est celle qui est indiqué dans le champ Length spécifié dans la section 4.3 du RFC 6126. La taille effective est celle déduite d'une analyse des données (plus ou moins compliquée selon le type de TLV). Comme les implémentations de Babel doivent ignorer les données situées après la taille naturelle, on peut s'en servir pour ajouter des données. Elles doivent être encodées sous forme de sous-TLV, chacun ayant type, longueur et valeur (leur format exact est décrit en section 3).

Babel a aussi six bits libres dans les TLV de type Update (champ Flags, RFC 6126, section 4.4.9). Notre RFC déconseille de les utiliser, pour l'instant.

Enfin, après le dernier TLV (Babel est transporté sur UDP, qui indique une longueur explicite), on peut encore ajouter des données. L'idée était d'y mettre une signature cryptographique mais le système d'authentification de Babel, spécifié dans le RFC 8967, se sert plutôt de nouveaux TLV. Cet espace potentiel est donc inutilisé pour l'instant.

Bon, mais alors quel mécanisme d'extension choisir ? La section 4 fournit des pistes aux développeurs. Le choix de faire une nouvelle version est un choix drastique. Il ne devrait être fait que si la nouvelle version est réellement incompatible avec la précédente.

Un nouveau TLV, ou bien un nouveau sous-TLV d'un TLV existant est la solution à la plupart des problèmes d'extension. Par exemple, si on veut mettre de l'information supplémentaire aux mises à jour de routes (TLV Update), on peut créer un nouveau TLV « Update enrichi » ou bien un sous-TLV de Update qui contiendra l'information supplémentaire. Attention, les conséquences de l'un ou l'autre choix ne seront pas les mêmes. Un TLV « Update enrichi » serait totalement ignoré par un Babel ancien, alors qu'un TLV Update avec un sous-TLV d'« enrichissement » verrait la mise à jour des routes acceptée, seules l'information supplémentaire serait perdue.

Il existe désormais, pour permettre le développement d'extensions, un registre IANA des types de TLV et un des sous-TLV (section 5 du RFC) et plusieurs extensions s'en servent déjà.


Téléchargez le RFC 7557


L'article seul

RFC 7513: SAVI Solution for DHCP

Date de publication du RFC : Mai 2015
Auteur(s) du RFC : J. Bi, J. Wu, G. Yao (Tsinghua Univ.), F. Baker (Cisco)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF savi
Première rédaction de cet article le 11 juin 2015


Le cadre SAVI (Source Address Validation Improvement), décrit dans le RFC 7039, vise à rendre plus difficile l'usurpation d'adresses IP. SAVI fournit un cadre général et plusieurs solutions techniques concrètes sont ensuite développées selon le type de réseau et selon le niveau de sécurité qu'on désire et qu'on est prêt à « payer ». Ainsi, le RFC 6620 décrivait un mécanisme où le réseau d'accès assurait que le premier titulaire d'une adresse IP puisse la garder. Ce nouveau RFC décrit un autre mécanisme, où c'est via l'utilisation de DHCP qu'on contrôle les adresses : le réseau d'accès va empêcher l'utilisation d'adresses qui n'ont pas été allouées par le serveur DHCP. (Ce mécanisme est largement déployé depuis des années, sous divers noms, comme « DHCP snooping », mais n'avait pas été formellement décrit dans un RFC.)

L'usurpation d'adresse IP est à la base de nombreuses attaques sur l'Internet, comme les attaques par réflexion. Il existe depuis longtemps des techniques pour limiter l'usurpation d'adresses IP (le RFC 2827 est un exemple classique, qui permet de protéger un réseau contre l'usurpation par un autre). Celles de SAVI visent surtout le réseau local (réseau d'accès pour un FAI) en limitant le risque d'usurpation interne (qu'un utilisateur du réseau local usurpe l'adresse d'un autre). Ici, dans ce RFC 7513, l'allocation d'une adresse IP via DHCP va créer un lien (binding) entre cette adresse et des informations qui permettront au réseau de filtrer les usurpateurs. Par exemple, en retenant le port physique du commutateur comme lien, le commutateur peut bloquer les paquets dont l'adresse IP source n'est pas celle qui a été allouée à la machine connectée à ce port. Un tel mécanisme est souvent présent dans les commutateurs existants, souvent sous le nom de DHCP snooping mais attention : parfois, ce DHCP snooping se limite à bloquer les réponses DHCP arrivant sur un port inattendu, et n'intégre pas forcément la protection contre l'usurpation d'adresses IP, le but principal de ce RFC. Vérifiez avec votre commutateur !

Ce mécanisme de lien (binding anchor) est décrit en section 3 du RFC 7039 et rappelé en section 3 de notre RFC. Un lien doit être un attribut caractéristique, et difficile à changer (un contre-exemple est l'adresse MAC, facile à changer sur beaucoup de systèmes, et pourtant citée par notre RFC). C'est le cas du port physique du commutateur Ethernet cité plus haut, ou bien d'une association de sécurité WiFi (la section 3.2 du RFC 7039 donne d'autres exemples).

SAVI-DHCP va donc surveiller le trafic DHCP, notant les requêtes et réponses DHCP et les associant aux liens. Notez que cela marche avec le DHCP avec état (RFC 2131 pour IPv4 et RFC 8415 pour IPv6), pas avec le DHCP sans état du RFC 8415, qui ne s'occupe pas d'allocation d'adresses IP. De même, SAVI-DHCP ne gère évidemment pas le cas des réseaux où les adresses IP sont obtenues par un autre moyen que DHCP, par exemple le SLAAC du RFC 4862. Idem pour les adresses locales au lien (RFC 4291, section 2.5.6). Dans ces deux derniers cas, il faut utiliser une autre technique SAVI, le FCFS du RFC 6620.

Bon, maintenant, les détails. La section 4 précise quels acteurs sont considérés : un serveur DHCP évidemment, des clients DHCP, et les machines SAVI, typiquement des commutateurs, qui vont faire respecter les règles SAVI (il y a aussi quelques commutateurs non-SAVI dans le réseau d'exemple, pour mieux refléter la réalité). La machine SAVI va avoir besoin d'une certaine configuration. Par exemple, si le réseau contient un serveur DHCP menteur, la machine SAVI ne peut pas le deviner, et il faut lui dire sur quel port est attaché le vrai serveur DHCP (attribut SAVI DHCP-trust, cf. par exemple cette documentation Cisco, la commande ip dhcp snooping trust indiquera qu'un serveur DHCP légitime opère sur cette interface). De même, certains ports physiques ne doivent pas valider les adresses IP (attribut SAVI Trust, par exemple un port attaché au routeur de sortie, port sur lequel on verra passer, et c'est normal, plusieurs adresses IP) et il faudra donc indiquer à la machine SAVI sur quels ports elle doit surveiller (ceux où ne se trouve normalement qu'une ou plusieurs machines obtenant des adresses par DHCP).

SAVI sépare le réseau en deux, la partie de confiance et le reste. Dans la partie de confiance, on peut être raisonnablement sûr que les adresses IP source sont authentiques : tous les commutateurs valident. SAVI ne prétend pas sécuriser tout l'Internet. Et, même dans le réseau local, une partie du réseau peut être non-SAVI et ne sera donc pas de confiance. Cette notion de périmètre (séparant la partie de confiance et le reste) est essentielle pour configurer SAVI, et pour savoir ce qu'on peut attendre de cette technique. Par exemple, des réponses DHCP venues d'un serveur situé en dehors du périmètre ne seront pas utilisées par SAVI : puisque cette zone n'est pas de confiance, il peut parfaitement s'agir d'un serveur pirate (section 4.3.3 du RFC, un bon exemple de l'utilisation de la notion de périmètre, avec un schéma d'exemple).

La sécurité de SAVI-DHCP dépend évidemment de la sécurité des liens. Il faut notamment s'assurer que les attributs utilisés pour construire le lien sont difficiles à usurper. Un port physique du commutateur est un bon exemple. A contrario, une adresse MAC est un mauvais attribut (trop facile à changer) et même un attribut fort peut être affaibli par certains usages. Par exemple, si on utilise le port physique du commutateur Ethernet comme binding anchor, mais que ce dernier est connecté à des commutateurs non-SAVI en cascade, les nombreuses machines qui partagent ce port physique peuvent encore usurper leurs adresses IP entre elles.

Ces liens et les adresses IP associées doivent être stockées dans la mémoire de la machine SAVI, dans un structure de données dite BST (Binding State Table, section 5). Chaque ligne de cette table stocke également la durée de vie du lien et l'état du lien (établi, en cours d'établissement, inconnu).

La BST se remplit en « espionnant » (snooping) le trafic DHCP (section 6). En résumant (beaucoup) : la machine SAVI voit passer une requête DHCP et la réponse arrive depuis un port marqué comme DHCP-trust. On stocke alors dans la BST le port d'où est venu la requête (le lien, le binding anchor), l'adresse IP dans la réponse, le fait que le lien est établi, et sa durée de vie (typiquement la durée du bail DHCP). Désormais, si on voit un paquet IP arriver par le port d'où venait la requête DHCP, on pourra regarder son adresse IP source, et jeter le paquet si elle ne correspond pas à ce qui est dans la BST (ce filtrage est décrit en section 8). Sur un Juniper, on peut afficher cette BST avec show dhcp snooping binding. Cet exemple est tiré d'une documentation Juniper :

user@switch> show dhcp snooping binding
DHCP Snooping Information:
MAC Address             IP Address Lease   Type     VLAN    Interface
-----------------       ---------- -----   -------  ----    ---------
00:00:01:00:00:03       192.0.2.0  640     dynamic  guest    ge-0/0/12.0
00:00:01:00:00:04       192.0.2.1  720     dynamic  guest    ge-0/0/12.0
00:00:01:00:00:05       192.0.2.5  800     dynamic  guest    ge-0/0/13.0

Attention, il y a quelques pièges. Par exemple, s'il existe plusieurs chemins entre le client et le serveur DHCP, et que la machine SAVI n'est que sur un seul de ces chemins, elle risque de rater le dialogue DHCP. Autre cas problématique si une machine se déplace d'un port à un autre sans refaire une requête DHCP.

La section 7 propose des solutions à ces problèmes de faux positifs. L'idée est de noter le trafic rejeté par SAVI-DHCP et de vérifier activement si le paquet a été rejeté à tort (le mal nommé « Data Snooping Process »). Par exemple, en IPv4, on peut envoyer des requêtes ARP (RFC 826 et RFC 5227) pour déterminer si deux machines (la vraie et l'usurpatrice) utilisent la même adresse IP (s'il n'y a qu'une machine, la vraie, on ne recevra qu'une réponse). En IPv6, on peut utiliser un message DAD (Duplicate Address Detection, cf. RFC 4862, section 5.4) pour faire le même test.

On peut aussi, si on a raté ou qu'on pense avoir raté le dialogue DHCP, demander directement au serveur DHCP, avec un message DHCPLEASEQUERY (RFC 4388) en IPv4 et LEASEQUERY (RFC 5007) en IPv6.

Bref, comme toujours en sécurité, on n'a pas de repas gratuit : SAVI-DHCP protège contre bien des usurpations mais, comme toute technique de filtrage, il peut mener au rejet de messages légitimes.

Le mécanisme de SAVI-DHCP nécessite de mémoriser un état, la BST (Binding State Table, décrite en section 5). Si elle est gardée en RAM et qu'on redémarre, la liste des liens est perdue et tous les paquets seront rejetés (c'est pourquoi, en général, IP déconseille de garder de l'état dans le réseau). La section 9 rappelle ce problème et demande donc que la BST soit stockée dans une mémoire qui survit aux redémarrages. (On pourrait récupérer un bon bout de la BST par les méthodes de la section 7 mais ça prendrait un temps fou.) À noter que, sur un Juniper, ce n'est pas fait par défaut (il faut la directive dhcp-snooping-file pour stocker la BST).

Terminons ce résumé du RFC avec la section 11, consacrée aux questions de sécurité. D'abord, les risques que crée le Data Snooping process de la section 7. Comme ce processus est coûteux en nombre de paquets envoyés, un attaquant pourrait être tenté de le déclencher afin de réaliser une attaque par déni de service. Pour cela, il aurait juste à envoyer quelques paquets usurpés. Le processus doit donc avoir une limitation de trafic.

Plusieurs autres attaques sont possibles contre ce mécanisme de sécurité complexe qu'est SAVI-DHCP (réutiliser l'adresse d'un client qui est parti et ne peut donc plus se défendre en cas de détection d'adresse dupliquée, créer de nombreux liens pour remplir la BST et faire une attaque par déni de service, etc). Il y a aussi un risque sur la vie privée, puisque la BST stocke de nombreuses informations sur l'arrivée et le départ des machines des utilisateurs. Elle ne doit donc pas être archivée. L'idée est qu'aucune information ne devrait être gardée sur les machines qui n'usurpent jamais d'adresse IP (ne pas fliquer les gens honnêtes).

À noter que Cisco prétend avoir inventé la technique et a un brevet sur l'idée, mais propose une licence (avec clause de représailles).

Merci à Cécile Grange pour des indications sur les solutions Juniper.


Téléchargez le RFC 7513


L'article seul

RFC 7564: PRECIS Framework: Preparation, Enforcement, and Comparison of Internationalized Strings in Application Protocols

Date de publication du RFC : Mai 2015
Auteur(s) du RFC : P. Saint-Andre (&yet), M. Blanchet (Viagenie)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF precis
Première rédaction de cet article le 7 juin 2015


Dans la longue marche vers une plus grande internationalisation de l'Internet, la question des identificateurs (comme par exemple les noms de domaine) a toujours été délicate. Ce sont en effet à la fois des éléments techniques, traités automatiquement par les programmes, et des marqueurs d'identité, vus par les humains (par exemple sur des cartes de visite) et manipulés par eux. Jusqu'à présent, chaque protocole internationalisait ses identificateurs comme il le souhaitait. Ce RFC du groupe de travail PRECIS tente une approche unificatrice, en élaborant des règles qui peuvent servir à de larges classes d'identificateurs, pour de nombreux protocoles différents. (Il a depuis été remplacé par le RFC 8264.)

Cette opposition entre « éléments techniques » et « textes prévus pour l'utilisateur » est au cœur du RFC 2277 qui pose comme principe politique qu'on internationalise les seconds, mais pas les premiers. Cet excellent principe achoppe souvent sur la question des identificateurs, qui sont les deux à la fois. D'un côté, les programmes doivent les traiter (les identificateurs doivent donc être clairement définis, sans ambiguité), de l'autre les humains les voient, les communiquent, les échangent (les identificateurs doivent donc permettre, sinon toutes les constructions du langage humain, en tout cas un sous-ensemble d'Unicode qui parait raisonnable aux humains ordinaires : pas question d'imposer stephane comme nom de login à un utilisateur nommé Stéphane, avec un accent sur le E). C'est cette double nature des identificateurs (ainsi, il est vrai, que l'énorme couche de bureaucratie qui gère les noms de domaine) qui explique la durée et la vivacité des discussions sur les IDN.

Maintenant que ces IDN existent (depuis plus de douze ans, RFC 3490), que faire avec les autres identificateurs ? Une possibilité aurait été que chaque protocole se débrouille avec ses propres identificateurs, comme l'a fait le DNS avec les noms de domaine. Mais cela menait à une duplication du travail (et tous les auteurs de protocole ne sont pas des experts Unicode) et surtout à un risque de choix très différents : certains protocoles autoriseraient tel caractère Unicode et d'autres pas, sans que l'utilisateur ordinaire puisse comprendre clairement les raisons de cette différence. L'idée de base du groupe PRECIS est donc d'essayer de faire des règles qui s'appliqueraient à beaucoup de protocoles, épargnant aux concepteurs de ces protocoles de les concevoir eux-mêmes, et offrant à l'utilisateur une certaine homogénéité. Le premier RFC de PRECIS était la description du problème, dans le RFC 6885. Le second est la normalisation du cadre de définition des identificateurs internationalisés, dans ce RFC 7564. Ce cadre permet la manipulation d'identificateurs internationalisés (par exemple leur comparaison, comme lorsqu'un utilisateur tape son nom et son mot de passe, et qu'il faut les vérifier). Il remplace complètement l'ancien système stringprep du RFC 3454.

Le nom du groupe de travail PRECIS reflète les trois fonctions essentielles que vont faire les programmes qui manipulent les identificateurs internationalisés :

  • PRE pour la préparation des identificateurs, les opérations préliminaires comme la conversion depuis un jeu de caractères local non-Unicode,
  • E pour la vérification (enforcement) des règles, afin de déterminer si une chaîne de caractères Unicode est légale ou pas pour un usage donné,
  • C pour la comparaison entre les identificateurs, afin de déterminer leur égalité (« cette ressource n'est accessible qu'à l'utilisateur Thérèse or elle est connectée avec le nom therese »),
  • Le IS final étant pour Internationalized Strings.

A priori, les serveurs Internet seront responsables de la vérification, les clients n'ayant à faire qu'une préparation. Ayant souvent moins de ressources, les clients pourraient en effet avoir du mal à faire certaines opérations Unicode complexes (section 3).

Stringprep (RFC 3454) avait été développé pour le système IDN (RFC 3490) mais était conçu pour être généraliste, et certaines applications n'ayant rien à voir avec les noms de domaine avaient utilisé stringprep. Ce dernier avait des limites, certaines font l'objet d'un consensus, comme le fait que stringprep était lié à une version particulière d'Unicode, ce qui l'empêchait d'évoluer automatiquement lorsque le consortium Unicode publiait une nouvelle version (la version actuelle est la version 7, la plus récente est toujours à l'URL http://www.unicode.org/versions/latest/). D'autres limites étaient plus contestées (RFC 4690). IDN n'utilise plus stringprep depuis le RFC 5890.

Les principes du travail de PRECIS sont :

  • Définir un petit nombre (deux, actuellement) de classes spécifiant un jeu de caractères autorisés, classes applicables à un grand nombre d'usages.
  • Définir le contenu de ces classes en fonction d'un algorithme, reposant sur les propriétés Unicode (contrairement à stringprep où le contenu des classes était énuméré dans le RFC). Ainsi, lorsqu'une nouvelle version d'Unicode sort, il suffit de refaire tourner l'algorithme et on obtient le contenu à jour de la classe.
  • Spécifier les classes par une inclusion : tout caractère non explicitement listé comme membre de la classe est automatiquement exclu.
  • Permettre aux protocoles applicatifs de définir un profil d'une classe, à savoir une restriction de ses membres, ou bien d'autres précisions sur des sujets comme la normalisation Unicode. Il y aura ainsi probablement un profil pour les noms d'utilisateurs, un profil pour les mots de passe, etc. Notez qu'il est prévu que le nombre de profils reste limité, pour ne pas réintroduire l'excessive variété que voulait justement éviter PRECIS.

Si tout va bien, ces principes permettront l'indépendance vis-à-vis des versions d'Unicode (ou, plus exactement, la possibilité de passer à une nouvelle version d'Unicode sans faire une nouvelle norme incompatible), le partage des tables et du logiciel entre applications (par exemple par le biais de bibliothèques communes, utilisables si toutes les applications reposent sur PRECIS), et moins de surprises pour les utilisateurs, qui auraient été bien embêtés si chaque protocole Internet avait eu une manière complètement différente de prévoir l'internationalisation.

Bien, quelles sont donc les classes prévues par PRECIS (section 4) ? L'idée est de faire un compromis entre expressivité et sécurité. Qu'est-ce que la sécurité vient faire là dedans ? Personne ne le sait trop (le RFC utilise plusieurs fois safe et safety sans expliquer face à quels risques) mais Unicode fait souvent peur aux informaticiens anglo-saxons et il est donc courant d'estimer qu'il existe des caractères dangereux.

Il y a donc deux classes en tout et pour tout dans PRECIS : IdentifierClass et FreeformClass. La première classe servira à identifier utilisateurs, machines, pièces de discussions en messagerie instantanée, fichiers, etc, et ne permettra que les lettres, les nombres et quelques symboles (comme le ! ou le +). C'est contraignant mais l'idée est qu'on veut des désignations simples et sans ambiguïté, pas écrire des romans. La seconde classe servira à tout le reste (mots de passe, textes affichés comme la description d'une pièce XMPP, nom complet d'une machine, etc). Par exemple, une imprimante sera imprimante-jean-et-thérèse pour les protocoles qui demandent un nom de la classe IdentifierClass et Imprimante de Jean & Thérèse lorsqu'on pourra utiliser un nom FreeformClass.

Les classes sont définies par les caractères inclus et exclus. Plus précisément, un caractère peut être, pour une classe donnée (voir aussi la section 8) :

  • Valide (ou PVALID pour Protocol Valid),
  • Interdit,
  • Autorisé dans certains contextes seulement, c'est-à-dire que l'autorisation dépendra des caractères voisins (pas facile de trouver un exemple dans l'alphabet latin, cela sert surtout à d'autres écritures),
  • Pas encore affecté dans Unicode.

La classe IdentifierClass se définit donc par :

  • Caractères valides : les lettres et chiffres (rappelons qu'on définit des identificateurs internationalisés : on ne se limite donc pas aux lettres et chiffres latins), et les symboles traditionnels, ceux d'ASCII (comme le tiret ou le tilde).
  • Caractères valides dans certains contextes : ceux de la rare catégorie JoinControl du RFC 5892, section 2.8.
  • Caractères interdits : tout le reste (espaces, ponctuation, la plupart des symboles...).
  • Les caractères non encore affectés sont également interdits.

La classe Freeform Class se définit, elle, par :

  • Caractères valides : les lettres et chiffres (rappelons qu'on définit des identificateurs internationalisés : on ne se limite donc pas aux lettres et chiffres latins), les espaces, la ponctuation, les symboles.
  • Caractères valides dans certains contextes : ceux de la catégorie JoinControl plus quelques exceptions.
  • Caractères interdits : tout le reste, ce qui fait surtout les caractères de contrôle comme U+0007 (celui qui fait sonner votre ordinateur).
  • Les caractères non encore affectés sont également interdits.

Ces listes de caractères autorisés ou interdits ne sont pas suffisantes. Il y a d'autres points à régler (section 5), ce qui se fait typiquement dans les profils. Ainsi, un profil doit définir :

  • Normalisation Unicode à utiliser. NFC est recommandé.
  • La correspondance entre les caractères et leur version large (width mapping). Est-ce que FULLWIDTH DIGIT ZERO (U+FF10) doit être considéré comme équivalent au zéro traditionnel, de largeur « normale », U+0030 ? Notez que certaines normalisations (mais qui ne sont pas celle recommandée), comme NFKC, règlent le problème. Autrement, la recommandation du RFC est « oui, il faut rendre ces caractères équivalents » car l'utilisateur serait certainement surpris que target0 et target0 soient considérés différents (le fameux POLA).
  • D'autres correspondances peuvent être spécifiées par le profil (comme de transformer tous les espaces Unicode en l'espace traditionnel ASCII U+0020).
  • Changement de la casse des caractères, par exemple pour tout mettre en minuscules. Si c'est décidé pour un profil, le RFC recommande que cela soit fait avec la méthode Unicode standard, « Default case folding » (section 3 de la norme Unicode). Attention, cette méthode Unicode ne gère pas des cas qui dépendent de la langue, dont le plus fameux est le i sans point du turc (U+0131 c'est-à-dire ı). Le changement de casse est évidemment déconseillé pour les mots de passe (puisqu'il diminue l'entropie).
  • Interdiction de certains mélanges de caractères de directionnalité différentes. Il y a des écritures qui vont de gauche à droite et d'autres de droite à gauche, et leur combinaison peut entrainer des surprises à l'affichage. Dans certains cas, un profil peut vouloir limiter ce mélange de directionnalités.

Un profil peut également interdire certains caractères normalement autorisés (mais pas l'inverse).

Au passage, pour la comparaison, le RFC (section 7) impose un ordre à ces opérations. Par exemple, la mise en correspondance de la version large sur la version normale doit se faire avant l'éventuel changement de casse. C'est important car ces opérations ne sont pas commutatives entre elles.

Les profils sont enregistrés à l'IANA. Le RFC met bien en garde contre leur multiplication : toute l'idée de PRECIS est d'éviter que chaque protocole ne gère l'internationalisation des identificateurs de manière différente, ce qui empêcherait la réutilisation de code, et perturberait les utilisateurs. Si on avait un cadre commun mais des dizaines de profils différents, on ne pourrait pas dire qu'on a atteint cet objectif. Par exemple, en matière d'interface utilisateur, PRECIS essaie de s'en tenir au POLA (Principle of Least Astonishment) et ce principe serait certainement violé si chaque application trouvait rigolo d'interdire un caractère ou l'autre, sans raison apparente. Le RFC estime d'ailleurs (section 5.1) qu'il ne devrait y avoir idéalement que deux ou trois profils. Mais ce n'est pas possible puisque les protocoles existent déjà, avec leurs propres règles, et qu'on ne peut pas faire table rase de l'existant (tous les protocoles qui ont déjà définis des caractères interdits, comme IRC, NFS, SMTP, XMPP, iSCSI, etc).

Un petit point en passant, avant de continuer avec les applications : vous avez noté que la classe IdentifierClass interdit les espaces (tous les espaces Unicode, pas seulement le U+0020 d'ASCII), alors que certaines applications acceptent les espaces dans les identificateurs (par exemple, Unix les accepte sans problèmes dans les noms de fichier, Apple permet depuis longtemps de les utiliser pour nommer Macintoshes et imprimantes, etc). La section 5.3 explique pourquoi :

  • Il est très difficile de distinguer tous ces espaces entre eux,
  • Certains interfaces utilisateurs risquent de ne pas les afficher, menant à confondre françoise durand avec françoisedurand.

C'est embêtant (toute contrainte est embêtante) mais le compromis a semblé raisonnable au groupe PRECIS.

Passons maintenant aux questions des développeurs d'applications (section 6 du RFC). Que doivent-ils savoir pour utiliser PRECIS correctement ? Idéalement, il suffirait de lier son code aux bonnes bibliothèques bien internationalisées et tout se ferait automatiquement. En pratique, cela ne se passera pas comme ça : sans être obligé de lire et de comprendre tout le RFC, le développeur d'applications devra quand même réflechir un peu à l'internationalisation de son programme :

  • Il est très déconseillé de créer son propre profil. Non seulement c'est plus compliqué que ça n'en a l'air, mais ça risque de dérouter les utilisateurs, si votre application a des règles légèrement différentes des règles des autres applications analogues.
  • Précisez bien quel partie de l'application va être responsable pour la préparation, la vérification et la comparaison. Par exemple, le travail de vérification sera-t-il fait par le client ou par le serveur ? Demandez-vous aussi à quel stade les applications devront avoir fait ce travail (par exemple, en cas de login, avant de donner un accès).
  • Définissez bien, pour chaque utilisation d'un identificateur (chaque slot, dit le RFC), quel profil doit être utilisé. Par exemple, « le nom du compte doit être conforme au profil UsernameCaseMapped de la classe IdentifierClass ».
  • Dressez la liste des caractères interdits (en plus de ceux déjà interdits par le profil) en fonction des spécificités de votre application. Par exemple, un @ est interdit dans la partie gauche d'une adresse de courrier électronique.

Sur ce dernier point, il faut noter que la frontière est mince entre « interdire plusieurs caractères normalement autorisés par le profil » et « définir un nouveau profil ». La possibilité d'interdire des caractères supplémentaires est surtout là pour s'accomoder des protocoles existants (comme dans l'exemple du courrier ci-dessus), et pour éviter d'avoir un profil par application existante.

Votre application pourra avoir besoin de constructions au dessus des classes existantes. Par exemple, si un nom d'utilisateur, dans votre programme, peut s'écrire « Prénom Nom », il ne peut pas être une instance de la classe IdentifierClass, qui n'accepte pas les espaces pour la raison indiquée plus haut. Il faudra alors définir un concept « nom d'utilisateur », par exemple en le spécifiant comme composé d'une ou plusieurs instances de IdentifierClass, séparées par des espaces. En ABNF :

username   = userpart *(1*SP userpart)
userpart   = ... ; Instance d'IdentifierClass

La même technique peut être utilisée pour spécifier des identificateurs qui ne seraient normalement pas autorisés par IdentifierClass comme stéphane@maçonnerie-générale.fr ou /politique/séries/Game-of-Thrones/saison05épisode08.mkv.

On a vu plus haut qu'un des principes de PRECIS était de définir les caractères autorisés de manière algorithmique, à partir de leur propriétés Unicode, et non pas sous la forme d'une liste figée (qu'il faudrait réviser à chaque nouvelle version d'Unicode). Les catégories de caractères utilisées par cet algorithme sont décrites en section 9. Par exemple, on y trouve :

  • LettersDigits qui rassemble les chiffres et les lettres. (Rappelez-vous qu'on utilise Unicode : ce ne sont pas uniquement les lettres et les chiffres d'ASCII.)
  • ASCII7, les caractères d'ASCII, à l'exception des caractères de contrôle,
  • Spaces, tous les espaces possibles (comme le U+200A, HAIR SPACE, ainsi appelé en raison de sa minceur),
  • Symbols, les symboles, comme U+20A3 (FRENCH FRANC SIGN, ₣) ou U+02DB (OGONEK, ˛),
  • Etc.

Plusieurs registres IANA sont nécessaires pour stocker toutes les données nécessaires à PRECIS. La section 11 les recense tous. Le plus important est le PRECIS Derived Property Value, qui est recalculé à chaque version d'Unicode. Il indique pour chaque caractère s'il est autorisé ou interdit dans un identificateur PRECIS. Voici sa version pour Unicode 6.3. (La version 7 est retardée par une tempête dans un verre d'eau.)

Les deux autres registres stockent les classes et les profils (pour l'instant, aucun). Les règles d'enregistrement dans le premier sont strictes (un RFC est nécessaire) et celles dans le second bien plus ouvertes (un examen par un expert est nécessaire).

La section 12 est consacrée aux problèmes de sécurité qui, comme toujours lorsqu'il s'agit d'Unicode, sont plus imaginaires que réels. Un des problèmes envisagés est celui du risque de confusion entre deux caractères qui sont visuellement proches. Le problème existe déjà avec le seul alphabet latin (vous voyez du premier coup la différence entre google.com et goog1e.com ?) mais est souvent utilisé comme prétexte pour retarder le déploiement d'Unicode. PRECIS se voulant fidèle au principe POLA, le risque de confusion est considéré comme important. Notez que le risque réel dépend de la police utilisée. Unicode normalisant des caractères et non pas des glyphes, il n'y a pas de solution générale à ce problème dans Unicode (les écritures humaines sont compliquées : c'est ainsi). Si le texte ᏚᎢᎵᎬᎢᎬᏒ ressemble à STPETER, c'est que vous utilisez une police qui ne distingue pas tellement l'alphabet cherokee de l'alphabet latin. Est-ce que ça a des conséquences pratiques ? Le RFC cite le risque accru de hameçonnage, sans citer les nombreuses études qui montrent le contraire (cf. le Unicode Technical Report 36, section 2, « the use of visually confusable characters in spoofing is often overstated », et la FAQ de sécurité d'Unicode).

Quelques conseils aux développeurs concluent cette partie : limiter le nombre de caractères ou d'écritures qu'on accepte, interdire le mélange des écritures (conseil inapplicable : dans la plupart des alphabets non-latins, on utilise des mots entiers en alphabet latin)... Le RFC conseille aussi de marquer visuellement les identificateurs qui utilisent plusieurs écritures (par exemple en utilisant des couleurs différentes), pour avertir l'utilisateur.

C'est au nom de ce principe POLA que la classe IdentifierClass est restreinte à un ensemble « sûr » de caractères (notez que ce terme « sûr » n'est jamais expliqué ou défini dans ce RFC). Comme son nom l'indique, FreeformClass est bien plus large et peut donc susciter davantage de surprises.

PRECIS gère aussi le cas des mots de passe en Unicode. Un bon mot de passe doit être difficile à deviner ou à trouver par force brute (il doit avoir beaucoup d'entropie). Et il faut minimiser les risques de faux positifs (un mot de passe accepté alors qu'il ne devrait pas : par exemple, des mots de passe insensibles à la casse seraient agréables pour les utilisateurs mais augmenteraient le risque de faux positifs). L'argument de l'entropie fait que le RFC déconseille de créer des profils restreints de FreeformClass, par exemple en excluant des catégories comme la ponctuation. Unicode permet des mots de passe vraiment résistants à la force brute, comme « 𝃍🐬ꢞĚΥਟዶᚦ⬧ »... D'un autre côté, comme le montre l'exemple hypothétique de mots de passe insensibles à la casse, il y a toujours une tension entre la sécurité et l'utilisabilité. Laisser les utilisateurs choisir des mots de passe comportant des caractères « exotiques » peut poser bien des problèmes par la suite lorsqu'utilisateur tentera de les taper sur un clavier peu familier. Il faut noter aussi que les mots de passe passent parfois par des protocoles intermédiaires (comme SASL, RFC 4422, ou comme RADIUS, RFC 2865) et qu'il vaut donc mieux que tout le monde utilise les mêmes règles pour éviter des surprises (comme un mot de passe refusé par un protocole intermédiaire).

Enfin, la section 13 de notre RFC se penche sur l'interopérabilité. Elle rappele qu'UTF-8 est l'encodage recommandé (mais PRECIS est un cadre, pas un protocole complet, et un protocole conforme à PRECIS peut utiliser un autre encodage). Elle rappelle aussi qu'il faut être prudent si on doit faire circuler ses identificateurs vers d'autres protocoles : tous ne savent pas gérer Unicode, hélas.

Il existe une mise en œuvre de PRECIS en Go : https://godoc.org/golang.org/x/text/secure/precis.


Téléchargez le RFC 7564


L'article seul

Qualité des clés cryptographiques

Première rédaction de cet article le 6 juin 2015


A priori, une clé cryptographique en vaut une autre, non ? Ce sont toutes des chaînes de bits incompréhensibles ? Mais non : une clé peut, sous une apparence normale, avoir des caractéristiques qui la rendent plus ou moins vulnérable à certaines attaques cryptanalytiques. Deux analyses récentes ont testé des grands ensembles de clés et ont parfois trouvé des failles.

La première porte sur les clés PGP stockées dans les serveurs de clé. Ces serveurs sont utilisés pour distribuer les clés publiques. Étant librement accessibles, ils permettent d'analyser par la suite la qualité des clés. C'est ce qu'a fait l'étude « A look at the PGP ecosystem through the key server data ». L'auteur télécharge les clés depuis les serveurs qui fournissent un moyen d'accès en masse, puis les analyse. Il a développé pour cela un analyseur en Python. (J'ai déjà parlé du manque regrettable d'outil de test automatique de la qualité d'une clé PGP.)

Je vous préviens tout de suite, cette analyse n'a montré aucun grave problème (tant mieux ! À moins que les problèmes n'aient pas été détectés... ) Par exemple, une faiblesse connue de DSA (et ECDSA) est la nécessité d'utiliser une valeur imprévisible (et pas forcément aléatoire, contrairement à ce qu'on lit souvent, cf. RFC 6979) à chaque signature. Le non-respect de cette règle a permis, par exemple, le libre accès à la PlayStation. L'auteur a donc cherché des exemples de plusieurs signatures (les serveurs de clés stockent des clés signées par d'autres clés, donc on a aussi un lot de signatures) faites avec le même paramètre. Les deux seuls cas trouvés concernaient des signatures incorrectes (les serveurs de clés ne testent pas les données soumises et on peut donc trouver des données corrompues) ou bien les clés de PrimeFactors, une société qui commercialise des solutions cryptographiques (!) et qui a répondu à l'alerte de sécurité de l'auteur par une explication montrant qu'ils n'avaient pas compris le problème. Bon rappel que les seules solutions de sécurité sérieuses sont en logiciel libre.

D'autres tests faits sur les clés PGP ont également été des échecs (du point de vue du chercheur : pour la sécurité, c'est une bonne chose !) Par exemple, deux clés RSA partageaient un facteur premier mais l'adresse associée à la clé, alice@example.com donne à penser qu'il ne s'agissait pas d'une vraie clé, avec une vraie utilisatrice, mais plutôt d'une expérimentation avec des clés délibérement vulnérables.

Bref, chou blanc, pas de problème sensationnel noté pendant l'analyse des clés PGP.

Une autre étude a donné des résultats plus inquiétants. « Auditing GitHub users’ SSH key quality » est le récit d'un audit des clés SSH utilisés sur GitHub (dont j'ai découvert à cette occasion qu'elles sont publiques, voir par exemple les miennes en https://github.com/bortzmeyer.keys). L'auteur a pu faire des statistiques, par exemple sur le type de clés (nette domination de RSA, DSS loin derrière et les courbes elliptiques encore plus).

Mais il a aussi trouvé des choses plus inquiétantes comme des clés RSA de seulement 256 bits (!) Une telle clé se factorise en 25 minutes sur un vieux processeur. Plus étonnant, GitHub stocke encore plusieurs clés qui ont été générées par la bogue Debian. Et ces clés « protègent » (cela a été corrigé depuis) des dépôts logiciels importants comme les bibliothèques cryptographiques de Python (!).

C'est donc l'occasion de rappeler que la cryptographie ne fait pas de miracles : il ne suffit pas d'utiliser PGP ou SSH pour être en sécurité, il faut aussi s'assurer de la solidité des clés. Il faudrait vraiment que des programmeurs courageux développent un site Web où on pourrait soumettre ses clés privées (non, je rigole, ses clés publiques) SSH ou PGP et avoir des diagnostics, du genre « clé privée prévisible suite à la bogue Debian » ou bien « clé trop courte » ou encore « facteur premier déjà vu ».


L'article seul

RFC 7526: Deprecating Anycast Prefix for 6to4 Relay Routers

Date de publication du RFC : Mai 2015
Auteur(s) du RFC : O. Troan (Cisco), B. Carpenter (Univ. of Auckland)
Réalisé dans le cadre du groupe de travail IETF v6ops
Première rédaction de cet article le 4 juin 2015


6to4 en anycast, c'est fini ! Cette technique de transition entre IPv4 et IPv6, reposant sur des tunnels établis automatiquement, a pu être utile à un moment pour faciliter l'accès à IPv6 depuis les opérateurs qui étaient en retard pour le déploiement. Mais elle a plein de défauts techniques, qui ont contribué à donner une mauvaise image d'IPv6. Elle est donc marquée par ce RFC comme officiellement abandonnée.

C'est dans le RFC 3068 que 6to4+anycast était normalisé (il existe plein d'autres techniques de transition). Le principe était d'avoir des relais anycast qui recevaient les paquets IPv6 encapsulés dans de l'IPv4, tunnelant ainsi le trafic IPv6 au-dessus d'opérateurs restés en IPv4. Pour éviter d'avoir à configurer manuellement ces relais, une correspondance existait entre les adresses IPv4 des machines, et des adresses IPv6 attribuées dans un préfixe spécifique à 6to4, le 2002::/16 (le réseau IPv6 associé à une adresse IPv4 était 2002:adresse-IPv4::/48). Des outils comme whois connaissaient ce préfixe et savaient donc faire une recherche « intelligente » (ici, d9ae:c921 = 217.174.201.33) :

% whois 2002:d9ae:c921::1

Querying for the IPv4 endpoint 217.174.201.33 of a 6to4 IPv6 address.
...
[affichage des informations au sujet de 217.174.201.33]

Un autre préfixe, en IPv4, était attribué aux relais, pour que les mécanismes de l'anycast trouvent ensuite le relais le plus proche. C'est ce second préfixe, 192.88.99.0/24, qui est retiré du service par ce RFC. En outre, le RFC 3068 est désormais marqué comme « intérêt historique seulement ».

La première version de ces tunnels automatiques, spécifiée dans le RFC 3056, utilisait un adressage unicast. C'est avec le RFC 3068 que 6to4 est passé à l'anycast. Les relais étaient gérés par des tas de volontaires situés sur la planète mais, en pratique, beaucoup marchaient mal ou pas du tout et l'anycast ne permettait pas de garantir qu'on tombe sur un relais valide, encore moins sur un relais proche et rapide. L'étude « Flailing IPv6 » a montré la quantité de problèmes que posait 6to4. Un test avec les sondes RIPE Atlas montre 23 % de timeout sur un serveur 6to4, 2002:d9ae:c921::1, contre 10 % pour une adresse IPv6 native. En test DNS, 343 sondes Atlas sur 470 répondent pour l'adresse 2002:d9ae:c921::1, contre 490 sur 500 pour l'adresse IPv4 du même serveur, 217.174.201.33.

Un résultat tragique de cette mauvaise qualité a été de ralentir le déploiement d'IPv6, bien des utilisateurs coupant IPv6 lorsqu'ils découvraient la lenteur et les pannes de 6to4, bien des gérants de serveurs ne fournissant pas IPv6 de peur que cela entraine une dégradation de la qualité de service.

Le RFC 6343 analysait le problème et faisait des recommandations pour améliorer 6to4. Il recommandait que 6to4 soit coupé par défaut (un scénario commun, avant, était que 6to4 était activé sans demande explicite, le trafic IPv6 passait par un relais lointain, et l'utilisateur en concluait qu'IPv6 était lent) : « it should always be a conscious decision by a user to enable 6to4 ». Le RFC 6343 recommandait aussi de suivre l'algorithme des « globes oculaires heureux » du RFC 6555, afin de masquer les défaillances éventuelles d'une des familles, IPv4 ou IPv6.

Mais ces conseils, quoique assez largement mis en œuvre, ne suffisent pas, et les serveurs accessibles en IPv6 voient toujours du trafic 6to4.

À noter que la technologie 6rd, normalisée dans le RFC 5969, est très proche de 6to4 mais s'en distingue par l'utilisation d'un préfixe IPv6 lié au fournisseur d'accès. Les relais, au lieu d'être gérés un peu partout par des volontaires inconnus, sont donc forcément sous la houlette du FAI qui utilise 6rd, et il peut donc garantir une voie de retour. 6rd n'est donc pas concerné par les critiques de notre RFC.

La section 3 revient en détail sur les problèmes rencontrés avec 6to4. Elle rappelle que les routes peuvent être asymétriques (un relais différent à l'aller et au retour). Si le choix du relais aller peut être contrôlé (par exemple par des préférences BGP pour telle ou telle annonce du préfixe 192.88.99.0/24), le chemin de retour échappe complètement au nœud 6to4, qui ne peut pas être sûr que ses pairs utiliseront un « bon » relais. C'est le cœur du problème de 6to4. (Notez bien que cela ne concerne que le mode anycast, avec le prefixe standard. Des variantes de 6to4, avec un préfixe contrôlé par le FAI, ou avec de l'unicast vers des relais connus, ne sont pas concernées par ce RFC. C'est par exemple le cas de 6rd, cité plus haut)

La section 4 du RFC contient les décisions formellement prises :

  • Le mécanisme d'anycast de 6to4 du RFC 3068 est abandonné,
  • Le préfixe 192.88.99.0/24 est marqué comme abandonné (dans le registre IANA),
  • Le 6to4 en unicast du RFC 3056 reste utilisable, tout comme le préfixe 2002::/16, c'est uniquement son annonce en anycast qui est abandonnée,
  • Les règles de sélection de l'adresse source du RFC 6724 ne sont pas modifiées (elles donnent la priorité à IPv4 sur 6to4, contrairement aux règles de son prédécesseur, le RFC 3484).

Comme indiqué dans la section 5, il est déconseillé d'inclure 6to4+anycast dans les mises en œuvre d'IPv6 et, si on le fait, il faut qu'il soit désactivé par défaut. (Bien des CPE IPv6 avaient imprudemment activé ce mécanisme par défaut, pour fournir une connectivité IPv6 dans tous les cas, même au-dessus d'un opérateur resté uniquement à IPv4.)

En revanche, contrairement à ce qui avait parfois été proposé, notre RFC ne formule pas de recommandations sur le filtrage des annonces de route 6to4 (un tel filtrage bloquerait 6to4 chez l'opérateur qui le ferait). Il conseille par contre aux actuels opérateurs de relais 6to4 de se poser sérieusement la question « est-ce que c'est vraiment la peine de continuer ? » Ces recommandations (ou absence de recommandations) avaient fait l'objet des plus vigoureuses discussions au sein du groupe de travail à l'IETF.


Téléchargez le RFC 7526


L'article seul

RFC 7516: JSON Web Encryption (JWE)

Date de publication du RFC : Mai 2015
Auteur(s) du RFC : M. Jones (Microsoft), J. Hildebrand (Cisco)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF jose
Première rédaction de cet article le 3 juin 2015


L'ensemble de normes de cryptographie JOSE, qui permet de sécuriser des textes JSON comprend plusieurs RFC, dont ce RFC 7516, qui normalise le chiffrement, permettant d'assurer la confidentialité des documents JSON.

Un document chiffré est baptisé JWE (pour JSON Web Encryption). Il peut exister sous deux formes (deux sérialisations), une compacte (en Base64, cf. section 3.1), qui peut notamment être utilisée dans les URL, et une en JSON, qui permet de passer par les programmes de traitement du JSON (sections 3.2 et 7.2.1). Elles utilisent les mêmes mécanismes cryptographiques sous-jacents. Les algorithmes utilisables sont normalisés dans le RFC 7518. Il est recommandé de lire également le RFC sur les signatures JOSE (RFC 7515) car beaucoup de règles applicables à la fois à la signature et au chiffrement ne sont décrites que dans ce RFC 7515 (comme la comparaison des chaînes de caractères de la section 5.3).

Les principes de base de JWE sont exposés dans la section 3 du RFC (en s'appuyant que la terminologie de la section 2). Quelle que soit la sérialisation choisie, un JWE peut comprendre :

  • L'en-tête JOSE, lui-même composé d'une partie protégée et d'une ou plusieurs parties non protégées,
  • La clé cryptographique, chiffrée,
  • Le vecteur d'initialisation,
  • L'AAD (Additional Authenticated Data), protégée en intégrité mais pas chiffrée, qui sert lorsqu'on fait de l'AEAD,
  • Le texte chiffré (et donc illisible par un indiscret),
  • L'authentication tag.

Dans la sérialisation en JSON, les composants binaires (comme le texte chiffré) sont encodés en Base64, JSON n'ayant pas de mécanisme pour les données binaires.

Un JWE en sérialisation compacte est la concaténation des différents composants cités ci-dessus, chacun encodé en Base64 (un exemple figure en section 3.3). Un JWE en sérialisation JSON est un objet JSON comportant un membre par composant, par exemple iv pour le vecteur d'initialisation, ciphertext pour le texte chiffré, recipients pour des informations sur les destinataires (optionnel : s'il n'y a qu'un seul destinataire, on peut mettre ces informations dans l'objet JWE, cf. section 7.2.2).

L'en-tête JOSE est détaillé dans la section 4. Il inclut la plupart des paramètres cryptographiques. On le représente par un objet JSON (qui sera ensuite encodé en Base64). Cet objet a des membres comme alg (l'algorithme de chiffrement utilisé pour la clé, en général un algorithme de chiffrement asymétrique) ou enc (l'algorithme de chiffrement utilisé pour le contenu, en général un algorithme de chiffrement symétrique), etc. Les algorithmes possibles sont décrits dans le RFC 7518. De nombreux autres membres sont possibles comme zip pour indiquer l'éventuel algorithme de compression utilisé (par exemple celui du RFC 1951).

Le mécanisme complet de chiffrement et de déchiffrement (ce dernier est l'inverse du chiffrement) est décrit dans la section 5. Voici un exemple, tiré de l'annexe A.4 : il y a deux destinataires, le premier utilisera RSA et le second AES pour chiffrer la clé :

"recipients":[
       {"header":
         {"alg":"RSA1_5","kid":"2011-04-29"},
       {"header":
         {"alg":"A128KW","kid":"7"},
	 ...

Le texte sera chiffré avec AES en mode CBC avec du HMAC sur SHA-256 pour produire l'authentication tag :

  {"enc":"A128CBC-HS256"}

(Cet objet formera l'en-tête protégé.) En utilisant cette valeur pour le vecteur d'initialisation :

  "iv":       "AxY8DCtDaGlsbGljb3RoZQ",

et cette clé de chiffrement :

  {"kty":"oct",
      "k":"GawgguFyGrWKav7AX4VKUg"
      }

Et le message en clair « Live long and prosper. », on arrive à ce JWE complet :

  {
      "protected":
       "eyJlbmMiOiJBMTI4Q0JDLUhTMjU2In0",
      "unprotected":
       {"jku":"https://server.example.com/keys.jwks"},
      "recipients":[
       {"header":
         {"alg":"RSA1_5","kid":"2011-04-29"},
        "encrypted_key":
         "UGhIOguC7IuEvf_NPVaXsGMoLOmwvc1GyqlIKOK1nN94nHPoltGRhWhw7Zx0-
          kFm1NJn8LE9XShH59_i8J0PH5ZZyNfGy2xGdULU7sHNF6Gp2vPLgNZ__deLKx
          GHZ7PcHALUzoOegEI-8E66jX2E4zyJKx-YxzZIItRzC5hlRirb6Y5Cl_p-ko3
          YvkkysZIFNPccxRU7qve1WYPxqbb2Yw8kZqa2rMWI5ng8OtvzlV7elprCbuPh
          cCdZ6XDP0_F8rkXds2vE4X-ncOIM8hAYHHi29NX0mcKiRaD0-D-ljQTP-cFPg
          wCp6X-nZZd9OHBv-B3oWh2TbqmScqXMR4gp_A"},
       {"header":
         {"alg":"A128KW","kid":"7"},
        "encrypted_key":
         "6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ"}],
      "iv":
       "AxY8DCtDaGlsbGljb3RoZQ",
      "ciphertext":
       "KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY",
      "tag":
       "Mz-VPPyU4RlcuYv1IwIvzw"
       }

Pour du code qui met en œuvre le chiffrement JOSE, voir mon article général.


Téléchargez le RFC 7516


L'article seul

Fiche de lecture : Charles Martel et la bataille de Poitiers, de l'histoire au mythe identitaire

Auteur(s) du livre : William Blanc, Christophe Naudin
Éditeur : Libertalia
9-782918-05-9608
Publié en 2015
Première rédaction de cet article le 3 juin 2015


En décembre 2013, le magazine de droite extrême Valeurs actuelles annonçait en couverture qu'on massacrait l'histoire de France et qu'on en faisait disparaitre les héros. L'image montrée était celle de Charles Martel, lors de la bataille de Poitiers. L'idée développée par le polémiste de droite était que Charles Martel avait toujours été une référence essentielle de l'histoire de France, et que « la gauche » tentait de le faire oublier. La plupart des discussions autour de cette idée opposaient les pro et les anti-Charles Martel, ceux qui se félicitaient de son rôle de défenseur de l'Occident chrétien, et ceux qui ne voyaient en lui qu'un militaire massacreur parmi d'autres. Mais ce livre de Blanc et Naudin aborde le problème d'une autre façon : non pas en se demandant qui était vraiment Charles Martel, mais en examinant son image, du Moyen Âge à nos jours. Car Valeurs actuelles se trompe dès ses prémisses : loin d'être un héros antique, Charles Martel est une invention récente.

La première partie du livre, la plus courte, analyse les faits historiques. Le problème est qu'on ne sait pas grand'chose. Il n'y a quasiment pas de sources arabes, et les sources franques sont peu nombreuses et bien postérieures à la bataille. Il est donc difficile de dire qui était vraiment Charles Martel. Des questions historiques comme « les Arabes faisaient-ils un simple raid de pillage, ou bien était-ce une invasion en bonne et due forme avec intention de s'installer ? » ne reçoivent pas de réponse satisfaisante.

Mais c'est la deuxième partie du livre qui est la plus intéressante, celle consacrée à l'image de Charles Martel. A-t-il été célébré comme un héros chrétien et européen pendant tout le Moyen Âge ? Loin de là. Dès le début, Charles Martel est contesté, même dans son « camp », celui du christianisme. Le héros n'était pas du genre à se confire en dévotion et, lorsqu'il fallait s'attacher la loyauté des soldats, il pillait les églises pour récolter des fonds. Une des images du Moyen Âge reproduites dans le livre le montre brûlant en enfer, une autre représente un évêque le piétinant... Le « héros de la chrétienté » n'a donc pas toujours été présenté comme cela, loin de là. Son succès médiatique, son aura de défenseur de l'Europe, qui lui a évité de devenir musulmane, ne date que du 19è siècle, notamment via Chateaubriand.

Il faut dire aussi que la vision de la bataille de Poitiers comme le choc de deux groupes complètement opposés, chrétiens contre musulmans, Européens contre Africano-Asiatiques, est elle-même construite historiquement. Dans les images du Moyen Âge représentant la bataille, rien ne distingue les deux camps (contrairement aux croisades, où les signes religieux se font ostentatoires). C'est, là encore, au 19è siècle que chaque camp acquiert ses attributs distinctifs, le sabre courbe des arabo-berbères et leur turban, les croix bien visibles des Francs (et le fameux marteau, absent autrefois puisque Charles, en bon guerrier franc, utilisait probablement une hache). L'étude des représentations graphiques de la bataille est, je trouve, la partie la plus intéressante du livre. L'imagerie pieuse illustrée par un fameux tableau est donc très récente, et date d'une époque où l'Occident chrétien l'était déjà beaucoup moins.

Cette vision ethnico-religieuse est d'autant plus anachronique que, aux différentes époques, chacun a accommodé Charles Martel à sa sauce et a tenté de l'enrôler dans la guerre du moment. Sous la IIIè République, le vainqueur des Arabes était plus souvent cité pour ses combats contre d'autres tribus germaniques, Alamans ou Saxons : le péril principal était de l'autre côté de la ligne bleue des Vosges. Et le raciste Drumont, dans un article, fait de Charles Martel un combattant contre... les Juifs.

Les auteurs n'analysent pas que les images, ils se livrent aussi à une intéressante étude d'image de marque, en comptant les mentions des différents héros dans les livres. Charles Martel est très loin dans le classement, qui est dominé par Jeanne d'Arc, suivie, mais de loin, par des personnages comme Roland ou Du Guesclin. Là encore, c'est l'époque moderne qui a fait de Charles Martel le héros de l'extrême-droite, ce n'est pas l'histoire.


L'article seul

RFC 7545: Protocol to Access White-Space (PAWS) Databases

Date de publication du RFC : Mai 2015
Auteur(s) du RFC : V. Chen (Google), S. Das (Applied Communication Sciences), L. Zhu (Huawei), J. Malyar (iconectiv), P. McCann (Huawei)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF paws
Première rédaction de cet article le 28 mai 2015


Ah, les espaces blancs (ou fréquences blanches, ou canaux non-utilisés), un nom qui fait rêver, et penser à des mystérieuses zones inconnues sur une carte, qui attendent leurs courageux explorateurs, qui vont s'installer, virer des indigènes inutiles, et faire pousser bananes et café dans ce qui n'était qu'une jungle. Dans le monde des ondes radios, les espaces blancs sont les fréquences qui ont été réservées à un moment mais qui ne sont pas utilisées en pratique, et sont donc susceptibles d'être affectées à un autre usage. Encore faut-il savoir pour cela quelles sont les fréquences libres dans une région donnée, et c'est le rôle du protocole décrit dans ce RFC.

La traduction de « white space » par « espace blanc » figure par exemple dans ce rapport de l'ANFR. On parle aussi de « canaux non utilisés » pour les fréquences libres, et de « réutilisation du spectre » pour le concept, qui agite pas mal de régulateurs des télécommunications et d'industriels. L'idée de base du groupe de travail PAWS de l'IETF (c'est son deuxième RFC après le RFC 6953) est de concevoir un protocole qui permette à une machine en promenade de trouver facilement quelles sont les fréquences libres dans sa zone géographique. En effet, « L’une des difficultés de l’utilisation de ces fréquences blanche [sic] est qu’elles forment un véritable "gruyère" parce que ce sont des petites bandes de fréquence qui se trouvent entre des canaux de TV affectés à des endroits différents selon les régions. La technologie doit donc déterminer avec précision les canaux pré-existants et éviter les interférences locales. » La machine en promenade ne peut donc pas utiliser une bande de fréquence pré-réglée, il faut qu'elle s'adapte aux conditions locales. L'idée est que toutes les fréquences du « gruyère » soient enregistrées dans des bases publiques, et que la machine nomade puisse interroger ces bases, avec ce nouveau protocole PAWS (Protocol to Access White-Space database).

Le RFC 6953 résumait le problème des espaces blancs et les scénario d'usage de ces espaces. L'idée centrale est d'avoir une base de données des espaces blancs (donc des fréquences utilisables) et de la rendre accessible aux engins en déplacement (ordinateurs, smartphones, etc). En effet, vu la complexité de ces espaces, et leur caractère partagé, ce qui a nécessité de nombreuses règles quand à leur usage (telle que la puissance maximale d'émission), et les changements permanents dans ce domaine, essayer de mettre l'information sur chaque appareil est une tâche sans espoir. On la met donc uniquement dans un petit nombre de bases de données. Ce choix impose donc un protocole standard d'accès à ces bases et ce protocole, sans surprise, est conçu au dessus de HTTPS, avec un encodage en JSON.

Donc, PAWS est client/serveur, le client (Master Device, dans le RFC) est l'appareil en mouvement, et qui voudrait bien émettre dans les espaces blancs, et le serveur est la base de données officielle (sections 2 et 3 du RFC). Le client doit d'abord obtenir l'URI du serveur, envoyer des requêtes HTTP pour savoir ce que la base de données peut lui dire (ce qu'on nomme l'initialisation), puis demander quels sont les espaces blancs utilisables dans la région où se trouve le client, et à quelles conditions. Le serveur va alors lui envoyer l'information. (La base de données n'est pas forcément publique, elle peut imposer à ses clients d'être préalablement enregistrés.)

La section 4 du RFC détaille chacune de ces étapes. Pour découvrir le serveur, le client a une liste d'URI en dur dans sa configuration. Ces URI peuvent désigner une base de données, ou bien un service « méta » (géré, par exemple, par le régulateur des télécommunications du pays) qui indiquent plusieurs bases possibles (cf. l'annexe A du RFC). Rien de très souple ici, surtout quand on change de pays.

Certaines bases vont demander que le client s'enregistre. Par exemple, aux États-Unis, la FCC l'impose pour les clients fixes. Il existe donc des messages d'enregistrement dans PAWS. Une fois l'initialisation et l'éventuel enregistrement fait, passons à l'essentiel, la requête demandant les fréquences disponibles. Le client indique sa localisation et certaines autres caractéristiques, comme les fréquences qu'il est techniquement capable d'utiliser, le serveur lui répond avec une liste de fréquences, avec les puissances d'émission maximale dans chaque plage, et les heures où on peut émettre (au format du RFC 3339). Le client peut alors choisir une fréquence, en fonction de ses critères.

La section 5 contient quelques détails sur les requêtes et réponses. Par exemple, la position du client est indiquée par un simple point, ou sous forme d'une région, selon les règles de la section 5 du RFC 5491 (pour les amateurs de géométrie). Le client indique les caractéristiques de son antenne (car elles peuvent influer la réponse) comme sa hauteur. D'autres caractéristiques (comme la direction dans laquelle pointe l'antenne) peuvent être indiquées, et, si elles ne sont pas dans ce RFC 7545, elles seront peut-être enregistrées dans le registre des paramètres PAWS. La requête, décidément très bavarde, peut inclure des informations sur le propriétaire de la machine cliente et, dans ce cas, elles doivent être au format jCard (RFC 7095, un exemple figure dans la section 6.4 de notre RFC).

Bien sûr, la requête peut échouer et, dans ce cas, un objet Error est renvoyé, contenant un code numérique et un message texte. Les codes numériques peuvent être négatifs, comme le -104 de l'exemple ci-dessous, qui signifie que la base de données n'a pas d'information sur la région demandée. (L'ensemble des codes d'erreur est dans un registre IANA.)

Tous ces messages sont encodés en JSON-RPC, avec du contenu en JSON (RFC 8259). La requête est un objet JSON dont un des membres est method, qui indique la méthode (le type de requête). La réponse est un objet JSON dont un des membres est result (ou error), qui contient le résultat demandé. Parmi les méthodes possibles, la plus importante est certainement spectrum.paws.getSpectrum qui est la demande des plages de fréquences blanches.

Il semble qu'il existe plusieurs mises en œuvres de PAWS, en tout cas c'est ce qui s'est dit dans des réunions IETF. Mais la seule que je connais est celle de Google (il y a une bonne documentation de la base utilisée). On peut avoir un accès limité sans engagement (à part un compte Google et une clé d'API), il faut signer un contrat si on veut un accès moins limité. Cette base ne couvre que les USA. Attention, les objets JSON utilisés sont ceux d'une version antérieure de la norme, pas tout à fait les mêmes que dans le RFC. Voici un exemple de script shell pour faire une requête, via curl :

#/bin/sh

# Replace with your own key, see https://developers.google.com/spectrum/paws/gettingstarted
API_KEY=XXXXXX

if [ -z "$2" ]; then
    echo "Usage: $0 longitude latitude" 
    exit 1
fi
lon=$1
lat=$2

curl -XPOST https://www.googleapis.com/rpc -H "Content-Type: application/json" --data "{
  \"jsonrpc\": \"2.0\",
  \"method\": \"spectrum.paws.getSpectrum\",
  \"apiVersion\": \"v1explorer\",
  \"params\": {
    \"type\": \"AVAIL_SPECTRUM_REQ\",
    \"version\": \"1.0\",
    \"deviceDesc\": { \"serialNumber\": \"your_serial_number\", \"fccId\": \"TEST\", \"fccTvbdDeviceType\": \"MODE_1\" },
    \"location\": { \"point\": { \"center\": {\"latitude\": $lon, \"longitude\": $lat} } },
    \"antenna\": { \"height\": 30.0, \"heightType\": \"AGL\" },
    \"owner\": { \"owner\": { } },
    \"capabilities\": { \"frequencyRanges\": [{ \"startHz\": 100000000, \"stopHz\": 950000000 }] },
    \"key\": \"$API_KEY\"
  },
  \"id\": \"Test PAWS\"
}"

Et son résultat, pour la ville de Denver :

% sh test-paws.sh 39.739167 -104.984722 
{
 "jsonrpc": "2.0",
 "id": "Test PAWS",
 "result": {
  "kind": "spectrum#pawsGetSpectrumResponse",
  "type": "AVAIL_SPECTRUM_RESP",
  "version": "1.0",
  "timestamp": "2015-05-24T16:20:35Z",
  "deviceDesc": {
   "serialNumber": "your_serial_number",
   "fccId": "TEST",
   "fccTvbdDeviceType": "MODE_1"
  },
  "spectrumSchedules": [
   {
    "eventTime": {
     "startTime": "2015-05-24T16:20:35Z",
     "stopTime": "2015-05-26T16:20:35Z"
    },
    "spectra": [
     {
      "bandwidth": 6000000.0,
      "frequencyRanges": [
       {
        "startHz": 5.4E7,
        "stopHz": 5.12E8,
        "maxPowerDBm": -56.799999947335436
       },
       {
        "startHz": 5.12E8,
        "stopHz": 5.24E8,
        "maxPowerDBm": 15.99999928972511
       },
       {
        "startHz": 5.24E8,
        "stopHz": 5.36E8,
        "maxPowerDBm": -56.799999947335436
       },
       {
        "startHz": 5.36E8,
        "stopHz": 5.42E8,
        "maxPowerDBm": 15.99999928972511
       },
       {
        "startHz": 5.42E8,
        "stopHz": 5.48E8,
        "maxPowerDBm": -56.799999947335436
       },
       {
        "startHz": 5.48E8,
        "stopHz": 5.54E8,
        "maxPowerDBm": 15.99999928972511
       },
       {
        "startHz": 5.54E8,
        "stopHz": 6.5E8,
        "maxPowerDBm": -56.799999947335436
       },
       {
        "startHz": 6.5E8,
        "stopHz": 6.56E8,
        "maxPowerDBm": 15.99999928972511
       },
       {
        "startHz": 6.56E8,
        "stopHz": 6.68E8,
        "maxPowerDBm": -56.799999947335436
       },
       {
        "startHz": 6.68E8,
        "stopHz": 6.74E8,
        "maxPowerDBm": 15.99999928972511
       },
       {
        "startHz": 6.74E8,
        "stopHz": 6.86E8,
        "maxPowerDBm": -56.799999947335436
       },
       {
        "startHz": 6.86E8,
        "stopHz": 6.98E8,
        "maxPowerDBm": 15.99999928972511
       }
      ]
     }
    ]
   }
  ],
  "needsSpectrumReport": false,
  "rulesetInfo": {
   "authority": "US",
   "maxLocationChange": 100.0,
   "maxPollingSecs": 86400,
   "rulesetIds": [
    "FccTvBandWhiteSpace-2010"
   ]
  }
 }
}

Si on tente un lieu situé en dehors des USA :

{
 "error": {
  "code": -104,
  "message": "Requested location is outside the supported coverage zone",
  "data": [
   {
    "domain": "global",
    "reason": "invalidParameter",
    "message": "Requested location is outside the supported coverage zone"
   }
  ]
 },
 "jsonrpc": "2.0",
 "id": "Test PAWS"
}

Le monde de la gestion des fréquences radio est évidemment lourdement régulé, puisqu'il s'agit d'un espace partagé. Dans l'exemple ci-dessus, on voit la mention que les règles de la FCC s'appliquent ("rulesetIds": ["FccTvBandWhiteSpace-2010"]). D'autres organismes de régulation peuvent intervenir, par exemple l'identifiant de règles (rulesetIds) de l'ETSI serait ETSI-EN-301-598-1.1.1.

Un peu de sécurité, pour finir (section 10). D'abord, PAWS ne permet pas de vérifier que le client utilisera correctement les informations fournies. PAWS envoie des données, c'est au client de les appliquer. Si ce dernier décide d'émettre dans d'autres bandes de fréquences que celles indiquées, ou bien d'utiliser les bandes indiquées, mais avec une puissance supérieure à ce qui est autorisé, PAWS n'offre aucun mécanisme pour l'en empêcher.

On peut imaginer d'autres risques, comme un client redirigé vers un faux serveur PAWS. L'utilisation de HTTPS protège normalement contre cela, le nom du serveur de la base devant être dans le certificat. Enfin, PAWS peut poser des problèmes de vie privée : le client fournit des données de localisation, ce qui permet au serveur de suivre le client.

Quelques lectures pour finir :


Téléchargez le RFC 7545


L'article seul

Mon compte mojeID

Première rédaction de cet article le 23 mai 2015


Le système d'identité mojeID, auparavant réservé aux habitants de la République tchèque, est désormais ouvert au monde. J'ai donc pu me créer un compte.

À quoi sert mojeID ? C'est un système d'identité, donc un stockage sécurisé des caractéristiques (publiques et privées) d'une personne ou d'une organisation, avec des interfaces pour utiliser cette identité depuis des sites tiers. Cela permet de garder une identité constante, tout en allant sur de nombreux sites. En République tchèque, mojeID est très populaire et est utilisé par de nombreux sites Web, soit via l'API spécifique de mojeID, soit via OpenID. En outre, le registre de .cz (qui a créé mojeID) permet de gérer ses domaines via mojeID. En dehors de ce pays, on peut toujours utiliser OpenID, par exemple, mon compte sur OpenStreetMap est un compte mojeID, https://bortzmeyer.mojeid.cz/ (avec OpenID, l'identificateur est un URL.) Au sujet d'OpenID, voir également mon exposé à JRES (un peu ancien).

mojeID fournit également une page Web sommaire rassemblant les informations qu'on a choisi de rendre publiques. Dans l'interface Web de mojeID, on peut choisir d'exporter ou pas l'adresse de son blog, de son compte Twitter, etc, mais il faut bien fouiller la page de son profil pour trouver comment les indiquer : c'est le petit bouton marqué d'un plus.

Et comment s'authentifie-t-on auprès de mojeID ? Le service fournit trois méthodes, le classique mot de passe, un certificat client, et un système à deux facteurs (je n'ai testé que le mot de passe).

Une des particularités de mojeID, par rapport à tant d'autres fournisseurs (au passage, mon compte OpenID habituel est chez Stack Exchange), est de lier ce compte à des informations extérieures (un peu comme le font les places de marché bitcoin ou bien comme le fait le service Keybase). Ainsi, mojeID vérifie l'adresse de courrier donnée (simplement en envoyant un cookie, appelé PIN, qu'on doit renvoyer), le numéro de téléphone (en envoyant un SMS avec le cookie), et l'adresse postale en envoyant une jolie lettre contenant le troisième PIN : mojeID.jpg

Ce sont ces vérifications qui limitaient autrefois mojeID au pays de Jan Hus.

Comme vous le voyez dans la lettre précédente, bien que l'interface Web soit largement traduite en anglais, une bonne partie de la communication avec mojeID se fait toujours dans la langue de Karel Čapek :-)

Merci à Alix Guillard, Ondřej Surý et Ondřej Filip pour le service, et pour m'avoir encouragé à l'utiliser.


L'article seul

RFC 7565: The 'acct' URI Scheme

Date de publication du RFC : Mai 2015
Auteur(s) du RFC : P. Saint-Andre (Cisco System)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF appsawg
Première rédaction de cet article le 23 mai 2015


Hop, encore un nouveau plan d'URI, le plan acct: (pour account) qui permet de désigner les informations qu'on peut récupérer sur un compte utilisateur. Désormais, acct:stephane@seenthis.net désignera donc mon compte à SeenThis.

Ne vous fiez pas à la ressemblance syntaxique avec les adresses de courrier : la syntaxe est la même (nom-du-compte@nom-du-service) mais les URI acct: sont indépendants du protocole d'accès. Dans l'exemple plus haut, SeenThis ne fournit pas de service de courrier, mais cela ne change rien à l'URI.

Le premier (et pour l'instant quasi-unique) demandeur de ces URI est le protocole WebFinger (RFC 7033). WebFinger permet d'accéder à des informations, via un protocole REST, en utilisant comme identificateur un URI qui, en pratique, est souvent un URI acct:. La version initiale de WebFinger utilisait uniquement des adresses de courrier électronique. Avant le plan acct:, les plans les plus proches identifiaient toujours un protocole particulier : le courrier pour les URI mailto: (RFC 6068) ou XMPP pour les xmpp:... du RFC 5122. Après moultes discussions au sein du groupe de travail sur WebFinger entre les partisans de l'ancien système (adresses de courrier seulement) et ceux d'un nouveau, fondé sur les URI (eux-même divisés entre amateurs de mailto: et fanas de http:), le choix a été fait de créer ce nouveau plan. Comme indiqué, il a l'avantage de ne pas supposer l'existence d'un protocole particulier. Ainsi, mon compte Twitter est désormais acct:bortzmeyer@twitter.com et il n'implique pas que Twitter fournisse du courrier ou de la messagerie instantanée ou quoi que ce soit d'autre.

À noter qu'un URI acct: identifie un compte, que son titulaire soit un humain ou une organisation ou un bot.

La section 4 fournit la définition rigoureuse de ces nouveaux URI (la syntaxe formelle étant repoussée en section 7). Elle rappelle qu'ils servent à l'identification et pas à l'interaction (RFC 3986, section 1.2.2). La partie gauche (à gauche du @) est le nom du compte auprès d'un fournisseur quelconque et la partie droite est un nom de domaine de ce fournisseur. Donc, acct:foobar@status.example.net, acct:user@example.com ou acct:hamlet@dk sont tous des URI valides. Si un client WebFinger cherche de l'information sur le premier de ces URI, il fera une requête HTTP à status.example.net :

GET /.well-known/webfinger?resource=acct%3Afoobar%40status.example.net HTTP/1.1

Si le nom du compte est une adresse de courrier (ce qui est fréquent sur le Web d'aujourd'hui), il faudra convertir le @ en caractères pour-cent. Par exemple, si le compte juliet@capulet.example existe chez le fournisseur shoppingsite.example, l'URI sera acct:juliet%40capulet.example@shoppingsite.example. Et si on prend mon compte au RIPE-NCC, bortzmeyer+ripe@nic.fr, l'URI sera acct:bortzmeyer%2Bripe%40nic.fr@ripe.net. C'est cet URI qui sera mis, par exemple, dans les requêtes WebFinger.

La section 5 du RFC traite des problèmes de sécurité. On ne met évidemment dans une réponse WebFinger que ce qu'on veut bien indiquer, surtout si le client HTTP n'est pas authentifié. Mais il existe un risque plus subtil : même si le client n'arrive pas à accéder aux informations derrière l'URI acct:, la seule existence de cet URI peut indiquer que le compte existe et cela peut donc être utile aux spammeurs et autres nuisibles. Bref, même si les acct: ne sont que des URI, que des identificateurs, ils peuvent en dire trop.

La section 6, elle, se penche sur l'internationalisation. Les URI acct: sont des URI comme les autres (RFC 3986) et peuvent donc contenir n'importe quel caractère Unicode. Il faut simplement qu'ils soient encodés en UTF-8 puis surencodés en pour-cent. Ainsi, un compte stéphane sur le service example.com pourra être représenté par acct:st%C3%A9phane@example.com. Quelques restrictions toutefois :

  • Le nom de compte est limité aux caractères autorisés par le RFC 8264, dans la classe IdentifierClass.
  • Le nom de domaine après le @ est limité aux caractères IDN autorisés dans le RFC 5892, et encodé en Punycode. Ainsi, le compte stéphane sur le service académie-française.fr sera acct:st%C3%A9phane@xn--acadmie-franaise-npb1a.fr.

La section 7 de notre RFC contient le formulaire d'enregistrement du nouveau plan (selon la procédure du RFC 4395), qui inclut la syntaxe formelle de ces URI, en ABNF. acct: est donc désormais dans le registre officiel des URI.

Si vous voulez voir des exemples réels, le mieux est de regarder le monde WebFinger, par exemple les exemples dans mon article sur le RFC 7033.

L'importance de ce plan d'URL acct: avait été décrite dans un article d'Eran Hammer de 2009 (c'est long, la normalisation).


Téléchargez le RFC 7565


L'article seul

RFC 7518: JSON Web Algorithms (JWA)

Date de publication du RFC : Mai 2015
Auteur(s) du RFC : M. Jones (Microsoft)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF jose
Première rédaction de cet article le 22 mai 2015


Ce nouveau RFC fait partie de la série des RFC JOSE (cryptographie pour JSON). Il normalise les algorithmes cryptographiques utilisables pour signer ou chiffrer des textes JSON et crée des registres IANA pour les conserver.

Comme le fait en général l'IETF en matière de cryptographie, les algorithmes cryptographiques ne sont pas inscrits « en dur » dans les RFC (rappelez-vous qu'un RFC, une fois publié, n'est jamais modifié) mais mis dans un registre IANA. En effet, la cryptanalyse progresse régulièrement et des algorithmes qui semblaient sûrs à un moment ne le sont plus par la suite. Il est plus facile et plus rapide de modifier un registre IANA que de créer un nouveau RFC.

Pour chaque registre, les algorithmes cités sont marqués Obligatoire, Recommandé ou Facultatif (cf. RFC 2119). En n'utilisant que des algorithmes marqués Obligatoire, on augmente l'interopérabilité.

Commençons par les algorithmes utilisés pour les signatures et MAC (section 3). C'est le membre alg de JWS (JSON Web Signature, cf. RFC 7515). La table complète est dans son registre IANA. Comme JOSE privilégie la concision, les termes utilisés sont plus courts que, par exemple, dans les registres prévus pour TLS. Ainsi, HS512 veut dire « HMAC avec SHA-512 ». (Pour l'algorithme HMAC, voir le RFC 2104.) Et ES256 désignera un algorithme de signature couplant ECDSA avec une courbe P-256 et SHA-256 (on peut aussi signer avec RSA mais les signatures sont plus courtes avec les courbes elliptiques).

Il y a même un algorithme none dans le registre, dont le nom indique clairement que le texte JSON n'est pas authentifié, ni protégé en intégrité. A priori, les applications qui veulent vérifier le JSON reçu vont rejeter des textes ainsi marqués (sections 3.6 et aussi 8.5), sauf cas très spécifiques, par exemple si on est absolument certain que le texte JSON est arrivé sur une connexion sécurisée (mais relire la section 8.5, sur les pièges que cela pose).

Maintenant, le chiffrement. Il faut pouvoir indiquer comment ont été chiffrées les clés ayant servi à chiffrer le contenu. La section 4 décrit les algorithmes prévus pour cela (qui sont aussi dans le même registre IANA), et qu'on met dans le membre alg d'un JWE (JSON Web Encryption, cf. RFC 7516).

Ainsi, un cas simple est celui où les deux parties chiffrent avec une clé statique symétrique, pré-échangée entre eux. On met alors dir (pour direct use of a key) comme algorithme. Si au contraire on chiffre la clé de chiffrement avec RSA, on mettra par exemple l'algorithme RSA1_5 qui veut dire « RSA avec PKCS#1 ». (On a droit aussi, bien sûr, aux échanges de clés Diffie-Hellman.)

Et le contenu lui-même, on le chiffre avec quoi ? La section 5 décrit les algorithmes de chiffrement symétriques utilisés (encore le même registre IANA). Ils se mettent dans le membre enc du JWE. Par exemple, A128CBC-HS256 est AES en mode CBC avec un HMAC sur SHA-256, alors que A256GCM est AES mais en mode GCM (qui, fournissant du chiffrement intègre, dispense d'utiliser HMAC).

À noter que le petit nouveau à l'IETF, le ChaCha20 du RFC 8439, n'est pas encore arrivé dans JOSE et ne figure pas dans ce registre, qui ne compte qu'AES.

Passons maintenant aux clés (section 6), représentés par un JWK (JSON Web Key, RFC 7517. Dans le membre kty (Key TYpe) d'un JWK, on peut trouver RSA, EC (Elliptic Curve) ou oct (octet), ce dernier désignant une clé symétrique. Les paramètres dépendent ensuite du type de clés. Par exemple, pour les courbes elliptiques, crv désigne la courbe utilisée (P-256, P-384, etc, les valeurs possibles ayant leur propre registre), pour RSA, n sera le modulo et e l'exposant. Les valeurs possibles pour ces paramètres de clés sont dans un registre IANA.

Je l'ai dit au début, les progrès de la cryptanalyse nécessitent de changer les algorithmes de temps en temps (section 8.1 sur l'« agilité cryptographique »). La section 7 fixe les règles de modification des registres. En gros, il faut avoir une spécification écrite (pas forcément un RFC) pour voir son algorithme entrer dans le registre (Specification Required, RFC 5226, section 4.1).


Téléchargez le RFC 7518


L'article seul

« Quand le DNS défaille », une infrastructure peu connue

Première rédaction de cet article le 21 mai 2015


Le 19 mai 2015, à l'Université de Bourgogne à Dijon, j'ai participé à l'atelier CNRS « Gestion d'incidents » avec un exposé sur le DNS.

Les supports de l'exposé :

Merci à Arnaud Da Costa pour l'organisation et à tous les participants pour une intéressante journée sur le terrain, avec des acteurs de la sécurité concrète.


L'article seul

JOSE, la cryptographie pour JSON

Première rédaction de cet article le 20 mai 2015


Le format JSON a largement remplacé XML dans les applications Web et sert aujourd'hui de base à plein d'applications. Il était donc logique qu'on cherche à la sécuriser par la cryptographie et c'est le rôle du groupe de travail JOSE (JavaScript Object Signing and Encryption) de l'IETF qui vient de publier une série de normes sur la signature et le chiffrement de textes JSON.

Un premier RFC avait déjà débroussaillé le terrain en expliquant les scénarios d'usage et le cahier des charges, c'était le RFC 7165. Les nouveaux RFC, eux, définissent les normes techniques. Ce sont :

  • RFC 7518 : JSON Web Algorithms (JWA) décrit les registres où sont stockés les identificateurs des algorithmes de cryptographie utilisables.
  • RFC 7517 : JSON Web Key (JWK) explique le format des clés.
  • RFC 7515 : JSON Web Signature (JWS) expose le mécanisme de signature cryptographique, qui permet d'authentifier des documents JSON.
  • RFC 7516 : JSON Web Encryption (JWE) normalise le chiffrement, grâce auquel les textes JSON peuvent rester confidentiels.
  • RFC 7520 : Examples of Protecting Content using JavaScript Object Signing and Encryption (JOSE) est simplement un recueil d'exemples.
  • En même temps que les RFC du groupe JOSE ont été publiés une autre série du groupe OAUTH décrivant notamment des utilisations de JOSE dans le contexte d'OAuth. C'est par exemple le cas du RFC 7519, JSON Web Token (JWT), bien décrit dans cette série d'articles.

Si vous voulez une très bonne explication de JOSE, avec plein d'explications simples, il y a l'article de Jan Rusnacko. Un exposé au contraire très critique de JOSE a été fait par Fraser Tweedale.

Si vous voulez plutôt pratiquer, il existe de nombreuses mises en œuvre de JOSE :

Merci à Virginie Galindo pour sa relecture.


L'article seul

RFC 7515: JSON Web Signature (JWS)

Date de publication du RFC : Mai 2015
Auteur(s) du RFC : M. Jones (Microsoft), J. Bradley (Ping Identity), N. Sakimura (NRI)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF jose
Première rédaction de cet article le 20 mai 2015


Dans la série des RFC JOSE, qui décrivent les possibilités de protéger des textes JSON avec la cryptographie, ce RFC 7515 normalise les signatures, qui permettent de garantir l'authenticité et l'intégrité des textes JSON.

Le format JSON, normalisé dans le RFC 8259, ne bénéficiait pas jusqu'alors d'un moyen standard pour permettre la vérification de son authenticité. Certes, on pouvait transport le JSON via un transport sécurisé comme HTTPS mais cela ne fournissait qu'une protection du canal, pas un contrôle d'intégrité de bout en bout.

Le principe de ce RFC est le suivant (section 3) : un texte JSON protégé par une signature, un JWS (JSON Web Signature), est composé de trois parties : l'en-tête JOSE (JavaScript Object Signing and Encryption), qui indique les paramètres cryptographiques, la charge utile JWS (le message d'origine), et la signature JWS. L'en-tête JOSE se sépare en un en-tête protégé (par la signature) et un en-tête non protégé. Le document rassemblant ces trois parties est ensuite sérialisé en une suite d'octets. Il y a deux sérialisations possibles. La sérialisation compacte est simplement la concaténation de l'encodage en Base64 de l'en-tête protégé, d'un point, de l'encodage en Base64 de la charge utile, un autre point et enfin l'encodage en Base64 de la signature. Un JWS ainsi sérialisé peut être utilisé dans un URL. Voici un exemple :

eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk

Pas très lisible, évidemment. La deuxième sérialisation possible est dite sérialisation JSON car son résultat est un texte JSON. C'est un objet JSON comportant quatre membres (pas forcément obligatoires), payload, la charge utile, protected, l'en-tête JOSE protégé, header, l'en-tête JOSE non protégé, et signature, la signature. Les trois derniers peuvent se retrouver regroupés dans un sous-objet nommé signatures. En voici un exemple :

{
      "payload":
       "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ",
      "signatures":[
       {"protected":"eyJhbGciOiJSUzI1NiJ9",
        "header":
         {"kid":"2010-12-29"},
        "signature":
         "cC4hiUPoj9Eetdgtv3hF80EGrhuB__dzERat0XF9g2VtQgr9PJbu3XOiZj5RZmh7AAuHIm4Bh-0Qc_lF5YKt_O8W2Fp5jujGbds9uJdbF9CUAr7t1dnZcAcQjbKBYNX4BAynRFdiuB--f_nZLgrnbyTyWzO75vRK5h6xBArLIARNPvkSjtQBMHlb1L07Qe7K0GarZRmB_eSN9383LcOLn6_dO--xi12jzDwusC-eOkHWEsqtFZESc6BfI7noOPqvhJ1phCnvWh6IeYI2w9QOYEUipUTI8np6LbgGY9Fs98rqVt5AXLIhWkWywlVmtVrBp0igcN_IoypGlUPQGe77Rw"},
       {"protected":"eyJhbGciOiJFUzI1NiJ9",
        "header":
         {"kid":"e9bc097a-ce51-4036-9562-d2ade882db0d"},
        "signature":
         "DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8ISlSApmWQxfKTUJqPP3-Kg6NU1Q"}]
}

Si vous n'avez pas de décodeur Base64 sous la main, notez que la charge utile (le texte JSON qu'on veut protéger) était :

{"iss":"joe",
 "exp":1300819380,
 "http://example.com/is_root":true}

Après cette vision générale, les détails. D'abord, l'en-tête JOSE (section 4). On a vu qu'il indiquait les paramètres algorithmiques de la signature. Les plus importants de ces paramètres :

  • alg indique l'algorithme cryptographique utilisé. Les valeurs possibles dans le registre IANA défini par le RFC 7518. Par exemple {"alg":"ES256"} identifiera l'algorithme ECDSA avec la courbe P-256 et la condensation en SHA-256.
  • jwk est la clé de signature, formatée selon le RFC 7517.
  • jku est un URL au bout duquel on trouvera un ensemble de clés, formatées également selon le RFC 7517. La clé de signature fait partie de cet ensemble. Évidemment, il faut utiliser un transport sécurisé (comme HTTPS, avec validation de l'identité du serveur, cf. RFC 6125) pour récupérer ces clés (section 8, sur les exigences TLS).
  • kid, que vous avez vu dans l'exemple plus haut, est un identificateur de la clé de signature (cf. section 6).
  • x5c est un certificat X.509 (RFC 5280) correspondant à la clé de signature.
  • x5u est un URL pointant vers un certificat X.509 correspondant à la clé de signature.

Les étapes pour créer un JWS sont décrites en section 5 :

  • Encoder la charge utile en Base64 (RFC 4648). Notez qu'il n'existe pas de mécanisme de canonicalisation standard d'un texte JSON et qu'on n'applique donc pas une telle canonicalisation.
  • Fabriquer l'en-tête JOSE avec les paramètres cryptographiques qu'on va utiliser, puis l'encoder en Base64.
  • Signer (les détails dépendent évidemment de l'algorithme de signature utilisé), et encoder la signature en Base64.
  • Sérialiser (en JSON ou en compact).

Pour valider une signature, on fait l'inverse. Si une étape échoue, la signature est rejetée.

  • Analyser la forme sérialisée pour en extraire les différents composants (en-tête, charge utile, signature).
  • Décoder (depuis le Base64) l'en-tête protégé et vérifier qu'on obtient bien du JSON correct.
  • Vérifier qu'on comprend tous les paramètres, par exemple l'algorithme de signature utilisé.
  • Décoder (depuis le Base64) la signature et la charge utile.
  • Valider la (ou les) signature(s).

S'il y a plusieurs signatures, ce que permet JWS, doivent-elles être toutes valides ou bien une seule suffit-elle ? Ce n'est pas défini par la norme JOSE : chaque application utilisant JOSE peut décider comme elle veut. Dans tous les cas, pour que le document soit considéré comme correctement signé, il faut qu'au moins une signature soit valide. Une autre décision est du ressort de l'application : quels sont les algorithmes de signature acceptables. Par exemple, une application peut décider de rejeter une signature car l'algorithme, trop faible cryptographiquement parlant, n'est pas accepté.

Notez que pas mal d'étapes de JOSE nécessitent de comparer des chaînes de caractères. Cela soulève immédiatement les problèmes de canonicalisation. Les règles JSON de comparaison pour les noms des membres d'un objet sont dans la section 8.3 du RFC 8259. Pour les valeurs, c'est plus compliqué et cela dépend de l'application. Ainsi, si une application a décidé que le membre kid (identificateur de la clé) contient un nom de domaine, elle peut faire des comparaisons insensibles à la casse.

La section 7 de notre RFC couvre les sérialisations. Comme on l'a vu plus haut, il y a deux sérialisations, la compacte et celle en JSON. Chaque application de JOSE va décider quelles sérialisations sont acceptables, la compacte, la JSON ou les deux. La sérialisation en JSON a une forme générale, où les signatures sont un tableau (éventuellement de taille 1) et une légère variante, la sérialisation en JSON aplati, où une seule signature est possible. Voici les deux cas, d'abord la forme générale, avec deux signatures :

{
      "payload":"...",
      "signatures":[
       {"protected":"...",
        "signature":"..."},
       ...
       {"protected":"...",
        "signature":"..."}]
     }

Puis la forme aplatie :

{
      "payload":"...",
      "protected":"...",
      "signature":"..."
     }

La sérialisation compacte, lorsqu'elle est envoyée via l'Internet, est étiquetée avec le type MIME application/jose. La sérialisation en JSON est application/jose+json. Ces deux types sont utilisables pour les JWS de ce RFC ou pour les JWE du RFC 7516.

La section 10 de notre RFC revient sur les exigences de sécurité, qui accompagnent tout protocole cryptographique. La plupart ne sont pas spécifiques à JOSE. Par exemple, si on laisse trainer sa clé privée n'importe où, des tas de gens pourront faire des fausses signatures. Autre cas bien connu, le générateur aléatoire utilisé pour générer les clés (et autres valeurs qui doivent être imprévisibles) doit être fiable (des tas de failles de sécurité ont été créées par des générateurs insuffisants). Mais certains problèmes sont un peu plus subtils. Par exemple, supposons qu'on valide la signature et que, cryptographiquement, tout soit au point. Mais qu'est-ce que ça nous prouve ? Ça nous prouve que le document a bien été signé par le titulaire de la clé privée utilisée. Mais, en général, on veut plus que cela. On veut que le document soit bien signé par Mme A ou par la société B. Il y a donc une étape entre la clé et l'entité à qui on fait confiance (Key Origin Authentication) qui n'est pas triviale.

Autre point qui n'est pas forcément maitrisé de tous, la différence entre signature et MAC. La section 10.5 l'explique bien : la clé utilisée pour MAC est entre les mains de plusieurs entités et l'authentification garantie par MAC est donc plus faible.

Il peut y avoir aussi des failles de sécurité dans JSON et pas dans JOSE, notamment en raison du flou de cette norme, et du laxisme de certaines mises en œuvre qui acceptent du JSON mal formé. Ainsi, le RFC 8259 n'impose pas que les membres d'un objet soient uniques. Un objet JSON :

{
  "voter": "Smith",
  "vote": "YES",
  "vote": "NO"
}

est légal (quoique très déconseillé). Si on sait qu'un utilisateur de cet objet a un analyseur qui ne garde que le dernier membre dupliqué, et qu'un autre a un analyseur qui ne garde que le premier membre dupliqué, on peut signer cet objet et faire croire au premier utilisateur que Smith a voté non, et au second que le même Smith a voté oui. Pour éviter cela, la norme JOSE durcit le RFC 8259 en interdisant les membres dupliqués (une meilleure solution aurait été d'imposer l'utilisation du sous-ensemble JSON du RFC 7493, je trouve, mais l'IETF a choisi une autre voie). Une conséquence de ce durcissement est qu'on ne peut pas signer tous les objets JSON. Les cas pathologiques sont exclus. (Ce point a été l'un des plus « chauds » dans la mise au point de JOSE à l'IETF.)

Plein d'examples de signatures se trouvent dans l'annexe A de notre RFC (mais qu'on avait aussi dans le RFC 7520).


Téléchargez le RFC 7515


L'article seul

RFC 7520: Examples of Protecting Content using JavaScript Object Signing and Encryption (JOSE)

Date de publication du RFC : Mai 2015
Auteur(s) du RFC : M. Miller (Cisco Systems)
Pour information
Réalisé dans le cadre du groupe de travail IETF jose
Première rédaction de cet article le 20 mai 2015


Ce RFC fait partie de l'l'ensemble des normes sur le système JOSE (JavaScript Object Signing and Encryption, opérations cryptographiques sur les textes JSON). Il présente des exemples d'utilisation de JOSE, permettant aux développeurs de voir s'ils ont bien compris les normes présentées dans les RFC 7515 et RFC 7516.

Composé essentiellement de textes JSON et de binaire, ce RFC est long : 117 pages. Je n'en décris ici qu'une toute petite partie. Il vaux mieux lire avant les autres RFC sur JOSE pour comprendre les exemples. JOSE est très riche et il existe plein d'options. Il n'est donc pas possible, malgré l'épaisseur de ce RFC, de couvrir tous les cas. Le but est d'avoir au moins un échantillon représentatif des cas les plus courants. JOSE fonctionne en deux temps : calcul des résultats cryptographiques puis sérialisation, qui est la représentation sous forme texte, de ces résultats. JOSE a trois sérialisations possibles : compacte (le résultat est une série de caractères, pas un texte JSON), générale (le résultat est lui-même du JSON) et aplatie (également du JSON). Si vous voulez vérifier les exemples vous-même, ils sont tous disponibles sur GitHub.

Normalement, le contenu du RFC suffit à reproduire l'exemple exactement : en le donnant à une mise en œuvre de JOSE, on doit trouver le même résultat. La principale exception concerne le cas des algorithmes qui utilisent en entrée des données aléatoires (comme DSA). Dans ce cas, il n'est pas possible de retrouver exactement les mêmes valeurs. En outre, pour la présentation dans le RFC, des espaces ont parfois été ajoutés, là où il n'affectait pas la sémantique des opérations cryptographiques.

Commençons par les premiers exemples (section 3), la représentation de clés en JOSE (RFC 7517). D'abord, une clé publique, sur une courbe elliptique, la P-521 :

{
     "kty": "EC",
     "kid": "bilbo.baggins@hobbiton.example",
     "use": "sig",
     "crv": "P-521",
     "x": "AHKZLLOsCOzz5cY97ewNUajB957y-C-U88c3v13nmGZx6sYl_oJXu9A5RkTKqjqvjyekWF-7ytDyRXYgCF5cj0Kt",
     "y": "AdymlHvOiLxXkEhayXQnNCvDX4h9htZaCJN34kfmC6pV5OhQHiraVySsUdaQkAgDPrwQrJmbnX9cwlGfP-HqHZR1"
   }

Ici, x et y sont des paramètres spécifiques des courbes elliptiques, encodés en Base64 (JSON n'a pas de moyen plus pratique de stocker du binaire). Si c'était une clé privée, on aurait également un paramètre d. kid est l'identificateur de la clé. Plus banale que les courbes elliptiques, une clé publique RSA :

   {
     "kty": "RSA",
     "kid": "bilbo.baggins@hobbiton.example",
     "use": "sig",
     "n": "n4EPtAOCc9AlkeQHPzHStgAbgs7bTZLwUBZdR8_KuKPEHLd4rHVTeT-O-XV2jRojdNhxJWTDvNd7nqQ0VEiZQHz_AJmSCpMaJMRBSFKrKb2wqVwGU_NsYOYL-QtiWN2lbzcEe6XC0dApr5ydQLrHqkHHig3RBordaZ6Aj-oBHqFEHYpPe7Tpe-OfVfHd1E6cS6M1FZcD1NNLYD5lFHpPI9bTwJlsde3uhGqC0ZCuEHg8lhzwOHrtIQbS0FVbb9k3-tVTU4fg_3L_vniUFAKwuCLqKnS2BYwdq_mzSnbLY7h_qixoR7jig3__kRhuaxwUkRz5iaiQkqgc5gHdrNP5zw",
     "e": "AQAB"
   }

Ici, n et e sont des paramètres spécifiques de RSA (le module et l'exposant). Une clé privée RSA nécessiterait davantage d'informations :

   {
     "kty": "RSA",
     "kid": "bilbo.baggins@hobbiton.example",
     "use": "sig",
     "n": "n4EPtAOCc9AlkeQHPzHStgAbgs7bTZLwUBZdR8_KuKPEHLd4rHVTeT-O-XV2jRojdNhxJWTDvNd7nqQ0VEiZQHz_AJmSCpMaJMRBSFKrKb2wqVwGU_NsYOYL-QtiWN2lbzcEe6XC0dApr5ydQLrHqkHHig3RBordaZ6Aj-oBHqFEHYpPe7Tpe-OfVfHd1E6cS6M1FZcD1NNLYD5lFHpPI9bTwJlsde3uhGqC0ZCuEHg8lhzwOHrtIQbS0FVbb9k3-tVTU4fg_3L_vniUFAKwuCLqKnS2BYwdq_mzSnbLY7h_qixoR7jig3__kRhuaxwUkRz5iaiQkqgc5gHdrNP5zw",
     "e": "AQAB",
     "d": "bWUC9B-EFRIo8kpGfh0ZuyGPvMNKvYWNtB_ikiH9k20eT-O1q_I78eiZkpXxXQ0UTEs2LsNRS-8uJbvQ-A1irkwMSMkK1J3XTGgdrhCku9gRldY7sNA_AKZGh-Q661_42rINLRCe8W-nZ34ui_qOfkLnK9QWDDqpaIsA-bMwWWSDFu2MUBYwkHTMEzLYGqOe04noqeq1hExBTHBOBdkMXiuFhUq1BU6l-DqEiWxqg82sXt2h-LMnT3046AOYJoRioz75tSUQfGCshWTBnP5uDjd18kKhyv07lhfSJdrPdM5Plyl21hsFf4L_mHCuoFau7gdsPfHPxxjVOcOpBrQzwQ",
     "p": "3Slxg_DwTXJcb6095RoXygQCAZ5RnAvZlno1yhHtnUex_fp7AZ_9nRaO7HX_-SFfGQeutao2TDjDAWU4Vupk8rw9JR0AzZ0N2fvuIAmr_WCsmGpeNqQnev1T7IyEsnh8UMt-n5CafhkikzhEsrmndH6LxOrvRJlsPp6Zv8bUq0k",
     "q": "uKE2dh-cTf6ERF4k4e_jy78GfPYUIaUyoSSJuBzp3Cubk3OCqs6grT8bR_cu0Dm1MZwWmtdqDyI95HrUeq3MP15vMMON8lHTeZu2lmKvwqW7anV5UzhM1iZ7z4yMkuUwFWoBvyY898EXvRD-hdqRxHlSqAZ192zB3pVFJ0s7pFc",
     "dp": "B8PVvXkvJrj2L-GYQ7v3y9r6Kw5g9SahXBwsWUzp19TVlgI-YV85q1NIb1rxQtD-IsXXR3-TanevuRPRt5OBOdiMGQp8pbt26gljYfKU_E9xn-RULHz0-ed9E9gXLKD4VGngpz-PfQ_q29pk5xWHoJp009Qf1HvChixRX59ehik",
     "dq": "CLDmDGduhylc9o7r84rEUVn7pzQ6PF83Y-iBZx5NT-TpnOZKF1pErAMVeKzFEl41DlHHqqBLSM0W1sOFbwTxYWZDm6sI6og5iTbwQGIC3gnJKbi_7k_vJgGHwHxgPaX2PnvP-zyEkDERuf-ry4c_Z11Cq9AqC2yeL6kdKT1cYF8",
     "qi": "3PiqvXQN0zwMeE-sBvZgi289XP9XCQF3VWqPzMKnIgQp7_Tugo6-NZBKCQsMf3HaEGBjTVJs_jcK8-TRXvaKe-7ZMaQj8VfBdYkssbu0NKDDhjJ-GtiseaDVWt7dcH0cfwxgFUHpQh7FoCrjFJ6h6ZEpMF6xmujs4qMpPz8aaI4"
   }

À noter que la seule indication qu'il s'agisse d'une clé privée est la présence des membres supplémentaires p, q, dp, dq et qi.

Passons maintenant à la cryptographie symétrique. Cette fois, il n'y a qu'une seule clé, stockée dans le membre k :

{
     "kty": "oct",
     "kid": "018c0ae5-4d9b-471b-bfd6-eef314bc7037",
     "use": "sig",
     "alg": "HS256",
     "k": "hJtXIZ2uSN5kbQfbtTNWbpdmhkV8FJG-Onbc6mxCcYg"
   }

Elle sera utilisée pour les signatures : on concatène la valeur de la clé au contenu et on SHA-256 le tout (non, en fait, c'est plus compliqué, voir RFC 2104). Le vérificateur fait la même opération et doit trouver le même condensat SHA-256.

Voici pour les clés. Passons aux signatures, en section 4. Un texte JSON signé est un JWS (JSON Web Signature). Le texte signé de tous les exemples est un extrait du Seigneur des anneaux, « It’s a dangerous business, Frodo, going out your door. You step onto the road, and if you don't keep your feet, there’s no knowing where you might be swept off to. ». Attention si vous recalculez les signatures vous-même, le caractère qui ressemble à une apostrophe est en fait le caractère Unicode U+2019, « RIGHT SINGLE QUOTATION MARK » (et, dans le RFC, il y a en plus remplacement de certains espaces par des sauts de ligne). Si vous voulez être sûr, l'encodage en Base64 (RFC 4648) de cette charge utile est SXTigJlzIGEgZGFuZ2Vyb3VzIGJ1c2luZXNzLCBGcm9kbywgZ29pbmcgb3V0IHlvdXIgZG9vci4gWW91IHN0ZXAgb250byB0aGUgcm9hZCwgYW5kIGlmIHlvdSBkb24ndCBrZWVwIHlvdXIgZmVldCwgdGhlcmXigJlzIG5vIGtub3dpbmcgd2hlcmUgeW91IG1pZ2h0IGJlIHN3ZXB0IG9mZiB0by4=.

Voici d'abord une bête signature RSA. L'en-tête protégé (cf. RFC 7515, sections 2 et 4) est :

{
     "alg": "RS256",
     "kid": "bilbo.baggins@hobbiton.example"
}

On signe la concaténation du Base64 de cet en-tête et du Base64 de la charge utile. Cela donne MRjdkly7_-oTPTS3AXP41iQIGKa80A0ZmTuV5MEaHoxnW2e5CZ5NlKtainoFmKZopdHM1O2U4mwzJdQx996ivp83xuglII7PNDi84wnB-BDkoBwA78185hX-Es4JIwmDLJK3lfWRa-XtL0RnltuYv746iYTh_qHRD68BNt1uSNCrUCTJDt5aAE6x8wW1Kt9eRo4QPocSadnHXFxnt8Is9UzpERV0ePPQdLuW3IS_de3xyIrDaLGdjluPxUAhb6L2aXic1U12podGU0KLUQSE_oI-ZnmKJ3F4uOZDnd6QZWJushZ41Axf_fcIe8u9ipH84ogoree7vjbU5y18kDquDg. Il reste à sérialiser le résultat, c'est-à-dire à le présenter sous une forme concrète. Le RFC 7515 prévoit plusieurs sérialisations possibles. La compacte, utilisable dans les URL, serait eyJhbGciOiJSUzI1NiIsImtpZCI6ImJpbGJvLmJhZ2dpbnNAaG9iYml0b24uZXhhbXBsZSJ9.SXTigJlzIGEgZGFuZ2Vyb3VzIGJ1c2luZXNzLCBGcm9kbywgZ29pbmcgb3V0IHlvdXIgZG9vci4gWW91IHN0ZXAgb250byB0aGUgcm9hZCwgYW5kIGlmIHlvdSBkb24ndCBrZWVwIHlvdXIgZmVldCwgdGhlcmXigJlzIG5vIGtub3dpbmcgd2hlcmUgeW91IG1pZ2h0IGJlIHN3ZXB0IG9mZiB0by4.MRjdkly7_-oTPTS3AXP41iQIGKa80A0ZmTuV5MEaHoxnW2e5CZ5NlKtainoFmKZopdHM1O2U4mwzJdQx996ivp83xuglII7PNDi84wnB-BDkoBwA78185hX-Es4JIwmDLJK3lfWRa-XtL0RnltuYv746iYTh_qHRD68BNt1uSNCrUCTJDt5aAE6x8wW1Kt9eRo4QPocSadnHXFxnt8Is9UzpERV0ePPQdLuW3IS_de3xyIrDaLGdjluPxUAhb6L2aXic1U12podGU0KLUQSE_oI-ZnmKJ3F4uOZDnd6QZWJushZ41Axf_fcIe8u9ipH84ogoree7vjbU5y18kDquDg (vous reconnaissez la charge utile, la phrase de Tolkien, et la signature, séparées par des points). Avec la sérialisation aplatie, qui donne un texte JSON, ce serait :

{
     "payload": "SXTigJlzIGEgZGFuZ2Vyb3VzIGJ1c2luZXNzLCBGcm9kbywgZ29pbmcgb3V0IHlvdXIgZG9vci4gWW91IHN0ZXAgb250byB0aGUgcm9hZCwgYW5kIGlmIHlvdSBkb24ndCBrZWVwIHlvdXIgZmVldCwgdGhlcmXigJlzIG5vIGtub3dpbmcgd2hlcmUgeW91IG1pZ2h0IGJlIHN3ZXB0IG9mZiB0by4",
     "protected": "eyJhbGciOiJSUzI1NiIsImtpZCI6ImJpbGJvLmJhZ2dpbnNAaG9iYml0b24uZXhhbXBsZSJ9",
     "signature": "MRjdkly7_-oTPTS3AXP41iQIGKa80A0ZmTuV5MEaHoxnW2e5CZ5NlKtainoFmKZopdHM1O2U4mwzJdQx996ivp83xuglII7PNDi84wnB-BDkoBwA78185hX-Es4JIwmDLJK3lfWRa-XtL0RnltuYv746iYTh_qHRD68BNt1uSNCrUCTJDt5aAE6x8wW1Kt9eRo4QPocSadnHXFxnt8Is9UzpERV0ePPQdLuW3IS_de3xyIrDaLGdjluPxUAhb6L2aXic1U12podGU0KLUQSE_oI-ZnmKJ3F4uOZDnd6QZWJushZ41Axf_fcIe8u9ipH84ogoree7vjbU5y18kDquDg"
   }

C'est un peu compliqué avec une signature ECDSA. En effet, cet algorithme exige des données imprévisibles (le RFC dit « aléatoires » mais il exagère, cf. RFC 6979) et donc chaque signature donnera un résultat différent. Ne vous étonnez donc pas si vous recalculez et que vous trouvez une valeur différente de celle du RFC. Ici, on réutilise la clé présentée plus haut (sur la courbe P-521), et, en sérialisation générale (qui est très proche de la sérialisation aplatie, elle donne aussi un texte JSON, mais elle a un tableau de signatures et pas une signature unique, voir la section 4.8 pour des exemples) :

{
     "payload": "SXTigJlzIGEgZGFuZ2Vyb3VzIGJ1c2luZXNzLCBGcm9kbywgZ29pbmcgb3V0IHlvdXIgZG9vci4gWW91IHN0ZXAgb250byB0aGUgcm9hZCwgYW5kIGlmIHlvdSBkb24ndCBrZWVwIHlvdXIgZmVldCwgdGhlcmXigJlzIG5vIGtub3dpbmcgd2hlcmUgeW91IG1pZ2h0IGJlIHN3ZXB0IG9mZiB0by4",
     "signatures": [
       {
          "protected": "eyJhbGciOiJFUzUxMiIsImtpZCI6ImJpbGJvLmJhZ2dpbnNAaG9iYml0b24uZXhhbXBsZSJ9",
          "signature": "AE_R_YZCChjn4791jSQCrdPZCNYqHXCTZH0-JZGYNlaAjP2kqaluUIIUnC9qvbu9Plon7KRTzoNEuT4Va2cmL1eJAQy3mtPBu_u_sDDyYjnAMDxXPn7XrT0lw-kvAD890jl8e2puQens_IEKBpHABlsbEPX6sFY8OcGDqoRuBomu9xQ2"
       }
     ]
   }

On peut aussi avoir des signatures « détachées », où le texte signé n'apparait pas. Le vérificateur devra récupérer le texte JSON signé, et récupérer la signature détachée, avant de vérifier. Ici, on utilise la clé symétrique montrée plus haut. L'en-tête sera donc :

{
     "alg": "HS256",
     "kid": "018c0ae5-4d9b-471b-bfd6-eef314bc7037"
   }

Et le résultat, en sérialisation aplatie :

{
     "protected": "eyJhbGciOiJIUzI1NiIsImtpZCI6IjAxOGMwYWU1LTRkOWItNDcxYi1iZmQ2LWVlZjMxNGJjNzAzNyJ9",
     "signature": "s0h6KThzkfBBBkLspW1h84VsJZFTsPPqMDA7g1Md7p0"
}

Passons maintenant au chiffrement (section 5). Le texte utilisé pour les exemples change. Il est également tiré de « La communauté de l'anneau » et est « You can trust us to stick with you through thick and thin–to the bitter end. And you can trust us to keep any secret of yours–closer than you keep it yourself. But you cannot trust us to let you face trouble alone, and go off without a word. We are your friends, Frodo. » Le tiret est un U+2013, « EN DASH ».

Premier exemple, avec RSA pour le chiffrement asymétrique de la clé (de la CEK, Content Encryption Key), AES (en mode CBC) pour le chiffrement symétrique, et SHA-256 lorsqu'il faut condenser. Voici la clé publique :

 {
     "kty": "RSA",
     "kid": "frodo.baggins@hobbiton.example",
     "use": "enc",
     "n": "maxhbsmBtdQ3CNrKvprUE6n9lYcregDMLYNeTAWcLj8NnPU9XIYegTHVHQjxKDSHP2l-F5jS7sppG1wgdAqZyhnWvXhYNvcM7RfgKxqNx_xAHx6f3yy7s-M9PSNCwPC2lh6UAkR4I00EhV9lrypM9Pi4lBUop9t5fS9W5UNwaAllhrd-osQGPjIeI1deHTwx-ZTHu3C60Pu_LJIl6hKn9wbwaUmA4cR5Bd2pgbaY7ASgsjCUbtYJaNIHSoHXprUdJZKUMAzV0WOKPfA6OPI4oypBadjvMZ4ZAj3BnXaSYsEZhaueTXvZB4eZOAjIyh2e_VOIKVMsnDrJYAVotGlvMQ",
     "e": "AQAB"
}

L'en-tête protégé est :

{
     "alg": "RSA1_5",
     "kid": "frodo.baggins@hobbiton.example",
     "enc": "A128CBC-HS256"
}

Et on se retrouve avec, en sérialisation générale :

{
     "recipients": [
       {
         "encrypted_key": "laLxI0j-nLH-_BgLOXMozKxmy9gffy2gTdvqzfTihJBuuzxg0V7yk1WClnQePFvG2K-pvSlWc9BRIazDrn50RcRai__3TDON395H3c62tIouJJ4XaRvYHFjZTZ2GXfz8YAImcc91Tfk0WXC2F5Xbb71ClQ1DDH151tlpH77f2ff7xiSxh9oSewYrcGTSLUeeCt36r1Kt3OSj7EyBQXoZlN7IxbyhMAfgIe7Mv1rOTOI5I8NQqeXXW8VlzNmoxaGMny3YnGir5Wf6Qt2nBq4qDaPdnaAuuGUGEecelIO1wx1BpyIfgvfjOhMBs9M8XL223Fg47xlGsMXdfuY-4jaqVw"
       }
     ],
     "protected": "eyJhbGciOiJSU0ExXzUiLCJraWQiOiJmcm9kby5iYWdnaW5zQGhvYmJpdG9uLmV4YW1wbGUiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0",
     "iv": "bbd5sTkYwhAIqfHsx8DayA",
     "ciphertext": "0fys_TY_na7f8dwSfXLiYdHaA2DxUjD67ieF7fcVbIR62JhJvGZ4_FNVSiGc_raa0HnLQ6s1P2sv3Xzl1p1l_o5wR_RsSzrS8Z-wnI3Jvo0mkpEEnlDmZvDu_k8OWzJv7eZVEqiWKdyVzFhPpiyQU28GLOpRc2VbVbK4dQKPdNTjPPEmRqcaGeTWZVyeSUvf5k59yJZxRuSvWFf6KrNtmRdZ8R4mDOjHSrM_s8uwIFcqt4r5GX8TKaI0zT5CbL5Qlw3sRc7u_hg0yKVOiRytEAEs3vZkcfLkP6nbXdC_PkMdNS-ohP78T2O6_7uInMGhFeX4ctHG7VelHGiT93JfWDEQi5_V9UN1rhXNrYu-0fVMkZAKX3VWi7lzA6BP430m",
     "tag": "kvKuFBXHe5mQr4lqgobAUg"
}

Le contenu chiffré, et donc désormais confidentiel, est dans le membre ciphertext. Attention si vous essayez de reproduire cet exemple, le résultat exact dépend du vecteur d'initialisation iv. En sérialisation compacte, on aurait :

eyJhbGciOiJSU0ExXzUiLCJraWQiOiJmcm9kby5iYWdnaW5zQGhvYmJpdG9uLmV4YW1wbGUiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0.laLxI0j-nLH-_BgLOXMozKxmy9gffy2gTdvqzfTihJBuuzxg0V7yk1WClnQePFvG2K-pvSlWc9BRIazDrn50RcRai__3TDON395H3c62tIouJJ4XaRvYHFjZTZ2GXfz8YAImcc91Tfk0WXC2F5Xbb71ClQ1DDH151tlpH77f2ff7xiSxh9oSewYrcGTSLUeeCt36r1Kt3OSj7EyBQXoZlN7IxbyhMAfgIe7Mv1rOTOI5I8NQqeXXW8VlzNmoxaGMny3YnGir5Wf6Qt2nBq4qDaPdnaAuuGUGEecelIO1wx1BpyIfgvfjOhMBs9M8XL223Fg47xlGsMXdfuY-4jaqVw.bbd5sTkYwhAIqfHsx8DayA.0fys_TY_na7f8dwSfXLiYdHaA2DxUjD67ieF7fcVbIR62JhJvGZ4_FNVSiGc_raa0HnLQ6s1P2sv3Xzl1p1l_o5wR_RsSzrS8Z-wnI3Jvo0mkpEEnlDmZvDu_k8OWzJv7eZVEqiWKdyVzFhPpiyQU28GLOpRc2VbVbK4dQKPdNTjPPEmRqcaGeTWZVyeSUvf5k59yJZxRuSvWFf6KrNtmRdZ8R4mDOjHSrM_s8uwIFcqt4r5GX8TKaI0zT5CbL5Qlw3sRc7u_hg0yKVOiRytEAEs3vZkcfLkP6nbXdC_PkMdNS-ohP78T2O6_7uInMGhFeX4ctHG7VelHGiT93JfWDEQi5_V9UN1rhXNrYu-0fVMkZAKX3VWi7lzA6BP430m.kvKuFBXHe5mQr4lqgobAUg

On peut aussi chiffrer et signer (section 6).

Attention, les exemples dans ce RFC sont juste... des exemples. Ils visent à permettre aux développeurs de comprendre la norme, et de tester leurs programmes (section 7). L'accent est donc mis, autant que possible, sur la reproductibilité et pas sur la sécurité. Ainsi, en violation des bonnes pratiques, tous les exemples utilisent la même clé symétrique de chiffrement (CEK, Content Encryption Key) et le même vecteur d'initialisation. Cette clé et ce vecteur doivent normalement changer à chaque opération de signature ou de chiffrement.

N'oubliez pas, si vous voulez reproduire les exemples de ce RFC, tous les résultats, sous un format lisible par vos programmes, sont dans un dépôt Github.


Téléchargez le RFC 7520


L'article seul

RFC 7517: JSON Web Key (JWK)

Date de publication du RFC : Mai 2015
Auteur(s) du RFC : M. Jones (Microsoft)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF jose
Première rédaction de cet article le 20 mai 2015


Le sigle JOSE (JavaScript Object Signing and Encryption) désigne l'utilisation de moyens cryptographiques pour sécuriser des textes JSON. JOSE permet notamment de signer (RFC 7515) et chiffrer (RFC 7516) des textes JSON. Pour cela, il faut des clés cryptographiques et ce RFC 7517 normalise la représentation de ces clés en JSON.

Une JWK (JSON Web Key) est donc une clé représentée par un objet JSON. Que les amateurs de X.509 se rassurent, il n'est pas prévu de remplacer ce format par JSON :-) Le but essentiel est de pouvoir manipuler des clés dans le contexte de JSON (transmettre la clé en même temps qu'une signature, chiffrer une clé privée pour la transporter de manière sûre, etc). Outre la JWK, notre RFC définit aussi le JWK set, un ensemble de JWK.

Commençons par un exemple simple, une clé sur une courbe elliptique :

     {"kty":"EC",
      "crv":"P-256",
      "x":"f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU",
      "y":"x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0",
      "kid":"Public key used in JWS A.3 example"
     }

Ici, le membre kty identifie la clé comme utilisant les courbes elliptiques, crv indique l'usage de la courbe NIST P-256, x et y sont les coordonnées de la clé sur cette courbe. kid est un identificateur de clé, dont le format est libre.

La section 4 décrit en détail tous les membres possibles de l'objet clé. Parmi les principaux :

  • kty vaut EC (courbes elliptiques) ou RSA (l'algorithme du même nom). D'autres valeurs sont possibles (cf. RFC 7518, et le registre IANA).
  • use (inutilisé dans l'exemple plus haut) indique l'utilisation prévue de la clé (sig pour signer, enc pour chiffrer...). Là encore, le RFC 7518 prévoit un registre des valeurs possibles.
  • alg désigne l'algorithme à utiliser avec cette clé, parmi ceux enregistrés à l'IANA.
  • kid (Key IDentification) sert à identifier la clé. Par exemple, lorsqu'on doit désigner une clé particulière au sein d'un ensemble de clés disponibles. Notez que son format n'est pas spécifié par notre RFC.
  • x5c est un certificat X.509 (RFC 5280), ou une chaîne de certificats. Les certificats sont une valeur en DER encodée en Base64.
  • x5u est un URL pointant vers un certificat X.509.

JWK peut servir pour la cryptographie asymétrique ou pour la symétrique. Voici un exemple de clé symétrique (le type oct signifie « suite d'octets », la clé elle-même est dans le membre k) :

{
   "kty":"oct",
   "k":"AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow",
   "kid":"HMAC key used in JWS A.1 example"
}

Si on veut manipuler plusieurs clés ensemble (section 5), on peut utiliser un objet JSON comportant un membre keys dont la valeur est un tableau de JWK. Ici, une clé sur une courbe elliptique et une clé RSA :

     {"keys":
       [
         {"kty":"EC",
          "crv":"P-256",
          "x":"MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
          "y":"4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM",
          "use":"enc",
          "kid":"1"},

         {"kty":"RSA",
          "n": "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
          "e":"AQAB",
          "alg":"RS256",
          "kid":"2011-04-29"}
       ]
     }

Le format JWK permet de représenter des clés privées, que ce soit la partie privée d'une clé asymétrique, ou bien une clé symétrique. Si on échange ces clés, il est évidemment recommandé de les chiffrer, ce qui peut se faire avec JOSE (RFC 7516). Une JWK chiffrée est alors un JWE (contenu chiffré en JOSE) comme les autres.

Comme tous les RFC JOSE, cette norme fait une forte consommation de registres IANA. La section 8 leur est consacrée. La politique d'enregistrement dans ces registres est « description nécessaire » (cf. RFC 5226), ce qui veut dire qu'un texte stable décrivant la valeur enregistrée est nécessaire. Par exemple, si on veut enregistrer un nouvel algorithme cryptographique pour les clés, on doit indiquer un texte décrivant précisément cet algorithme. Les registres sont notamment :

  • Les paramètres des clés (comme use pour l'usage prévu, ou kid pour l'identificateur). Comme toujours dans le monde JSON, les membres inconnus d'un objet sont ignorés. Ainsi, un nouveau membre enregistré ici pourra être utilisé sans risque puisque les mises en œuvre de JOSE plus anciennes ignoreront ce nouveau membre.
  • Les utilisations des clés comme sig pour la signature ou bien enc pour le chiffrement.

Outre ces nouveaux registres, ce RFC ajoute au registre des types de média le type application/jwk+json qui identifie une clé encodée en JSON et application/jwk-set+json qui identifie un ensemble de clés.

La section 9 de notre RFC se penche sur la sécurité, évidemment un sujet important quand on manipule des clés. Les règles à suivre sont les règles classiques de la cryptographie. Par exemple, les clés privées doivent être gardées à l'abri des regards indiscrets, comme rappelé dans les RFC 3447 et RFC 6030.

Autre piège, risquer de croire que, parce qu'un texte est signé, il a davantage de valeur. Cela n'est vrai que si on peut s'assurer de l'origine de la clé. Autrement, cela ne signifie rien, n'importe qui ayant pu se créer une clé. Un des moyens de vérifier cette origine est de valider le certificat PKIX dans le membre x5c. Au passage, les exemples de certificats dans le RFC sont, comme le veut le format JWK de JOSE, du DER encodé en Base64. Pour les lire, on peut par exemple, mettre le contenu en Base64 (après avoir retiré les espaces et sauts de ligne qui se trouvent dans le RFC) dans un fichier, le décoder avec base64 puis le lire avec OpenSSL :

% base64 -d < rfc.b64 > rfc.der              
% openssl x509 -text -inform der -in rfc.der
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            01:3c:ff:16:e2:e2
    Signature Algorithm: sha1WithRSAEncryption
        Issuer: C=US, ST=CO, L=Denver, O=Ping Identity Corp., CN=Brian Campbell
        Validity
            Not Before: Feb 21 23:29:15 2013 GMT
            Not After : Aug 14 22:29:15 2018 GMT
        Subject: C=US, ST=CO, L=Denver, O=Ping Identity Corp., CN=Brian Campbell
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
...

Téléchargez le RFC 7517


L'article seul

RFC 7541: HPACK - Header Compression for HTTP/2

Date de publication du RFC : Mai 2015
Auteur(s) du RFC : R. Peon (Google), H. Ruellan (Canon CRF)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF httpbis
Première rédaction de cet article le 16 mai 2015


Une des nouveautés de la version 2 de HTTP, désormais normalisée dans le RFC 7540, est de représenter les en-têtes des requêtes et des réponses, non plus sous une forme texte, mais sous une forme binaire, avec compression. Ce RFC normalise le mécanisme de compression, nommé HPACK.

Fini, donc, de taper des en-têtes HTTP à la main dans une session telnet, ou bien d'écrire un serveur HTTP qui envoie simplement ses réponses avec un fprintf. Désormais, tout se fait en binaire et sera comprimé, pour gagner quelques octets. L'encodage peu efficace des en-têtes de HTTP version 1 faisait perdre de l'espace, donc du temps, d'autant plus qu'ils sont répétés à chaque requête. Il fallait donc comprimer. Mais un algorithme de compression général, comme le DEFLATE (RFC 1951) qu'utilisait le premier prototype de HTTP 2, le protocole SPDY, avait des conséquences néfastes en terme de sécurité, lorsqu'il était combiné au chiffrement. D'où l'idée d'un algorithme spécifique à HTTP et n'ayant pas ces défauts, l'actuel HPACK. HPACK se veut simple (le RFC fait quand même 58 pages, celui de DEFLATE n'en faisait que 17), et inflexible (pas d'options à négocier).

HPACK est prévu (section 1.1 du RFC) pour comprimer des en-têtes HTTP, c'est-à-dire une suite ordonnée de doublets {nom, valeur}. La duplication des noms est autorisée.

La spécification de HPACK n'impose pas un algorithme spécifique pour le compresseur, elle décrit juste ce à quoi doivent ressembler les données comprimées, pour que le décompresseur arrive à les reconstituer.

Les données comprimées vont contenir des index, qui référencent une table, et des valeurs littérales. HPACK utilise deux tables, qui permettent d'associer un index à un en-tête. La première table est statique : définie dans ce RFC, dans l'annexe A, elle comporte les en-têtes les plus courants. Ainsi, Accept-encoding: gzip,deflate (RFC 7231, section 5.3.4), présent chez presque tous les navigateurs Web, sera représenté par l'index 16. Cette table statique a surtout des entrées qui sont des pseudo-en-têtes, c'est-à-dire des valeurs dans les requêtes ou les réponses qui n'étaient pas définies comme des en-têtes en HTTP 1 mais qui sont assimilés à des en-têtes en HTTP 2 (on les reconnait à leur nom qui commence par deux-points). Ainsi, le classique GET (:method GET pour HTTP 2) sera l'index 2 et /index.html (:path /index.html en HTTP 2) sera l'index 5.

La seconde table est dynamique : vide au début, elle se remplit au fur et à mesure de la compression ou de la décompression. Ses index commencent là où la table statique se termine (à l'index 61).

Un en-tête pourra donc être représenté par un index (cas du Accept-encoding: gzip,deflate plus haut) ou bien par une combinaison d'un nom d'en-tête et d'une valeur. Le nom d'en-tête pourra être un index (Content-type:, index 31, est un exemple dans la table statique) ou bien indiqué littéralement.

Quelles données peut-on mettre dans un flot de données HPACK ? La section 5 expose comment sont représentés entiers et chaînes de caractères. Rappelez-vous que le but est de gagner de la place et les entiers peuvent donc avoir une représentation un peu baroque, un entier pouvant commencer au beau milieu d'un octet (des exemples figurent en annexe C.1). Les chaînes de caractères peuvent être représentées telles quelles mais aussi être comprimées avec Huffman (le code Huffman utilisé est dans l'annexe B).

La section 6 décrit la représentation complète en binaire. Bon, et la table dynamique, elle est gérée comment ? Sa taille peut changer dynamiquement mais la taille maximale est déterminée par le paramètre SETTINGS_HEADER_TABLE_SIZE. Certains éléments dans les données ne changent pas la table mais d'autres ajoutent une entrée à la table dynamique. Selon les bits placés au début d'un élément (section 6), le décodeur sait si la donnée est indexée ou littérale et, si elle est littérale, s'il faut l'ajouter à la table dynamique. De nombreux exemples en annexe C permettent de se faire une meilleure idée de l'encodage.

Enfin, la section 7 se penche sur quelques problèmes de sécurité. Contrairement à DEFLATE (RFC 1951) qui permettait de deviner un préfixe du terme comprimé (ce qui, combiné avec le fait que TLS ne masque pas la longueur des données, seulement leur contenu, menait à l'attaque CRIME), HPACK oblige l'attaquant actif à tester un terme entier. Une attaque par force brute pour essayer de deviner le contenu en se basant sur la longueur observée reste donc possible, bien que nettement plus coûteuse qu'avec DEFLATE. Pour rendre plus difficile cette attaque, on peut avoir intérêt à ne pas comprimer les en-têtes les plus sensibles (comme les cookies). D'autres méthodes dépendent de l'application : par exemple, un navigateur Web ne devrait pas permettre l'utilisation de la même connexion HTTP 2 (donc du même contexte de compression/décompression) par du code issu de deux origines (RFC 6454) différentes.

Attention enfin à la consommation mémoire : compression et décompression peuvent en nécessiter beaucoup. La limite à la taille de la table dynamique est là pour empêcher les excès.

Toutes les mises en œuvre de HTTP 2 ont également HPACK, et en voici une liste.


Téléchargez le RFC 7541


L'article seul

RFC 7540: Hypertext Transfer Protocol version 2

Date de publication du RFC : Mai 2015
Auteur(s) du RFC : M. Belshe (Twist), R. Peon (Google), M. Thomson (Mozilla)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF httpbis
Première rédaction de cet article le 16 mai 2015
Dernière mise à jour le 10 octobre 2021


Le protocole HTTP, à la base des échanges sur le Web, a connu plusieurs versions successives, la première était 0.9, la suivante 1.0 et la plus courante aujourd'hui est la 1.1. L'évolution entre ces versions était progressive. Mais HTTP/2, dont la norme vient de sortir, marque un saut plus important : s'il garde la sémantique de HTTP (ses en-têtes, ses codes de retour, etc), il a désormais un encodage binaire et un transport spécifique (binaire, multiplexé, avec possibilité de push). Fini de déboguer des serveurs HTTP avec telnet. En échange, le nouveau protocole promet d'être plus rapide, notamment en diminuant la latence lors des échanges. La norme de cette version a depuis été mise à jour dans le RFC 9113 . Oubliez donc le RFC 7540.

C'est un groupe de travail IETF, nommé httpbis, qui a mis au point cette nouvelle version (voir son site Web). Ce groupe httpbis travaillait sur deux projets parallèles : d'abord réorganiser les normes sur HTTP 1.1 pour corriger les innombrables bogues, et mieux organiser la norme, sans changer le protocole (projet conclus en juin 2014). Et un deuxième projet, HTTP version 2, connu aussi sous le nom de code de SPDY (initialement lancé par Google). Si SPDY a changé de nom, on peut toutefois prévoir que cet acronyme apparaitra pendant encore un certain temps, dans les API, codes source, messages d'erreur...

La section 1 de notre nouveau RFC résume les griefs qu'il y avait contre HTTP 1.1, normalisé dans le RFC 7230 :

  • Une seule requête au plus en attente sur une connexion TCP donnée. Cela veut dire que, si on a deux requêtes à envoyer au même serveur, et que l'une est lente et l'autre rapide, il faudra faire deux connexions TCP (la solution la plus courante), ou bien se résigner au risque que la lente bloque la rapide. (La section 6.3.2 du RFC 7230 permettait d'envoyer la seconde requête tout de suite mais les réponses devaient être dans l'ordre des requêtes, donc pas moyen pour une requête rapide de doubler une lente.)
  • Un encodage des en-têtes inefficace, trop bavard et trop redondant.

Au contraire, HTTP/2 n'utilisera toujours qu'une seule connexion TCP, de longue durée (ce qui sera plus sympa pour le réseau). L'encodage étant entièrement binaire, le traitement par le récepteur sera plus rapide.

La section 2 de notre RFC résume l'essentiel de ce qu'il faut savoir sur HTTP/2. Il garde la sémantique de HTTP 1 (donc, par exemple, un GET de /cetteressourcenexistepas qui faisait un 404 avant le fera toujours après) mais avec une représentation sur le réseau très différente. On peut résumer en disant que HTTP/2 ne change que le transport des messages, pas les messages ou leurs réponses.

Avec HTTP/2, l'unité de base de la communication est la trame (frame, et, dans HTTP 2, vous pouvez oublier la définition traditionnelle qui en fait l'équivalent du paquet, mais pour la couche 2). Chaque trame a un type et, par exemple, les échanges HTTP traditionnels se feront avec simplement une trame HEADERS en requête et une DATA en réponse. Certains types sont spécifiques aux nouvelles fonctions de HTTP/2, comme SETTINGS ou PUSH_PROMISE.

Les trames voyagent ensuite dans des ruisseaux (streams), chaque ruisseau hébergeant un et un seul échange requête/réponse. On crée donc un ruisseau à chaque fois qu'on a un nouveau GET ou POST à faire. Les petits ruisseaux sont ensuite multiplexés dans une grande rivière, l'unique connexion TCP entre un client HTTP et un serveur. Les ruisseaux ont des mécanismes de contrôle du trafic et de prioritisation entre eux.

Les en-têtes sont comprimés, en favorisant le cas le plus courant, de manière à s'assurer, par exemple, que la plupart des requêtes HTTP tiennent dans un seul paquet de la taille des paquets Ethernet.

Bon, maintenant, les détails pratiques (le RFC fait 92 pages). D'abord, l'établissement de la connexion. HTTP/2 tourne au-dessus de TCP. Comment on fait pour commencer du HTTP/2 ? On utilise un nouveau port, succédant au 80 de HTTP ? (Non. Les ports sont les mêmes, 80 et 443.) On regarde dans le DNS ou ailleurs si le serveur sait faire du HTTP/2 ? (Non plus.) Il y a deux méthodes utilisées par les clients HTTP/2. Tout dépend de si on fait du TLS ou pas. Si on fait du TLS, on va utiliser ALPN (RFC 7301), en indiquant l'identificateur h2 (HTTP/2 sur TLS). Le serveur, recevant l'extension ALPN avec h2, saura ainsi qu'on fait du HTTP/2 et on pourra tout de suite commencer l'échange de trames HTTP/2. (h2 est désormais dans le registre IANA.) Si on ne fait pas de TLS (identificateur h2c pour « HTTP/2 in clear » mais il est juste réservé pour information puisqu'on ne peut pas utiliser ALPN si on n'utilise pas TLS), on va passer par l'en-tête HTTP Upgrade: (section 6.7 du RFC 7230) :

GET / HTTP/1.1
Host: www.example.com
Connection: Upgrade, HTTP2-Settings
Upgrade: h2c
HTTP2-Settings: [base64url encoding of HTTP/2 SETTINGS payload]

Si le serveur est un vieux serveur qui ne gère pas HTTP/2, il ignorera le Upgrade: :

HTTP/1.1 200 OK
Content-Length: 243
Content-Type: text/html

Si le serveur est d'accord pour faire de l'HTTP/2, il répondra 101 (Switching Protocols) :

HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: h2c

[Tout ce qui suit est en HTTP/2]

Dans ce dernier cas, la première trame envoyée par le serveur sera de type SETTINGS. Rappelez-vous que chaque couple requête/réponse HTTP aura lieu dans un ruisseau séparé. Ici, le ruisseau numéro 1 aura été créé implicitement, et servira à la requête Upgrade:.

Une fois qu'un client aura réussi à établir une connexion avec un serveur en HTTP/2, il sait que le serveur gère ce protocole. Il peut s'en souvenir, pour les futures connexions (mais attention, ce n'est pas une indication parfaite : un serveur peut abandonner HTTP/2, par exemple).

Maintenant, c'est parti, on s'envoie des trames. À quoi ressemblent-elles (section 4) ? Elles commencent par un en-tête indiquant leur longueur, leur type (comme SETTINGS, HEADERS, DATA... cf. section 6), des options (comme ACK qui sert aux trames de type PING à distinguer requête et réponse) et l'identificateur du ruisseau auquel la trame appartient (un nombre sur 31 bits). Le format complet est en section 4.1.

Les en-têtes HTTP sont comprimés selon la méthode normalisée dans le RFC 7541.

Les ruisseaux (streams), maintenant. Ce sont donc des suites ordonnées de trames, bi-directionnelles, à l'intérieur d'une connexion HTTP/2. Une connexion peut comporter plusieurs ruisseaux, chacun identifié par un stream ID (un entier de quatre octets, pair si le ruisseau a été créé par le serveur et impair autrement). Les ruisseaux sont ouverts et fermés dynamiquement et leur durée de vie n'est donc pas celle de la connexion HTTP 2. Contrairement à TCP, il n'y a pas de « triple poignée de mains » : l'ouverture d'un ruisseau est unilatérale et peut donc se faire très vite (rappelez-vous que chaque échange HTTP requête/réponse nécessite un ruisseau qui lui est propre ; pour vraiment diminuer la latence, il faut que leur création soit rapide).

Un mécanisme de contrôle du flot s'assure que les ruisseaux se partagent pacifiquement la connexion. C'est donc une sorte de TCP dans le TCP, réinventé pour les besoins de HTTP/2 (section 5.2 et relire aussi le RFC 1323). Le récepteur indique (dans une trame WINDOWS_UPDATE) combien d'octets il est prêt à recevoir (64 Kio par défaut) et l'émetteur s'arrête dès qu'il a rempli cette fenêtre d'envoi. (Plus exactement, s'arrête d'envoyer des trames DATA : les autres, les trames de contrôle, ne sont pas soumises au contrôle du flot).

Comme si ce système des connexions dans les connexions n'était pas assez compliqué comme cela, il y a aussi des dépendances entre ruisseaux. Un ruisseau peut indiquer qu'il dépend d'un autre et, dans ce cas, les ressources seront allouées d'abord au ruisseau dont on dépend. Par exemple, le code JavaScript ne peut en général commencer à s'exécuter que quand toute la page est chargée, et on peut donc le demander dans un ruisseau dépendant de celle qui sert à charger la page. On peut dépendre d'un ruisseau dépendant, formant ainsi un arbre de dépendances.

Il peut bien sûr y avoir des erreurs dans la communication. Certaines affectent toute la connexion, qui devra être abandonnée, mais d'autres ne concernent qu'un seul ruisseau. Dans le premier cas, celui qui détecte l'erreur envoie une trame GOAWAY (dont on ne peut pas garantir qu'elle sera reçue, puisqu'il y a une erreur) puis coupe la connexion TCP. Dans le second cas, si le problème ne concerne qu'un seul ruisseau, on envoie la trame RST_STREAM qui arrête le traitement du ruisseau.

Notre section 5 se termine avec des règles qui indiquent comment gérer des choses inconnues dans le dialogue. Ces règles permettent d'étendre HTTP/2, en s'assurant que les vieilles mises en œuvre ne pousseront pas des hurlements devant les nouveaux éléments qui circulent. Par exemple, les trames d'un type inconnu doivent être ignorées et mises à la poubelle directement, sans protestation.

On a déjà parlé plusieurs fois des trames, la section 6 du RFC détaille leur définition. Ce sont aux ruisseaux ce que les paquets sont à IP et les segments à TCP. Les trames ont un type (un entier d'un octet). Les types possibles sont enregistrés à l'IANA. Les principaux types actuels sont :

  • DATA (type 0), les trames les plus nombreuses, celles qui portent les données, comme les pages HTML,
  • HEADERS (type 1), qui portent les en-têtes HTTP, dûment comprimés selon le RFC 7541,
  • PRIORITY (type 2) indique la priorité que l'émetteur donne au ruisseau qui porte cette trame,
  • RST_STREAM (type 3), dont j'ai parlé plus haut à propos des erreurs, permet de terminer un ruisseau (filant la métaphore, on pourrait dire que cela assèche le ruisseau ?),
  • SETTINGS (type 4), permet d'envoyer des paramètres, comme SETTINGS_HEADER_TABLE_SIZE, la taille de la table utilisée pour la compression des en-têtes, SETTINGS_MAX_CONCURRENT_STREAMS pour indiquer combien de ruisseaux est-on prêt à gérer, etc (la liste des paramètres est dans un registre IANA),
  • PUSH_PROMISE (type 5) qui indique qu'on va transmettre des données non sollicitées (push), du moins si le paramètre SETTINGS_ENABLE_PUSH est à 1,
  • PING (type 6) qui permet de tester le ruisseau (le partenaire va répondre avec une autre trame PING, ayant l'option ACK à 1),
  • GOAWAY (type 7) que nous avons déjà vu plus haut, sert à mettre fin proprement (le pair est informé de ce qui va se passer) à une connexion,
  • WINDOW_UPDATE (type 8) sert à faire varier la taille de la fenêtre (le nombre d'octets qu'on peut encore accepter, cf. section 6.9.1),
  • CONTINUATION (type 9), indique la suite d'une trame précédente. Cela n'a de sens que pour certains types comme HEADERS (ils peuvent ne pas tenir dans une seule trame) ou CONTINUATION lui-même. Mais une trame CONTINUATION ne peut pas être précédée de DATA ou de PING, par exemple.

Dans le cas vu plus haut d'erreur entrainant la fin d'un ruisseau ou d'une connexion entière, il est nécessaire d'indiquer à son partenaire en quoi consistait l'erreur en question. C'est le rôle des codes d'erreur de la section 7. Stockés sur quatre octets (et enregistrés dans un registre IANA), ils sont transportés par les trames RST_STREAM ou GOAWAY qui terminent, respectivement, ruisseaux et connexions. Parmi ces codes :

  • NO_ERROR (code 0), pour les cas de terminaison normale,
  • PROTOCOL_ERROR (code 1) pour ceux où le pair a violé une des règles de HTTP/2, par exemple en envoyant une trame CONTINUATION qui n'était pas précédée de HEADERS, PUSH_PROMISE ou CONTINUATION,
  • INTERNAL_ERROR (code 2), un malheur est arrivé,
  • ENHANCE_YOUR_CALM (code 11), qui ravira les amateurs de spam et de Viagra, demande au partenaire en face de se calmer un peu, et d'envoyer moins de requêtes.

Toute cette histoire de ruisseaux, de trames, d'en-têtes comprimés et autres choses qui n'existaient pas en HTTP 1 est bien jolie mais HTTP/2 n'a pas été conçu comme un remplacement de TCP, mais comme un moyen de faire passer des dialogues HTTP. Comment met-on les traditionnelles requêtes/réponses HTTP sur une connexion HTTP/2 ? La section 8 répond à cette question. D'abord, il faut se rappeler que HTTP/2 reste du HTTP. L'essentiel des RFC « sémantiques » HTTP, à savoir les RFC 7231, RFC 7232 et les suivants s'applique toujours. Le RFC 7230 reste partiellement applicable : la sémantique est la même mais son expression change. Certains en-têtes disparaissent comme Connection: qui n'est plus utile en HTTP/2.

HTTP reste requête/réponse. Pour envoyer une requête, on utilise un nouveau ruisseau (envoi d'une trame avec un numéro de ruisseau non utilisé), sur laquelle on lira la réponse (les ruisseaux ne sont pas persistents). Dans le cas le plus fréquent, la requête sera composée d'une trame HEADERS contenant les en-têtes (comme User-Agent: ou Host:, cf. RFC 7230, section 3.2) et les « pseudo-en-têtes » comme la méthode (GET, POST, etc), avec parfois des trames DATA (cas d'un POST). La réponse comprendra une trame HEADERS avec les en-têtes (comme Content-Length:) et les pseudo-en-têtes comme le code de retour HTTP (200, 403, 500, etc) suivie de plusieurs trames DATA contenant les données (HTML, CSS, images, etc). Des variantes sont possibles (par exemple, les trames HEADERS peuvent être suivies de trames CONTINUATION). Les en-têtes ne sont pas transportés sous forme texte (ce qui était le cas en HTTP 1, où on pouvait utiliser telnet comme client HTTP) mais encodés selon le RFC 7541. À noter que cet encodage implique une mise du nom de l'en-tête en minuscules.

J'ai parlé plus haut des pseudo-en-têtes : c'est le mécanisme HTTP 2 pour traiter des informations qui ne sont pas des en-têtes HTTP 1. Ces informations sont mises dans les HEADERS HTTP/2, précédés d'un deux-points. C'est le cas de la méthode (RFC 7231, section 4), donc GET sera encodé :method get. L'URL sera éclaté dans les pseudo-en-têtes :scheme, :path, etc. Idem pour la réponse HTTP, le fameux code à trois lettres est désormais un pseudo-en-tête, :status.

Voici un exemple (mais vous ne le verrez pas ainsi si vous espionnez le réseau, en raison de la compression du RFC 7541) :

### HTTP 1, pas de corps dans la requête ###
GET /resource HTTP/1.1          
Host: example.org         
Accept: image/jpeg          

### HTTP/2 (une trame HEADERS)
:method = GET
:scheme = https
:path = /resource
host = example.org
accept = image/jpeg

Puis une réponse qui n'a pas de corps :

### HTTP 1 ###
HTTP/1.1 304 Not Modified      
ETag: "xyzzy"              
Expires: Thu, 23 Jan ... 

### HTTP/2, une trame HEADERS ###
:status = 304
etag = "xyzzy"
expires = Thu, 23 Jan ...

Une réponse plus traditionnelle, qui inclut un corps :

### HTTP 1 ###
HTTP/1.1 200 OK 
Content-Type: image/jpeg   
Content-Length: 123        

{binary data} 

### HTTP/2 ###
# trame HEADERS
:status = 200
content-type = image/jpeg
content-length = 123

# trame DATA
{binary data}

Plus compliqué, un cas où les en-têtes de la requête ont été mis dans deux trames, et où il y avait un corps dans la requête :

### HTTP 1 ###
POST /resource HTTP/1.1    
Host: example.org     
Content-Type: image/jpeg
Content-Length: 123     

{binary data}           

### HTTP/2 ###
# trame HEADERS
:method = POST
:path = /resource
:scheme = https

# trame CONTINUATION
content-type = image/jpeg
host = example.org
content-length = 123

# trame DATA
{binary data}

Nouveauté de HTTP/2, la possibilité pour le serveur de pousser (push, section 8.2 de notre RFC) du contenu non sollicité vers le client (sauf si cette possibilité a été coupée par le paramètre SETTINGS_ENABLE_PUSH). Pour cela, le serveur (et lui seul) envoie une trame de type PUSH_PROMISE au client, en utilisant le ruisseau où le client avait fait une demande originale (donc, la sémantique de PUSH_PROMISE est « je te promets que lorsque le moment sera venu, je répondrai plus longuement à ta question »). Cette trame contient une requête HTTP. Plus tard, lorsque le temps sera venu, le serveur tiendra sa promesse en envoyant la « réponse » de cette « requête » sur le ruisseau qu'il avait indiqué dans le PUSH_PROMISE.

Et enfin, à propos des méthodes HTTP 1 et de leur équivalent en HTTP/2, est-ce que CONNECT (RFC 7231, section 4.3.6) fonctionne toujours ? Oui, on peut l'utiliser pour un tunnel sur un ruisseau. (Un tunnel sur un ruisseau... Beau défi pour le génie civil.)

La section 9 de notre RFC rassemble quelques points divers. Elle rappelle que, contrairement à HTTP 1, toutes les connexions sont persistentes et que le client n'est pas censé les fermer avant d'être certain qu'il n'en a plus besoin. Tout doit passer à travers une connexion vers le serveur et les clients ne doivent plus utiliser le truc d'ouvrir plusieurs connexions HTTP avec le serveur. De même, le serveur laisse les connexions ouvertes le plus longtemps possible, mais a le droit de les fermer s'il doit économiser des ressources.

À noter qu'on peut utiliser une connexion prévue pour un autre nom, du moment que cela arrive au même serveur (même adresse IP). Le pseudo-en-tête :authority sert à départager les requêtes allant à chacun des serveurs. Mais attention si la session utilise TLS ! L'utilisation d'une connexion avec un autre :authority (host + port) n'est possible que si le certificat serveur qui a été utilisé est valable pour tous (par le biais des subjectAltName, ou bien d'un joker).

À propos de TLS (certainement un des points les plus chaudement disputés à l'IETF dans les discussions sur HTTP/2), la section 9.2 prévoit quelques règles qui n'existaient pas en HTTP 1 (et dont la violation peut entrainer la coupure de la connexion avec l'erreur INADEQUATE_SECURITY) :

  • TLS 1.2 (RFC 5246), minimum,
  • Gestion de SNI (RFC 6066) obligatoire,
  • Compression coupée (RFC 3749), comme indiqué dans le RFC 7525 (permettre la compression de données qui mêlent informations d'authentification comme les cookies, et données contrôlées par l'attaquant, permet certaines attaques comme BREACH) ce qui n'est pas grave puisque HTTP a de meilleures capacités de compression (voir aussi la section 10.6),
  • Renégociation coupée, ce qui empêche de faire une renégociation en réponse à une certaine requête (pas de solution dans ce cas) et peut conduire à couper une connexion si le mécanisme de chiffrement sous-jacent ne permet pas d'encoder plus de N octets sans commencer à faire fuiter de l'information.
  • Très sérieuse limitation du nombre d'algorithmes de chiffrement acceptés (voir l'annexe A pour une liste complète), en éliminant les algorithmes trop faibles cryptographiquement (comme les algorithmes « d'exportation » utilisés dans la faille FREAK). Peu d'algorithmes restent utilisables après avoir retiré cette liste !

TLS avait été au cœur d'un vigoureux débat : faut-il essayer systématiquement TLS, même sans authentification, même si l'URL est de plan http: et pas https: ? Ce « chiffrement opportuniste » avait été proposé à l'IETF, pour diminuer l'efficacité de la surveillance massive (RFC 7258). C'était le ticket #314 du groupe de travail, et ce fut un des plus disputés. Quelques articles sur ce sujet du « tentons TLS à tout hasard » : http://bitsup.blogspot.fr/2013/08/ssl-everywhere-for-http2-new-hope.html, http://it.slashdot.org/story/13/11/13/1938207/http-20-may-be-ssl-only, http://www.pcworld.com/article/2061189/next-gen-http-2-0-protocol-will-require-https-encryption-most-of-the-time-.html, https://www.tbray.org/ongoing/When/201x/2013/11/05/IETF-88-HTTP-Security, http://www.mnot.net/blog/2014/01/04/strengthening_http_a_personal_view ou http://lists.w3.org/Archives/Public/ietf-http-wg/2013OctDec/0625.html. Il faut préciser que l'IETF n'a pas de pouvoirs de police : même si le RFC sur HTTP/2 avait écrit en gros « le chiffrement est obligatoire », rien ne garantit que cela aurait été effectif. Finalement, la décision a été de ne pas imposer ce passage en TLS, mais la question reste en discussion à l'IETF pour le plus grand déplaisir de ceux qui voudraient espionner le trafic plus facilement.

Puisqu'on parle de sécurité, la section 10 traite un certain nombre de problèmes de sécurité de HTTP/2. Parmi ceux qui sont spécifiques à HTTP/2, on note que ce protocole demande plus de ressources que HTTP 1, ne serait-ce que parce qu'il faut maintenir un état pour la compression. Il y a donc potentiellement un risque d'attaque par déni de service. Une mise en œuvre prudente veillera donc à limiter les ressources allouées à chaque connexion.

Enfin, il y a la question de la vie privée, un sujet chaud dans le monde HTTP depuis longtemps. Les options spécifiques à HTTP/2 (changement de paramètres, gestion du contrôle de flot, traitement des innombrables variantes du protocole) peuvent permettre d'identifier une machine donnée par son comportement. HTTP/2 facilite donc le fingerprinting.

En outre, comme une seule connexion TCP est utilisée pour toute une visite sur un site donné, cela peut rendre explicite une information comme « le temps passé sur un site », information qui était implicite en HTTP 1, et qui devait être reconstruite.

Question mises en œuvre de la nouvelle version de HTTP, un bon point de départ est la liste du groupe de travail. nginx avait décrit ses plans et a désormais une mise en œuvre de HTTP/2. Pour le cas particulier des navigateurs Web, il y a un joli tableau.

curl a désormais HTTP/2 :


% curl -v --http2 https://www.ietf.org/
* Connected to www.ietf.org (2400:cb00:2048:1::6814:55) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* ALPN, server accepted to use http/1.1
> GET / HTTP/1.1
> Host: www.ietf.org
> User-Agent: curl/7.52.1
> Accept: */*
> 
< HTTP/1.1 200 OK
< Date: Tue, 16 May 2017 14:25:47 GMT
< Content-Type: text/html
< Transfer-Encoding: chunked
< Connection: keep-alive
< Set-Cookie: __cfduid=d980f0f518518e9abb9e786531b1cf7ed1494944747; expires=Wed, 16-May-18 14:25:47 GMT; path=/; domain=.ietf.org; HttpOnly
< Last-Modified: Tue, 02 May 2017 20:16:22 GMT

Désolé de ne pas vous montrer un joli pcap de HTTP/2 mais la plupart des sites accessibles en HTTP/2 (et parfois des clients, « Firefox will only be implementing HTTP/2 over TLS ») imposent TLS, ce qui rend un peu plus compliquée l'analyse. Je n'ai pas encore trouvé de pcap HTTP/2 sur pcapr non plus, mais il y en a à la fin de la page http://daniel.haxx.se/http2/.

Et, sinon, si vous voulez activer HTTP/2 sur un serveur Apache, c'est aussi simple que de charger le module http2 et de configurer :

Protocols h2 h2c http/1.1

Sur Debian, la commande a2enmod http2 fait tout cela automatiquement. Pour vérifier que cela a bien été fait, vous pouvez utiliser curl -v comme vu plus haut, ou bien un site de test (comme KeyCDN) ou encore la fonction Inspect element (clic droit sur la page, puis onglet Network puis sélectionner une des ressources chargées) de Firefox : http2-test.png

Quelques articles pertinents :


Téléchargez le RFC 7540


L'article seul

RFC 7539: ChaCha20 and Poly1305 for IETF protocols

Date de publication du RFC : Mai 2015
Auteur(s) du RFC : Y. Nir (Check Point), A. Langley (Google)
Pour information
Réalisé dans le cadre du groupe de recherche IRTF cfrg
Première rédaction de cet article le 15 mai 2015


Les algorithmes de cryptographie ChaCha20 et Poly1305 n'avaient jamais fait l'objet d'une spécification stable, permettant leur référencement pour les protocoles IETF. C'est désormais fait avec ce RFC (depuis remplacé par le RFC 8439), qui normalise aussi bien leur utilisation isolée (ChaCha20 seul ou Poly1305 seul) que leur combinaison, qui fournit du chiffrement intègre (AEAD).

Aujourd'hui, la référence en matière de chiffrement symétrique est AES, entre autres en raison de ses performances très élevées sur du matériel dédié. AES est quatre à dix fois plus rapide que 3DES, qui était la précédente référence. Il est donc logique que AES soit utilisé partout, et notamment qu'il chiffre la quasi-totalité des sessions TLS. Le problème alors est qu'on dépend trop d'AES : si une faille est découverte par la cryptanalyse, on est fichu (AES est par exemple vulnérable dans certains cas). Il serait plus rassurant d'avoir des alternatives sérieuses à AES (n'obligeant pas à revenir à 3DES), pour que d'éventuelles percées en cryptanalyse ne cassent pas toute la crypto d'un coup. D'autant plus qu'AES a un défaut : rapide sur du matériel spécialisé, il l'est moins sur du matériel généraliste.

D'où les algorithmes décrits formellement dans ce RFC. Inventés par Bernstein, ils ont déjà fait l'objet d'un certain nombre d'analyses de sécurité (« New Features of Latin Dances: Analysis of Salsa, ChaCha, and Rumba » et « Latin Dances Revisited: New Analytic Results of Salsa20 and ChaCha »). ChaCha20 est un algorithme de chiffrement symétrique, plus rapide qu'AES sur un matériel générique (mise en œuvre purement en logiciel), Poly1305 est un MAC, et les deux peuvent être combinés pour faire du chiffrement intègre (et cela figure désormais dans le registre sur AEAD).

La section 2 du RFC décrit les algorithmes (je ne la reprends pas ici, la crypto, c'est trop fort pour moi), et ajoute du pseudo-code, des exemples et des vecteurs de test (il y en a d'autres dans l'annexe A). À l'origine, Poly1305 était décrit comme lié à AES, pour obtenir, par chiffrement du numnique, une chaîne de bits unique et secrète. Mais, en fait, n'importe quelle fonction de chiffrement convient, pas uniquement AES. (L'article du Wikipédia anglophone sur Poly1305 continue à colporter cette erreur.)

En cryptographie, ce sont plus souvent les mises en œuvre que les algorithmes qui ont une faille. La section 3 est donc consacrée aux avis aux programmeurs, pour éviter qu'une erreur de leur part n'affaiblisse ces beaux algorithmes. Poly1305 nécessite de travailler avec des grands nombres et le RFC déconseille d'utiliser la plupart des bibliothèques existantes de gestion des grands nombres comme celle d'OpenSSL. Celles-ci sont trop souvent vulnérables à des attaques par mesure du temps écoulé et le RFC conseille d'utiliser uniquement des bibliothèques qui font leur travail en un temps constant, comme NaCl. Un exemple de mise en œuvre de Poly1305 est poly1305-donna.

La section 4, sur la sécurité, détaille les points importants à suivre pour ne pas se faire casser sa jolie crypto. Pour ChaCha20, avant tout, il faut utiliser un numnique (numnique ?) vraiment unique. On peut utiliser un compteur, on peut utiliser un LFSR, mais il doit être unique.

ChaCha20 et Poly1305 n'utilisent que des opérations simples, normalement faciles à implémenter en un temps constant, qui ne permettra pas à l'attaquant de déduire quoi que ce soit de la mesure des temps de réponse. Attention, programmeurs, certaines fonctions comme la classique memcmp() ne s'exécutent pas en un temps constant, et, si elles sont utilisées, permettent certaines attaques.

À noter que ces algorithmes ne sont pas encore dans le registre IANA des algorithmes TLS. Leur mise en œuvre dans Chrome et chez CloudFlare utilise une valeur non-standard et non interopérable pour identifier l'algorithme. Les discussions se poursuivent pour intégrer ChaCha20 à Firefox. Notez aussi un bon article d'explication de CloudFlare.

La norme pour ces algorithmes est, depuis mai 2018, le RFC 8439.


Téléchargez le RFC 7539


L'article seul

RFC 7535: AS112 Redirection using DNAME

Date de publication du RFC : Mai 2015
Auteur(s) du RFC : J. Abley (Dyn), B. Dickson (Twitter), W. Kumari (Google), G. Michaelson (APNIC)
Pour information
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 15 mai 2015


Les serveurs DNS, notamment ceux de la racine, sont en permanence bombardés par un trafic « inutile », des demandes de résolution DNS d'origine locale, et qui n'auraient jamais dû sortir. Par exemple, dans les réseaux qui utilisent les adresses IP privées du RFC 1918, les demandes de « résolution inverse » (« quel est le nom correspondant à 192.168.24.66 ? ») devraient toujours être résolues localement (après tout, il s'agit d'adresses privées) mais souvent les gestionnaires de ces réseaux ne configurent pas correctement leurs résolveurs et paf, la requête 66.24.168.192.in-addr.arpa arrive à la racine, qui ne peut pas en faire grand'chose. Idem si un réseau local utilise (bien à tort) un TLD local comme .home ou .corp. Les requêtes pour des TLD inexistants font plus de 25 % du trafic atteignant la racine. Pour les noms correspondants aux adresses du RFC 1918, le problème a été réglé par la création d'un « puits DNS », l'AS112 (RFC 7534). Les serveurs de l'AS112 sont des machines sacrifiées, à qui on envoie toutes les requêtes pour les noms en in-addr.arpa correspondant au RFC 1918. Cela marche très bien depuis de nombreuses années. Tellement bien qu'on se dit qu'on pourrait jeter dans ce puits bien d'autres choses comme les équivalents IPv6 du RFC 1918 (d.f.ip6.arpa, par exemple, cf. RFC 4193), ou comme les TLD tel que .home. Seulement, voilà, l'AS112 n'a pas été prévu pour cela et, avec leur configuration actuelle, ses serveurs ne répondraient pas correctement à ces requêtes. Il suffit de changer cette configuration ? Plus facile à dire qu'à faire, car l'AS112 est composé de nombreux serveurs plus ou moins coordonnés. Il est probablement impossible de les reconfigurer tous. D'où la nouvelle technique, utiliser (pour la première fois en grand) les enregistrements DNAME.

La nature même de l'AS112, système très décentralisé, sans direction claire, fait qu'il est impossible de changer la configuration de tous les nœuds. Même si l'IETF, l'ARCEP, l'ICANN, la NSA, le CSA et Jean-Kevin étaient tous d'accord, on ne pourrait pas garantir qu'il ne traine pas des nœuds AS112 ayant l'ancienne liste. Et puis on ne veut pas faire juste un changement une fois. On voudrait davantage de souplesse, permettant d'ajouter (ou de retirer) des noms à l'AS112 facilement, sans passer à chaque fois des mois, voire des années, à rappeler aux gérants des serveurs AS112 qu'ils doivent changer leur configuration.

Comme toujours avec l'AS112, l'idéal serait que les administrateurs DNS fassent tous correctement leur travail et suivent le RFC 6303, qui leur impose de servir des zones comme *.168.192.in-addr.arpa localement. Mais, dans le monde réel, ça n'arrive pas et l'AS112 (nommé, j'ai oublié de le dire, d'après le numéro de système autonome qui lui a été attribué) reste indispensable.

On a vu plus haut que l'AS112 n'était que faiblement coordonné. Ses serveurs sont anycastés (RFC 4786) et composés de nombreuses machines, administrées par des personnes différentes. Si on décidait de déléguer, mettons, .home, aux serveurs de l'AS112, blackhole-1.iana.org et blackhole-2.iana.org, certaines des instances de ces deux serveurs seront correctement configurées et répondront, à juste titre, NXDOMAIN (ce domaine n'existe pas : c'est la réponse unique de l'AS112). Mais d'autres instances, administrées avec retard, ou gérées par des gens surmenés qui ont raté l'annonce faite sur la liste des gérants AS112, ne sauront pas qu'elles doivent répondre aux requêtes pour *.home. Elles seront en lame delegation, avec des résultats plus ou moins bons (selon le logiciel utilisé) tels qu'une réponse REFUSED (qui poussera les résolveurs à essayer un autre serveur de la zone, alors que l'objectif était au contraire de diminuer le trafic).

L'IETF a donc choisi une voie différente pour l'évolution de l'AS112 : créer un nouveau préfixe, qui recevra les délégations des nouveaux in-addr.arpa, ip6.arpa, TLD, etc. Les nœuds utilisant ce nouveau préfixe utiliseront une nouvelle technique, à base de DNAME (RFC 6672), pour ne pas avoir à être configuré avec la liste des domaines à servir. Cela permettra de faire évoluer cette liste, ce qui est organisationnellement impossible avec les préfixes actuels de l'AS112.

Un enregistrement DNAME dit qu'une zone est un alias d'une autre. Ainsi :

example.com.     DNAME    example.net.

va faire que tous les noms sous example.com (mais pas example.com lui-même, attention), sont les alias des noms correspondants en example.net. Si on veut trouver l'adresse IPv6 associée à foobar.example.com, le résolveur DNS, en trouvant le DNAME, fera une requête pour foobar.example.net et en transmettra le résultat à l'utilisateur.

La nouvelle zone de l'AS112 se nomme empty.as112.arpa et elle est déléguée à un seul serveur (anycasté), blackhole.as112.arpa (192.31.196.1 / 2001:4:112::1). Ce serveur n'a pas les mêmes adresses que les serveurs traditionnels de l'AS112, il y aura deux jeux de serveurs complètement différents, puisqu'ils auront une configuration distincte (une liste fixée de domaines pour les anciens serveurs, cf. RFC 6304, et une seule zone, la cible des DNAME, pour les nouveaux serveurs). Certains serveurs pourront faire partie des deux jeux à la fois (par exemple des anciens serveurs qui seraient modifiés pour gérer les nouvelles adresses en même temps que les anciennes). L'ancien AS112 continue à fonctionner comme avant. Les nouveaux préfixes anycast correspondants sont 192.31.196.0/24 et 2001:4:112::/48, qui ne servent qu'à l'AS112. (Vous pouvez les chercher dans le looking glass de votre choix. L'AS d'origine sera le 112. L'AS112 est désormais à l'origine de quatre préfixes.) Ces adresses IP du serveur du nouvel AS112 ont été enregistrées dans le registre des adresses spéciales créé par le RFC 6890.

Donc, si vous voulez rediriger une zone DNS vers le puits du nouvel AS112, il suffit d'en faire un DNAME de empty.as112.arpa. Oui, aucun besoin de prévenir qui que ce soit, ou de demander une autorisation, vous n'avez qu'à ajouter cet enregistrement.

Un petit mot pour les fanas de gouvernance : le RFC 3172 confie la gestion politique de .arpa à l'IAB et c'est donc celle-ci qui a eu à approuver, sinon ce RFC, du moins le domaine dont il avait besoin, as112.arpa.

À l'heure actuelle, je n'ai pas l'impression qu'il y ait déjà des redirections vers empty.as112.arpa (en tout cas, DNSDB n'en trouve pas). Il faut dire qu'il y a encore peu de serveurs dans le nouvel AS112. Une fois qu'il sera peuplé, et pourra donc gérer le trafic, on pourra mettre des redirections. Rappelez-vous que l'installation d'une redirection ne nécessite aucun changement dans les serveurs du nouvel AS112. Pour tester, vous pouvez utiliser ma zone sink.bortzmeyer.fr. Normalement, nimportequoi.sink.bortzmeyer.fr doit vous obtenir un NXDOMAIN de la part du serveur AS112 « le plus proche ». Voici, vu par les sondes Atlas les différentes réponses possibles pour le nouvel AS112, ce qui semble indiquer qu'il n'a que quatre serveurs :

%  python resolve-name.py -t SOA empty.as112.arpa
Measurement #2004698 for empty.as112.arpa/SOA uses 497 probes
[] : 11 occurrences
[as112.ottix.net. dns.ottix.net. 1 604800 60 604800 604800] : 2 occurrences
[blackhole.as112.arpa. dns.ripe.net. 1 604800 60 604800 604800] : 226 occurrences
[as112.hivane.net. info.hivane.net. 1 604800 60 604800 604800] : 184 occurrences
[blackhole.as112.arpa. noc.dns.icann.org. 1 604800 60 604800 604800] : 60 occurrences
Test done at 2015-05-14T10:59:36Z

Et l'ancien AS112 ? Il continue à fonctionner comme avant. Si le nouvel AS112 marche bien, s'il est largement peuplé, on pourra changer les actuelles délégations des zones RFC 1918 comme 10.in-addr.arpa et les remplacer par une redirection DNAME vers empty.as112.arpa, le nouvel AS112. Une fois que cela sera fait, l'ancien AS112 et ses serveurs blackhole-1.iana.org et blackhole-2.iana.org pourront être supprimés. Il n'y a toutefois pas de plan précis pour cela : il faut d'abord que le nouvel AS112 fasse ses preuves.

Quelles zones seront mises dans le nouvel AS112 ? Comme indiqué plus haut, n'importe quelle zone peut être déléguée au nouvel AS112 de manière unilatérale. Mais ce service est surtout utile pour les zones à fort trafic, comme celles listées dans le RFC 6303 (qui ne sont pas toutes dans l'ancien AS112, par exemple aucune zone en ip6.arpa n'y est) ou comme certains TLD (les plus importants à l'heure actuelle sont, dans l'ordre, .local, .home, .html, .localdomain et .internal). Dans le cas des TLD, toutefois, il est probable que l'incroyable bureaucratie ICANN et la mainmise du gouvernement états-unien sur le contenu de la racine ne retardent considérablement le projet.

Le choix d'utiliser DNAME n'a pas été sans mal. En effet, DNAME ne fait pas partie du DNS original, et ce n'est pas un simple type d'enregistrement pour des données passives, il nécessite un traitement spécifique dans les résolveurs (et, dans une certaine mesure, dans les serveurs faisant autorité). On ne peut donc pas compter sur 100 % de serveurs DNS gérant DNAME. Est-ce un problème ? Le RFC 6672 prévoit un mécanisme de secours, où l'enregistrement DNAME est accompagné d'un CNAME (les alias classiques) synthétisé à la demande par le serveur. En théorie, tout doit donc bien se passer, même dans un monde imparfait où tous les serveurs ne gèrent pas DNAME. Et en pratique ? L'annexe A décrit les expérimentations qui avaient été faites avant de choisir la solution DNAME (quelques autres avaient été proposées). Le test avait consisté en quatre images sur une page Web que devait charger les navigateurs. La page était distribuée sous forme d'une publicité payante, envoyée par la régie publicitaire à de nombreux navigateurs. Le premier URL, http://a.UNIQUE_STRING.dname.example.com/1x1.png?a.UNIQUE_STRING.dname utilise un domaine qui a un DNAME vers un autre domaine. Si tout l'Internet peut travailler avec des DNAME sans problème, l'image correspondante sera chargée dans 100 % des cas. (La chaîne de caractères UNIQUE_STRING est la même pour toutes les images mais varie à chaque chargement de la page. C'est donc l'identificateur d'un test donné.) Le second URL, http://b.dname.example.com/1x1.png?b.UNIQUE_STRING.dname, qui, contrairement au premier, utilise un nom de domaine qui a un DNAME, et qui n'a pas de partie unique et est donc fréquemment mis en cache. Le troisième URL, http://c.UNIQUE_STRING.target.example.net/1x1.png?c.UNIQUE_STRING.target, ressemble beaucoup au premier mais n'utilise pas du tout de DNAME. C'est du DNS on ne peut plus traditionnel, et il sert donc de contrôle : si le score est de moins de 100 % sur cette troisième image, c'est que le navigateur, la machine sur laquelle il tourne, ou bien le réseau qui l'héberge, ont d'autres problèmes que les DNAME. Un script en Flash dans la page mesure le résultat et le temps nécessaire pour l'obtenir. Enfin, une quatrième image, http://results.recorder.example.net/1x1.png? results.UNIQUE_STRING?za=FIRST_RESULT&zb=SECOND_RESULT&zc=THIRD_RESULT, sert juste à transmettre les résultats. Le journal du serveur HTTP ressemblera à :

GET /1x1.png?results.UNIQUE_STRING?za=1822&zb=1674&zc=1582

(Les chiffres sont les temps de chargement en millisecondes.)

Les résultats ? 98,1 % des tests ont permis le chargement de la première ou de la seconde image, celles qui utilisaient les DNAME. Il y a donc 1,9 % de clients qui ne peuvent pas utiliser les DNAME ? Non, car 2,8 % des tests de chargement de la troisième image (qui n'utilise pas de DNAME, que du DNS d'avant-guerre) ont également échoué. Ce qui montre que ce chiffre de 1,9 % est inférieur au pourcentage d'erreur (soubresauts du réseau, etc). Bref, les DNAME marchent très bien.

À noter que les serveurs du nouvel AS112, eux, n'ont aucun besoin de savoir gérer les DNAME. Seuls les résolveurs, et les serveurs faisant autorité pour les zones redirigées doivent le faire.

Le as112.arpa a été délégué début février 2015 :

% check-soa -i as112.arpa
a.iana-servers.net.
	199.43.132.53: OK: 2014122469 (2 ms)
	2001:500:8c::53: OK: 2014122469 (14 ms)
b.iana-servers.net.
	199.43.133.53: OK: 2014122469 (149 ms)
	2001:500:8d::53: OK: 2014122469 (156 ms)
c.iana-servers.net.
	2001:500:8e::53: OK: 2014122469 (13 ms)
	199.43.134.53: OK: 2014122469 (15 ms)

Et son fils :

% check-soa -i empty.as112.arpa
blackhole.as112.arpa.
        2001:4:112::1: OK: 1 (31 ms)
        192.31.196.1: OK: 1 (23 ms)

Voici une réponse actuelle pour le nouveau domaine :


% dig ANY empty.as112.arpa

; <<>> DiG 9.8.4-rpz2+rl005.12-P1 <<>> ANY empty.as112.arpa
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 30414
;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 1, ADDITIONAL: 5

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

;; ANSWER SECTION:
empty.as112.arpa.	604800 IN SOA blackhole.as112.arpa. dns.ripe.net. (
				1          ; serial
				604800     ; refresh (1 week)
				60         ; retry (1 minute)
				604800     ; expire (1 week)
				604800     ; minimum (1 week)
				)
empty.as112.arpa.	3599 IN	RRSIG NSEC 8 3 3600 20150515204633 (
				20150508164936 52494 as112.arpa.
				lZf9d6oYISRAq8i6gLXXCwUoQP+qmOfAEIiY3hNr6PvD
				DE1kSeGGR3lo3fK6P/CajYv/8twZm/CNQvpAxlRLUyrY
				Hc2WHhgxCtiQx01pLrY9d/QRhiL1WqYZaMSrfNZX0H0S
				GUD1BOcVNzT/lYPz0EdZZKzEXle98ZGWwkIvewE= )
empty.as112.arpa.	3599 IN	NSEC hostname.as112.arpa. NS RRSIG NSEC
empty.as112.arpa.	3599 IN	NS blackhole.as112.arpa.

;; AUTHORITY SECTION:
empty.as112.arpa.	3599 IN	NS blackhole.as112.arpa.

;; ADDITIONAL SECTION:
blackhole.as112.arpa.	3599 IN	A 192.31.196.1
blackhole.as112.arpa.	3599 IN	AAAA 2001:4:112::1
blackhole.as112.arpa.	3599 IN	RRSIG A 8 3 3600 20150516053029 (
				20150508164936 52494 as112.arpa.
				B4eU9u5ZQVGf+Haro2CeCanWwFLeK3hvil8dIlpz1fMm
				xR8K1No4rWTV5hWME1GhFatZVgpATfat9A3rghGWB9Xm
				hcmsaE5uHTOB+56DNhiokWsVtj+WT828naDMlfvGWiP4
				cXIxF/tLcR10XYviczlKYYR/SgAVxgmwjFkBHXg= )
blackhole.as112.arpa.	3599 IN	RRSIG AAAA 8 3 3600 20150515212644 (
				20150508164936 52494 as112.arpa.
				Yk2l+kWkYbYruCNHIKZwGg8GZPDp9y5Qezqk+Ogq5rGF
				/3+R/UjPPw240zdnLi4D2DeBFwlvM8rDq0xt3sreEmdk
				jMdxGcAc8eEfM6O1heP7lgRJW4eCzwOdNX6f1IXEIerg
				XwYWu+3VjI6y4NsrYoczfo+ORAHsdUvz9rdYumk= )

;; Query time: 854 msec
;; SERVER: 217.70.184.225#53(217.70.184.225)
;; WHEN: Fri May  8 20:43:04 2015
;; MSG SIZE  rcvd: 726


Téléchargez le RFC 7535


L'article seul

RFC 7534: AS112 Nameserver Operations

Date de publication du RFC : Mai 2015
Auteur(s) du RFC : J. Abley (Dyn), W. Sotomayor (OttIX)
Pour information
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 15 mai 2015


Le système AS112, décrit dans ce RFC, est à la fois un utile composant du DNS, améliorant les performances et reduisant la charge du réseau, un banc d'essai pour des nouvelles techniques comme l'anycast, et une expérimentation sociale, celle d'un service 100 % acentré.

Un certain nombre de sites connectés à l'Internet utilisent des adresses IP privées, tirées du RFC 1918. Bien des logiciels, lorsqu'ils voient passer un nouveau client, font une résolution DNS pour obtenir le nom du client en fonction de son adresse IP (résolution dite PTR). C'est par exemple le cas du serveur de courrier Postfix, chez qui ce comportement n'est pas débrayable. Lorsque l'adresse IP est privée, il ne sert à rien de poser la question au DNS public. Par définition, celui-ci ne peut pas savoir que MaPetiteEntreprise utilise 192.168.1.0/24 et a attribué 192.168.1.33 à posteclientX.mapetiteentreprise.example. La bonne pratique est donc que l'administrateur réseaux d'un site qui utilise ces adresses privées doit configurer des serveurs DNS pour répondre aux requêtes PTR (cf. RFC 6303). Pour voir cela, on peut utiliser l'option -x de dig, qui permet de faire automatiquement une résolution d'adresse en nom. Le domaine in-addr.arpa (RFC 5855) accueille la forme inversée des adresses (192.168.1.33 devient 33.1.168.192.in-addr.arpa). Testons ici une adresse publique :

% dig -x 192.134.4.20
...
;; ANSWER SECTION:
20.4.134.192.in-addr.arpa. 172800 IN    PTR     rigolo.nic.fr.

Mais beaucoup d'administrateurs réseaux sont négligents, surchargés de travail, incompétents ou les trois à la fois. Ils ne configurent pas ces serveurs DNS et, résultat, la requête PTR sort de leur réseau et va taper sur les serveurs DNS de la racine puis à ceux de in-addr.arpa. (Une bonne partie du trafic semble ainsi venir des réseaux 3G, où le smartphone ne reçoit qu'une adresse privée et où le résolveur DNS qui lui est indiqué ne connait pas les zones correspondantes.) Ceux-ci ont normalement autre chose à faire que de répondre à des requêtes qui sont, dès le départ, des erreurs. Ils délèguent donc à l'AS112, un ensemble de serveurs de noms qui est chargé de répondre « ce nom n'existe pas » à toutes ces requêtes parasites. L'AS112 est donc un puits où finissent les erreurs. Initialement normalisé dans le RFC 6304, il est désormais décrit par ce nouveau RFC. Le nouvel AS112 introduit une importante nouveauté, un mécanisme de délégation utilisant les enregistrements DNAME (RFC 6672) et qui permet de désigner plus facilement des zones à diriger vers le puits. Il y a donc désormais l'ancien AS112 (qui continue à fonctionner et à servir les zones du RFC 1918) et le nouvel AS112, qui servira les futures zones comme les ULA IPv6 du RFC 4193, ou comme des TLD tels que .local ou .home.

On peut voir la délégation de l'ancien AS112 (ancien mais toujours utilisé) avec dig (sauf si votre résolveur suit les recommandations du RFC 6303) :


% dig NS 168.192.in-addr.arpa

; <<>> DiG 9.8.4-rpz2+rl005.12-P1 <<>> NS 168.192.in-addr.arpa
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 56121
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 5

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;168.192.in-addr.arpa.  IN NS

;; ANSWER SECTION:
168.192.in-addr.arpa.   8726 IN NS blackhole-2.iana.org.
168.192.in-addr.arpa.   8726 IN NS blackhole-1.iana.org.

;; ADDITIONAL SECTION:
blackhole-1.iana.org.   604 IN A 192.175.48.6
blackhole-1.iana.org.   603 IN AAAA 2620:4f:8000::6
blackhole-2.iana.org.   603 IN A 192.175.48.42
blackhole-2.iana.org.   603 IN AAAA 2620:4f:8000::42

;; Query time: 2 msec
;; SERVER: 217.70.184.225#53(217.70.184.225)
;; WHEN: Fri May 15 10:28:38 2015
;; MSG SIZE  rcvd: 197

La délégation va être conservée dans les mémoires caches des résolveurs DNS et la racine ou in-addr.arpa ne seront donc plus embêtés, après la première requête.

Pour le nouvel AS112, utilisant la technique du RFC 7535, la délégation est :


% dig NS empty.as112.arpa

; <<>> DiG 9.8.4-rpz2+rl005.12-P1 <<>> NS empty.as112.arpa
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 25550
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 3

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;empty.as112.arpa.      IN NS

;; ANSWER SECTION:
empty.as112.arpa.       3595 IN NS blackhole.as112.arpa.

;; ADDITIONAL SECTION:
blackhole.as112.arpa.   3595 IN A 192.31.196.1
blackhole.as112.arpa.   3595 IN AAAA 2001:4:112::1

;; Query time: 2 msec
;; SERVER: 217.70.184.225#53(217.70.184.225)
;; WHEN: Fri May 15 10:29:25 2015
;; MSG SIZE  rcvd: 113

Mais qui sont ces machines 192.175.48.6, 192.175.48.42 et 192.31.196.1 ? Des très gros serveurs payés par un mécène et installés à un endroit bien connecté ? Pas du tout. C'est ici que rentre en jeu l'AS112. Ce dernier est composé d'un réseau informel de dizaines de machines un peu partout dans le monde et qui annoncent toutes être 192.175.48.6 et 192.175.48.42 (pour l'ancien préfixe) et 192.31.196.1 (pour le nouveau). Chacune de ces machines encaisse une partie de la charge. L'AS112 n'a pas de chef, juste un site Web et un RFC, ce RFC 7534.

L'AS112 doit son nom au numéro de système autonome qui lui a été attribué (et qui est désormais dans le registre des AS spéciaux, créé par le RFC 7249). Ses serveurs utilisent l'anycast (RFC 4786) pour distribuer la charge entre eux. Avant Global Anycast, c'était donc le premier projet d'anycast entre serveurs faiblement coordonnés. Une histoire complète de l'AS112 figure en annexe A de notre RFC.

Les détails pratiques, maintenant. La liste des zones servies par l'ancien AS112 (Direct Delegation) figure en section 3.2. (Le nouvel AS112 suit un système de délégation dynamique décrit dans le RFC 7535.) Elle comprend 10.in-addr.arpa pour le réseau 10.0.0.0/8, de 16.172.in-addr.arpa à 31.172.in-addr.arpa pour le 172.16.0.0/12, et 168.192.in-addr.arpa pour le 192.168.0.0/16, les préfixes du RFC 1918. Elle inclus aussi 254.169.in-addr.arpa pour le préfixe « local au lien » du RFC 5735. Pour aider à l'identification du nœud qui répond, les serveurs de l'AS112 servent également la zone hostname.as112.net, ici à Paris :


% dig +nsid TXT hostname.as112.net

; <<>> DiG 9.7.3 <<>> +nsid TXT hostname.as112.net
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 1078
;; flags: qr rd ra; QUERY: 1, ANSWER: 5, AUTHORITY: 2, ADDITIONAL: 3

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;hostname.as112.net.            IN      TXT

;; ANSWER SECTION:
hostname.as112.net.     267     IN      TXT     "Unicast IP: 193.17.192.194"
hostname.as112.net.     267     IN      TXT     "See http://as112.net/ for more information."
hostname.as112.net.     267     IN      TXT     "See http://noc.hivane.net/cgi-bin/dsc-grapher.pl for local information."
hostname.as112.net.     267     IN      TXT     "Paris, FR"
hostname.as112.net.     267     IN      TXT     "Hivane Networks"

;; AUTHORITY SECTION:
hostname.as112.net.     267     IN      NS      blackhole-2.iana.org.
hostname.as112.net.     267     IN      NS      blackhole-1.iana.org.

;; ADDITIONAL SECTION:
blackhole-1.iana.org.   241     IN      A       192.175.48.6
blackhole-2.iana.org.   241     IN      A       192.175.48.42

;; Query time: 1 msec
;; SERVER: 217.70.184.225#53(217.70.184.225)
;; WHEN: Wed Jul  6 12:36:14 2011
;; MSG SIZE  rcvd: 348

On note que les préfixes IPv6 n'y figurent pas. Pour le nouvel AS112, voici le même test :


% dig +nsid TXT hostname.as112.arpa

; <<>> DiG 9.9.2-P2 <<>> +nsid TXT hostname.as112.arpa
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 22893
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;hostname.as112.arpa.   IN TXT

;; ANSWER SECTION:
hostname.as112.arpa.    604318 IN TXT "RIPE NCC" "Amsterdam, The Netherlands"
hostname.as112.arpa.    604318 IN TXT "See http://www.as112.net/ for more information."

;; AUTHORITY SECTION:
hostname.as112.arpa.    604317 IN NS blackhole.as112.arpa.

;; Query time: 16 msec
;; SERVER: 192.168.2.254#53(192.168.2.254)
;; WHEN: Fri May 15 10:34:06 2015
;; MSG SIZE  rcvd: 180

(On peut avoir une liste des serveurs, à jour, sur le site officiel).

La section 3.3 décrit les serveurs de noms qui reçoivent la délégation, joliment (mais incorrectement, puisqu'ils répondent) nommés blackhole-1.iana.org et blackhole-2.iana.org, et blackhole.as112.arpa pour le nouvel AS (en dépit de leurs noms, les serveurs de l'AS112 ne sont pas gérés par l'IANA, cf. section 7). Dans le champ MNAME du SOA de la zone déléguée, on trouve également (pour l'ancien AS112) prisoner.iana.org dont la tâche principale est de répondre aux mises à jour dynamiques (RFC 2136) que certaines machines envoient audit MNAME. Du temps du RFC 6304, ces serveurs n'étaient accessibles qu'en IPv4 mais ils ont désormais également des adresses IPv6.

Ce RFC 7534 n'est pas seulement la description d'une technique mais également un HOWTO sur la configuration d'un serveur de l'AS112. De tels textes, prévus pour les administrateurs système, sont rares dans les RFC. La section 4 décrit ainsi tout ce que doit savoir le volontaire qui va créer un nouveau nœud. Il doit connaître BGP (RFC 4271), nécessaire pour l'anycast (RFC 4786) et la gestion d'un serveur DNS faisant autorité. Les serveurs de l'AS112 peuvent être situés n'importe où mais ils sont surtout utiles dans les endroits bien connectés, notamment les points d'échange. Ils peuvent être locaux (annonçant les routes avec la communauté BGP no-export, 0xFFFFFF01, cf. RFC 1997), ou globaux (servant le monde entier). Et naturellement, ils doivent se coordonner (via une liste de diffusion) avec les autres serveurs de l'AS112.

L'AS112 n'impose pas de système d'exploitation particulier (section 4.3) mais tous les serveurs existants semblent utiliser Unix et un grand nombre (c'est difficile à dire, puisque l'AS112 ne contrôle pas tout ce qui se passe sur les serveurs) se servent de BIND. Il est recommandé que la machine AS112 soit dédiée à cette tâche : ces serveurs reçoivent parfois un trafic intense qui pourrait perturber leurs autres activités.

Le serveur signale son existence et sa disponibilité en BGP. Il faut donc coupler le serveur de noms au serveur BGP, pour que l'arrêt du serveur DNS entraîne l'arrêt de l'annonce (le RFC ne fournit pas de script pour cela). Un exemple de comment cela peut se réaliser sur Linux, avec les adresses de l'AS112 attachées à une interface dummy, est (code utilisé sur un serveur anycast réel, quoique pas de l'AS112) :

# Load the variables (the machine is a RedHat)
. /etc/sysconfig/network-scripts/ifcfg-eth0

# Test if the name server actually works. Do not use ps: the server
may be there but unresponsive
TMP=(`dig +short +time=1 +tries=1 @${IPADDR} SOA example.`)
MASTER=${TMP[0]:=somethingwaswrong}

# Normal reply or not?
if test ${MASTER} != "nsmaster.nic.example."
then
    # Disable the interface: Quagga will stop announcing the route
    ifdown dummy0
    # Raise an alarm, send SMS, etc
fi

Le serveur BGP annonce les préfixes de l'ancien AS112, 192.175.48.0/24 et 2620:4f:8000::/48, qui couvrent les adresses de tous les serveurs et l'origine est évidemment 112 (les préfixes IP sont dans le registre des préfixes spéciaux créé par le RFC 6890). Si le serveur gère la zone du nouvel AS112, il annonce en BGP 192.31.196.0/24 et 2001:4:112::/48.

Les exemples du RFC supposent que le serveur BGP est Quagga mais cela peut évidemment marcher avec d'autres. Dans l'exemple ci-dessous, tiré du RFC (section 4.4), le router ID est 203.0.113.1 et le serveur BGP a deux pairs, 192.0.2.1 et 192.0.2.2. Voici un extrait du bgpd.conf (la version intégrale est dans le RFC) :

   hostname my-router
...
   router bgp 112
    bgp router-id 203.0.113.1
    network 192.175.48.0/24
    neighbor 192.0.2.1 remote-as 64496
    neighbor 192.0.2.1 next-hop-self
    neighbor 192.0.2.2 remote-as 64497
    neighbor 192.0.2.2 next-hop-self

En farfouillant sur le site officiel (pas très bien organisé, je trouve), on peut trouver d'autres exemples.

Le serveur AS112 a ensuite besoin d'un serveur DNS faisant autorité (section 4.5), évidemment compatible avec toutes les règles du DNS (RFC 1034). Les exemples de configuration du RFC sont fondés sur BIND. Voici un extrait du named.conf (la version intégrale est dans le RFC) :

   options {
     listen-on {
        ...
        // the following addresses correspond to AS112 addresses, and
        // are the same for all AS112 nodes
        192.175.48.1;      // prisoner.iana.org (anycast)
        192.175.48.6;      // blackhole-1.iana.org (anycast)
        192.175.48.42;     // blackhole-2.iana.org (anycast)

	// The following address is used to support DNAME redirection
        // AS112 service and is the same for all AS112 nodes.
	192.31.196.1;      // blackhole.as112.arpa (anycast)
	};

      listen-on-v6 {
       ...
       // The following addresses are used to support Direct Delegation
       // AS112 service and are the same for all AS112 nodes.
       2620:4f:8000::1;   // prisoner.iana.org (anycast)
       2620:4f:8000::6;   // blackhole-1.iana.org (anycast)
       2620:4f:8000::42;  // blackhole-2.iana.org (anycast)

       // The following address is used to support DNAME redirection
       // AS112 service and is the same for all AS112 nodes.
       2001:4:112::1;    // blackhole.as112.arpa (anycast)
       };
       
     recursion no;        // authoritative-only server
   };

   // RFC 1918
   zone "10.in-addr.arpa" { type master; file "db.empty"; };
   ...

   // RFC 5735
   zone "254.169.in-addr.arpa" { type master; file "db.empty"; };

   // DNAME redirection AS112 Service
   zone "empty.as112.arpa" { type master; file "db.dr-empty"; };

   // also answer authoritatively for the HOSTNAME.AS112.NET zone,
   // which contains data of operational relevance
   zone "hostname.as112.net" {
     type master;
     file "db.hostname.as112.net";
   };

   zone "hostname.as112.arpa" {
     type master;
     file "db.hostname.as112.arpa";
   };
   

Un exemple équivalent pour NSD (utilisé sur le nœud AS112 de Paris) est disponible en as112-nsd.conf (ancien AS112 seulement). Pour simplifier son écriture, il a été produit à partir d'un source en M4, as112-nsd.conf.m4.

Que contiennent les fichiers de zone db.empty, db-fr.empty, db.hostname.as112.net et db.hostname.as112.arpa ? Conformes à la syntaxe de la section 5 du RFC 1035, ils sont communs à BIND et NSD. Les deux premiers, comme leur nom l'indique, sont des fichiers de zone vide, puisque le serveur AS112 ne connait évidemment rien : il ne peut que répondre NXDOMAIN (ce nom n'existe pas) à toutes les requêtes. Ils ne contiennent donc que les informations obligatoires à toute zone (SOA, avec une adresse de contact appropriée) et NS. Les deux autres zones servent au débogage de l'AS112, lorsqu'on veut obtenir des informations sur le serveur AS112 courant. Un contenu typique est juste composé d'enregistrements TXT :

           TXT     "Human AS112 server" "Minas Tirith, Gondor"
           TXT     "Forbidden to orcs and nazguls."
           TXT     "See http://www.as112.net/ for more information."

et parfois d'une localisation (cf. RFC 1876). Le résultat sur un site réel étant :


% dig ANY hostname.as112.net.

; <<>> DiG 9.7.3 <<>> ANY hostname.as112.net.
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 41528
;; flags: qr rd ra; QUERY: 1, ANSWER: 7, AUTHORITY: 2, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;hostname.as112.net.            IN      ANY

;; ANSWER SECTION:
hostname.as112.net.     604796  IN      LOC     37 58 22.590 N 23 44 43.890 E 100.00m 100m 10m 10m
hostname.as112.net.     604796  IN      TXT     "See http://as112.net/ for more information."
hostname.as112.net.     604796  IN      TXT     "Unicast IP: as112.grnet.gr"
hostname.as112.net.     604796  IN      TXT     "Greek Research & Technology Network" "Athens, Greece"
hostname.as112.net.     604796  IN      SOA     flo.gigafed.net. dns.ryouko.imsb.nrc.ca. 1 604800 60 604800 604800
hostname.as112.net.     604796  IN      NS      blackhole-2.iana.org.
hostname.as112.net.     604796  IN      NS      blackhole-1.iana.org.

;; AUTHORITY SECTION:
hostname.as112.net.     604796  IN      NS      blackhole-1.iana.org.
hostname.as112.net.     604796  IN      NS      blackhole-2.iana.org.

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Wed Jul  6 12:51:53 2011
;; MSG SIZE  rcvd: 391

(La version intégrale des quatre fichiers de zone figure dans le RFC.)

Une fois le nœud installé, il faut évidemment le tester (avec dig, par exemple). Si les réponses aux requêtes PTR sont correctes, mais pas celles aux requêtes pour le nom hostname.as112.{net,arpa}, c'est sans doute un problème de routage (on est envoyés sur un autre nœud de l'AS112) et il faut alors sortir traceroute et les looking glasses (section 4.6). Des tests dignes de ce nom doivent être faits depuis plusieurs FAI, et doivent tester les trois (ou quatre pour les nouveaux nœuds) adresses IPv4 de l'AS112, plus ses adresses IPv6.

Le bon fonctionnement de l'AS112 ne dépend pas uniquement de sa configuration initiale mais aussi de sa gestion et surveillance quotidiennes. La section 5 est consacrée aux questions opérationnelles. Le nœud doit être surveillé automatiquement, pour s'assurer qu'il répond toujours. S'il doit être arrêté (par exemple pour une maintenance prévue), il faut s'assurer que l'annonce BGP stoppe (autrement, BGP annonce un trou noir, d'où aucune réponse ne reviendra). Autre point important de la gestion opérationnelle d'un serveur de l'AS112, des statistiques, obtenues à partir d'outils comme DSC ou dnstop. Quelle est l'utilisation réelle de l'AS112 ? Ces statistiques n'étant pas consolidées globalement, c'est difficile à dire. Certains opérateurs publient leurs chiffres mais pas tous. Par exemple, le serveur d'Ottawa voit mille requêtes par seconde (cf. « AS112 Intro » par l'un des auteurs du RFC), celui géré par le RIPE-NCC dans les mille cinq cents, et celui à Paris deux fois plus (voir les graphiques), ce qui fait quand même quelques mégabits par seconde. La majorité des types demandés est évidemment du PTR mais il y a aussi un flux important de TXT, apparemment dus à la technologie SD (Service Discovery) d'Apple (voir des statistiques plus détaillées à la fin).

Le nouveau serveur peut alors être annoncé sur les listes appropriées (par exemple, chaque point d'échange a en général la sienne). Enfin, bien que chaque serveur de l'AS112 puisse fonctionner indépendemment des autres, il est évidemment préférable de se coordonner avec les petits camarades (section 6) en écrivant à la liste officielle.

Et dans le futur ? La section 7 explore l'avenir possible de l'AS112. Idéalement, il devrait disparaître petit à petit au fur et à mesure que les administrateurs réseaux prennent soin de ne pas laisser fuir les requêtes PTR pour les réseaux privés, comme recommandé dans le RFC 6303. Le déploiement de logiciels respectant ce principe dès le début pourrait aider. Toutefois, aujourd'hui, les opérateurs de l'AS112 n'observent pas de tendance à la baisse du trafic. Même des années après le déploiement de serveurs mettant en œuvre le RFC 6303, il est probable que le trafic de l'AS112 ne tombera pas à zéro et que ce service restera donc nécessaire.

Enfin, qu'en est-il de la sécurité ? Comme le rappelle la section 9, les requêtes DNS auxquelles répond l'AS112 ne devraient jamais y arriver, normalement. Elles auraient dû rester sur le réseau local. En sortant, elles exposent de l'information interne, qui était peut-être privée (qu'il y ait un serveur AS112 qui y réponde ou pas ne change guère ce risque).

Plus rigolo, comme ces requêtes sont en général involontaires (comme indiqué, elles auraient dû rester privées), les réponses sont inattendues. Plus d'un IDS a donc crié que l'AS112 essayait d'attaquer le réseau. Le RFC 6305 a été écrit pour fournir une réponse toute faite aux administrateurs incompétents qui accusaient l'IANA ou l'AS112.

Comme l'AS112 n'a pas de chef et que l'anycast ne permet pas de limiter le nombre de participants, il est tout à fait possible de fantasmer sur l'hypothèse d'un nœud AS112 voyou, qui donnerait exprès de mauvaise réponses. Ce problème (purement théorique) n'a pas vraiment de solution. Signer les zones avec DNSSEC semble franchement excessif, et difficile à réaliser de manière sûre puisqu'il faudrait distribuer la clé privée à tous les opérateurs de l'AS112.

L'annexe A du RFC expose la longue histoire de l'AS112, de ses débuts en 2002 (les adresses IP privées datent de 1996) à son état actuel, après la redélégation en 2011 de in-addr.arpa, autrefois sur les serveurs de la racine (RFC 5855). L'AS112 a été le premier déploiement massif de l'anycast et a donc joué un rôle primordial dans l'évaluation de cette technologie.

À noter que, d'après la liste officielle des sites, il existe au moins un serveur AS112 en France, chez Hivane, désormais (novembre 2011) connecté au France-IX. Malgré cela, les requêtes françaises pour les serveurs de l'AS112 voyagent souvent loin. C'est un problème banal comme le montrait l'excellente présentation « Investigating AS112 Routing and New Server Discovery ».

Voici quelques analyses sur le trafic de ce serveur français, faites avec DNSmezzo. Le fichier pcap fait 6,8 Go. Il y a 43 701 087 paquets DNS dont 21 858 845 sont des requêtes. Les données ont été prises un vendredi, de 13h40 à 15h30 (heure locale). Regardons d'abord les types de données demandés :

dnsmezzo=> SELECT (CASE WHEN type IS NULL THEN qtype::TEXT ELSE type END),
       meaning,                                                           
       count(results.id)*100/(SELECT count(id) FROM DNS_packets WHERE query) AS requests_percent FROM
             (SELECT id, qtype FROM dns_packets
                 WHERE query)  AS Results
          LEFT OUTER JOIN DNS_types ON qtype = value
              GROUP BY qtype, type, meaning ORDER BY requests_percent desc;


 type  |                meaning                 | requests_percent 
-------+----------------------------------------+------------------
 PTR   | a domain name pointer                  |               57
 TXT   | text strings                           |               35
 SOA   | marks the start of a zone of authority |                6
 CNAME | the canonical name for an alias        |                0
 MX    | mail exchange                          |                0
 AAAA  | IP6 Address                            |                0
 40    |                                        |                0
 DS    | Delegation Signer                      |                0
 ...

La première place des PTR est normale. Celle des TXT est plus surprenante. En regardant les noms utilisés (cf._dns-sd._udp.Y.X.243.10.in-addr.arpa...), on voit qu'ils sont dus à la technique Service Discovery d'Apple, un système normalement confiné au réseau local mais qui bave beaucoup à l'extérieur.

Et quels sont les domaines les plus populaires ?

dnsmezzo=> SELECT substr(registered_domain,1,46) AS domain, 
          count(id)*100/(SELECT count(id) FROM DNS_packets WHERE query) AS requests_percent  
       FROM dns_packets WHERE query GROUP BY registered_domain ORDER BY requests_percent DESC LIMIT 30;
      domain      | requests_percent 
------------------+------------------
 10.in-addr.arpa  |               78
 192.in-addr.arpa |               12
 172.in-addr.arpa |                7
 169.in-addr.arpa |                1
 151.in-addr.arpa |                0
 i~-addr.arpa     |                0
 83.in-addr.arpa  |                0
                  |                0
 gfi.private      |                0
 local.de         |                0
 grupofdez.com    |                0
....

On voit que le réseau 10.0.0.0/8 est nettement le plus populaire. On notera les trois derniers, sans doute des erreurs de configuration.

Et quels sont les résolveurs les plus actifs ? En agrégeant les préfixes IPv4 en /28 :

dnsmezzo=>  SELECT set_masklen(src_address::cidr, 28) AS client, count(id)*100/(SELECT count(id) FROM DNS_packets WHERE query) AS requests_percent                                                                  
     FROM dns_packets WHERE query GROUP BY set_masklen(src_address::cidr, 28)
           ORDER by requests_percent DESC LIMIT 30;
       client       | requests_percent 
--------------------+------------------
 CENSURE.160/28     |               29
 CENSURE.0/28       |               10
 CENSURE.16/28      |                8
 CENSURE.96/28      |                6
...

Oui, j'ai préféré ne pas donner les adresses. Je dirai simplement que ces quatre plus gros sont des opérateurs de téléphonie mobile, deux français et deux extrême-orientaux (les mystères du routage...).

Merci à Clément Cavadore, administrateur du plus gros (en nombre de requêtes) serveur AS112 du monde, pour les données et pour sa relecture.

Les principaux changements depuis le RFC 6304 :

  • Adresses IPv6 pour les serveurs de l'AS112,
  • « Nouvel AS112 », servant la zone empty.as112.arpa, vers laquelle les zones à gérer seront redirigées par un DNAME,
  • Enregistrement des préfixes à l'IANA.

Téléchargez le RFC 7534


L'article seul

RFC 7536: Large-Scale Broadband Measurement Use Cases

Date de publication du RFC : Mai 2015
Auteur(s) du RFC : Marc Linsner (Cisco Systems), Philip Eardley, Trevor Burbridge (BT), Frode Sorensen (Nkom)
Pour information
Réalisé dans le cadre du groupe de travail IETF lmap
Première rédaction de cet article le 8 mai 2015


Mesurer les performances d'un réseau, c'est crucial. Cela permet de savoir si le réseau a bien les caractéristiques promises et cela permet de comparer les réseaux entre eux. D'où l'existence du groupe de travail LMAP de l'IETF, dont voici le premier RFC. Il décrit deux études de cas où la mesure est nécessaire : un opérateur qui veut s'assurer de la qualité du service qu'il fournit, et un régulateur des télécommunications qui veut vérifier que les opérateurs livrent bien ce qu'ils promettent, et ne discriminent pas certaines utilisations. Il y a bien sûr d'autres cas possibles (l'utilisateur final qui veut mesurer les performances de sa connexion...)

Ce RFC concerne aussi bien les mesures de l'accès fixe (ADSL, par exemple) que de l'accès par un mobile. Il n'y a aucune différence dans les problèmatiques métrologiques entre ces deux accès.

La section 2 de notre RFC décrit les deux scénarios d'usage, repris ensuite en détail dans la section 3 pour le cas du FAI et dans la section 4 pour le cas du régulateur. Commençons par le FAI. La mesure de son réseau l'aide à :

  • Identifier et isoler des problèmes (par exemple un lien saturé),
  • Vérifier que des SLA sont respectés,
  • Concevoir les extensions à son réseau (où faut-il déployer le nouveau matériel et les nouvelles fibres, en priorité),
  • Comprendre le vécu des clients (ce qu'on nomme parfois la QoE - Quality of Experience, qui ne dépend pas seulement de données brutes, comme la capacité des câbles, mais aussi de services comme les résolveurs DNS ou comme les CDN),
  • Comprendre (voire prédire) l'impact de nouvelles technologies déployées dans le réseau. (Le RFC prend l'exemple d'IPv6, pour les opérateurs attardés qui ne l'ont pas encore déployé.) Cela peut aussi concerner des problèmes bien plus triviaux comme la mise à jour du firmware d'une machine qui entraine tout à coup une chute des performances.

Il y a plein de détails techniques à prendre en compte pour ce genre de mesures et le problème est bien plus complexe que ne le croit l'amateur qui débarque dans le domaine. Par exemple, le RFC note que la mesure du vécu de l'utilisateur nécessite des mesures de bout en bout, jusqu'à la machine de M. Michu, mais que le réseau de ce dernier, dans sa maison, n'est pas sous le contrôle du FAI (le Wi-Fi peut être peu efficace en raison de problèmes radio). Le FAI tend donc plutôt à mesurer jusqu'au CPE, ce qui est plus fiable mais moins représentatif.

La meilleure façon de mesurer les caractéristiques du réseau est de faire des mesures actives, avec une machine qui envoie des requêtes et mesure le résultat. Pour ne pas interférer avec le trafic normal de l'utilisateur, il vaut mieux faire ces mesures actives lorsque l'utilisateur ne fait rien. Cela implique que le dispositif de mesure puisse savoir quand l'utilisateur est inactif (la documentation de SamKnows demande que l'engin soit placé en coupure sur le réseau local, lui permettant ainsi d'observer tout le trafic).

Des mesures actives lancées à la demande peuvent même être utilisées en réponse à une plainte d'un utilisateur. Il appelle le support en disant « Ça rame », l'employé au support clique sur un bouton sur son interface Web et cela lance des tests de performance depuis la box de cet abonné et, quelques secondes plus tard, leurs résultats s'affichent sur l'écran du support.

Une autre solution est de faire uniquement des mesures passives mais elles ne permettent d'observer que le débit, pas la capacité (qui est le débit maximum possible). Si on mesure 2 Mb/s de trafic, est-ce parce que le réseau ne permet pas plus ou bien simplement parce que c'est ce que fait l'utilisateur en ce moment ? En outre, les mesures passives soulèvent des problèmes liés à la protection de la vie privée.

Le régulateur, lui, veut évaluer les performances de plusieurs opérateurs et, typiquement, les publier (ce qui nécessite de la rigueur dans les faits et de la pédagogie dans les explications). Cela peut servir par exemple à mesurer le déploiement de l'accès Internet à « haut débit », ou bien à mesurer les pratiques de « gestion du trafic » (terme qui, dans le code des FAI, désigne les discriminations contre tel ou tel type de trafic). Dans tous les cas, vu les conséquences de la publication de ces mesures, le régulateur va devoir s'assurer qu'elles sont précises, significatives et reproductibles.

Il existe plusieurs façons de faire ces mesures : on peut utiliser par exemple un panel d'utilisateurs supposés représentatifs, et installer chez eux un équipement de mesure active, qui signale ce qu'il a obtenu à un serveur central. C'est ainsi que fonctionne SamKnows (ou bien un autre système, non utilisé par le régulateur, les sondes Atlas). Une autre solution, non mentionnée par notre RFC, est de mettre les sondes de mesure, non pas chez les utilisateurs (où il est très difficile de s'assurer qu'elles sont branchées correctement, et où elles peuvent rentrer en concurrence avec le trafic normal de l'utilisateur) mais dans des locaux spécialisés, loués à cette fin. C'est ce que fait l'ARCEP pour ses mesures de l'accès à l'Internet en France.

Une des motivations, pour le régulateur, est de déterminer les violations de la neutralité de l'Internet, afin de savoir s'il est utile de prendre des mesures légales ou autres, pour rétablir cette neutralité. Déterminer, par des mesures actives, si certains services réseau ou certaines destinations sont favorisés ou au contraire défavorisés n'est pas facile (cf. le projet Glasnost et sa publication « Enabling End Users to Detect Traffic Differentiation »). À l'inverse, détecter un blocage complet (par exemple la fermeture du port 25) est plus simple. Le sujet de la neutralité du réseau est, à juste titre, très chaud, et cette demande d'une mesure du phénomène restera sans doute élevée (cf. les règles du BEREC).

La section 5 de notre RFC se penche ensuite sur des détails pratiques dans la mise en œuvre de ces mesures. On va donc avoir N sondes qui font faire des mesures et un serveur central qui collectera les mesures (ce qui nécessitera un protocole de communication, de préférence sécurisé, entre les sondes et ce serveur). Les mesures seront répétées automatiquement et/ou pourront être activées à la demande (par exemple pour déboguer un problème précis). Une fois téléversés dans le serveur, les résultats des mesure devront être analysés (et ce sont parfois d'assez gros fichiers). L'analyse, quoique non couverte dans ce RFC, est également une source de risques. Comme dit l'adage « les chiffres, on leur fait dire ce qu'on veut ». Par exemple, le comité technique de l'ARCEP qui était chargé de superviser les décisions techniques pour le programme de mesure a eu à étudier des questions délicates comme la suppression de mesures aberrantes.

De nombreux choix pratiques vont ensuite se poser. Par exemple, la sonde active doit-elle être faite avec du matériel spécialisé (c'est le cas de SamKnows, de la mesure ARCEP, ou des RIPE Atlas) ou bien avec du logiciel que les utilisateurs téléchargeront (comme Grenouille ou Netalyzr). Ces sondes spécialisées sont plus coûteuses, compliquées à déployer (on ne peut pas en mettre partout, il faut des critères de sélection, etc) mais plus fiables que la machine de M. Michu, probablement bourrée de virus qui la ralentissent, et qui n'est pas forcément allumée en permanence. (Une autre différence vient du fait que la sonde spécialisée peut être branchée immédiatement après le routeur, s'épargnant ainsi d'utiliser un LAN peu fiable et irrégulier.) Dans les deux cas, il faudra se demander si l'échantillon est vraiment représentatif ou si l'auto-sélection plus ou moins grande des utilisateurs a trop biaisé les résultats.

Enfin, la section 7 de notre RFC se penche sur les problèmes de sécurité, notamment de protection de la vie privée (RFC 6973). Parmi les risques, si on crée une infrastructure de mesures actives, on a fabriqué un gentil botnet. Si un méchant peut en prendre le contrôle, il peut l'utiliser pour des attaques par déni de service réparties. (C'est une des raisons pour lesquelles l'exécution de mesures par les sondes Atlas, ouverte au public, est soumise à la dépense d'un certain nombre de crédits.) Toujours en cas de mesures actives, les sondes peuvent potentiellement balayer des réseaux internes qui ne seraient normalement pas accessibles de l'Internet (c'est pour cela que les Atlas ne peuvent pas tester les adresses du RFC 1918, car elles pourraient alors être utilisées pour la reconnaissance du réseau local où elles sont situées). Si les sondes ont des capacités de collecte passive, un méchant peut les utiliser comme « boîtes noires » d'espionnage des réseaux sur lesquels elles sont connectées. Il est donc nécessaire de ne pas fournir un accès illimité à ces sondes. Elle doivent n'être accessibles qu'à leur contrôleur, après authentification forte, et, si elle peuvent exécuter des mesures choisies par les utilisateurs (cas des sondes Atlas), ces mesures doivent être limitées (ainsi, les 1es Atlas ne peuvent pas lancer de téléchargement HTTP depuis un URL quelconque).

Dans le cas de mesures comparatives (« le FAI X est 20 % plus rapide que le FAI Y »), un autre risque de sécurité est celui de triche. Un attaquant qui contrôlerait, au moins partiellement, le système, risquerait de pouvoir fausser les résultats et favoriser un FAI par rapport aux autres. Là encore, de bonnes pratiques de sécurité sont nécessaires. Il y a enfin des attaques plus subtiles, comme d'identifier les lignes où des mesures sont faites, et les favoriser, obtenant ainsi de meilleurs résultats.


Téléchargez le RFC 7536


L'article seul

RFC 7525: Recommendations for Secure Use of TLS and DTLS

Date de publication du RFC : Mai 2015
Auteur(s) du RFC : Y. Sheffer (Intuit), R. Holz (TUM), P. Saint-Andre (&yet)
Première rédaction de cet article le 6 mai 2015


Le protocole de sécurité TLS sécurise aujourd'hui, par la cryptographie, un grand nombre de communications par l'Internet. Le protocole et ses mises en œuvre dans des bibliothèques comme OpenSSL ont eu plusieurs failles, réparées au fur et à mesure. Mais les plus grosses failles restent dans l'utilisation pratique de TLS : programmeurs et administrateurs systèmes font des erreurs qui affaiblissent la sécurité de TLS. Ce RFC, le deuxième du groupe UTA (utilisation de TLS par les applications) résume les bonnes pratiques qui devraient être suivies en matière de sécurité pour que TLS atteigne complètement ses objectifs.

TLS est normalisé dans le RFC 5246. Ce RFC documente la version 1.2 et la 1.3 est en cours de normalisation. Il est surtout connu pour sa sécurisation de HTTP, nommée HTTPS. Mais il sert aussi pour sécuriser SMTP, XMPP, IMAP, etc. TLS lui-même ne marche que sur TCP mais il a un équivalent pour UDP, nommé DTLS, et normalisé dans le RFC 6347. Si un attaquant veut casser la protection qu'offre TLS (par exemple pour accéder au contenu en clair d'une communication normalement chiffrée), il peut viser (le RFC 7457 donne une bonne liste)  :

  • Le protocole lui-même. Ainsi, SSL v3, un précurseur de TLS, avait une faille de conception qui permettait l'attaque Poodle. Les failles du protocole, par définition, sont indépendantes d'une mise en œuvre particulière de TLS.
  • Les algorithmes cryptographiques utilisés. TLS a la propriété d'« agilité cryptographique » qui fait qu'il n'est pas lié à un algorithme particulier mais offre un choix. Cela permet, au fur et à mesure des progrès de la cryptanalyse, de changer d'algorithme. Par exemple, les algorithmes AES-CBC (RFC 3602) et RC4 (RFC 7465) ont tous les deux montré des faiblesses sérieuses, ce qui fait que leur utilisation dans TLS est découragée. La liste des algorithmes possibles dépend de la bibliothèque TLS utilisée mais aussi de la configuration du client et du serveur TLS. Pour retirer un algorithme désormais trop faible, comme RC4, on peut donc agir dans le logiciel (en retirant le code correspondant) ou dans la configuration, en supprimant l'algorithme de la liste acceptée.
  • TLS est mis en œuvre dans des bibliothèques logicielles qui, comme tous les logiciels, ont des bogues. Cette fois-ci la faille est spécifique à une mise en œuvre donnée et la correction est de mettre à jour le logiciel, une fois la version corrigée sortie. Ce fut le cas pour la faille Heartbleed, spécifique à OpenSSL, ou de la faille goto fail, spécifique à Apple.
  • Même si le protocole est parfait, n'utilisant que des algorithmes cryptographiques incassés, et programmé sans une bogue, des failles de sécurité peuvent quand même surgir si TLS est utilisé imprudemment. Par exemple, si une application utilise TLS en ayant débrayé (ou pas activé) la vérification du certificat, TLS peut être contourné via une attaque de l'Homme du Milieu. L'article « The most dangerous code in the world: validating SSL certificates in non-browser software » en donne plusieurs exemples.

Bref, l'analyse de sécurité de TLS est complexe et on voit pourquoi il faut se méfier comme de la peste des résumés journalistiques qui annoncent une faille TLS alors qu'il ne s'agissait que d'une bogue dans une bibliothèque.

Le RFC 7457 décrivait déjà les failles, avec plein d'exemples. Notre nouveau RFC se concentre sur les recommandations. Il définit un plancher de sécurité (pas un plafond : on peut toujours être plus strict que ce que définit le RFC). D'autre part, le RFC prévient évidemment que ces recommandations évolueront avec le temps.

Le cœur de notre RFC n'est donc pas l'analyse des risques, mais les recommandations pratiques (sections 3 et suivantes). D'abord, sur la version du protocole :

  • Ne jamais utiliser SSL, que ce soit la v2 (RFC 6176) ou la v3. Décrite dans le RFC 6101, cette dernière a encore bien trop de trous (comme celui qui permet POODLE) et ne gère pas des extensions essentielles à la sécurité comme celle du RFC 5746.
  • N'utiliser TLS 1.0 (RFC 2246) que si on n'a pas le choix. Publié il y a seize ans (!), il n'accepte pas certains algorithmes de cryptographie moderne et il a d'autres faiblesses.
  • TLS 1.2 doit être privilégié. Notons que les algorithmes cryptographiques recommandés dans notre RFC ne sont disponibles qu'avec cette version 1.2.

Si un client TLS a un mécanisme de repli (on tente de se connecter avec la version N, ça échoue, on ré-essaie avec N-1, ce qui se nomme la downgrade dance), on ne doit jamais se replier vers SSL. Autrement, un Homme du Milieu aurait juste à faire échouer la connexion initiale, pour garantir l'utilisation d'un protocole faible (notez que le RFC 7507 fournit une solution contre ce repli). Aux dernières nouvelles, seuls 3 % des serveurs Web TLS/SSL de l'Internet étaient SSL-seulement.

Lorsque client et serveur essaient de se connecter avec TLS mais acceptent des connexions sans TLS, des attaques actives peuvent forcer un repli vers la connexion sans TLS, en clair et pas sécurisée du tout (la négociation de TLS n'est pas elle-même protégée par TLS). Pour éviter cela, client et serveur devraient insister sur l'utilisation de TLS et utiliser des techniques comme HSTS (RFC 6797) pour signaler qu'on sait faire du TLS et qu'il ne faut pas essayer en clair.

Plusieurs attaques sont facilitées par l'utilisation de la compression (RFC 5246, section 6.2.2), comme CRIME. Il est recommandé de la couper, sauf si on est sûr que le protocole applicatif qui utilise TLS n'est pas vulnérable à ces attaques.

L'établissement d'une session TLS nécessite d'échanger plusieurs paquets, ce qui prend du temps. Pour limiter ce problème, TLS dispose d'un mécanisme de reprise de session (RFC 5246). Ce mécanisme doit être autant protégé que le serait une session normale. Par exemple, dans le cas du RFC 5077, si on chiffrait le ticket utilisé pour la reprise de session avec un algorithme bien plus faible que celui utilisé dans la session elle-même, un attaquant pourrait choisir de tenter une « reprise » d'une session inexistante, court-circuitant ainsi l'authentification. À noter aussi que ce mécanisme de reprise de session peut annuler l'effet de la forward secrecy : si l'attaquant met la main sur les tickets, il peut déchiffrer les sessions qu'il a enregistré (cf. section 3.4 de notre RFC). Il faut donc changer les clés des tickets de temps en temps.

L'extension de renégociation sécurisée du RFC 5746 doit être disponible (ou, sinon, il faut couper la renégociation).

Une dernière recommandation générale porte sur SNI (RFC 6066, section 3). Bien que cela n'affecte pas directement la sécurité, cette extension est recommandée, pour des protocoles comme HTTPS, car elle permet des politiques de sécurité plus souples et donc plus implémentables (comme d'avoir un certificat par site Web).

La section 3 de notre RFC portait sur des recommandations générales. La section 4 s'attaque aux algorithmes de cryptographie (cipher suites). Ceux-ci s'usent avec le temps, quand les progrès de la cryptanalyse exposent leurs failles. Cette usure se fait à un rythme très variable : certains algorithmes durent depuis longtemps, d'autres ont été éliminés rapidement. Mais aucun algorithme n'est éternel et voilà pourquoi il est nécessaire de séparer le protocole des algorithmes, ce qu'on nomme l'« agilité cryptographique ». Notre RFC recommande donc de ne pas utiliser l'algorithme NULL, qui ne chiffre pas du tout (pas besoin de cryptanalyse pour le casser...) et n'a d'intérêt que pour les tests et le débogage. Plus récemment, les progrès de la cryptanalyse, documentés dans le RFC 7465, ont montré que RC4 ne devait pas être utilisé non plus. Le problème des algorithmes trop faibles est aggravé par l'action des États qui veulent pouvoir espionner les communications et qui imposent, dans certains cas, l'utilisation d'algorithmes dont les faiblesses sont connues. C'est le cas aux États-Unis des algorithmes dit export (car ils étaient les seuls légalement exportables à une époque). Si ces algorithmes sont présents, l'attaque FREAK permettra à un attaquant actif de les sélectionner, flanquant en l'air toute la sécurité de TLS.

Les révélations de Snowden ont montré que la NSA (et peut-être d'autres organisations) enregistre de nombreuses communications chiffrées qu'elle ne sait pas décrypter. L'idée est que si, un jour, on met la main sur la clé privée (par perquisition physique, piratage de l'ordinateur à distance ou tout autre méthode), on pourra alors déchiffrer et certaines de ces communications seront encore intéressantes. Pour éviter cela, notre RFC conseille de privilégier les algorithmes qui mettent en œuvre la forward secrecy comme la famille DHE.

Quels algorithmes restent-ils après ces nombreuses éliminations ? Notre RFC en mentionne quatre (après une discussion longue et acharnée à l'IETF) : TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 et TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384. Ils utilisent DHE ou ECDHE, avec RSA, AES en mode GCM (voir RFC 5288 section 6, sur la sécurité de ce mode) et SHA-2. Ils font tous du chiffrement intègre (authenticated encryption, RFC 5116). Tout logiciel TLS devrait être configuré pour préferer ces algorithmes (cf. « Applied Crypto Hardening »).

Attention, notre RFC parle uniquement de préférer ces algorithmes, pas de les imposer. Pour permettre l'interopérabilité, TLS a en effet des algorithmes obligatoires, qui doivent être mis en œuvre dans chaque bibliothèque TLS. C'est le cas de TLS_RSA_WITH_AES_128_CBC_SHA, obligatoire mais pas le plus fort, loin de là. Mais on peut compter sur lui puisqu'il est obligatoire, contrairement aux quatre algorithmes cités plus haut, qui peuvent ne pas être présents. Il peut donc être nécessaire d'arbitrer entre interopérabilité et sécurité...

Ce RFC a également des recommandations sur les clés publiques utilisées dans les certificats : 2 048 bits au moins en RSA (ce qui est imposé par la plupart des AC depuis un certain temps, c'est le cas de CAcert, par exemple), et SHA-256 pour condenser la clé (et plus SHA-1).

Un petit mot en passant sur un point abordé dans la section 5. Celle-ci concerne l'« applicabilité » des recommandations faites ici. Cette applicabilité est très large, quasiment tous les usages de TLS sont concernés. Il existe un usage fréquent de TLS, parfois appelé « chiffrement opportuniste » (RFC 7435) où une des parties qui communiquent va essayer de faire du TLS mais, si cela ne marche pas (par exemple parce que l'autre partie ne gère pas le chiffrement), on se rabat sur une communication en clair. Dans ce contexte, certaines des recommandations du RFC peuvent être trop strictes. Par exemple, on a vu qu'il ne fallait pas utiliser RC4, trop faible cryptographiquement. Si on prend au pied de la lettre cette recommandation, qu'une des deux parties ne connait que RC4 et qu'on est dans un contexte de chiffrement opportuniste, on pourrait arriver à ce résultat paradoxal que, RC4 étant refusé, on communique en clair, ce qui est certainement bien pire que le plus mauvais des algorithmes de cryptographie. Il peut donc être nécessaire de dévier des recommandations de notre RFC 7525.

Enfin, pour terminer ce RFC déjà riche, une section 6 consacrée à divers problèmes de sécurité qui n'avaient pas été traités avant. D'abord, la nécessité, lorsqu'on vérifie un certificat, de vérifier également que le nom du serveur, dans le certificat, corespond au nom auquel on voulait se connecter. Cela parait évident mais ce n'est pas toujours fait par la bibliothèque qu'on utilise (cf. mon exposé à Devoxx - et ses transparents - pour des exemples.) Il peut donc être utile que l'application fasse la validation elle-même, sans quoi un attaquant actif peut détourner le trafic chiffré, de manière triviale. La section 3 du RFC 2818 et le RFC 6125 détaillent ce qu'il faut exactement valider. Bien sûr, pour que cette validation ait un sens, il faut que le nom du serveur ait lui-même été obtenu de manière sûre. Si on a cliqué sur un lien https://... dans un message de hameçonnage, vérifier que le nom est correct n'aide pas tellement (« oui, c'est bien secure-serious-bank.ab451e239f.ru »). Idem si le nom vient d'une requête DNS (par exemple de type MX) non sécurisée par DNSSEC.

J'ai déjà parlé plus haut de la forward secrecy, une propriété qui fait que le vol des clés privées a posteriori est inutile, même pour un attaquant qui avait enregistré les communications chiffrées. Dans la vie, ce vol peut arriver pour des tas de raisons, machines jetées à la poubelle sans les avoir effacées, et récupérées par un indiscret, clés trop faibles face à la force brute (cf. « Mining Your Ps and Qs: Detection of Widespread Weak Keys in Network Devices »), clé générée par un tiers (dans le « cloud ») et ensuite obtenue par piratage, attaque violente et/ou légale contre les administrateurs système pour obtenir la clé, et toutes les autres méthodes d'accès aux clés privées qui peuvent exister. La forward secrecy n'empêche pas ces attaques mais elle empêche l'attaquant d'exploiter son succès. Elle s'obtient en général en faisant un échange Diffie-Hellman. Dans le contexte de la sécurité de TLS, le principal problème est que beaucoup d'algorithmes utilisés ne permettent pas le forward secrecy, et que les autres, les bons, ne sont pas sélectionnés en priorité.

L'authentification du serveur TLS (on peut aussi authentifier le client mais c'est plus rare) repose presque toujours sur un certificat X.509. Si la clé privée associée au certificat est volée, le mécanisme de sécurité de X.509 est la révocation (RFC 5280, section 3.3). On sait que ce mécanisme nécessite une bonne connexion Internet, et est peu fiable : les listes de certificats révoqués, à distribuer partout, ne passent pas à l'échelle, le protocole OCSP (RFC 6960) est souvent bloqué (et il pose de toute façon des problèmes de passage à l'échelle et de vie privée), menant les clients à ignorer les échecs OCSP, etc. Il existe des solutions partielles (section 8 du RFC 6066, RFC 6961, RFC 6698) mais pas assez déployées.

Si vous voulez lire des recommandations en français sur la configuration de TLS, il y a deux guides ANSSI qui sont en rapport avec ce RFC, le RGS pour les algorithmes de cryptographie, et le guide pour la sécurité des sites Web, avec des recommandations précises pour OpenSSL (SSLCipherSuites Apache).

Et pour terminer sur une note personnelle, si vous regardez la configuration HTTPS de mon blog, elle est actuellement perturbée par deux sérieuses bogues du module GnuTLS d'Apache : #754960 et #642357.

Merci à Manuel Pégourié-Gonnard pour une relecture attentive qui a permis de trouver plusieurs erreurs. D'autres bonnes lectures :


Téléchargez le RFC 7525


L'article seul

RFC 7542: The Network Access Identifier

Date de publication du RFC : Mai 2015
Auteur(s) du RFC : DeKok, Alan (FreeRADIUS)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF radext
Première rédaction de cet article le 2 mai 2015


Ce nouveau RFC normalise le concept d'identificateur pour l'accès au réseau (NAI pour Network Access Identifier). Cet identificateur est traditionnellement utilisé lors d'un accès authentifié au réseau, pour indiquer la personne ou l'entité qui veut se connecter (avec un mot de passe, ou autre information de créance, pour s'authentifier). Le NAI a une forme qui ressemble aux adresses de courrier ou XMPP. Par exemple, un NAI peut être marie@example.com ou jean_dupont@labs.potamochère.fr. Contrairement au traditionnel login ou nom d'utilisateur, le NAI inclut l'indication d'un domaine (ou plutôt royaume) d'origine, permettant au point d'accès d'accepter des utilisateurs issus d'un autre domaine. Le NAI permet donc des accès fédérés. Ce concept, en dépit de ce nom, est désormais utilisé pour bien d'autres choses que l'accès au réseau. Notre RFC remplace la norme précédente, le RFC 4282, notamment en développant bien plus l'internationalisation (un NAI n'est pas forcément en ASCII). Bienvenue dans le monde merveilleux (et très bordélique) du AAA.

Initialement, la principale motivation pour le NAI (Network Access Identifier) était le roaming : un utilisateur abonné au FAI X se déplace dans une zone où X ne fournit pas d'accès mais a un accord avec le FAI Y qui, lui, est présent. Pour éviter de recopier la base d'utilisateurs de X dans celle de Y, l'utilisateur présente un NAI qui indique son rattachement à X (son home domain). Le point d'accès de Y sait alors qu'il doit demander l'authentification à X. Une fois que c'est fait, on peut donner l'accès via Y (le visited domain). C'est par exemple ainsi que fonctionne la fédération Eduroam. (L'auteur du RFC est d'ailleurs l'auteur et le mainteneur de FreeRADIUS, un des logiciels les plus utilisés pour cette tâche. Le protocole RADIUS est normalisé dans le RFC 2865.)

Le NAI permet donc à des FAI purement régionaux d'accueillir des clients d'autres régions du pays, à des FAI nationaux d'accueillir des clients d'autres pays, à des hotspots WiFi de servir plusieurs FAI avec la même infrastructure, etc. Une description de l'usage des NAI dans des situations de roaming est donné dans le RFC 2194.

On l'a vu, le NAI peut servir à bien d'autres choses que l'accès au réseau. Sa définition est donc indépendante du protocole qui va l'utiliser (le NAI n'est pas spécifique à RADIUS.) Par contre, son encodage effectif dépendra du protocole (par exemple, il faudra assurer l'échappement de certains caractères, le NAI sophie@internautique.fr deviendra sophie@internautique%2Efr dans un URL). À noter que le NAI, quoique répandu, n'est pas le format unique d'identificateur sur le réseau. Certains protocoles existants ont un autre format, et certains permettent le NAI et d'autres formats. Pour les protocoles futurs, notre RFC recommande qu'ils adoptent le NAI, pour uniformiser les identificateurs. C'est déjà le cas de 3GPP dont la norme « TS 23.003 Numbering, addressing, and Identification (Release 12) » précise que l'identificateur est un NAI comme 234150999999999@ims.mnc015.mcc234.3gppnetwork.org.

Attention, le but est d'uniformiser le format, pas les identificateurs. Le NAI n'implique pas que chaque utilisateur ait un identificateur et un seul ! Cela poserait, entre autres, de sérieux problèmes liés à la vie privée. Le RFC recommande d'ailleurs de permettre des identificateurs anonymes (pseudonymes, plutôt) dès qu'ils sont visibles publiquement.

Un peu de terminologie nécessaire pour comprendre le NAI figure en section 1.1. Notez le NAS (Network Access Server) qui est la première machine à laquelle les utilisateurs se connectent pour avoir un accès à l'Internet. Pour les technologies PPTP et L2TP, ce sera le concentrateur d'accès. En WiFi, ce sera le point d'accès (hotspot). Lorsque l'utilisateur envoie son NAI, c'est le NAS qui extrait le domaine de l'utilisateur et relaie (par exemple en RADIUS) la demande d'authentification à ce domaine.

Une bonne partie des changements depuis le RFC 4282 avait été motivé par l'expérience d'Eduroam. Par exemple, la section 2.1 du RFC 4282 demandait que le nom de domaine soit uniquement composé de lettres ASCII, de chiffres et de tirets. Pour les IDN, l'idée était d'utiliser la forme Punycode. Celle-ci est peu pratique, et souvent inutile puisque plusieurs protocoles utilisant les NAI (comme RADIUS ou comme l'EAP du RFC 3748) ne sont pas limités à l'ASCII et recommandent UTF-8 comme encodage des chaînes de caractères (cf. section 3.2). Le RFC 4282 avait d'autres problèmes d'internationalisation comme d'exiger une normalisation des chaînes (qui peut rentrer en conflit avec des exigences locales) ou comme d'exiger des opérations qui soient dépendantes de la langue (que le NAS et autres équipements intermédiaires ne connaissent pas forcément, et ne savent pas toujours gérer). D'autre part, le RFC 4282 interdisait l'utilisation de points de code Unicode non affectés. Cela empêchait le déploiement de toute nouvelle écriture puisque, au début, tous les équipements réseau auraient considéré ces nouveaux caractères comme non affectés ! En pratique, d'ailleurs, aucun équipement réseau n'a mis en œuvre les recommandations d'internationalisation du RFC 4282. Le roaming international se développant, il était temps de changer ces recommandations irréalistes.

La section 2 de notre RFC présente la définition formelle du NAI. Il est en UTF-8, normalisé NFC. Il est divisé en deux parties, le nom d'utilisateur, et le royaume (realm). Ces deux parties sont séparées par un @. Le nom d'utilisateur peut être composée de lettres (Unicode, pas uniquement ASCII), de chiffres et de quelques symboles. fred=?#$&*+-/^smith est donc un nom d'utilisateur valable. Le royaume ressemble à un nom de domaine, avec ses composants séparés par des points mais n'en est pas forcément un. Un exemple de NAI est donc eng%geneviève@example.neteng%geneviève est le nom d'utilisateur et le domaine (royaume) est example.net. (La grammaire formelle est en section 2.2.) Un nom de royaume ne doit pas être réduit à un seul composant donc maire@paris n'est pas un NAI même si le TLD .paris existe. En effet, certains équipements considèrent qu'un royaume d'un seul composant est un sous-royaume du royaume local (donc, chez le FAI example.net, le NAI maire@paris serait interprété maire@paris.example.net).

Le royaume peut être en Unicode, bien des protocoles AAA autorisent à la transporter nativement et il est donc désormais déconseillé d'encoder en Punycode (RFC 3492). Ainsi, le NAI faïza@café.example s'écrit bien ainsi, et pas faïza@xn--caf-dma.example. (Il semble bien que c'est ce que faisaient déjà tous les équipements qui géraient des noms de royaumes en Unicode, malgré ce que disait le RFC 4282.)

Il n'y a pas de limite de taille aux NAI, juste la recommandation de pouvoir gérer au moins 72 octets et, de préférence, 253. (Attention, en UTF-8, un caractère ne fait pas forcément un octet.) Les NAI étant utilisés dans des protocoles très différents, on a parfois des surprises. Ainsi, l'attribut User-Name de RADIUS exige d'accepter jusqu'à 63 octets mais ne dit rien au delà (RFC 2865, section 5.1). En revanche, le protocole concurrent Diameter (RFC 6733) impose à ses mises en œuvre des noms d'utilisateur jusqu'à 16 777 207 octets. Si on est sûr de toujours passer par Diameter (ce qui est très peu probable), on peut utiliser des NAI très longs.

Le nom d'utilisateur est opaque aux autres royaumes (comme pour le courrier électronique même si beaucoup d'ignorants violent cette règle). Par exemple, dans le eng%geneviève@example.net donné plus haut, on peut soupçonner que le nom d'utilisateur indique un routage interne (vers le service d'ingéniérie puis vers l'utilisatrice Geneviève) mais on ne peut pas en être sûr, chaque royaume a ses propres règles. On doit donc traiter le nom d'utilisateur comme un tout, sauf si on est le home domain. Parfois, des protocoles transmettent juste le nom de royaume, faisant passer le nom d'utilisateur dans un canal plus sûr, afin de préserver la vie privée (cf. le TTLS du RFC 5281). L'habitude dans ce cas est de remplacer le nom d'utilisateur par anonymous mais c'est désormais déconseillé, il vaut mieux un nom vide (@internautique.fr est donc un NAI valide). Avec les autres protocoles, notre RFC recommande d'utiliser des noms d'utilisateurs éphémères, pour la vie privée, mais c'est très rarement le cas aujourd'hui.

On a vu qu'on pouvait utiliser des caractères Unicode aussi bien pour le nom de royaume que pour celui de l'utilisateur. Pour les noms d'utilisateur, les règles se basent sur celles du RFC 6532. Pour le nom de royaume, on est restreint aux caractères utilisables dans un nom de domaine (RFC 5891). L'éventuelle traduction en UTF-8 (au cas où l'utilisateur ait rentré des caractères dans un autre encodage) et la normalisation en NFC doivent être faites au tout début, lorsqu'on est encore proche de l'utilisateur et qu'on sait ce qu'il veut (on connait sa langue, par exemple, ce qui n'est pas le cas des équipements réseau intermédiaires ; ces équipements intermédiaires ont tout intérêt à ne pas tripoter les NAI). Ceci dit, cette situation idéale (les terminaux normalisent, les intermédiaires ne changent rien) n'est pas respectée aujourd'hui. Il existe des terminaux qui ne normalisent pas, injectant ainsi des chaînes non-UTF8 dans le système d'authentification. Le RFC note donc que le principe « les terminaux normalisent, les intermédiaires ne changent rien » doit parfois être violé. « The suggestion in the above sentence contradicts the suggestion in the previous section. This is the reality of imperfect protocols. » Ce point a été l'un des plus disputés lors de l'écriture de ce RFC.

Une fois le NAI défini, notre RFC s'attaque au routage des requêtes (section 3). Typiquement, le système d'authentification et autorisation (AAA) extrait le royaume du NAI et s'en sert comme clé pour une table où sont stockés les royaumes qu'on connait et avec qui on a une relation d'acceptation de leurs utilisateurs. Si le royaume n'est pas trouvé dans la table, on refuse l'utilisateur. S'il est trouvé, le contenu de la table nous dira le serveur à interroger pour ce royaume (ainsi que des informations comme le secret partagé RADIUS, le port, etc). Attention, la sémantique des noms de royaume n'est pas forcément connue et, par exemple, les équipements réseau ne savent pas si on peut les consulter de manière insensible à la casse. Parfois, ça marche (rappelez-vous le paragraphe précédent : le monde de l'AAA est imparfait...) Si on ne trouve pas un nom de royaume dans la table, on peut router sur une partie du royaume, par exemple utiliser example.net si le royaume france.example.net n'a pas été trouvé. Attention, ce n'est valable que si le nom raccourci reste un nom valide (net ne le serait pas, vu la prohibition des noms d'un seul composant).

Les NAI ressemblent aux adresses de courrier électronique et certaines normes sont communes aux deux (comme le RFC 6532) mais attention, les règles ne sont pas exactement les mêmes. Toute adresse de courrier n'est donc pas forcément un NAI valide. En pratique, les deux se ressemblent suffisamment pour que beaucoup de FAI utilisent l'adresse de courrier du client comme son NAI.

On a vu que l'AAA était un monde très riche, ancien, et qui contient donc plein de choses surprenantes et de traditions historiques. La section 3.3.1 contient quelques exemples rigolos, avec les recommandations actuelles. Par exemple, les utilisateurs de RADIUS ont longtemps utilisé du routage explicite, où une partie du NAI contenait d'autres instructions de routage (chezmoi.example!utilisateur@fai.example...). Cette méthode (citée par le RFC 4282, section 2.7) s'est avérée très fragile, cassant dès qu'on change le réseau. RADIUS n'ayant pas de protocole de routage (qui diffuserait automatiquement les informations de routage), il fallait informer beaucoup de systèmes en cas de changement. (Diameter - RFC 5729 - ou 3G sont des cas différents car ils utilisent un protocole de routage.)

Le NAI étant en général utilisé dans un contexte de sécurité (point d'entrée pour une authentification), notre RFC consacre une section, la 4, à ces problèmes. Par exemple, si le protocole transporte le nom d'utilisateur en clair (c'est le cas de RADIUS), un écoutant sur le trajet peut apprendre des noms d'utilisateurs existants. Pour empêcher cela, il faut protéger (RADIUS avec IPsec, RFC 3579, Diameter avec TLS, RFC 6733). Si on utilise plusieurs protocoles qui tous se servent de NAI, et que l'utilisateur n'a qu'un seul NAI, un observateur pourra relier entre elles ces différentes utilisations. D'où l'intérêt de ne pas transporter les NAI en clair. Dans le futur, il serait encore mieux d'avoir des NAI éphémères, changés de temps en temps.

Le monde de l'accès réseau étant compliqué, il y a également des risques liés au fait qu'un identificateur peut être interprété d'une façon par un protocole et d'une autre façon par un autre protocole.

Dernier problème des NAI à régler, celui de l'avitaillement (création, maintenance, suppression) des identificateurs. Les noms de royaumes ressemblent à des noms de domaine pour éviter d'avoir à créer une nouvelle infrastructure d'avitaillement. Ainsi, si on est déjà titulaire du domaine lesrépublicains.fr, on n'a pas besoin d'autre chose pour créer des NAI comme nicolas@lesrépublicains.fr, tout en étant sûr de leur unicité, sur laquelle repose le routage. Bien qu'on puisse toujours, techniquement parlant, prendre un nom, sans l'enregistrer comme nom de domaine, pour faire des NAI, cette pratique est interdite. Par contre, l'usage du DNS n'est pas obligatoire et ces noms n'ont donc pas besoin d'être publiés. Si Diameter permet d'utiliser le DNS pour localiser un serveur d'authentification, les autres protocoles n'ont pas forcément cette possibilité : RADIUS repose sur des configurations statiques.

L'annexe A résume les (importants) changements depuis le RFC 4282, notamment :

  • UTF-8 autorisé dans le nom de royaume,
  • Abandon de Punycode.

Ces deux changements sont déjà largement déployés dans les équipements qui gèrent des NAI en Unicode.


Téléchargez le RFC 7542


L'article seul

Assez des URL spécifiques pour les clients « mobiles »

Première rédaction de cet article le 28 avril 2015


Un certain nombre de sites Web (pas tous, heureusement) redirigent les clients qui semblent être des appareils mobiles vers un autre URL, spécifique aux mobiles. C'est une très mauvaise idée.

En général, la redirection se fait dès que le serveur Web croit, à tort ou à raison, qu'il voit passer un appareil mobile, par exemple un phono sapiens. On peut le voir avec wget, en faisant varier le champ HTTP User-Agent: (RFC 7231, section 5.5.3) :

% wget --user-agent="Mozilla/5.0 (Android; Mobile; rv:37.0) Gecko/37.0 Firefox/37.0" http://fr.wikipedia.org/wiki/Virgule_d%27exclamation 
--2015-04-27 17:29:04--  http://fr.wikipedia.org/wiki/Virgule_d%27exclamation
Resolving fr.wikipedia.org (fr.wikipedia.org)... 91.198.174.192, 2620:0:862:ed1a::1
Connecting to fr.wikipedia.org (fr.wikipedia.org)|91.198.174.192|:80... connected.
HTTP request sent, awaiting response... 302 Found
Location: http://fr.m.wikipedia.org/wiki/Virgule_d%27exclamation [following]
--2015-04-27 17:29:04--  http://fr.m.wikipedia.org/wiki/Virgule_d%27exclamation
Resolving fr.m.wikipedia.org (fr.m.wikipedia.org)... 91.198.174.204, 2620:0:862:ed1a::1:c
Connecting to fr.m.wikipedia.org (fr.m.wikipedia.org)|91.198.174.204|:80... connected.
HTTP request sent, awaiting response... 200 OK
...

On a été redirigé (code de réponse 302, RFC 7231, section 6.4) depuis le bon URL http://fr.wikipedia.org/wiki/Virgule_d%27exclamation vers http://fr.m.wikipedia.org/wiki/Virgule_d%27exclamation (le composant m dans le nom de domaine indiquant une version pour mobile). Avec un User-Agent: qui n'indiquait pas un mobile, on n'était pas redirigé :

% wget --user-agent="Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Firefox/31.0 Iceweasel/31.6.0" http://fr.wikipedia.org/wiki/Virgule_d%27exclamation
--2015-04-27 17:28:31--  http://fr.wikipedia.org/wiki/Virgule_d%27exclamation
Resolving fr.wikipedia.org (fr.wikipedia.org)... 91.198.174.192, 2620:0:862:ed1a::1
Connecting to fr.wikipedia.org (fr.wikipedia.org)|91.198.174.192|:80... connected.
HTTP request sent, awaiting response... 200 OK
...

On trouve de telles redirections dans Wikipédia mais aussi les Échos, Rue89, etc.

Ces URL sont utilisés pour transmettre un contenu différent selon les clients. Les problèmes que posent ces URL spécifiques aux mobiles sont les suivants :

  • Ils violent un principe de base du Web, qui est que l'URL est la même pour tout le monde, afin qu'on puisse la transmettre, la passer à quelqu'un d'autre, et que l'affichage suive automatiquement. Le Web a été conçu pour cela. Il n'y a aucune bonne raison technique de faire du contenu spécifique pour mobile.
  • Il n'y a pas un seul type de « mobile » mais des tas de modèles, avec notamment des tailles d'écran très différentes. Même si on pense qu'il faut des contenus différents selon les machines, ces URL spécifiques ne dispensent donc pas le webmestre d'adapter le contenu à chaque écran.
  • Ces URL empêchent d'utiliser une des fonctions de base du Web, passer un URL d'un utilisateur à l'autre (par XMPP, courrier, Twitter, etc). En effet, si je consulte un site sur un smartphone, que je l'envoie en XMPP et que le destinataire est sur un ordinateur de bureau, il verra une version inadaptée. (Rue89 redirige depuis le site mobile vers le site « immobile », mais Wikipédia ne le fait pas.)
  • Si on stocke les URL dans une base de données, à des fins de documentation ou de constitution d'une base de connaissances, on aura des doublons puisque le système croira qu'il s'agit de deux ressources différentes. Ainsi, SeenThis affiche un joli petit triangle noir devant chaque URL qui a déjà été cité mais il ne peut plus le faire si on utilise l'URL « mobile » et l'URL « normal » pour la même ressource.
  • La redirection nécessite une nouvelle connexion TCP et une nouvelle requête, donc augmente la latence, alors que les mobiles ont justement souvent la plus mauvaise connexion.

Est-ce qu'au moins on peut corriger à la main l'URL qu'on voulait partager ou enregister ? Chez Wikipédia, c'est relativement facile, le schéma est évident. On retire juste le composant m du nom de domaine, et http://fr.m.wikipedia.org/wiki/Potamoch%C3%A8re redevient http://fr.wikipedia.org/wiki/Potamoch%C3%A8re. Par contre, Rue89 utilise des URL radicalement différents (http://m.rue89.nouvelobs.com/node/257496 est http://rue89.nouvelobs.com/2015/04/23/deconnectes-mal-connectes-les-pauvres-numerique-257496, excellent article, au passage) et empêche donc cette réécriture.

Terminons par un argument d'autorité avec deux excellents textes du W3C contre cette idée d'URL spécifiques aux mobiles. Ces deux articles ont été écrits dans le contexte du TLD .mobi (un échec complet et mérité) : « The ".mobi" Proposal is Inconsistent with Device Independence Principles » et « New Top Level Domains .mobi and .xxx Considered Harmful » (qui couvre en outre bien d'autres sujets et est donc plus difficile à utiliser pour ce problème des URL pour mobiles).

Et si vous voulez un point de vue différent sur ce sujet, il y a cette réflexion.


L'article seul

Qui est le numéro 1 de l'Internet ?

Première rédaction de cet article le 27 avril 2015


Le 23 avril dernier, le gouvernement français annonce qu'il a rencontré « les dirigeants d'internet ». Cela a, à juste titre, beaucoup fait rire, mais pas toujours pour de bonnes raisons. C'est que c'est compliqué de savoir qui dirige (ou pas) l'Internet.

Le communiqué du gouvernement français est en ligne mais a été modifié depuis. Le texte original disait « le Gouvernement mobilise les dirigeants d'internet » et la version modifiée suite aux rires des internautes dit « le Gouvernement mobilise les dirigeants des grands opérateurs de l'internet ». Notez que l'URL, qui reprend le titre du communiqué, n'a pas changé. C'est bien de ne pas l'avoir changé mais, désormais, le titre et l'URL ne sont plus en accord (voilà pourquoi il faut éviter de mettre trop de sémantique dans les URL).

Il y a bien des choses à critiquer dans le communiqué du gouvernement, notamment le ridicule des mouvements martiaux du menton (« le Gouvernement mobilise... ») ou surtout la gravissime faute qu'est la sous-traitance de la censure à des entreprises privées, plus soucieuses d'éviter les problèmes que de défendre la liberté d'expression. Mais les nombreuses critiques du communiqué gouvernemental se sont surtout focalisées sur le titre, comme celle de Numérama. Ce journal constate à juste titre qu'il est ridicule de parler des « dirigeants d'Internet » (et le gouvernement français doit être de cet avis puisqu'il a modifié son texte irréfléchi) car la gouvernance de l'Internet est complexe et ne se réduit pas à une poignée de « dirigeants ».

L'erreur n'est pas innocente, de la part du gouvernement. Celui-ci est en effet complètement perdu devant le mécanisme complexe qu'est l'Internet. Comme le héros du Prisonnier, les ministres passent leur temps à demander « qui est le numéro 1 ? » Ils ne peuvent en effet pas imaginer d'autres systèmes politiques que ce qu'ils ont appris à Sciences Po : un système très hiérarchique, avec une poignée d'acteurs (publics ou privés, peu importe pour eux), quelques dirigeants régnant sur une masse de « fond d'organigramme ». Rien d'étonnant que, perturbés par l'Internet, ils cherchent à toute force à le ramener au seul cas qu'ils connaissent, celui où on discute dans des bureaux feutrés, loin des rumeurs du monde, avec quelques messieurs « responsables ». Numérama a raison de pointer du doigt cette curieuse réduction de l'Internet à « Google, Facebook, Microsoft, Apple et Twitter mais aussi des responsables des principaux fournisseurs d'accès à Internet (dont les membres de l'association des fournisseurs d'accès et de services Internet comme Orange, Bouygues Telecom, SFR) ». Pourquoi ces entreprises privées particulières, et qui a décidé de leur confier l'Internet ? Personne, et surtout pas un processus démocratique. Mais ces entreprises sont toutes prêtes à suivre la voie de la censure privée (Facebook s'y est engagé depuis très longtemps). En façade, les politiciens français aiment se plaindre des GAFA (Google, Apple, Facebook, Amazon), mais ils sont très à l'aise avec cet oligopole de (pour citer Numérama) « gigantesques silos contenant des quantités inouïes de données personnelles, pour le plus grand bonheur des services de renseignement ». Bien plus à l'aise en tout cas qu'avec les millions d'acteurs de l'Internet qui le façonnent au quotidien. Il suffit de voir comment les politiciens français font tout pour détruire les échanges de contenu en pair à pair, encourageant ainsi les utilisateurs à se servir uniquement de quelques gros silos, avec lesquels on pourra ensuite parler.

Mais, si le gouvernement a tort de désigner les GAFA et les telcos comme « dirigeants d'Internet », qui sont alors les vrais dirigeants ? Numérama dérape ici en reprenant le jargon inimitable de l'ICANN et en prétendant que l'Internet serait géré par tout le monde, avec une très large participation. Ce serait en effet idéal mais, contrairement à ce que prétend l'ICANN pour essayer de faire oublier sa très faible légitimité, ce n'est pas le cas. Des entreprises comme les gros telcos, ou comme les GAFA, ont effectivement un pouvoir disproportionné. Si le terme de « dirigeants d'Internet » est exagéré, on ne peut pourtant pas nier, et c'est un gros problème de gouvernance en soi, que l'excessive concentration des échanges dans quelques silos (encouragée, comme on l'a vu, par les gouvernements successifs, que le pair à pair hérisse), entraine forcément un excès de pouvoir chez ces silos.

Et Numérama se contredit ensuite en prétendant avoir trouvé les vrais dirigeants : « ce n'est pas en direction des "GAFA" qu'il fallait se tourner, mais plutôt vers l'ICANN, le forum sur la gouvernance d'Internet (IGF), l'Internet Engineering Task Force (IETF), l'Internet Research Task Force (IRTF), l'Internet Society (ISOC), les registres Internet régionaux, l'ISO 3166 MA (Autorité de Maintenance), le W3C ou encore l'Internet Architecture Board (IAB), les forums de rencontre des opérateurs ainsi que les agences intergouvernementales ». À quelques exceptions près comme les « forums de rencontre des opérateurs », cette liste fait la part belle à des institutions clairement identifiables, justement ce que voudraient Cazeneuve et ses pareils. D'ailleurs, la liste tient du catalogue de Prévert en mêlant des organisations ayant un vrai pouvoir (RIR, ICANN, ISOC), des simples forums de bavardage (IGF), des organisations aux pouvoirs purement techniques et limités (IETF) et de mystérieuses « agences intergouvernementales » (on penserait à l'UIT si elle jouait le moindre rôle dans la gouvernance d'Internet).

Bref, il faut s'y résigner, la gouvernance de l'Internet est complexe, il n'y a pas de numéro 1 (dommage pour les ministres français), mais il n'y a pas non plus de « processus ouverts, bottom->up et multipartiesprenantes », quoi que prétende l'ICANN. Il y a beaucoup d'acteurs, avec des rôles variés et des pouvoirs très différents. Ça le rend difficile à gouverner ? Tant mieux, c'est aussi ce qui assure sa résilience face aux tentatives de contrôle.


L'article seul

RFC 7507: TLS Fallback Signaling Cipher Suite Value (SCSV) for Preventing Protocol Downgrade Attacks

Date de publication du RFC : Avril 2015
Auteur(s) du RFC : B. Moeller, A. Langley (Google)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF tls
Première rédaction de cet article le 25 avril 2015


Le protocole TLS offre un grand nombre de choix : choix de la version, choix des algorithmes cryptographiques, plein d'options... Tous ces choix ne sont pas équivalents en terme de sécurité : les versions anciennes de TLS ont des vulnérabilités absentes des plus récentes, par exemple. Dès qu'un protocole cryptographique a des choix, il y a un risque de sécurité : que l'attaquant tente de perturber la négociation initiale entre les deux parties, pour les amener à choisir les variantes les moins sécurisées, en faisant croire à chacun que son partenaire ne peut pas gérer les meilleures variantes. C'est ce qu'on nomme une attaque par repli (downgrade attack) et c'est une plaie classique des protocoles cryptographiques (sauf de ceux qui n'offrent aucun choix, mais qui ont d'autres problèmes, notamment l'impossibilité d'évoluer). Ce RFC présentait une technique TLS pour empêcher certaines attaques par repli : annoncer un algorithme cryptographique qui n'est pas un vrai algorithme mais qui signale qu'on a effectué un repli, permettant au partenaire de détecter que quelqu'un a interféré avec la communication. Cette technique se nomme SCSV, pour Signaling Cipher Suite Value. Elle a été abandonnée par le RFC 8996, qui retirait du service les versions de TLS vulnérables.

Normalement, un tel signalement n'est pas nécessaire (c'est très bien expliqué dans cet article sur StackExchange), les règles de négociation de TLS se chargent de tout (RFC 5246, sections 7.3 et 7.4). Mais il y a des serveurs TLS bogués qui réagissent mal avec certaines variantes. Au lieu d'indiquer proprement qu'ils ne gèrent pas ces variantes, ils coupent la communication. Un client TLS qui veut donc maximiser ses chances de se connecter va donc réessayer, en ne proposant pas les choix qui ont pu mener au précédent échec. C'est sympa du point de vue de l'interopérabilité mais cette downgrade dance est dangereuse du point de vue de la sécurité : le serveur, lors de la deuxième tentative, ne sait pas qu'il s'agit d'un repli. Prenons l'exemple d'un attaquant qui a trouvé une faille dans TLS 1.0 mais qui n'existe plus dans TLS 1.2 (celui du RFC 5246). Si Alice et Bob savent tous les deux parler 1.2, c'est cette version qu'ils choisiront, par défaut. Il faut donc les convaincre de se replier en 1.0. Un attaquant actif peut perturber la négotiation TLS (par exemple en ne transmettant pas le ServerHello, donnant au client l'impression que le serveur a ignoré son ClientHello). Certains clients vont alors se dire « zut, demander 1.2 perturbe le serveur, je vais réessayer directement en 1.0 ». Et l'attaquant aura atteint son but. Le serveur, qui sait faire du TLS 1.2, verra une demande en 1.0 et se dire juste « tiens, un vieux client qui ne sait pas faire de 1.2 ». Jusqu'à ce nouveau RFC, la seule protection contre ces attaques était de configurer le serveur pour refuser certains choix vraiment trop mauvais, question sécurité. Cette solution était trop rigide (pour reprendre l'exemple précédent, TLS 1.0 n'est pas catastrophique : il est raisonnable d'autoriser les vieux clients à se connecter en 1.0, mais on veut empêcher que les clients récents ne soient amenés à se limiter à 1.0). Au passage, un exemple d'une telle démarche est discutée dans l'article présentant la configuration TLS de mon blog (la ligne GnuTLSPriorities SECURE:-VERS-SSL3.0:-ARCFOUR-128:-ARCFOUR-40).

L'idéal serait bien sûr qu'il n'y ait pas de serveurs bogués, que la négociation TLS normale suffise, et que les clients n'aient jamais à faire de downgrade dance. Mais, dans le monde cruel où nous vivons, cela n'arrivera pas, les programmeurs ne lisent pas les normes et ne testent pas leur travail. À noter que, même en l'absence d'un attaquant actif, on voit parfois des replis malencontreux : un problème temporaire de réseau peut mener le client TLS à se dire « tiens, pas de réponse, je vais réessayer en TLS 1.0 et sans les extensions, pour voir ».

Donc, pour permettre au serveur de détecter que le client a fait un repli à tort, notre RFC introduit un nouveau pseudo-algorithme de chiffrement, TLS_FALLBACK_SCSV, valeur 0x56,0x00 (désormais dans le registre IANA). Il sera envoyé uniquement par le client, jamais par le serveur. Ce n'est pas un vrai algorithme, juste un signalement par le client qu'une première connexion a échoué et que le client tente un repli (section 4 du RFC). Si le client envoie le pseudo-algorithme TLS_FALLBACK_SCSV dans son ClientHello, et indique un protocole de version inférieure à ce que le serveur peut gérer, le serveur peut alors se rendre compte que le client a effectué un repli à tort (cf. section 3). Il peut alors répondre avec un nouveau message d'erreur, l'alerte TLS inappropriate_fallback (valeur 86). Voici ce que ça donne avec Firefox : inappropriate-fallback.png

Le signalement par le client qu'il s'est replié est un (pseudo-)algorithme de chiffrement, pas une extension TLS, car le but est qu'il ne pose de problème avec aucun serveur, même le plus ancien et le plus bogué. Le mécanisme d'indication des algorithmes de chiffrement date des débuts de SSL et on peut donc certainement compter dessus. Au passage, la technique de notre nouveau RFC est la deuxième utilisation de ce principe du SCSV, après la TLS_EMPTY_RENEGOTIATION_INFO_SCSV de la section 3.3 du RFC 5746.

La section 6 de notre RFC explore les cas où le client a intérêt à envoyer un TLS_FALLBACK_SCSV ou pas. Si le client n'a pas pu se connecter en TLS v1 ou supérieur, et se replie sur SSL v3, alors, le TLS_FALLBACK_SCSV est vraiment nécessaire car SSL v3 a de nombreuses faiblesses (la faille Poodle par exemple). Par contre, quand un client a une toute nouvelle version de TLS (à l'heure de la publication de ce RFC, la version 1.3 est en cours de développement), des difficultés avec les vieux serveurs sont à prévoir et il peut être préférable de ne pas envoyer TLS_FALLBACK_SCSV, et d'accepter le repli.

Des mesures faites en novembre 2014 indiquaient que 14 % des serveurs TLS sur l'Internet géraient déjà ce pseudo-algorithme TLS_FALLBACK_SCSV. Si vous voulez tester vous-même, vous pouvez par exemple vous servir d'OpenSSL en ligne de commande :

% openssl s_client -connect google.com:443 -state -fallback_scsv -tls1_1
CONNECTED(00000003)
SSL_connect:before/connect initialization
SSL_connect:SSLv3 write client hello A
SSL3 alert read:fatal:unknown
SSL_connect:failed in SSLv3 read server hello A
1077786776:error:1409443E:SSL routines:SSL3_READ_BYTES:tlsv1 alert inappropriate fallback:s3_pkt.c:1260:SSL alert number 86
1077786776:error:1409E0E5:SSL routines:SSL3_WRITE_BYTES:ssl handshake failure:s3_pkt.c:598:

Ici, on a tenté de se connecter à Google en envoyant le SCSV (option -fallback_scsv) et en indiquant comme numéro de version TLS 1.1 (alors que Google et OpenSSL savent tous les deux faire du 1.2). Google a donc envoyé l'alarme (le message alert inappropriate fallback). Avec un serveur qui ne gère pas SCSV, on aurait au contraire eu une connexion sans alerte. Si, au lieu du programme openssl, on veut le faire depuis une application qu'on écrit, il y a instructions et code sur le Wiki d'OpenSSL. Notez que le test des SSL Labs regarde aussi SCSV (message « This server supports TLS_FALLBACK_SCSV to prevent protocol downgrade attacks » ou bien aucune indication dans le cas contraire). Vu avec tshark, le test avec openssl montrera :

client -> serveur:

        Handshake Protocol: Client Hello
            Version: TLS 1.1 (0x0302)
                Cipher Suite: Unknown (0x5600) [version trop ancienne
		de Wireshark, qui n'affiche pas le nom de la SCSV]

serveur -> client:

    TLSv1.1 Record Layer: Encrypted Alert                                                                     
        Content Type: Alert (21)                                                                              
        Version: TLS 1.1 (0x0302)                                                                             
        Length: 2                                                                                             
        Alert Message: Encrypted Alert         

(L'alerte est chiffrée et donc pas décodée par défaut par Wireshark.)

Côté navigateurs Web, Firefox et Chrome gèrent cette technique SCSV mais il semble qu'Internet Explorer ne le fera pas.

Et, pour finir, une bonne explication de SCSV, avec des exemples Wireshark. Et merci à Florian Maury pour sa relecture.


Téléchargez le RFC 7507


L'article seul

RFC 7512: The PKCS#11 URI Scheme

Date de publication du RFC : Avril 2015
Auteur(s) du RFC : J. Pechanec, D. Moffat (Oracle Corporation)
Chemin des normes
Première rédaction de cet article le 23 avril 2015


La norme technique PKCS#11 décrit une interface d'accès à des fonctions cryptographiques. Par exemple, elle permet à un logiciel de signature de signer en utilisant une clé privée stockée dans une base de données, un HSM, une carte à puce (smart card) ou autres dépôts. Jusqu'à présent, la désignation des objets auxquels on pouvait accéder par PKCS#11 n'était pas normalisée et chaque logiciel avait sa méthode. Désormais, il existe un plan d'URI standard pour cela, spécifié dans ce RFC. Bienvenue à pkcs11:object=cle-de-machin;type=public;id=%69%95%3E%5C%F4%BD%EC%91 et à ses copains.

Prenons l'exemple de l'outil de manipulation de certificats certtool, de GnuTLS. Son option load-ca-certificate permet de charger le certificat d'une AC. La valeur de cette option peut être le nom d'un fichier local mais cela peut aussi être un URI PKCS#11, autorisant ainsi l'accès à tous les mécanismes de stockage ayant une interface PKCS#11. Le principe de ces URI PKCS#11 est de permettre l'accès à des objets (comme les certificats, les clés publiques, les clés privées, etc), en donnant une série d'attributs qui identifient l'objet (dans mon exemple au premier paragraphe, les attributs étaient object, type et id). Le but de ces URI est limité à la récupération d'objets existants, on ne s'en sert pas pour créer de nouveaux objets.

Donc, la définition formelle de ce plan d'URI (section 3 de notre RFC) : le plan est pkcs11 (et les URI commencent donc par pkcs11: et ce plan a été réservé dans le registre IANA), et l'URI est ensuite composé de paires attribut-valeur, séparées par des points-virgules. L'attribut id a une valeur binaire (et qui est donc pourcent-encodée dans l'exemple au premier paragraphe), tous les autres sont du texte en UTF-8. Voici les principaux attributs, avec leur nom dans les URI et l'équivalent dans l'API PKCS#11 :

  • id (CKA_ID) est l'identificateur d'un objet. C'est, comme on l'a vu, une valeur binaire opaque.
  • object (CKA_LABEL) est le nom d'un objet. Contrairement à l'id, c'est du texte.
  • serial (serialNumber dans CK_TOKEN_INFO) est le numéro de série du token, le dispositif de stockage des objets (un HSM, par exemple).
  • token (label dans le CK_TOKEN_INFO), le nom du dispositif de stockage.
  • type (CKA_CLASS), désigne le type d'objet stocké qu'on veut récupérer. Cela peut être cert (un certificat), public (une clé publique), private (une clé privée en cryptographie asymétrique), secret-key (une clé secrète en cryptographie symétrique).

Il est également possible d'ajouter des requêtes dans l'URI, après le point d'interrogation. Par exemple, si le dispositif de stockage réclame un PIN, on peut mettre quelque chose comme ?pin-source=file:/etc/dnssec/token_pin dans l'URI (ici, cela dit que le PIN se trouve dans le fichier /etc/dnssec/token_pin).

La section 4 contient plusieurs exemples d'URI PKCS#11, désignant :

  • Une clé publique, identifiée uniquement par son nom : pkcs11:object=my-pubkey;type=public.
  • Un certificat, en indiquant le nom du dépôt matériel (token) utilisé, et l'id du certificat : pkcs11:token=The%20Software%20PKCS%2311%20Softtoken;manufacturer=Snake%20Oil,%20Inc.;model=1.0;object=my-certificate;type=cert;id=%69%95%3E%5C%F4%BD%EC%91. Notez les attributs manufacturer et model, que je n'avais pas cité dans la liste des attributs les plus utilisés.
  • Une clé privée, en utilisant une nouvelle requête, module-name, qui permet d'indiquer la bibliothèque dynamique à charger pour parler au dépôt des clés (PKCS#11 est une API, pas un protocole, et il faut donc une bibliothèque différente par type de HSM ou smart card) : pkcs11:object=my-sign-key;type=private?module-name=snakeoil-pkcs11. Ici, sur une machine Unix, l'application PKCS#11 va donc tenter de charger la bibliothèque snakeoil-pkcs11.so.

Il existe plusieurs implémentations des URI PKCS#11, le document était en développement depuis longtemps. Ainsi, OpenConnect documente « Objects from PKCS#11 tokens are specified by a PKCS#11 URI. ». Le projet Fedora tente de standardiser tous ses logiciels qui font de la cryptographie autour de ces URI « Currently, there are many different ways to tell each application how to find the certificate. [...] where PKCS#11 objects are specified in a textual form which is visible to the user (e.g. on the command line or in a config file), objects SHOULD be specified in the form of a PKCS#11 URI as as described ». Pour un programme développé avec GnuTLS :

/* In addition the following functions can be used to load PKCS #11
key and certificates by specifying a PKCS #11 URL instead of a
filename. */
int gnutls_certificate_set_x509_trust_file (gnutls_certificate_credentials_t cred, const char * cafile, gnutls_x509_crt_fmt_t type)
...

Téléchargez le RFC 7512


L'article seul

RFC 7469: Public Key Pinning Extension for HTTP

Date de publication du RFC : Avril 2015
Auteur(s) du RFC : C. Evans, C. Palmer, R. Sleevi (Google)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF websec
Première rédaction de cet article le 18 avril 2015
Dernière mise à jour le 19 novembre 2019


Depuis que les piratages de Comodo et DigiNotar ont fait prendre conscience du peu de sécurité qu'apportent les certificats X.509, plusieurs solutions ont été proposées pour combler les failles des autorités de certification. La proposition de ce RFC, HPKP (HTTP Public Key Pinning), consistait à permettre à un client d'épingler (to pin) les clés cryptographiques d'un serveur HTTP utilisant TLS, c'est-à-dire à s'en souvenir pendant une durée spécifiée par le serveur. Ainsi, même si un faux certificat est émis par une AC, il ne serait pas accepté. En pratique, HPKP a été peu adopté et semble aujourd'hui en voie d'abandon.

Un exemple plus récent d'un « vrai / faux certificat » (certificat vrai car émis par une AC reconnue, mais faux car émis sans l'autorisation du titulaire du nom de domaine, et dans l'intention de tromper les utilisateurs) est celui du ministère des finances français. Comme souvent avec les certificats mensongers, celui-ci visait Google (je soupçonne fort que le but était de lire le courrier Gmail des employés, mais, à Bercy, on dément, et on affirme que les buts étaient de pouvoir effectuer un filtrage du contenu sur le Web externe, et de passer les flux à l'antivirus) et c'est ce qui explique que cette compagnie soit très présente dans les forums comme l'IETF où on cherche des solutions aux sérieuses faiblesses de X.509. Parmi les solutions élaborées, il y a DANE, qui s'appuie sur le DNS (RFC 6698), mais Google préfère les certificats à la lumière du jour du RFC 6962 et l'épinglage (pinning) des clés, dans ce tout nouveau RFC 7469.

À noter qu'il existe déjà des en-têtes HTTP permettant au serveur de spécifier au client son comportement, comme le HSTS du RFC 6797. Mais l'épinglage de clés est indépendant de HSTS.

L'épinglage fait partie des techniques TOFU (Trust On First Use) : la première fois qu'un client se connecte au serveur, il ne peut pas savoir si la clé est bonne (il doit se fier à la validation X.509, avec ses limites). À la première connexion, le client HTTP (par exemple un navigateur Web) doit espérer qu'il n'y a pas d'homme du milieu ayant réussi à obtenir un faux certificat (pour cette raison, une attaque persistente, comme celle du ministère des finances, citée plus haut, ne serait pas empêchée par l'épinglage). Aux connexions suivantes, le client HTTP pourra par contre vérifier l'identité du serveur, grâce à la clé épinglée, c'est-à-dire gardée en mémoire. Ce n'est pas idéal (imaginez un homme du milieu ayant un faux certificat pour la première connexion et épinglant ses propres clés, empêchant ainsi toute correction ultérieure !) mais c'est un progrès sur la situation actuelle (valider les clés est un problème difficile en cryptographie). À part des clés partagées à l'avance directement entre les correspondants (ce qui ne passerait évidemment pas à l'échelle pour le Web entier), il n'y a pas de solution parfaitement sûre pour la validation des clés.

La section 2 décrit les détails pratiques. Elle définit un nouvel en-tête HTTP, Public-Key-Pins:. Présent dans une réponse HTTPS, cet en-tête indique au client HTTP que ce serait souhaitable qu'il épingle, qu'il mémorise, la clé publique. Le contenu de l'en-tête Public-Key-Pins: est le condensat de la clé publique utilisée pour TLS, condensat encodé en Base64 (RFC 4648). L'algorithme de condensation est indiqué dans la valeur de l'en-tête. Aujourd'hui, c'est forcément SHA-256 (RFC 6234). La clé est l'encodage DER du champ subjectPublicKeyInfo du certificat X.509 (à noter que les cas des clés brutes du RFC 7250 ou des clés PGP du RFC 6091 ne semblent pas traités, car elles n'ont pas les problèmes des certificats X.509). Une directive max-age est obligatoire dans l'en-tête HTTP, pour indiquer le nombre de secondes que doit durer l'épinglage (après quoi le client HTTP « oublie » la clé). Voici un exemple :

Public-Key-Pins: max-age=604800;
       pin-sha256="d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM="

Il existe aussi deux directives facultatives. includeSubDomains indique que l'épinglage s'applique aussi aux serveurs dont le nom est un sous-domaine de celui-ci. Si le client se connecte en HTTPS à bar.example.com et reçoit un Public-Key-Pins: avec includeSubDomains, et qu'il se connecte plus tard à foo.bar.example.com, il exigera de trouver la clé épinglée (voir la section 4.2 pour quelques pièges de cette directive). Autre directive facultative, report-uri indique à quel URI le client doit signaler les erreurs résultant de l'épinglage. En effet, on peut prévoir que, comme avec toute technique de sécurité, il y aura des problèmes. Par exemple, des webmestres changeront de clé et oublieront de modifier le Public-Key-Pins:. Il est donc important que ces problèmes soient détectés rapidement. Ce signalement se fera selon la technique décrite plus loin en section 3. Attention aux conséquences pour la vie privée ! La très détaillée section 5 couvre ce risque d'intrusivité. Voici un exemple avec ces deux directives, et l'utilisation de plusieurs clés (par exemple parce qu'un remplacement est en cours) :

Public-Key-Pins: max-age=2592000;
       pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=";
       pin-sha256="LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ=";
       includeSubDomains;
       report-uri="https://other.example.net/pkp-report"

À noter qu'un deuxième en-tête est défini, Public-Key-Pins-Report-Only:, qui a exactement la même syntaxe, mais une sémantique différente : le client HTTP teste la clé épinglée et, si elle est fausse, le signale à l'URI indiqué par report-uri (qui devient donc obligatoire), mais n'empêche pas l'accès au serveur. C'est utile pour tester avant le vrai déploiement. Les deux en-têtes sont désormais dans le registre des en-têtes.

Comme indiqué plus haut, la section 3 décrit la façon dont un client HTTP peut signaler une erreur de validation. Pour cela, le client HTTP doit fabriquer un message en JSON (RFC 8259) et l'envoyer avec la méthode POST de HTTP à l'URI indiqué dans la directive report-uri. Voici un exemple d'un tel message (la date est au format du RFC 3339) :

 {
    "date-time": "2014-04-06T13:00:50Z",
    "hostname": "www.example.com",
    "port": 443,
    "effective-expiration-date": "2014-05-01T12:40:50Z"
    "served-certificate-chain": [
      "-----BEGIN CERTIFICATE-----\n
      MIIEBDCCAuygAwIBAgIDAjppMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT\n
      ...
    ],
    "validated-certificate-chain": [
      "-----BEGIN CERTIFICATE-----\n
      MIIEBDCCAuygAwIBAgIDAjppMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT\n
      ...
    ],
    "known-pins": [
      'pin-sha256="d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM="',
      "pin-sha256=\"E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=\""
    ]
  }

Comme souvent en sécurité, le diable est dans les détails, et c'est ce qui explique que la section 4, l'obligatoire « Security Considerations » soit particulièrement longue. Par exemple, l'épinglage peut avoir des conséquences néfastes si on s'est fait voler sa clé privée : normalement, on génère une nouvelle clé, un nouveau certificat et on demande à l'AC de re-signer. Mais on ne pourra pas l'utiliser car la clé publique correspondant à la clé volée est toujours épinglée dans des tas de navigateurs. On peut réduire ce problème en diminuant la durée d'épinglage. Mais, alors, on réduit aussi la durée de la protection dans le cas où une AC génère un certificat mensonger. Un compromis est donc nécessaire. Une approche possible est d'épingler, non pas la clé du serveur mais une clé intermédiaire dans la chaîne des certificats. Supposons que la société Example, qui gère example.com soit cliente de l'AC SmallAC qui a elle-même son certificat signé par une AC très largement reconnue, BigAC. En épinglant la clé de SmallAC, on se protège contre un vol de la clé privée d'example.com, et contre un faux certificat, même émis par BigAC. La société Example reste vulnérable à un faux certificat produit par SmallAC mais cela diminue sérieusement le nombre d'acteurs qui peuvent attaquer Example. (Notez que DANE a les mêmes possibilités : on peut publier dans le DNS sa propre clé, ou bien celle d'une AC.)

On a vu plus haut qu'on pouvait avoir plusieurs clés dans l'en-tête Public-Key-Pins:. Une des utilisations de cette possibilité est le cas où on a une clé de réserve (backup pin), non utilisée mais gardée en un endroit différent de la clé du certificat actuel. Ainsi, si, pour une raison ou pour une autre, la clé est inutilisable, la clé de réserve peut prendre le relais immédiatement puisqu'elle est déjà épinglée.

Autre cas où l'épinglage peut avoir un effet néfaste, celui de l'épinglage hostile. Imaginons un méchant qui obtienne un faux certificat. Il détourne le trafic (par exemple par un empoisonnement DNS) et envoie les gens vers son serveur HTTPS, qui semblera légitime, en raison du faux certificat. Avec l'épinglage, il peut même prolonger son attaque en épinglant sa clé. Si le site légitime n'avait pas été visité avant, ou s'il ne faisait pas d'épinglage, l'attaque peut réussir, bloquant le client HTTPS sur la clé de l'agresseur pour la durée max-age spécifiée par ledit agresseur. Il n'y a pas de solution miracle pour ce problème. Une possibilité est de précharger les clés de sites connus dans le navigateur. Une autre est d'utiliser les certificats au grand jour du RFC 6962. (Et, bien sûr, il y a DANE, RFC 6698, que Google prend toujours soin de ne pas mentionner.)

Autres risques, ceux pour la vie privée (section 5). Un serveur peu sympathique peut utiliser l'épinglage comme une sorte de cookie discret. Par exemple, il peut mettre une petite image dans un sous-domaine, épingler des fausses clés pour ce sous-domaine (une différente par visiteur) et attendre les signalements à report-uri pour identifier un client HTTPS unique. Des sites différents peuvent même coopérer pour avoir le même report-uri, pour suivre un client à travers plusieurs sites.

À noter aussi que les signalements d'un problème de validation contiennent la chaîne de certificats utilisée. Cela peut permettre d'identifier l'utilisation de faux certificats par telle ou telle organisation. C'est plutôt une bonne chose pour détecter des attaques comme celle effectuée au ministère des finances mais cela ne sera évidemment pas apprécié de ceux qui veulent faire du détournement de trafic.

Comme toujours en sécurité, l'utilisabilité est cruciale (section 7). Lorsqu'un épinglage a eu lieu, et que le trafic est ensuite détourné vers un faux serveur, le client HTTPS (par exemple le navigateur Web) va refuser l'accès à ce faux serveur ce qui, du point de vue de M. Toutlemonde devant son navigateur, est un déni de service. Il va donc falloir bien expliquer à M. Toutlemonde ce qui se passe, pour éviter qu'il n'accuse le site légitime.

Le RFC recommande aussi que l'utilisateur puisse accéder facilement à la liste des clés épinglées et aussi, ce qui me semble plus contestable, qu'il puisse la modifier, par exemple en désépinglant les clés. Cela me semble dangereux car cela peut ouvrir une voie à l'ingénierie sociale (« il y a un petit problème technique, si l'accès vous est refusé, cliquez sur Clear all pinned keys »).

L'annexe A contient un exemple, utilisant OpenSSL en ligne de commande, pour générer le Public-Key-Pins:. J'en ai fait un petit script qui s'utilise ainsi :

% make-pin.sh www.ietf.org
...
DHKscLdFrBmZiBGxMdZiyaxp29vnyyPltRS1ZmTF09Y=

Et hop, on n'a plus qu'à mettre Public-Key-Pins: max-age=604800; pin-sha256="DHKscLdFrBmZiBGxMdZiyaxp29vnyyPltRS1ZmTF09Y=" dans la réponse du serveur HTTP. (Tom me fait remarquer à juste titre qu'une clé de secours est obligatoire - section 4.3 - et que donc il faut toujours au moins deux pin-sha256. J'ai simplifié.) Les premières versions de l'Internet-Draft qui a mené à ce RFC utilisaient un programme en Go, make-pin.go :

% openssl s_client -servername www.ietf.org -connect www.ietf.org:443 > ietf.pem
...
% ./make-pin ietf.pem 
Hex: 0c72ac70b745ac19998811b131d662c9ac69dbdbe7cb23e5b514b56664c5d3d6
Base64: DHKscLdFrBmZiBGxMdZiyaxp29vnyyPltRS1ZmTF09Y=

À noter que l'annexe B contient quelques conseils pratiques à l'usage des gérants de serveurs HTTPS, sur le bon déploiement de l'épinglage. Par exemple, il est recommandé de commencer doucement, en mode report-only avant de se jeter dans le grand bain et de risquer de bloquer ses clients. Comme avec n'importe quelle technique de sécurité, on risque de se planter soi-même si on ne fait pas attention : n'épinglez pas bêtement !

Question mises en œuvre, Chrome et Firefox avaient déjà de l'épinglage, avec une série de clés mise en dur dans le logiciel (voir la description de Mozilla et leur annonce). Vous pouvez tester ici si votre navigateur gère l'épinglage. Une description de l'épinglage des clés dans Chrome avait été faite par Adam Langley et sa lecture est recommandée (par exemple pour comprendre pourquoi on épingle juste des clés et pas des certificats entiers). Pour le monde Microsoft, voir leur article. Il y aussi un article détaillé sur le concept, chez OWASP, et l'article de Robert Love avec des détails pratiques. Le peu de succès de HPKP fait que Firefox, par exemple, a annoncé son intention de l'abandonner (cf. ticket #1412438.)

Merci à Florian Maury et Kim Minh Kaplan pour leur relecture.


Téléchargez le RFC 7469


L'article seul

RFC 7498: Service Function Chaining Problem Statement

Date de publication du RFC : Avril 2015
Auteur(s) du RFC : P. Quinn (Cisco Systems), T. Nadeau (Brocade)
Pour information
Réalisé dans le cadre du groupe de travail IETF sfc
Première rédaction de cet article le 15 avril 2015


Le projet SFC à l'IETF, dont voici le premier RFC, vise à mettre de l'ordre dans les innombrables traitements que suivent les flux IP dans l'Internet. Pare-feux, répartiteurs de charge, dispositifs de censure et d'espionnage, et leurs copains veulent tous appliquer des traitements aux communications et, actuellement, il n'existe pas de cadre unificateur pour ordonnancer proprement ces traitements, encore moins de normes techniques. Ce premier RFC expose le problème qu'on tente de résoudre.

Certains des traitements souhaités sont plutôt dans la couche 3, d'autres peuvent concerner les applications. La liste des traitements potentiellement effectués est très vaste, elle comprend les services de surveillance utilisant la DPI (comme les boîtes noires de Cazeneuve), le NAT, les caches, les divers optimiseurs (TCP, TLS) qui assurent certaines fonctions à la place de la machine terminale, etc. Le RFC n'en parle pas mais des fonctions de censure comme les mensonges DNS du réseau chinois rentrent également dans cette liste.

Certains traitements peuvent concerner une seule machine et d'autres la totalité des communications. Actuellement, ces traitements sont très couplés à la topologie du réseau. Par exemple, pour filtrer le trafic indésirable, on met un pare-feu en coupure du réseau, forçant tout le trafic à passer par le pare-feu. Si on veut effectuer un autre traitement, il faut mettre une seconde machine. Le tout devient vite très rigide, difficile à changer, et difficile à analyser dans ses effets combinés. C'est surtout dommage dans les environnements « à la demande » où on crée et détruit très vite des machines virtuelles et même des réseaux entiers.

Le terme de SFC (Service Function Chain) a été créé pour désigner une nouvelle façon de concevoir ces services : on définit des fonctions abstraites (comme celle de pare-feu) et on a une liste ordonnée de telles fonctions, que le réseau peut appliquer, indépendamment de sa topologie. Le concept est développé plus longuement en section 3 du RFC.

Mais, d'abord, en section 2, l'exposé plus détaillé du problème. Cette section est le gros morceau de ce RFC. On l'a vu brièvement plus haut, aujourd'hui, pour assurer une fonction sur les flux réseau, il faut une topologie particulière. Par exemple, le pare-feu doit être sur le chemin et avoir deux « pattes », introduire un pare-feu là où il n'y en avait pas nécessite donc souvent de ré-architecturer son réseau, ajoutant des sous-réseaux IP qui n'étaient pas nécessaires. Ça manque sérieusement de souplesse. Idéalement, on voudrait que le réseau soit architecturé uniquement autour de la délivrance des paquets, et que les services en plus soient déployables en appuyant sur un bouton, sans refaire le réseau à chaque nouveau service.

Un autre exemple de rigidité concerne les répartiteurs de charge, si communs devant les serveurs Web. Il faut souvent configurer le répartiteur comme étant le routeur par défaut des serveurs HTTP, si bien que même le trafic non-Web (par exemple les communications de gestion en SNMP ou SSH) passe par le répartiteur, sans nécessité.

Autre conséquence de cette dépendance vis-à-vis de la topologie, cela rend difficile le changement du service de transport sous-jacent. Si on passe de MPLS à GRE, on risque de devoir changer pas mal de services, alors que, a priori, ils étaient indépendants des couches basses.

Tout cela fait que les réseaux sont plus complexes qu'ils ne le devraient. Changer un paramètre aussi simple que l'ordre dans lequel sont appliqués des services (filtrer d'abord, puis répartir le trafic après, ou bien le contraire) nécessite de changer la topologie. Résultat, les réseaux tendent à rester plutôt statiques, et à ne pas profiter à fond de la souplesse que permettrait la virtualisation (section 2.7). Et assurer la haute disponibilité devient très compliqué, puisque les services de secours doivent conserver la même topologie que le service principal (afin de recevoir les mêmes traitements).

Un autre problème lié au couplage trop fort entre les services et la topologie du réseau est celui de la sélection du trafic (section 2.8). Souvent, on ne veut appliquer les services qu'à une partie du trafic. Or, dans les architectures actuelles, cela va souvent obliger à faire passer tout le trafic par la machine qui met en œuvre le service. Ou, sinon, à mettre en œuvre des mécanismes de redirection peu pratiques. Prenons un exemple : on veut censurer certaines pages de Wikipédia mais pas toutes. Faire passer la totalité du trafic par le système de DPI qui déterminera quelles pages sont demandées serait lent, nécessiterait de grosses machines pouvant faire de la DPI à ce rythme et pourrait être considéré comme abusif par rapport au but à atteindre. Actuellement, les censeurs déploient donc souvent des architectures mixtes (proxy HTTP transparent, puis redirection du trafic des serveurs Wikipédia - et de seulement ceux-ci - vers le système de DPI, qui n'aura donc à traiter qu'une partie du trafic). C'est quand même peu élégant, et il serait donc souhaitable de découpler sélection du trafic et application du service.

Et, bien sûr, dans l'état actuel des choses, comme il n'y a aucun standardisation des services réseaux et de la manière dont ils s'insèrent, faire coexister des services réseau de plusieurs vendeurs différents est très difficile. Une standardisation, même partielle, simplifierait la vie des administrateurs réseau (le but de ce RFC n'est pas de réaliser cette standardisation, ce qui serait très prématuré, mais d'explorer le problème).

La section 3 de notre RFC, elle, décrit de manière positive ce qu'on attend du service chaining, de la composition des services. Pour découpler le service de la topologie, il faudra un overlay par service. Changer la liste, ou l'ordre de la liste des services appliqués, ne nécessitera donc que de changer la connexion entre ces overlays.

Le mécanisme devra fournir un moyen de classer le trafic, en fonction de critères de sélection. En pratique, les possibilités exactes du système de classification dépendront du matériel et logiciel sous-jacents, et la classification sera donc plus ou moins grossière.

Souvent, les services réseau n'ont besoin que des métadonnées pour agir, et il n'est donc pas forcément nécessaire d'envoyer aux services la totalité des flux.

Voilà, c'est très vague, comme description, je sais, mais c'est l'état actuel de la réflexion sur la composition de services (et cette section 3 a déjà suscité beaucoup de discussion dans le groupe de travail). D'autres RFC sont en préparation, plus concrets, comme le document d'architecture de SFC, le RFC 7665.

Un tel système de composition de services soulève évidemment d'amusantes questions de sécurité (section 4). Certaines sont traitées par des protocoles existants (par exemple la création et la maintenance des overlays, qui n'est pas un problème nouveau).

Le RFC note que certains services peuvent nécessiter des connaissances détaillées sur les données transmises, et que des techniques comme le chiffrement peuvent donc limiter ces services. En pratique, on aura moins d'informations, mais on pourra souvent se débrouiller avec. (Il reste des métadonnées non chiffrées.) D'ailleurs, à propos de chifffrement, le RFC note qu'il faudra aussi protéger le trafic SFC : les machines qui effectuent un certain service peuvent être loin de celles qui se « contentent » de faire passer les paquets et il ne faudrait pas que le trafic entre les deux soit espionné ou, pire, modifié, par un tiers (la protection est parfois assurée par le protocole d'overlay). C'est particulièrement important dans un contexte multi-clients (un grand réseau partagé par de nombreux utilisateurs).

À noter qu'Ericsson prétend avoir un brevet même sur la simple description du problème !


Téléchargez le RFC 7498


L'article seul

RFC 7500: Principles for Operation of Internet Assigned Numbers Authority (IANA) Registries

Date de publication du RFC : Avril 2015
Auteur(s) du RFC : R. Housley (Vigil Security), O. Kolkman (Internet Society)
Pour information
Première rédaction de cet article le 14 avril 2015


Traditionnellement, le fonctionnement de la normalisation dans l'Internet sépare deux fonctions : l'IETF développe les normes techniques (qui sont publiées dans les RFC, documents immuables) et l'IANA gère les nombreux registres qui stockent les paramètres des protocoles de l'IETF. Au contraire des RFC, ces registres changent tout le temps. Ce nouveau RFC décrit les principes de haut niveau sur lesquels repose le fonctionnement de l'IANA. (Il a depuis été remplacé par le RFC 8720.)

Pendant longtemps, la gestion des registres et la publication des RFC étaient assurés par le même homme, Jon Postel à l'ISI. Aujourd'hui, les deux opérations sont complètement séparées, https://www.iana.org/ et https://www.rfc-editor.org/.

Ces registres sont cruciaux pour le bon fonctionnement de l'Internet. Presque tous les protocoles Internet dépendent d'un ou de plusieurs registres. Aujourd'hui, il existe plus de 2 000 registres à l'IANA (la liste complète est en https://www.iana.org/protocols). Les valeurs stockées peuvent être des nombres, des chaînes de caractères, des adresses, etc. Leur allocation peut être centralisée (tout est à l'IANA) ou décentralisée, avec l'IANA déléguant à des registres qui à leur tour délèguent, comme c'est le cas pour les noms de domaine et pour les adresses IP.

L'IANA n'a pas de pouvoirs de police : le respect des registres IANA dépend uniquement de la bonne volonté générale. Évidemment, la pression est forte pour respecter ces registres, puisque le bon fonctionnement de l'Internet en dépend. Ce RFC présente les principes sur lesquels ces registres reposent (sections 2 et 3 du RFC) :

  • Unicité des identificateurs. C'est l'un des principaux buts des registres, s'assurer que qu'il n'y a qu'un seul .fr ou .org, ou que l'algorithme 13 de DNSSEC désigne bien ECDSA pour tout le monde.
  • Stabilité. Les registres doivent tenir plus longtemps que la page Web corporate moyenne. Leur contenu existant ne doit pas changer sauf s'il y a une très bonne raison.
  • Prédictabilité. Le processus d'enregistrement doit être prévisible et ne pas comporter de soudaines surprises (« finalement, il faut tel papier en plus »). Parfois, un jugement humain est nécessaire donc le processus n'a pas à être algorithmique, ni à être limité dans le temps, mais il ne doit pas soudainement ajouter des étapes non prévues.
  • Publicité. Les registres doivent être publics (en pratique, le principal mode de distribution est via le Web). Ce n'est pas si évident que cela, les dinosaures attardés de la normalisation, comme l'AFNOR, l'ISO ou l'IEEE ne le font pas.
  • Ouverture. Le processus qui détermine les politiques d'enregistrement doit être ouvert à tous ceux qui désirent participer. Dans presque tous les cas, c'est l'IETF qui détermine cette politique (les exceptions sont importantes comme la gestion de la racine des noms de domaine), via un RFC développé en effet dans un processus ouvert. Le RFC 5226 détaille les politiques IANA possibles. (Parmi elles, certaines nécessitent un examen par un expert, le jugement humain mentionné plus haut.)
  • Transparence. La gestion des registres ne doit pas être opaque. On peut écrire à l'IANA, ou bien passer les voir Away From Keyboard pendant les réunions IETF, où l'IANA a toujours un stand.
  • Redevabilité. L'IANA doit rendre compte de sa gestion. Selon le RFC 6220, la supervision de la fonction IANA incombe à l'IAB (RFC 2850). En outre, l'IAOC (RFC 4071) a un SLA avec l'actuel opérateur de la fonction IANA, l'ICANN. L'IAB et l'IAOC sont eux-même redevables devant une communauté plus large, via le processus NomCom (RFC 3777). Pour les adresses IP et les ressources associées, le RFC 7249 fait gérer la redevabilité par les RIR (RFC 7020). Ceux-ci sont des organisations ouvertes et eux-même redevables devant leurs membres. (Avez-vous noté quel registre n'était pas mentionné comme bon exemple par le RFC ?)

Téléchargez le RFC 7500


L'article seul

RFC 7497: Rate Measurement Test Protocol Problem Statement and Requirements

Date de publication du RFC : Avril 2015
Auteur(s) du RFC : A. Morton (AT&T Labs)
Pour information
Réalisé dans le cadre du groupe de travail IETF ippm
Première rédaction de cet article le 13 avril 2015


La capacité d'un accès Internet est un critère de choix important pour l'utilisateur et c'est même en général le seul qui est mis en avant dans la publicité (« choisissez la fibre qui fonce à 100 Mb/s »). Peut-on la mesurer sérieusement et objectivement ? Ce RFC explore la question, sans donner encore de réponse définitive.

La capacité est définie dans le RFC 5136. Notre nouveau RFC parle de rate et pas de capacity mais la différence est subtile (je vous laisse la découvrir dans le RFC si vous êtes intéressé). En revanche, il faut se méfier de termes flous et souvent utilisés de manière erronée comme « bande passante » ou « débit ». Ce qui intéresse M. Michu (ou, plus exactement, sa fille qui veut télécharger les quatre premiers épisodes de la saison 5 le plus vite possible), c'est bien la capacité de son accès Internet (cf. RFC 6703). Comme c'est un argument commercial essentiel, bien des gens souhaiteraient la mesurer, qu'ils soient simples citoyens, associations de défense des consommateurs ou bien régulateurs des télécoms. C'est ainsi que l'ARCEP a un tel programme de mesure et que l'Union européenne en a lancé un à travers les sondes SamKnows, qui a donné lieu à un excellent rapport, montrant bien les différences entre les proclamations commerciales et la réalité.

Le groupe de travail IPPM de l'IETF travaille depuis longtemps à normaliser les mesures de performance (qui sont souvent floues et approximatives, permettant ainsi toutes les manipulations). Avec la normalisation de la mesure, on pourrait envisager des comparaisons sérieuses entre les offres des FAI. Ce RFC 7497 ne propose pas encore une telle normalisation mais essaie simplement de décrire rapidement le problème. Il se focalise sur l'accès à l'Internet, pas sur les mesures au sein du cœur du réseau (où les capacités sont beaucoup plus élevées). La plupart du temps, le goulet d'étranglement du chemin suivi par les paquets IP sera le lien entre l'utilisateur et le FAI. Ce choix de mesurer l'accès à l'Internet met quelques limites à l'efficacité de la mesure (dans le cœur, on peut utiliser des engins de mesure perfectionnés et coûteux ; chez l'utilisateur, on devra souvent se contenter de dispositifs moins sophistiqués, par exemple ayant une horloge moins précise). Combien de bits/seconde va pouvoir faire passer M. Michu ? Notez que tout dépend d'où on part. De la box ? D'un PC connecté en Wi-Fi ? Le RFC 7398 mettait déjà en avant l'importance de décrire le chemin emprunté par la mesure (le réseau Wi-Fi de M. Michu peut être très chargé, donnant l'impression d'une capacité plus faible qu'elle ne l'est réellement). Autre piège, les FAI imposent souvent aux abonnés des capacités asymétriques : la capacité descendante (dans la terminologie des FAI, qui se voient au-dessus des utilisateurs) est supérieure à la capacité montante.

Une des nombreuses difficultés de la mesure est que les paquets peuvent être traités différemment selon leurs caractéristiques (RFC 2330, section 13) : paquets longs vs. paquets courts, TCP vs. UDP, différence selon le port de destination, etc. Idéalement, le trafic de test, que l'on injectera pour mesurer combien de bits/seconde passeront, devra être une imitation aussi proche que possible du trafic réel de M. Michu. Ce n'est qu'un des très nombreux pièges qui se présentent lorsqu'on veut faire des mesures sur l'Internet. Au moment de la sortie du rapport ARCEP, on avait ainsi vu pas mal de gens peu informés et n'ayant manifestement jamais réfléchi à la question s'exprimer très fort sur divers forums. Ils affirmaient bien haut leurs certitudes (« LOL mais non, c'est idiot, il ne faut pas faire comme cela ») sans que rien n'indique qu'ils avaient compris la complexité du problème.

Dernier piège cité en section 2 de notre RFC, le moment où faire les mesures actives qui sont indispensables à la détermination de la capacité. Si on les fait aux moments pré-définis, on aura des résultats différents selon qu'à ces moment l'utilisateur télécharge en HD ou pas. Il serait préférable d'attendre un moment calme. Mais cela soulève d'intéressants problèmes de protection de la vie privée (par exemple, la documentation de la SamKnows précise qu'il faut l'installer en coupure, de manière à ce qu'elle puisse voir passer tout le trafic).

La section 3 du RFC décrit plus précisément ces mesures actives. Il faut évidemment un protocole de contrôle permettant la coordination entre la sonde de mesure et l'amer (genre RFC 5357 et RFC 4656). Il faut d'autre part que le trafic généré pour le test soit réduit à ce qui est strictement nécessaire pour mesurer la capacité (l'un des problèmes essentiels des mesures actives est qu'elles perturbent le réseau, cf. section 5 du RFC 7680 et section 4 du RFC 3148, et les sections 6 et 7 de notre RFC, qui insistent sur l'importance du consentement). Comme le lien d'accès typique a des capacités asymétriques, l'idéal serait de pouvoir faire des mesures dans une seule direction. Mais c'est en général irréaliste (il faut des équipements de mesure bien synchronisés, notamment du point de vue temporel, et qui soient des boîtes spécialisées, sachant faire ce que ne peut pas faire une machine Unix ordinaire). Donc, la plupart des mesures seront une mesure de l'aller-retour, dont il faudra extraire ensuite les capacités dans chaque direction.

Au bout du compte, ces mesures actives nécessiteront trois composants :

  • L'émetteur, qui est capable d'envoyer des paquets ayant les caractéristiques souhaitées,
  • Le receveur,
  • Et le rapporteur, qui mesure et envoie les résultats dans le format demandé.

Parmi les caractéristiques demandées pour les paquets (section 4), il faut pouvoir choisir la longueur, le contenu (certains équipements réseaux, par exemple ceux qui effectuent de la compression, donnent des résultats différents selon le contenu), les différents champs de l'en-tête IP (comme ceux du RFC 2474), le protocole (TCP ou UDP), les ports, etc. Ces paquets doivent pouvoir être transmis à un rythme choisi. Bien que le RFC passe très rapidement sur ce point, il faut aussi pouvoir, si on utilise TCP, contrôler l'algorithme d'évitement de la congestion.


Téléchargez le RFC 7497


L'article seul

RFC 7401: Host Identity Protocol Version 2 (HIPv2)

Date de publication du RFC : Avril 2015
Auteur(s) du RFC : R. Moskowitz (Verizon), T. Heer (Hirschmann Automation and Control), P. Jokela (Ericsson Research NomadicLab), T. Henderson (University of Washington)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF hip
Première rédaction de cet article le 10 avril 2015


HIP, décrit dans ce RFC, est un protocole très ambitieux, puisqu'il vise à compléter IP en fournissant une séparation de l'identificateur et du localisateur, permettant d'améliorer la sécurité (notamment la résistance aux DoS) et de mieux gérer la mobilité et le multi-homing. Ce RFC décrit la version 2 de HIP, désormais norme officielle (au lieu de protocole expérimental, ce qu'était HIP v1).

L'architecture générale de HIP est décrite dans le RFC 9063 (vous pouvez lire mon article de résumé de HIP). Notre RFC normalise, lui, le protocole concret. HIP repose d'abord sur la séparation entre un nouvel identificateur, le HI (Host Identity) et un localisateur, plus concret, qui sera simplement l'adresse IP, réduite à un rôle moins visible, sans exigence de stabilité. Par exemple, HIP permettra le changement de localisateur (d'adresse IP) en cours de connexion, sans rompre celle-ci, ce qui sera précieux pour la mobilité.

HIP est donc déployable uniquement en modifiant les machines terminales du réseau (si les coupe-feux le laissent passer), sans toucher aux routeurs. Il en existe des mises en œuvres pour FreeBSD et Linux. Le projet OpenHIP adapte également des logiciels comme Wireshark pour qu'ils aient un support HIP. InfraHIP travaille également à l'infrastructure HIP.

Si on ne veut pas lire le RFC 9063, on peut néanmoins avoir une bonne introduction à HIP en lisant les sections 1 et 2 de notre RFC (ou, si on est très pressé, mon article). Elles expliquent le vocabulaire (par exemple, HIP, étant un protocole situé en haut de la couche 3 n'utilise pas le terme de connexion mais celui d'association), le nouvel espace de nommage et les principes du protocole.

L'espace de nommage fait l'objet de la section 3. On distingue les HI (Host Identity), qui sont des clés publiques d'un couple clé privée / clé publique et qui sont de taille variable, et les HIT (Host Identity Tag, décrits dans la section 3.1), qui sont un résumé cryptographique des HI. Ils sont de taille fixe (donc plus faciles à traiter), 128 bits, la taille d'une adresse IPv6. Un préfixe ORCHID (RFC 7343), le 2001:20::/28, sert à éviter toute collision avec les « vraies » adresses IPv6. Avec OpenHIP, la clé peut être générée par le programme hitgen qui fabrique un fichier XML ressemblant à ceci :


<?xml version="1.0" encoding="UTF-8"?>
<my_host_identities>
  <host_identity alg="RSA" alg_id="5" length="128" anon="no" incoming="yes" r1count="10">
    <name>horcrux-1024</name>
    <N>C6EBA2894C33A1312B38853A8ECC0D7967496237A65529807EDF23C4DA753EE88F8FBF71BE38B6910181D5B75DB075B9962326D9BB50C65121DBFD712F1B7F4E2B035953AD650EB5C96B56295FE2731B3B36E8AFED7FB5CD48B73C31A224D4CE4F097D84888EC2E3CA8F3A78939D89B7BCFC5E6DEEAF670695349BFFFE8445F1</N>
    <E>010001</E>
    <D>383A51165838DBDE872611DACC94775692D09677BE87A214954843D7181D3E2C04B0905FF9721481069909AD2C497DED78B7F4FA64CD5F517DADAE8538D89FF21B0498A72F1132545328ABD371B1BAC8ED46441D900921523B78BA55F3FC227F432F2061C92CE9665CB99C1CF425AA90CFC6345FA4E7DA43E477EAF69F86A801</D>
    <P>FF03F93454C9C2D8EC47FE8C9DBF0D82F05E13905F304A5ACA42C45E579F917B4C8CEFEF6B06AAB9BCB7A911D5514B7AEE685DA91E7CC60DDC4C37BA94A22E71</P>
    <Q>C7B0394EB5506B2B75E19E5654262E843659BB76A465C2A7AC47A430749944378E3161FF805B4C6CB037B5CB111F0EF49FF03047FB1CFC51DC0D72DEDAD64F81</Q>
    <dmp1>7426C128DEBD8EEBF2A2D004080D6F0006AF32C5FD352788B6BB3669AA0B59DE08FDE082F202755C67E25735722DB6ED650D502BA961376C34BCDA5D3739AF61</dmp1>
    <dmq1>1B97DE5361FA9AD4869586ABA7351F78658A40BD443A4B8B9FE2C66D6BAF421DEB2827C2869A17156DC444FAAA83002E0D6BC3402F12F24ADD7D7E420D3B5001</dmq1>
    <iqmp>7499A27F59CA1746F1A6E5DE832592F8ACF80B814DD511C490614C44DC92B5CD1650AC944ED5751F28846487C221E8C17E68264DFEF748B86E38EB1F238D94A9</iqmp>
    <HIT>2001:1f:cd4:7125:2427:f77c:d1b6:e15f</HIT>
    <LSI>1.182.225.95</LSI>
  </host_identity>
</my_host_identities>

Notez bien que le fait d'utiliser XML est un choix de OpenHIP, qui n'est utilisé qu'en local. Il n'est pas imposé par la norme qui, sur le câble, n'utilise que du binaire. Les éléments comme P, Q ou iqmp sont les éléments d'une clé RSA (HIP peut utiliser d'autres algorithmes que RSA, comme ECDSA). Le HIT est représenté en utilisant la syntaxe des adresses IPv6, puisqu'il a la même taille et a été conçu pour être stocké comme une adresse par les applications.

La section 3.2 explique comment générer un HIT à partir du HI. Étant un résumé cryptographique (fait avec SHA-256 ou un équivalent), il est sûr, on ne peut pas fabriquer facilement un HI qui aurait le même HIT (cf. annexe E).

Pour signer les paquets, les deux machines utiliseront au début un échange de Diffie-Hellman.

La section 4 donne une vision générale du protocole, qui sera ensuite détaillée dans les sections ultérieures. HIP a reçu le numéro de protocole 139 (il n'a pas changé avec la version 2 de HIP).

La section 4.1 décrit comment former une association entre deux machines HIP. Celle qui demande l'association est nommée l'initiateur, celle qui l'accepte le répondeur. Le protocole d'association nécessite quatre paquets. En effet, avec seulement trois paquets, comme le fait TCP (RFC 793) lors de l'établissement d'une connexion (three-way handshake), on ne peut pas à la fois se protéger contre les DoS et permettre des options par connexion. Se protéger contre les DoS nécessite de ne pas garder d'état tant que le pair n'est pas authentifié, même faiblement. Les techniques qui permettent à TCP de ne pas garder d'état sur le « répondeur », telles que les SYN cookies du RFC 4987 sont incompatibles avec les options TCP.

Voici pourquoi les protocoles plus récents comme SCTP (RFC 3286) ou comme HIP nécessitent quatre paquets.

Dans HIP, ils sont nommés I1, R1, I2 et R2. Les paquets I sont envoyés par l'initiateur et les paquets R par le répondeur.

L'établissement d'une association se passe donc comme ceci :

  • L'initiateur envoie I1 au répondeur. Le paquet contient l'identificateur (le HIT) de l'initiateur et (optionnellement) celui du répondeur. Il contient également les paramètres de la session Diffie-Hellman (attention, c'est un changement par rapport à HIP v1). Aucun état n'est créé chez le répondeur.
  • Le répondeur envoie R1. Ce paquet contient un « puzzle » cryptographique que l'initiateur devra résoudre. Et ce paquet est signé. (Si l'initiateur ne connaissait pas le HI du répondeur, ce qu'on nomme le « mode opportuniste », il ne peut évidemment pas vérifier cette signature, et le mode opportuniste est donc vulnérable aux attaques de l'homme du milieu lors de l'établissement de la connexion, mais pas après. Même ce mode fournit donc au moins autant de sécurité que l'IP actuel.)
  • L'initiateur envoie I2, qui contient la solution du puzzle et les paramètres Diffie-Hellman pour le répondeur. Ce paquet est signé. Tant que cet I2 n'a pas été reçu, le répondeur ne garde aucun état chez lui, ce qui le protège de la plupart des attaques par déni de service.
  • Le répondeur envoie R2 pour accepter l'association. Ce paquet est signé.

Le puzzle, détaillé en section 4.1.1, est un petit problème de calcul que l'initiateur doit résoudre pour montrer qu'il est prêt à « payer », à faire un effort pour que l'association soit acceptée. La difficulté du puzzle peut être réglée par le répondeur, par exemple en étant plus difficile lorsqu'une attaque dDoS est en cours. D'une manière analogue au « minage » Bitcoin, le puzzle consiste simplement à trouver un nombre J tel que, concaténé avec le nombre I envoyé par le répondeur (et imprévisible, pour empêcher les pré-calculs par un attaquant), et avec les HIT des deux pairs, le condensat comprenne un certain nombre K de zéros initiaux (voir l'annexe A pour les détails). Ce K est donc la difficulté du puzzle. À noter qu'il n'y a pas d'estampille temporelle dans les paramètres de la demande de connexion, et que les attaques par rejeu sont donc possibles (mais cela dispense d'une synchronisation d'horloges globale, cf. section 4.1.4).

En pratique, il est très difficile d'imaginer un puzzle qui soit dissuasif contre des attaquants disposant d'un botnet entier, tout en étant soluble par des appareils simples, genre téléphone portable, ne possédant guère de puissance de calcul. (La section 4.1.1 détaille ce problème et les solutions possibles.)

La section 4.1.3 détaille l'utilisation du Diffie-Hellman.

Une des nouveautés de HIP v2 est l'agilité cryptographique, c'est-à-dire le fait que les algorithmes cryptographiques utilisés sont des paramètres du protocole, pas des décisions définitives. On peut donc ainsi changer d'algorithme suivant les progrès de la cryptanalyse. Mais l'agilité a aussi des inconvénients comme le risque d'attaques par repli où, lors de la négociation entre les deux pairs, un homme du milieu réussit à faire croire à Alice que Bob ne gère pas tel algorithme, forçant ainsi Alice à se replier sur un algorithme plus faible. Une nouveauté de ce RFC 7401 est donc la section 4.1.7 sur les protections contre le repli. Contrairement à d'autres protocoles cryptographiques, HIP signe presque tous les paquets relatifs à la négociation d'algorithmes. Ils ne peuvent donc pas être modifiés. Une attaque par rejeu reste possible : Bob met à jour son logiciel, accepte désormais de meilleurs algorithmes mais Mallory a enregistré ses anciens paquets et les envoie à Alice, qui croira alors (même après la vérification de la signature) que Bob continue à ne gérer que de vieux algorithmes. HIP dispose donc d'autres protections comme le fait que les paramètres Diffie-Hellman sont aussi dans ces paquets de négociation et qu'un vieux paquet mènera donc à un échec de la négociation Diffie-Hellman.

Une des grandes forces de HIP est la possibilité de mettre à jour une association existante (section 4.2). À tout moment, pendant la session, un paquet de type UPDATE peut être envoyé pour changer certains paramètres de la session, comme les localisateurs (les adresses IP) utilisées. La signature des paquets permet de s'assurer que le paquet UPDATE est authentique.

Une fois l'association établie, les machines peuvent échanger des données. Si elles utilisent des protocoles comme ESP (RFC 7402), ces données sont protégées contre l'écoute et la modification (HIP lui-même ne chiffre pas).

La section 5 est longue car elle détaille le format, bit par bit, de tous les paquets échangés. Il y a huit types de paquets (section 5.3) comme I1, R1, I2, R2 ou comme UPDATE, présenté plus haut. Dans l'en-tête fixe, commun à tous les paquets, se trouve une liste de paramètres HIP, encodés en TLV, qui permettent de transporter des informations comme les caractéristiques du puzzle (dans les paquets R1), la liste des algorithmes cryptographiques, etc). La liste de tous les paramètres se trouve dans un registre IANA.

Enfin, la section 6 détaille le traitement des paquets, ce qu'il faut faire en les recevant, les erreurs et la façon de les gérer (règle simple : ne pas renvoyer de paquets HIP en cas d'anomalie, seulement des ICMP, et avec un débit limité, car on ne peut pas être sûr du pair s'il y a une erreur), etc.

Notez aussi la section 7 de notre RFC, qui est consacrée à la politique de gestion des identificateurs. Elle recommande fortement que toute mise en œuvre de HIP permette de gérer au moins deux HI différents par machine. Un sera publié et servira à être contacté et au moins un autre sera « anonyme » (terme inexact mais c'est celui du RFC), non publié, utilisé uniquement pour initier des connexions et sera donc plus difficilement traçable. Un inconvénient de l'authentification forte des machines est en effet que cela risque de faire perdre de la vie privée. D'où cette idée d'identificateurs non reliables à une autre identité (si on est très prudent, on utilise un HI différent pour chaque répondeur auquel on se connecte).

La section 8 de notre RFC se penche sur les problèmes de sécurité, une plaie récurrente sur l'Internet d'aujourd'hui, et qui frappera certainement également HIP, s'il est massivement déployé. D'abord, les attaques par déni de service. Celles-ci prennent en général leur source dans une asymétrie, par exemple dans le fait que les coûts soient plus élevés pour l'une des parties. Voici pourquoi il faut quatre paquets pour établir une association : le premier envoyé par le répondeur, R1, peut être un paquet général, envoyé pour toutes les demandes d'association. Le répondeur ne stocke aucun état tant que l'initiateur n'a pas pu prouver son identité.

Comme le R1 est bien plus gros que le I1, HIP pourrait être utilisé pour une attaque par amplification (une attaque où la réponse est plus grosse que la question), en usurpant l'adresse IP source de sa victime. Comme avec le DNS et son RRL, un bon répondeur devrait limiter le rythme d'envoi des R1 par adresse IP.

Enfin, le plus dur, quand on compte sur la cryptographie pour se protéger, c'est de combattre les Hommes du Milieu. Rien ne sert de chiffrer avec les meilleurs algorithmes de cryptographie si, en croyant parler à son correspondant, on parle en fait à un homme du milieu qui s'est fait passer pour le correspondant. HIP a donc ce problème. Certes, les paquets sont signés mais comment être sûr que le HI du correspondant, qui sert à vérifier ces signatures, est le bon ? La seule solution fiable est de valider le HI du correspondant via un tiers. Par exemple, on a trouvé ce HI dans le DNS, dans une zone sécurisée par DNSSEC. Ou bien le HI était dans un certificat X.509 qu'on a validé.

On l'a vu, ce RFC 7401 normalise la version 2 de HIP. Quels sont les principaux changements par rapport à la version 1, normalisée dans le RFC 5201 ? La section 11 répond à cette question. D'abord, on utilise pour représenter les HIT la version 2 d'ORCHID, normalisée dans le RFC 7343 et non plus la v1 du RFC 4843, qui ne permettait l'agilité cryptographique. Résultat, les HIT commenceront désormais par 2001:20... et non plus 2001:10.... Ensuite, les HI peuvent désormais utiliser les courbes elliptiques, via ECDSA. Le protocole d'établissement de l'association a sérieusement changé, avec les paramètres Diffie-Hellman mis plus tôt. Et il y a également d'innombrables changements moins importants, mais qui font que le protocole est différent et incompatible avec la v1. La base installée de HIP étant très faible pour l'instant, cela n'est pas trop gênant. Ces modifications viennent de l'expérience avec HIP v1, obtenue par de nombreux essais avec les différentes mises en œuvre du protocole. Cette expérience a permis de faire passer HIP du statut « Expérimental », celui du RFC 5201, à celui de « Chemin des normes ».

Il existe plusieurs mises en œuvre de HIP v1 (cf. RFC 6538) et HIP for Linux ainsi que OpenHIP ont annoncé leur intention de les adapter à HIP v2.


Téléchargez le RFC 7401


L'article seul

RFC 7538: The Hypertext Transfer Protocol (HTTP) Status Code 308 (Permanent Redirect)

Date de publication du RFC : Avril 2015
Auteur(s) du RFC : J. Reschke (greenbyte)
Chemin des normes
Première rédaction de cet article le 10 avril 2015


Le protocole HTTP définit plusieurs codes de retour pour une redirection (« la ressource que tu cherches n'est pas ici, va voir là »). La section 6.4 du RFC 7231 classe ces trois codes de retour en notant que deux désignent des redirections temporaires (302 et 307) et qu'un désigne une redirection permanente (301). Deux codes permettent au client HTTP de remplacer, pour la nouvelle requête, la méthode POST par un GET (301 et 302), un autre ne le permet pas (307). Si vous avez suivi, vous avez noté qu'il manquait un code voulant dire « redirection permanente mais sans changer la méthode HTTP ». C'est l'objet du nouveau code décrit à l'origine dans le RFC 7238, et normalisé pour la première fois dans ce RFC, le code 308. Depuis, le RFC 9110 a intégré ce code, qui n'a donc plus de RFC séparé.

Donc, 308 veut dire (section 3 de notre RFC) que la ressource Web convoitée a changé de place, que c'est permanent et que le client HTTP devrait donc aller chercher la ressource au nouvel endroit et, s'il le peut, modifier sa base de données (dans le cas d'un crawler, par exemple, ou dans celui d'un navigateur qui modifie les marque-pages). Où est indiqué « le nouvel endroit » ? Par l'en-tête Location: de la réponse HTTP (cf. section 7.1.2 du RFC 7231). Il est recommandé d'inclure un petit texte en HTML fournissant un autre moyen de suivre la redirection, si le client HTTP n'a pas compris le 308. Bref, le 308 est très proche du 301, à la seule exception près qu'un client n'a pas le droit de changer la méthode HTTP (POST, GET, etc) utilisée. Le nouveau code est désormais dans le registre IANA.

Est-ce que l'information comme quoi il y a redirection peut être mémorisée dans les caches ? Il n'y a pas de mécanisme parfait pour cela mais lesdits caches sont invités à regarder le RFC 7234.

Ajouter un nouveau code HTTP peut provoquer des problèmes de déploiement (section 4). En effet, la section 6 du RFC 7231 dit que les codes inconnus commençant par 3 doivent être traités comme le code 300 (qui annonce des choix multiples, en cas de négociation de contenu). Au début, 308 va être inconnu de tous les clients HTTP et sera donc mal interprété. (Vous pouvez tester votre navigateur ici.) Il n'y aura pas de redirection automatique. En attendant que tous les clients soient mis à jour, le webmestre prudent n'utilisera 308 que s'il connait les clients utilisés, ou s'il sait que l'absence de redirection automatique n'est pas trop grave. Le RFC déconseille formellement de faire varier la réponse selon le client (ou selon ce qu'on croit être le client, rappelez-vous que le champ User-Agent: peut être trompeur), cela rend le Web trop difficile à déboguer.

Une façon de s'en tirer pourrait être via le code HTML suggéré plus haut. Par exemple :


HTTP/1.1 308 Permanent Redirect
Content-Type: text/html; charset=UTF-8
Location: http://example.com/new
Content-Length: 454

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
                      "http://www.w3.org/TR/html4/strict.dtd">
<html>
   <head>
      <title>Permanent Redirect</title>
      <meta http-equiv="refresh"
                 content="0; url=http://example.com/new">
   </head>
   <body>
      <p>
         The document has been moved to
         <a href="http://example.com/new">
         http://example.com/new</a>.
      </p>
   </body>
</html>

Ainsi, un navigateur Web qui ne comprend pas le 308 sera redirigé, via le <meta http-equiv="refresh" ....

Où en sont les mises en œuvre ? Vous pouvez tester sur le test de libcurl. Pour les navigateurs et autres clients :

Enfin, je signale deux bons articles sur le 308, un en français et un en anglais. Et, plus technique, la liste des tests qui ont montré que les déploiements du code 308 étaient suffisants pour que l'ancien RFC, expérimental, le RFC 7238, soit remplacé par ce nouveau RFC, qui est, lui, sur le chemin des normes. Aucun changement technique n'a été apporté, juste ce changement de statut.


Téléchargez le RFC 7538


L'article seul

RFC 7503: OSPFv3 Auto-Configuration

Date de publication du RFC : Avril 2015
Auteur(s) du RFC : A. Lindem (Cisco Systems), J. Arkko (Ericsson)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF ospf
Première rédaction de cet article le 10 avril 2015


Le protocole de routage OSPF est traditionnellement configuré statiquement, et à la main par l'administrateur réseaux. Certains réseaux, comme par exemple des réseaux un peu complexes à la maison, ont besoin d'un protocole de routage, mais sans avoir d'administrateur réseaux disponible. Il faudrait un OSPF qui se configure tout seul, « plug and play ». Ce court RFC montre que c'est possible, avec très peu de modifications des mises en œuvre d'OSPF.

Ce RFC concerne OSPF v3, normalisé dans le RFC 5340. Les changements du protocole par rapport à cette norme sont minimes. Par exemple, deux routeurs OSPF sont désormais autorisés à devenir adjacents (à établir une sorte de session entre eux), même si leurs valeurs des paramètres annoncés dans le paquet Hello, comme HelloInterval, diffèrent (dans un réseau auto-configuré, on ne peut pas espérer que tous les routeurs aient la même valeur, malgré ce que demandait l'annexe A.3.2 du RFC 5340). Autre exemple, une hystérésis a été ajouté lors de l'envoi de certains LSA (Link State Advertisement, les messages d'OSPF). Un routeur ayant les modifications permettant l'auto-configuration peut participer à un réseau avec des routeurs n'ayant pas ces modifications (l'inverse n'est pas vrai : un routeur OSPF classique aura du mal à s'insérer dans un réseau auto-configuré). Ces changements sont nécessaires pour s'adapter aux réseaux qui, tout en étant non-gérés, sont composés de plusieurs liens et plusieurs routeurs, commme ceux envisagés par le projet Homenet (RFC 7368).

La section 2 de notre RFC liste les paramètres que doivent adopter les routeurs auto-configurés :

  • La zone (area) doit être 0.
  • OSPF doit être activé sur toutes les interfaces IPv6 du routeur, sauf si on est sûr d'avoir une très bonne raison de ne pas le faire. Par exemple, pour un routeur CPE, genre box, le RFC 7084 demande évidemment qu'on ne fasse pas tourner de protocole de routage dynamique sur l'interface qui mène au FAI.
  • Le type de réseau OSPF (broadcast network ou point-à-point) doit être configuré en fonction du type de réseau physique (Ethernet et Wi-Fi seront tous les deux broadcast network, cf. RFC 2328, section 1.2).
  • Chaque routeur a le choix de paramètres comme HelloInterval (voir la section 3 du RFC pour les détails).
  • Le choix de l'Instance ID (RFC 5838) doit être 0 pour IPv6 et 64 pour IPv4.

A priori, les réseaux auto-configurés n'auront aucune forme d'authentification, celle-ci nécessitant une certaine action de l'administrateur, par exemple entrer les mots de passe (section 4 de notre RFC). Si, toutefois, on veut authentifier, il est recommandé d'utiliser l'option du RFC 7166.

Dans OSPF, chaque routeur a un router ID (RFC 2328, section 1.2), qui fait 32 bits mais n'est pas une adresse IPv4. Il doit être unique dans la zone donc il faut que tous les routeurs auto-configurés se débrouillent pour ne pas prendre le même (autrefois, c'était une adresse IPv4, et celle du routeur - RFC 5340, annexe C.1, donc l'unicité était facilement garantie). Il faut donc désormais la générer aléatoirement, en utilisant comme graine du générateur aléatoire une information unique, comme le router hardware fingerprint décrit en section 7.2.2.

Même dans ce cas, des collisions de router ID sont possibles. Il faut donc une procédure de détection des duplicatas (section 7) qui consiste, pour les voisins immédiats, à se rendre compte qu'un LSA porte le même router ID que vous, avec une adresse IPv6 différente. Il faudra alors changer : c'est le routeur avec la plus petite adresse IP qui doit changer son router ID. Cette procédure de détection et de correction a été le plus gros sujet de discussion au sein du groupe de travail à l'IETF.

Pour les routeurs non-voisins, on utilise un nouveau TLV placé dans le LSA d'auto-configuration, Router-Hardware-Fingerprint, déjà mentionné au paragraphe précédent (au passage, ce nouveau LSA, prévu pour l'auto-configuration, est le numéro 15 et les valeurs qu'il contient font l'objet d'un nouveau registre). Sa valeur est un nombre qui a de très fortes chances d'être unique. Il est recommandé de le fabriquer en concaténant des valeurs probablement uniques, mais stables, comme l'adresse MAC, et numéro de série du routeur.

Comme vu plus haut au sujet de l'authentification, la sécurité ne s'entend pas bien avec l'auto-configuration (section 8 du RFC). L'auto-configuration fait que n'importe quelle nouvelle machine va être « adoptée » par le réseau et pourra y participer immédiatement. Une aubaine pour un attaquant. Si on n'est pas prêt à accepter cela, il faut recourir aux mécanismes d'authentification décrits dans la section 4 (RFC 7166 ou RFC 4552).

Tout le monde n'a pas forcément envie d'utiliser l'auto-configuration, surtout étant donné ses conséquences en termes de sécurité. Il faut donc un moyen de débrayer cette possibilité (section 9 de notre RFC). (Bien sûr, il faut aussi des moyens de configurer des paramètres comme le HelloInterval ou comme le mot de passe, si on veut faire de l'auto-configuration mais en choisissant certains paramètres.)

Voilà, il ne reste plus qu'à déployer ces nouveaux réseaux : d'après les auteurs, il y a déjà deux ou trois mises en œuvre d'OSPF qui incorporent les règles de ce RFC.


Téléchargez le RFC 7503


L'article seul

RFC 7485: Inventory and Analysis of WHOIS Registration Objects

Date de publication du RFC : Mars 2015
Auteur(s) du RFC : L. Zhou, N. Kong, S. Shen (CNNIC), S. Sheng (ICANN), A. Servin (LACNIC)
Pour information
Réalisé dans le cadre du groupe de travail IETF weirds
Première rédaction de cet article le 9 avril 2015


Dans le cadre de la mise au point du protocole RDAP d'accès aux informations sur des objets enregistrés, le groupe de travail à l'IETF s'était livré à une intéressante étude sur les objets enregistrés et accessibles via l'ancien protocole whois. Cette étude a servi à mieux définir ce qu'il fallait comme services dans RDAP, et à spécifier le format de sortie de RDAP, normalisé dans le RFC 7483. Elle a montré, sans surprises, une grande variabilité : si beaucoup d'éléments d'information sont communs à un grand nombre de registres, c'est souvent sous des noms différents. Cette variabilité est, selon les goûts, un des charmes ou un des principaux défauts des registres de l'Internet.

L'étude qui a servi de base à ce RFC date de 2012 (section 3 de notre RFC, pour la méthodologie). Les données ont été récoltées via whois mais aussi via les interfaces Web d'interrogation des registres (à la fois registres de noms de domaine et registres d'adresses IP). Pour les TLD, le nom nic.$TLD a été utilisé, 106 ccTLD ont permis de récupérer de l'information sur ce nom, ainsi que 18 gTLD. Parfois, l'information a été vérifiée en essayant d'autres noms que nic.$TLD. Les capacités des serveurs whois interrogés étaient très variées (cf. section 5.1). Par exemple, si tous permettent évidemment des requêtes au sujet d'un domaine donné, certains permettent aussi des requêtes pour un contact précis ou pour un BE particulier. Pour les registres d'adresses IP, les cinq RIR ont été interrogés.

La section 4 présente les résultats pour les RIR. On y voit déjà la variété des étiquettes qui fait la beauté de whois. Ainsi, le nom de l'organisation titulaire d'un préfixe IP est étiqueté organisation à AfriNIC, Owner à LACNIC et org-name au RIPE-NCC. La date d'enregistrement d'un contact est changed à AfriNIC, RegDate à ARIN et created à LACNIC. Un préfixe IP se nomme inetnum à l'APNIC ou au RIPE-NCC, mais NetRange ou CIDR à l'ARIN (selon qu'il est IPv4 ou IPv6 !) Voici un exemple à l'APNIC :

inetnum:        1.2.2.0 - 1.2.2.255
netname:        KNET
descr:          KNET Techonlogy (BeiJing) Co.,Ltd.
descr:          4,South 4th treet, Zhongguancun,Haidian District,Beijing
admin-c:        ZX2975-AP
tech-c:         WL1818-AP
country:        CN
mnt-by:         MAINT-CNNIC-AP
mnt-irt:        IRT-CNNIC-CN
mnt-routes:     MAINT-CNNIC-AP
status:         ALLOCATED PORTABLE
changed:        ipas@cnnic.cn 20150107  

Certains éléments ne sont pas présents dans tous les RIR et ceux qui le sont reçoivent, comme on vient de le voir, des noms différents.

Et pour les registres de noms de domaine ? C'est évidemment encore plus varié (au fait, les résultats bruts de la collecte faite pendant l'étude sont disponibles en ligne). Au total, 68 éléments différents ont été identifiés, sous 550 étiquettes distinctes. Les auteurs du RFC les ont classé en éléments publics et autres éléments. Les éléments publics sont ceux qui sont mentionnés dans le document ICANN, « gTLD Applicant Guidebook » de 2012, ou bien dans les RFC sur EPP, RFC 5730, RFC 5731, RFC 5732 ou RFC 5733 (un choix très contestable qui donne une sorte de privilège aux règles des TLD régulés par le gouvernement états-unien).

Parmi les exemples d'éléments publics, on peut trouver évidemment le nom de domaine (l'étiquette la plus fréquente étant domain name mais cinq autres ont été trouvées) suivi de la date de création (en général created mais vingt-trois autres étiquettes sont possible, la deuxième plus grande variété de vocabulaire). 95 % des registres ont donc un élément « nom de domaine » (on peut se demander comment font les 5 % restants...), 85 % une date de création, 77 % un statut du domaine, etc. Par contre, « dernier transfert », le moins fréquent, n'est présent que chez 3 % des registres.

On retrouve la même variété pour les titulaires et les contacts. Aucun élément n'est présent dans la majorité des registres (même pas l'adresse de courrier électronique). Ceux qui le sont ont des noms très variés. Ainsi, pour le contact technique, le téléphone dudit contact est décrit par pas moins de dix étiquettes différentes.

Le cas des serveurs de noms est plus compliqué car, contrairement aux contacts, le serveur de noms n'est pas forcément un objet de première classe dans le modèle de données du registre : il peut être un simple attribut du domaine. C'est pour cela que, dans le monde EPP, le RFC 5732 n'est pas mis en œuvre partout. Ainsi, alors que 92 % des registres indiquent les serveurs de noms dans les réponses (sous 63 étiquettes distinctes, un record, en partie dû à des mécanismes de nommage comme nameserver N avec N indiquant le rang du serveur), tous ne permettent pas des requêtes whois directes sur un serveur de noms.

Enfin, il y a les éléments « divers », ceux qui ne sont pas spécifiés dans les règles ICANN ou dans les RFC sur EPP et qui incluent, par exemple, l'URL d'un site Web associé au domaine, un champ de commentaires (remarks), une date d'anniversaire (six TLD sont dans ce cas, probablement tous à l'AFNIC), un identificateur de marque déposée, etc. La section 6 de notre RFC suggère que des extensions au modèle de données de RDAP pourraient s'inspirer de ces éléments divers, par exemple le point de contact du NOC (pourquoi diable ne pas se contenter du contact technique ?), le fait que l'identité du titulaire soit masquée (ce qui est parfois noté, bien à tort, anonymous), etc.

Il n'y a pas que le modèle de données (et la terminologie associée) qui varie beaucoup d'un registre à l'autre, il y a aussi le format de présentation. Les deux les plus populaires sont clé:valeur et en bloc. Un exemple en clé:valeur est donné par .org :

Domain Name:TV5.ORG
Creation Date: 1995-09-29T04:00:00Z
Updated Date: 2013-09-30T14:24:25Z
Sponsoring Registrar:Gandi SAS (R42-LROR)
...
Registrant Name:Thomas Derobe
Registrant Organization:TV5 Monde
Registrant Street: 131 avenue de Wagram

Un exemple de bloc par le registre de .za :

    Domain Name:
        sab.co.za

    Registrant:
        The South African Breweries Limited
        
        Email: domains@sabmiller.com
        Tel: +27.118818414
        Fax: +27.118818136

    Registrant's Address:
        P.O.Box 782178
        2196 Sandton Sandown
        ZA

    Registrar:
        Ascio

    Relevant Dates:
        Registration Date: 1997-05-06
        Renewal Date:      2015-05-06

    Domain Status:
        Registered until renewal date

Mais il faut remarquer qu'on trouve de tout. Comment classer le résultat du whois de .jp ?

Domain Information:
a. [Domain Name]                YAMAHA.CO.JP
g. [Organization]               YAMAHA Corporation
l. [Organization Type]          Corporation
m. [Administrative Contact]     HN050JP
n. [Technical Contact]          TT9781JP
p. [Name Server]                ns1.dhs.jtidc.jp
p. [Name Server]                ns2.dhs.jtidc.jp
s. [Signing Key]                
[State]                         Connected (2016/03/31)
[Registered Date]                
[Connected Date]                2010/08/02
[Last Update]                   2015/04/01 01:12:19 (JST)

À noter également que onze registres envoient l'information autrement qu'en anglais dans l'alphabet latin (le RFC, comme beaucoup de documents écrits dans le milieu ICANN, confond langue et écriture et écrit « 11 registries give local script responses. The WHOIS information of other registries are all represented in English. »).

Bref, ce RFC illustre bien une des motivations principales du projet RDAP : normaliser la sortie du serveur, de façon à faciliter les traitements automatiques.


Téléchargez le RFC 7485


L'article seul

RFC 7530: Network File System (NFS) Version 4 Protocol

Date de publication du RFC : Mars 2015
Auteur(s) du RFC : T. Haynes (Primary Data), D. Noveck (Dell)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF nfsv4
Première rédaction de cet article le 7 avril 2015


Le protocole d'accès aux fichiers NFS est très ancien. Sa version 2 est décrite dans le RFC 1094, sa version 3 dans le RFC 1813 et la version 4 faisait l'objet du RFC 3530, qui vient d'être remplacé par ce nouveau RFC. Rien de spectaculaire, juste des clarifications. Notez que, malgré son ancienneté, NFSv3 reste encore très utilisé.

NFS est un gros protocole compliqué (ce RFC fait 300 pages tout rond, et la section 1.1 affirme sans rire qu'une des caractéristiques de NFS est sa simplicité) et n'est pas ma spécialité donc je vais passer rapidement et me contenter des grandes lignes du protocole. NFS permet donc l'accès distant à des fichiers. Les versions anciennes utilisaient au moins deux protocoles distincts, NFS lui-même et « mount » mais NFSv4 n'en a plus qu'un. De même, les éventuels protocoles supplémentaires pour avoir des fonctions de verrouillage des fichiers ont disparu, tout étant désormais intégré dans NFS. Autres caractéristiques importantes de la version 4 (qui fêtera ses quinze ans à la fin de l'année), une meilleure prise en compte de la sécurité (avec négociation de la sécurité), de l'internationalisation, des possibilités de cache chez le client, et un meilleur fonctionnement au dessus de l'Internet (les versions précédentes marchaient surtout en réseau local). NFSv4 essaie aussi d'être plus agnostique par rapport au système d'exploitation sous-jacent, les précédentes versions étant très orientées Unix.

À noter que les RFC sur les versions 2 et 3 de NFS étaient de simples documentations d'un protocole développé de manière fermée par Sun, alors que NFSv4 est entièrement développé à l'IETF.

NFS repose sur la représentation XDR, RFC 7531 et sur le mécanisme RPC (RFC 4506 et RFC 5531, étendu, pour la sécurité, par le RFC 5403).

NFS est un service d'accès aux fichiers : son modèle est celui d'un système de fichiers hiérarchique (avec des répertoires qui peuvent contenir des fichiers et d'autres répertoires). Les noms des fichiers et répertoires sont forcément en UTF-8, pour l'internationalisation. Le contenu des fichiers n'est pas interprété par NFS, c'est juste une suite d'octets. Quand un client NFS ouvre un fichier, il reçoit un filehandle, un identificateur qu'il utilisera dans les requêtes d'entrée/sortie suivantes. Avec les précédentes versions de NFS, on obtenait ce filehandle via le protocole « mount » mais ce protocole a désormais disparu (entre autres en raison de sa faible sécurité, et car il ne permettait pas facilement de passer les pare-feux). Désormais (idée qui remonte aux RFC 2054 et RFC 2055), les filehandles s'obtiennent directement avec le protocole NFS. Les filehandles peuvent être permanents ou temporaires (une nouveauté de NFSv4). Chaque fichier peut avoir toute une collection d'attributs, comme le type du fichier (fichier ordinaire ou répertoire) ou comme des ACL.

Autre changement par rapport à NFSv3, les opérations d'ouverture et de fermeture du fichier sont désormais explicites. La fermeture permet au serveur de libérer tout état associé au fichier, ce qui était impossible dans les vieilles versions de NFS.

Autre propriété importante de NFSv4 : le serveur peut déléguer à un client certaines responsabilités. Si un client a une délégation de lecture, il est sûr qu'aucun autre client ne pourra écrire dans le fichier pendant ce temps. S'il a une délégation d'écriture, personne n'aura aucun accès au fichier tant que la délégation durera.

NFSv2 et NFSv3 utilisaient un port fixe, 2049 (tout en dépendant de portmap pour des raisons que je n'ai jamais comprises). NFSv4 permet d'utiliser plusieurs transports, comme TCP ou SCTP, et n'est pas forcément sur le port 2049.

La section 1.5 de notre RFC résume les changements qu'a connus NFSv4 depuis le RFC 3530. Le protocole est le même, ce sont surtout des différences de rédaction comme :

  • XDR a été déplacé vers un RFC distinct, le RFC 7531.
  • Les références à des noms de domaine, par exemple pour les noms de propriétaires des fichiers, suivent désormais la nouvelle norme IDN, le RFC 5891.

Il existe aujourd'hui des mises en œuvre de NFS pour tous les systèmes. Certaines font au choix du NFSv3 ou du NFSv4, certaines sont encore purement NFSv3.


Téléchargez le RFC 7530


L'article seul

Fiche de lecture : Hadopi - Plongée au cœur de l'institution la plus détestée de France

Auteur(s) du livre : Tris Acatrinei
Éditeur : Fyp
978-2-36405-101-0
Publié en 2013
Première rédaction de cet article le 6 avril 2015


Qui s'intéresse encore à l'HADOPI ? Cette institution, créée pour plaire aux ayant-trop-de-droits qui veulent à tout prix maintenir leur modèle économique existant, a été en effet « l'institution la plus détestée de France », au moins chez les internautes. Depuis, nous avons eu les révélations de Snowden sur la NSA, la censure administrative du Web, le projet de loi Renseignement et l'HADOPI semble, par comparaison, bien inoffensive. Pourtant, c'était une des institutions qui ont pavé la voie pour un contrôle de plus en plus étroit de l'Internet par l'administration et, à ce titre, il est toujours utile de suivre son histoire. Ce récit très vivant par une ex-employée de l'HADOPI est toujours intéressant à lire. (Le site officiel.)

C'est que l'HADOPI a eu une histoire compliquée, hésitant entre jouer franchement son rôle de méchant, chargé de la répression des tentatives de partage de la culture, et faire semblant d'être une organisation progressiste, défrichant des nouvelles voies, faisant de la pédagogie, développant des nouveaux moyens de diffuser la culture. Plusieurs personnes de bonne volonté se sont fait prendre à ce discours et ont choisi de donner un coup de main pendant un certain temps à l'HADOPI (notamment dans ses « Labs »). L'auteure de ce livre, elle, a été recrutée pour le plus beau métier du monde : community manager, elle était chargée de défendre la HADOPI face à ces internautes que l'institution était chargée de persécuter.

Difficile de tirer un bilan de cette courte expérience : malgré un budget démesuré, l'HADOPI ne s'est jamais lancé dans des projets vraiment ambitieux (par exemple développer l'offre légale...) Détestée des internautes, ridiculisée par des campagnes de publicité lamentables, ou par des projets sans suite (comme le label PUR, pour lequel j'avais failli remplir un dossier, pour que ce blog soit labelisé...), vite rejetée par les ayant-tous-les-droits qui la trouvaient pas assez répressive, l'HADOPI ne laissera que le souvenir d'un grand gaspillage.

L'intérieur ne vaut pas l'extérieur et Tris Acatrinei raconte tout ce qui avait aussi plombé l'HADOPI en interne : bureaucratie incompréhensible, règles administratives ultra-contraignantes qui bloquaient bien des projets, luttes entre services, les ingrédients habituels d'une administration. Son récit du cheminement d'un simple article de blog, qui devait être validé à l'issue d'un long processus (utilisant le papier, bien sûr), illustre bien le décalage entre l'administration française et l'Internet.

Bien sûr, tout n'était pas de la faute de l'HADOPI. Tris Acatrinei décrit bien l'étonnant maquis des intermédiaires de la culture, comme ces innombrables organisations qui collectent l'argent à la place des créateurs, bénéficient d'un statut bizarre (organisations de droit privé mais bénéficiant d'un monopole public) et s'opposent à tout changement, sauf s'il va encore plus loin dans la protection de leurs droits (qui ne sont évidemment pas ceux des auteurs).

L'auteure remet bien la question, finalement très secondaire, de l'HADOPI en perspective : elle rappelle la genèse de cette organisation, au milieu de tous les débats qui ont agité la France au sujet de la diffusion de la culture sur l'Internet. Et, après avoir exposé le fonctionnement de l'HADOPI vu de l'intérieur, elle se lance dans une réflexion sur les moyens d'améliorer cette diffusion. Finalement, le plan du livre résume bien ce qu'a été la trajectoire de l'HADOPI : un problème mal posé, une organisation inefficace et répressive, un problème toujours grand ouvert.


L'article seul

RFC 7481: Security Services for the Registration Data Access Protocol

Date de publication du RFC : Mars 2015
Auteur(s) du RFC : S. Hollenbeck (Verisign Labs), 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 4 avril 2015


Une des faiblesses les plus souvent citées de l'ancien protocole whois est son manque de sécurité : pas d'authentification du client (et donc pas de moyen simple de servir des contenus plus ou moins complets selon le client), et pas de confidentialité. Le candidat à sa succession, RDAP, va-t-il faire mieux ? En tout cas, il propose de nombreux services de sécurité, détaillés dans ce RFC. Comment et au profit de qui les utiliser, voici qui va sans doute déclencher de nouvelles disputes de gouvernance.

Le nouveau protocole RDAP est normalisé dans plusieurs RFC comme le RFC 7480 qui décrit comment faire tourner RDAP sur HTTP avec une architecture REST. La grande majorité des fonctions de sécurité de RDAP découlent de cette utilisation de HTTP. Ces fonctions étaient réclamés dès le cahier des charges pour un successeur de whois, le RFC 3707.

La section 3 de notre RFC liste les services de sécurité attendus, et la manière dont RDAP les fournit, en général en s'appuyant sur les services équivalents fournis par HTTP et HTTPS. Ainsi, la premier service demandé est le contrôle d'accès et la section 10.2.2 du RFC 7483, RFC consacré au format des réponses RDAP (en JSON) prévoit un mécanisme standard pour indiquer qu'une partie de la réponse a été délibérement tronquée ou omise.

Ensuite, l'authentification (section 3.1.4.2 du RFC 3707). Pas d'autorisation fine sans authentification préalable. Avec whois, on doit servir les mêmes données à tout le monde, car il n'y a pas d'authentification disponible (parfois, une authentification sommaire est faite via l'adresse IP du client, un registre peut servir davantage d'informations à ses employés, en vérifiant que l'adresse IP source est celle du réseau local du registre). Quand RDAP tourne sur HTTP, il doit donc utiliser les mécanismes d'authentification de HTTP, décrits dans le RFC 7235. Si on utilise le mécanisme basic, qui envoie en clair le mot de passe, il faut en plus utiliser TLS (RFC 2818). On peut aussi tout faire avec TLS, en authentifiant le client par un certificat (section 7.4.6 du RFC 5246) mais c'est optionnel dans RDAP, contrairement aux mécanismes du RFC 7235, qui doivent être présents. Ces mécanismes ne permettent pas d'authentifier le serveur, mais on peut, là encore, se servir de TLS pour cela (en vérifiant le certificat du serveur).

Les mécanismes classiques d'authentification via HTTP nécessitent que le client gère des informations de créance pour tous les serveurs. Or, un même client RDAP peut parler à de nombreux serveurs. Il est donc intéressant de regarder du côté des mécanismes d'authentification fédérés, qui peuvent permettre de n'avoir qu'une seule information de créance, utilisée pour tous les serveurs. Il existe pour cela plusieurs techniques utilisable en HTTP, OAuth (RFC 6749), OpenID, des assertions SAML, ou bien des certificats client avec des AC reconnues par tous les serveurs. À noter que RDAP ne dispose pas (pas encore ?) d'une solution pour découvrir quel mécanisme d'authentification est utilisé par quel serveur.

Une fois qu'on a l'authentification, on peut bâtir l'autorisation et donner des accès aux clients en fonction de leur identité (section 3.1.4.2 du RFC 3707). On peut par exemple :

  • Permettre un accès à tout client (mode « anonyme » comme avec le whois actuel) mais en ne donnant accès qu'à peu d'informations,
  • Ne donner un accès complet qu'aux informations ayant un rapport avec le client (par exemple permettre à un titulaire de tout voir sur ses propres noms),
  • Donner un accès complet aux clients authentifiés comme travaillant pour la NSA.

Au bout du compte, il s'agit de décisions politiques, à prendre dans chaque registre, et ce RFC n'indique donc pas de politique, il indique juste les bases sur lesquelles mettre en œuvre une telle politique.

Parmi les services de sécurité, il y a bien sûr la disponibilité : un serveur RDAP super-protégé mais qui serait tout le temps en panne n'aurait guère d'utilité. Notre RFC rappelle donc qu'il existe un RFC sur les attaques par déni de service (le RFC 4732). Un serveur RDAP est autorisé à se prémunir contre les attaques et les excès, par exemple en limitant d'autorité le trafic. Si un client est refusé en raison de cette limitation, le code de retour HTTP recommandé est le 429 (RFC 6585). Si le client est simplement trop enthousiaste, il ralentira alors ses accès. Évidemment, si c'est un attaquant, il continuera.

Autre service de sécurité essentiel, la confidentialité. Whois n'avait aucun mécanisme de protection contre un tiers qui écoute le réseau (d'un autre côté, comme tout était public...) RDAP permet d'utiliser HTTP sur TLS (RFC 2818), permettant ainsi au chiffrement de protéger la confidentialité des données. (On note que les serveurs RDAP expérimentaux actuellement existants sont loin de tous permettre un accès en HTTPS.) À noter que TLS protège le canal, pas les données : il n'y a pas de chiffrement de bout en bout dans RDAP, pour l'instant.

Et le dernier service de sécurité dont on veut disposer est l'intégrité, la garantie que les données ne soient pas modifiées en route. Il n'existe pas non plus de mécanisme de signature des données dans RDAP, mécanisme qui assurerait une protection de bout en bout. Il faut donc utiliser TLS, dont les paquets comportent un MAC qui permet de détecter les modifications.

On a parlé de confidentialité mais la section 4 de notre RFC pose le problème dans une perspective plus générale, celle de la protection de la vie privée. Ce problème est la plaie de whois (« notre conflit du Moyen-Orient », disait Fadi Chehadé en faisant allusion à la durée du problème et à l'absence de perspectives de solution) et a fait l'objet d'innombrables débats, à l'ICANN ou ailleurs. Comme whois ne fournit aucun accès différencié (tout est public ou pas distribué du tout), les données stockées dans les registres, qui sont souvent sensibles, sont envoyées à tous. Résultat, la seule protection est souvent de mentir, dissimulant ses données personnelles. Parfois, il existe des services intermédiaires qui masquent les données, relaient le courrier, etc. RDAP ne change pas la question des données récoltées et stockées par le registre (si le registre se fait pirater, ou bien s'il donne toutes ses données à des services de surveillance étatiques ou non, la vie privée sera compromise, RDAP ou pas RDAP). En revanche, il permet de ne pas envoyer les données à tout le monde, réservant par exemple les données personnelles à certains clients. RDAP permet par exemple de transmettre davantage de données à des membres des forces de l'ordre, dûment authentifiés. Notez donc que RDAP va soulever des problèmes à lui, que n'avait pas whois. Whois ne permettait techniquement pas de donner plus d'informations aux forces de l'ordre, ou aux ayant-droits, ou à d'autres catégories. RDAP le permet techniquement et certains acteurs le demanderont sans aucun doute.

Comme toujours en protection des données personnelles, le mieux, pour éviter les ennuis, est de ne pas récolter les données du tout. Cette solution simple est la plus efficace, protégeant aussi bien du piratage que d'un opérateur indélicat. Ainsi, les réponses RDAP utilisent jCard (RFC 7095) pour les données personnelles. jCard a énormément de champs possibles et tous ne sont pas pertinents pour le registre. Il est donc possible de ne pas les collecter (et donc de ne pas les envoyer).

À noter qu'il existe aussi un risque lié à la vie privée pour le client : les requêtes qu'il fait peuvent donner des informations sur son activité. Le chiffrement protège contre l'accès d'un tiers à ces informations, mais pas contre le registre lui-même, qui doit donc rester discret sur les requêtes qu'il reçoit.

La section 5 du RFC couvre quelques risques de sécurité résiduels. Par exemple, on voit souvent dans les réponses whois des tentatives d'injection, notamment de code HTML. Notre RFC rappelle donc que les données renvoyées par RDAP ne sont pas forcément sûres et qu'un client RDAP ne doit pas les afficher aveuglément, ni les mettre dans une base de données sans faire attention.

Et, enfin, la section 5 de notre RFC rappelle aussi que le protocole peut assurer des choses comme l'intégrité des données (ce qui a été reçu par le client est bien ce qui avait été envoyé par le serveur) mais que cela ne garantit pas l'exactitude des données : celles-ci étaient peut-être fausses dès le début, soit par négligence de la part de celui qui les a déclarées, soit parce que mentir est, à l'heure actuelle, souvent le seul moyen de protéger ses données personnelles.


Téléchargez le RFC 7481


L'article seul

Fiche de lecture : Neuroland

Auteur(s) du livre : Sébastien Bohler
Éditeur : Robert Laffont
9-782221-144756
Publié en 2015
Première rédaction de cet article le 4 avril 2015


Ce roman commence avec des attentats islamistes et un ministre de l'Intérieur qui veut en profiter pour faire avancer un projet de haute technologie que lui avait vendu un commercial ambitieux. Non, ce n'est pas Blue Coat convaincant Bernard Cazeneuve de déployer des boîtes noires dans l'Internet. (Le livre a été écrit avant les événements de janvier et avant le projet de loi Renseignement.) C'est plus que cela, il s'agit d'explorer directement le cerveau. Comme dans la précédent roman de Sébastien Bohler, « Les soldats de l'or gris », on va exploiter la neurologie pour faire la guerre.

Mais les ambitions scientifiques ont un peu baissé : on n'essaie plus de contrôler le cerveau, juste de lire dedans. Un ambitieux scientifique prétend qu'on pourra bientôt connaître les pensées grâce aux avancées en traitement des images de l'activité cérébrable. Le ministre est facilement convaincu : après un attentat épouvantable, les gens réclament de l'action. Et puis le ministre espère bien avoir un monopole sur cette activité, imaginant déjà toutes les polices du monde apportant discrètement leurs suspects dans les locaux de Neuroland, à Saclay, pour lire leurs pensées.

Mais est-ce réellement faisable techniquement ? Et le scientifique qui a vendu cette idée est-il de confiance ? Les ambitions des scientifiques ne sont pas forcément compatibles entre elles, ni avec celles du patron de Neuroland, ou avec celles du ministre, et beaucoup de choses ont été dissimulées pour lancer le projet, choses dont la révélation peut le mettre en péril. Pour sauver le projet, il faudra un peu oublier les principes du début...

Excellent mélange de science, de violence, et de politique, une lecture très recommandée. Je vous laisse essayer de retrouver de quels personnages réels sont inspirés des gens comme le fondateur de Neuroland. Ne vous arrêtez pas aux trois premiers chapitres, la fin est bien plus riche et plus compliquée.

Avertissement : j'ai reçu un exemplaire gratuit (mais je ne fais de critiques favorables que s'il est accompagné d'une boîte de chocolats.)

Une bonne critique radiophonique (mais qui révèle un peu trop de l'intrigue) est chez France Bleu. (Il y a aussi celle-ci sur Europe 1, vers 25'30 du début, mais je ne l'ai pas encore écoutée.)


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. (Depuis, ce RFC a été remplacé par le RFC 9224, mais il y a peu de changements.)

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 8259), 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. 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"
}

Et celui des TLD, qui nous montre les deux pionniers, la république tchèque et l'Argentine :


% curl -v http://data.iana.org/rdap/dns.json
{
  "description": "RDAP bootstrap file for Domain Name System registrations",
  "publication": "2016-12-09T04:10:13Z",
  "services": [
    [
      [
        "ar"
      ],
      [
        "https://rdap.nic.ar"
      ]
    ],
    [
      [
        "cz"
      ],
      [
        "https://rdap.nic.cz"
      ]
    ]
  ],
  "version": "1.0"
}

Testons si cela marche vraiment :

% curl -v https://rdap.nic.ar/domain/edu.ar
...
   "nameservers": [
      {
        "objectClassName": "nameserver",
        "handle": "noc.uncu.edu.ar",
        "links": [
          {
            "href": "https://rdap.nic.ar/nameserver/noc.uncu.edu.ar",
            "type": "application/rdap+json",
            "rel": "self",
            "value": "https://rdap.nic.ar/nameserver/noc.uncu.edu.ar"
          }
        ],
        "ldhName": "noc.uncu.edu.ar"
      },
      {
        "objectClassName": "nameserver",
        "handle": "ns1.mrecic.gov.ar",
        "links": [
          {
            "href": "https://rdap.nic.ar/nameserver/ns1.mrecic.gov.ar",
            "type": "application/rdap+json",
            "rel": "self",
            "value": "https://rdap.nic.ar/nameserver/ns1.mrecic.gov.ar"
          }
        ],
        "ldhName": "ns1.mrecic.gov.ar"
      },
      ...

Parfait, tout marche.

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

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 8259, 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ésout 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 8259) 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 8259), et les noms de membres dupliqués dans les objets (cf. la section 4 du RFC 8259). 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 8259, 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 lettres 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

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

Première rédaction de cet article le 30 mars 2015
Dernière mise à jour le 7 avril 2015


Hier, aux JDLL (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é :


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 a finalement été décrit dans le RFC 8825.)

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 (la bonne solution serait bien sûr de déployer IPv6 mais l'opposition des opérateurs rend les choses difficiles),
  • 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 8489) et TURN (RFC 8656, le tout avec ICE (RFC 8445). 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 bouillonnement 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. (Voir le RFC 8569.)

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 ressources. 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 distribuer 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 ensuite 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é (traitée plus en détail, par la suite, dans le RFC 7927).


Téléchargez le RFC 7476


L'article seul

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 elles-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é 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 8259). 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 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. (Depuis, ce RFC a été légèrement mis à jour par son remplaçant, le RFC 9082.)

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 non 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 rappelle 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'autorisation : qu'est-ce que je renvoie, et à qui ?

Téléchargez le RFC 7482


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 tout 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 9111. 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 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. (Depuis, le RFC 9083 a remplacé ce RFC. Les quelques changements vont surtout dans le sens d'un durcissement des obligations, avec moins de choix laissés à l'initiative du serveur.)

JSON est normalisé dans le RFC 8259 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 8259, 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 8288 :

         "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 notices 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 davantage, 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 notices, remarks, status, roles 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

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 Laurent 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 1 mai 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.

J'ai recommencé, avec un format plus court, le 17 avril, à Lyon pour Mix-IT (merci à Agnès Crepet) et, cette fois, cela a été filmé. Guillaume Lucas en a fait une version visible avec du logiciel libre et a ajouté quelques commentaires.


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 8259. 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 8259, 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 8259, 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.

Notez un format proche (mais différent : ce serait trop simple autrement), JSON Lines.


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 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. (En 2021, les paramètres recommandés étaient toujours valables.)

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

RFC 7444: Security Labels in Internet Email

Date de publication du RFC : Février 2015
Auteur(s) du RFC : K. Zeilenga, A. Melnikov (Isode)
Pour information
Première rédaction de cet article le 19 février 2015


On a souvent besoin, lorsqu'on transmet un document, d'indiquer le niveau de sensibilité ou de confidentialité du document. Quelque chose du genre SECRET ou CONFIDENTIEL. Cela peut être fait de manière non structurée, par du texte (par exemple dans l'objet du message) mais cela ne permet pas aux logiciels d'agir automatiquement sur la base de ce texte. D'où l'idée d'un nouveau champ dans l'en-tête du message, SIO-Label:, pour indiquer de manière structurée la sécurité souhaitée pour ce message.

Dans beaucoup d'organisations (l'armée étant un exemple typique), la présence d'une telle indication a des conséquences pratiques comme « les documents marqués CONFIDENTIEL ou supérieur doivent être enfermés dans un coffre quand on sort du bureau » ou bien « on ne doit envoyer les documents marqués SECRET qu'aux gens disposant de telle habilitation ». D'où l'importance de pouvoir indiquer ces niveaux de sécurité. À noter qu'ils sont présentés et discutés dans la norme UIT X.841, Security information objects for access control.

Le protocole XMPP avait déjà une norme pour les niveaux de sécurité, XEP-0258. Ce nouveau RFC part des mêmes concepts et les applique au courrier électronique (RFC 5322).

La section 1.1 de notre RFC rappelle les anciennes méthodes. Typiquement, on met en avant un texte qui indique le niveau de sécurité. Par exemple :


To: author <author@example.com>
From: Some One <someone@example.net>
Subject: [SECRET] the subject 

SECRET

Text of the message.

SECRET

Dans ce message à la syntaxe RFC 5322, le niveau de sécurité (SECRET) a été mis dans le champ Subject: (encadré entre crochets pour être clairement séparé de l'objet normal), et répété au début (marquage FLOT First Line Of Text) et à la fin (LLOT Last Line Of Text) du message. De telles conventions sont fréquentes dans une communauté donnée (par exemple dans la même organisation, ou bien dans un groupe de gens travaillant sur le même projet). Elles vont sans doute continuer à être utilisées pendant longtemps, le nouveau système venant juste d'être spécifié. Pour un humain, même distrait, ces marques indiquent clairement le caractère secret du message. Mais, comme indiqué plus haut, ce n'est pas exploitable par un logiciel.

On notera que le RFC 2634 proposait déjà un mécanisme pour ces niveaux de sécurité, lié à l'utilisation de S/MIME. Notre nouveau RFC spécifie une solution alternative (S/MIME n'a pas été un grand succès...), plus légère. La solution du RFC 2634 était très perfectionnée (avec signature pour éviter qu'un tiers malveillant ne modifie les marques). Ici, on fait plus simple et on suppose qu'il existe un autre mécanisme pour assurer l'intégrité.

Donc, la solution nouvelle est de mettre un champ SIO-Label: dans le message. On suppose que le MUA proposera à l'utilisateur une liste de choix possibles et, une fois le choix fait, le logiciel le traduira dans le format standard. Les MTA et MDA pourront utiliser ce champ pour prendre des décisions. Par exemple, si un MTA a été configuré pour faire suivre automatiquement le courrier de jean@example.com à marie@internautique.fr, il pourra refuser de faire suivre un message marqué SECRET, ne sachant pas si la destinataire a l'habilitation nécessaire. Autre utilisation, le MUA du destinataire pourra afficher clairement le niveau de sécurité. On peut imaginer bien d'autres usages, comme le tri automatique des messages dans des dossiers différents selon le niveau de sécurité.

Les intermédiaires comme les MTA sont autorisés à modifier le champ SIO-Label: (ou l'ajouter s'il n'est pas présent) et, dans ce cas, il doivent indiquer les anciennes valeurs dans le champ SIO-Label-History: qui, comme son nom l'indique, garde trace des changements effectués.

La section 4 décrit formellement la grammaire des nouveaux en-têtes. SIO-Label: comprend une série de paramètres, chacun formé d'une clé et d'une valeur. Le paramètre principal est sans doute label qui indique le niveau de sécurité. Quelles valeurs peut-il prendre ? Plutôt que d'essayer de normaliser une liste de valeurs (ce qui ne marchera jamais, chaque organisation ayant déjà sa liste), notre RFC délègue à d'autres normes, indiquées par le paramètre type. Ainsi, type=":ess"; label="MQYGASkCAQM="; indique que le type est ESS (Enhanced Security Services for S/MIME, RFC 2634, déjà cité) et le label est alors un encodage en BER d'une étiquette ESS. Un type :x411 va indiquer un encodage BER d'une étiquette de sécurité X.411. Enfin, un type :xml indique que le label est l'encodage en Base64 d'un élément XML qui, on le suppose, fera référence à une norme de niveaux de sécurité (si label est trop long, il peut être écrit en plusieurs fois, avec un astérisque et un numéro d'ordre derrière label). Dans cet exemple, la norme est http://example.com/sec-label/0 (un exemple imaginaire) :


       type=":xml";
       label*0="PFNlY0xhYmVsIHhtbG5zPSJodHRwOi8vZXhhbX";
       label*1="BsZS5jb20vc2VjLWxhYmVsLzAiPjxQb2xpY3lJ";
       label*2="ZGVudGlmaWVyIFVSST0idXJuOm9pZDoxLjEiLz";
       label*3="48Q2xhc3NpZmljYXRpb24+MzwvQ2xhc3NpZmlj";
       label*4="YXRpb24+PC9TZWNMYWJlbD4=";

Ce qui se traduit, une fois le Base64 décodé, par :


<SecLabel xmlns="http://example.com/sec-label/0">
       <PolicyIdentifier URI="urn:oid:1.1"/>
       <Classification>3</Classification>
</SecLabel>

Un autre paramètre fréquent est marking qui indique le texte à afficher à l'utilisateur (marking="FOR YOUR EYES ONLY";). Si vous êtes un vrai paranoïaque, vous avez déjà noté que rien ne garantit que ce texte soit cohérent avec le vrai niveau de sécurité, label (cf. section 7). Plus rigolos, fgcolor et bgcolor permettent de suggérer des couleurs à utiliser pour l'affichage, couleurs indiquées par un code hexadécimal ou un nom (cela me semble une mauvaise idée : l'intérêt des niveaux de sécurité écrits sous une forme structurée est justement que le logiciel qui les affichera aura toute l'information pour choisir une couleur adaptée à son utilisateur). En combinant ces paramètres, un en-tête complet pourrait être :

SIO-Label: marking="TOP SECRET";
       fgcolor= #000011; bgcolor=fuschia;
       type=":x411"; label="MQYGASkCAQM="

On a vu qu'un logiciel de courrier était autorisé à modifier les niveaux de sécurité. Dans ce cas, pour permettre l'analyse de ce qui s'est passé, il devrait enregistrer le niveau précédent dans l'en-tête SIO-Label-History:, normalisé dans la section 5 de notre RFC. Cet en-tête de traçabilité (comme Received:) indique si le SIO-Label: a été ajouté par le logiciel, supprimé ou modifié. Voici un exemple où le message a été modifié deux fois, par l'ajout d'un niveau, puis par sa suppression :

SIO-Label-History: marking="EXAMPLE CONFIDENTIAL";
       type=":ess"; label="MQYGASkCAQM=";
       change=delete;
       changed-by="smtp.example.com";
       changed-at="18 Feb 2013 9:24 PDT";
       changed-comment="Pas confiance dans celui-là, je supprime"
SIO-Label-History: new-marking="EXAMPLE CONFIDENTIAL";
       new-type=":ess"; new-label="MQYGASkCAQM=";
       change=add;
       changed-by="smtp.example.net";
       changed-at="18 Feb 2013 7:24 PDT";
       changed-comment="Pas de niveau indiqué, j'en mets un"

Les deux en-têtes SIO-Label: et SIO-Label-History: sont désormais dans le registre des en-têtes.

La bonne utilisation de ces niveaux de sécurité nécessite quelques précautions (section 7 du RFC). Par défaut, le message, y compris ses en-têtes et donc y compris SIO-Label:, n'est pas protégé et un méchant peut donc mettre un faux niveau ou modifier un niveau existant. Ce RFC ne fournit pas à lui seul de services de sécurité et ne dispense donc pas de mettre des protections adaptées, comme PGP pour assurer la confidentialité du message ou TLS pour qu'il soit transporté sans modification.

À noter également un paradoxe des niveaux de sécurité : leur seule présence donne déjà une indication à un éventuel espion. Si OSS 117 est dans un bureau du KGB et n'a que quelques secondes pour choisir les documents à emporter, le fait que les documents les plus intéressants soient marqués en gros « ultra-secret » va l'aider. C'est encore plus vrai si les niveaux de sécurité sont trop parlants, du genre « Project Roswell/Area51 Secret ».

Je ne connais pas de mise en œuvre de ce RFC. Certains clients de messagerie ont déjà des niveaux de sécurité, utilisant d'autres normes. Voir par exemple TrustedBird, présenté aux JRES en 2009. Si vous êtes intéressés par ces questions, vous pouvez aussi regarder la spécification de XIMF.


Téléchargez le RFC 7444


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 7679) 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 7465: Prohibiting RC4 Cipher Suites

Date de publication du RFC : Février 2015
Auteur(s) du RFC : A. Popov (Microsoft)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF tls
Première rédaction de cet article le 19 février 2015


Fini, RC4, au moins dans TLS ! Cet algorithme de cryptographie, qui était secret à l'origine et prétendait être ainsi plus sûr, a fait l'objet de tellement d'attaques cryptanalytiques réussies qu'il ne doit plus être utilisé dans le protocole TLS.

Normalisé dans le RFC 5246, TLS sécurise un grand nombre de protocoles TCP/IP, le plus connu étant HTTP. Comme tous les protocoles IETF utilisant la cryptographie, il n'est pas lié à un algorithme de cryptographie particulier. En effet, les progrès de la cryptanalyse font que les algorithmes qui semblaient sûrs à une époque ne durent pas forcément éternellement. Il est donc crucial de permettre l'arrivée de nouveaux algorithmes, et le retrait des vieux (comme cela a été fait pour MD5, cf. RFC 6151). C'est ce qu'on nomme l'agilité cryptographique. Dans TLS, la liste des algorithmes acceptés est enregistrée à l'IANA et ceux acceptés par le client TLS sont transmis au début de la négociation, dans le message ClientHello (RFC 5246, section 7.4.1.2). Parmi ceux proposés, le serveur en choisira un et l'indiquera dans le message ServerHello (RFC 5246, section 7.4.1.3). (En fait, c'est un peu plus compliqué, le client transmet des suites, chaque suite contenant plusieurs algorithmes, notamment un asymétrique, et un symétrique comme l'est RC4. Par exemple, TLS_ECDH_ECDSA_WITH_RC4_128_SHA est l'algorithme asymétrique ECDSA avec RC4) Depuis ce RFC 7465, les suites cryptographiques utilisant RC4 ne doivent plus apparaître dans ces messages.

RC4 n'a pas été normalisé (il était secret au début, un exemple illustrant bien la vanité de la sécurité par l'obscurité) mais a été documenté dans le livre de Schneier, « Applied Cryptography » (à partir de la deuxième édition). Parmi les attaques réussies contre RC4 :

Toutes ces attaques ne sont pas forcément exploitables de manière réaliste. Mais la cryptanalyse progresse tous les jours. Si l'attaque est un peu trop dure aujourd'hui, elle sera possible demain et triviale après-demain (sans compter le fait qu'en cryptanalyse, tout n'est pas publié, certaines organisations ne disent pas ce qu'elles font). Notre RFC estime qu'aujourd'hui, ces attaques sont presque utilisables en pratique. Il est donc temps de virer RC4.

La section 2 est donc simple et courte : le client TLS ne doit plus indiquer de suite cryptographique utilisant RC4 et, s'il le fait, le serveur ne doit plus les sélectionner. Si la totalité des suites proposées par le client utilise RC4, le serveur doit rejeter la connexion, en utilisant l'alerte insufficient_security(71) (cf. RFC 5246, section 7.2). Ce dernier point avait fait l'objet d'un débat dans le groupe de travail, car il revient à rejeter complètement certaines mises en œuvre de TLS (rappelons que certains sont toujours incapables de parler les versions 1.1 et 1.2 de TLS, malgré les failles de sécurité que cela cause). Toutefois, ce cas de logiciels ne gérant que RC4 semble rare dans la nature.

Par contre, le registre IANA ne dispose pas d'un moyen pour indiquer cette obsolescence de RC4 donc des programmeurs / administrateurs système distraits ne feront peut-être pas attention à ce RFC. Diffusez-le largement !

Un exemple de faille de sécurité récente (publiée un mois après le RFC) concernant RC4 : la faille Invariance Weakness. Un autre exemple est présenté sur Numerous Occurrence MOnitoring & Recovery Exploit.


Téléchargez le RFC 7465


L'article seul

RFC 7457: Summarizing Known Attacks on TLS and DTLS

Date de publication du RFC : Février 2015
Auteur(s) du RFC : Y. Sheffer (Porticor), R. Holz (TUM), P. Saint-Andre (&yet)
Pour information
Réalisé dans le cadre du groupe de travail IETF uta
Première rédaction de cet article le 10 février 2015


Depuis quelques années, on entend souvent parler de failles dans TLS ou dans les mises en œuvre de TLS, comme OpenSSL. Un groupe de travail a été créé à l'IETF pour essayer de durcir la sécurité de TLS, le groupe UTA (Using TLS in Applications). Son premier RFC est un rappel de ces récentes failles. C'est l'occasion de réviser BEAST, CRIME ou Heartbleed.

Le protocole de cryptographie TLS (autrefois nommé SSL) est normalisé dans le RFC 5246. Les attaques récentes contre TLS sont très variées : mauvaise utilisation de TLS par les applications (la principale motivation pour la création du groupe UTA, et son centre d'intérêt principal), bogues dans un programme mettant en œuvre TLS, erreurs dans le protocole, erreurs dans un des algorithmes cryptographiques qu'il utilise... Ce RFC dresse une liste des problèmes de sécurité de ces dernières années, mais on peut être sûr que la liste va s'allonger. Comme le dit la NSA, « Attacks always get better; they never get worse » (cf. RFC 4270).

Le gros morceau du RFC est sa section 2, qui liste les problèmes. Par exemple, la plus évidente est d'empêcher complètement l'usage de TLS (ce qu'on nomme parfois SSL stripping). Par exemple, si un client HTTP se connecte en HTTP et compte sur le serveur pour le rediriger en HTTPS, un attaquant actif peut modifier la redirection, empêchant ainsi TLS de démarrer. Le SSL stripping est donc un cas particulier des attaques par repli (downgrade attacks). Normalement, HSTS (RFC 6797) est la bonne solution contre cette attaque.

Pour HTTP, il est habituel de démarrer directement en TLS. Pour les protocoles où on démarre sans TLS et où on utilise ensuite une commande STARTTLS pour commencer à chiffrer (comme SMTP), une attaque par repli analogue est possible en supprimant la commande STARTTLS. La seule protection possible serait un équivalent de HSTS (le RFC oublie de mentionner DANE, qui pourrait être utilisé à des fins de signalisation). Autre problème avec STARTTLS, les attaques où le tampon d'entrée n'est pas vidé après le passage à TLS, ce qui fait que les commandes injectées avant que TLS ne sécurise la connexion sont exécutées après, en les croyant sûres (CVE-2011-0411). Ce n'est pas une faille du protocole mais de l'application.

Autre attaque, avec un nom rigolo, cette fois, BEAST (CVE-2011-3389). Elle ne touchait que TLS 1.0 (version dépassée depuis longtemps) et seulement le mode CBC.

Plusieurs attaques sont du type padding oracle. C'est le cas de Lucky Thirteen (CVE-2013-0169). Elle peut être combattue en utilisant un mode de chiffrement intègre, ou bien en faisant le chiffrement avant de calculer le MAC (mécanisme dit « encrypt-then-MAC » et recommandé pour TLS par le RFC 7366). Une autre attaque padding oracle, Poodle (CVE-2014-3566 ou bien l'article d'Andréa Fradin), qui ne touche que des versions encore plus anciennes (avant que cela ne s'appelle TLS) et n'a pas de solution connue (à part arrêter d'utiliser des versions archaïques de SSL).

Le protocole TLS est complexe et plein de failles se cachent dans des détails subtils. Par exemple, l'attaque triple handshake (CVE-2014-1295) permet de faire en sorte que deux sessions TLS utilisent les mêmes clés, autorisant ainsi plusieurs autres attaques.

Passons à des attaques plus cryptographiques, celles portant sur l'algorithme RC4. RC4 est utilisé depuis longtemps, a des faiblesses connues depuis longtemps (voir le RFC pour une bibliographie comportant plusieurs articles), et ces faiblesses commencent à devenir exploitables en pratique (aujourd'hui, elles requièrent encore trop de calculs). Il ne faut donc plus utiliser RC4 (RFC 7465).

La compression des données dans TLS apporte ses propres attaques comme CRIME (CVE-2012-4929). Pour les empêcher, on peut couper la compression ou, pour certaines attaques, choisir des solutions au niveau de l'application.

Autre propriété de TLS qui semblait pratique quand elle a été définie, mais qui s'est avérée dangereuse, la renégociation (CVE-2009-3555). La solution a été fournie par le RFC 5746.

TLS utilisant presque toujours des X.509 pour authentifier le serveur (et parfois le client), il n'est pas étonnant que les failles de X.509, ou d'un des algorithmes utilisés dans les certificats, se retrouvent dans la liste des problèmes de sécurité avec TLS. C'est le cas par exemple de l'attaque RSA de Klima, V., Pokorny, O., and T. Rosa, « Attacking RSA-based sessions in SSL/TLS ». ou de celle de Brubaker, C., Jana, S., Ray, B., Khurshid, S., et V. Shmatikov, « Using frankencerts for automated adversarial testing of certificate validation in SSL/TLS implementations ».

Une autre attaque possible est lorsque l'attaquant met la main sur la clé privée a posteriori, et qu'il a enregistré le trafic chiffré. Avec la plupart des algorithmes utilisés par TLS, la connaissance de la clé privée permet de déchiffrer le trafic passé, qui peut être encore intéressant. Cela permet, par exemple, l'utilisation de Wireshark pour analyser un trafic HTTPS. Mais c'est dangereux pour la vie privée : un attaquant patient et ayant beaucoup de place sur ses disques durs pourrait enregistrer tout le trafic chiffré, attendant le moment où il entre en possession des clés privées (ce que fait la NSA, cf. RFC 7258). On peut se protéger contre ces attaques en sécurisant mieux ses clés privées (un HSM ?) mais le mieux est sans doute de passer aux algorithmes qui fournissent la perfect forward secrecy.

Même lorsque le protocole est parfait, des failles peuvent apparaitre en raison de bogues dans les programmes qui mettent en œuvre TLS. On peut même dire qu'il y a bien plus de bogues d'implémentation que de protocole, et elles sont en général plus facilement exploitables, et avec des conséquences plus graves. Ces failles peuvent être dans les bibliothèques TLS (comme OpenSSL, qui en a connu beaucoup, dont la fameuse Heartbleed, CVE-2014-0160, cf. RFC 6250 ou bien l'article de Fradin) ou dans les programmes qui utilisent ces bibliothèques (une excellente étude à ce sujet est celle de Georgiev, M., Iyengar, S., Jana, S., Anubhai, R., Boneh, D., et V. Shmatikov, « The most dangerous code in the world: validating SSL certificates in non-browser software »). Une liste non-exhaustive de ces bogues dans les applications :

  • Absence de vérification du certificat, comme l'ont fait pendant longtemps les bibliothèques Python (voir le CVE-2013-2191). Ce n'est pas une faille du protocole mais de l'application ou des bibliothèques.
  • Si on vérifie le certificat, absence du test du nom du serveur dans le certificat. La faille « goto fail » était de cette catégorie. Voir mon exposé à Devoxx (et ses transparents).

Il n'y a pas que des attaques dues aux bogues du protocole ou des implémentations. Un méchant peut aussi utiliser les simples attaques par déni de service. TLS impose davantage de calculs aux machines qui communiquent et cela peut être utilisé pour le déni de service. Si les processeurs ont progressé (rendant réaliste l'idée d'activer systématiquement TLS pour toutes les connexions), un attaquant disposant d'un grand botnet peut toujours épuiser les capacités de sa victime, en lui imposant des calculs cryptographiques complexes.

De même que les programmeurs d'application peuvent se tromper, mal interpréter les complexes API des bibliothèques TLS, et introduire ainsi des failles de sécurité, les utilisateurs finaux peuvent également prendre des décisions qui annulent la sécurité de TLS, quelle que soit la qualité des protocoles et des logiciels. L'utilisabilité est un élément de la sécurité, si on ne veut pas que M. Michu fasse des erreurs. Par exemple, les logiciels permettent d'accepter un mauvais certificat et les utilisateurs disent presque toujours Oui (et souvent pour des raisons rationnelles). Ici, un exemple avec le logiciel de messagerie instantanée Pidgin : cert-xmpp.png

Lutter contre ce problème nécessitera à la fois HSTS (pour priver de choix l'utilisateur), de l'épinglage des clés, et de meilleurs interfaces utilisateur, une tâche très complexe.

Si vous voulez vous documenter sur ces problèmes TLS, le RFC recommande l'article de Sarkar, P. et S. Fitzgerald, « Attacks on SSL, a comprehensive study of BEAST, CRIME, TIME, BREACH, Lucky13 and RC4 biases ».

Un autre mécanisme TLS contre les attaques par repli est celui décrit dans le RFC 7507.


Téléchargez le RFC 7457


L'article seul

Fiche de lecture : Sécurité et espionnage informatique \ Connaissance de la menace APT

Auteur(s) du livre : Cédric Pernet
Éditeur : Eyrolles
978-2-212-13965-5
Publié en 2015
Première rédaction de cet article le 10 février 2015


Les médias sont plein de récits d'attaques informatiques spectaculaires, où deux lycéens piratent le Pentagone, par des méthodes techniques très avancées, ou bien où une horde de Chinois, forcément fourbes et cruels, s'emparent des plans du dernier avion de combat. Dans la communication sur les attaques informatiques, un sigle s'est imposé : APT pour Advanced Persistent Threat. Peu de gens ont une idée précise de ce que cela veut dire mais c'est en général un synomyme de « attaque qui n'a pas été faite par un gusse dans son garage, un après-midi où il s'ennuyait ». Vous voulez en savoir plus ? Alors, je vous recommande le livre de Cédric Pernet, un expert de la question, et qui sait bien expliquer posément ce que sont les APT, dans leur complexité.

Le livre est court, 220 pages, ce qui le rend accessible aux gens curieux mais pressés (et le prix est élevé, à 40 €...) Mais il couvre bien tous les aspects d'une APT. L'auteur discute d'abord d'une définition rigoureuse de ce concept (on a vu plus haut que le terme est souvent utilisé à tort et à travers, en général avec une bonne dose de sensationnalisme). La définition de l'auteur (« une attaque informatique persistante ayant pour but une collecte d'informations sensibles d'une entreprise publique ou privée ciblée, par la compromission et le maintien de portes dérobées sur le système d'information ») ne fait pas appel au terme « avancé ». En effet, son analyse est que les APT ne sont pas forcément d'une haute technologie. Elles se caractérisent davantage par la mobilisation de moyens humains importants (des dizaines, voire des centaines de personnes), par la ténacité, par le professionnalisme et le souci du détail, que par la sophistication des techniques utilisées.

L'auteur expose ensuite les différentes phases d'une APT : la phase de reconnaissance, où le groupe d'attaquants rassemble toutes les informations possibles sur sa cible, celle de la compromission initiale, où l'attaquant a trouvé une faille à exploiter pour pénétrer dans le système, par exemple par du hameçonnage ciblé (spear phishing), une phase de « renforcement des accès et mouvements latéraux », où l'attaquant va mettre en place des moyens de revenir même si la faille originelle est comblée (rappelez-vous qu'une APT prend du temps), et où il va se déplacer dans le système d'information, à la recherche de nouvelles machines à compromettre, et enfin une phase d'exfiltration des données, où l'attaquant va tenter de faire sortir tous les giga-octets qu'il a obtenu, afin de les rapporter chez lui, mais sans se faire détecter.

Vu du point de vue de l'attaquant, une APT n'est pas forcément glamour et spectaculaire. La phase de reconnaissance, par exemple, est plutôt routinière. C'est un travail de besogneux, pas de flamboyants hackers. Des tas d'informations sont disponibles publiquement, il faut les récolter. L'auteur note que « une préparation rigoureuse et minutieuse est la clé de la réussite [de l'APT] », ce qui est aussi exaltant qu'une leçon de morale du temps de Jules Ferry (« c'est en travaillant bien qu'on réussit »).

(Au passage, Cédric Pernet parle longuement de l'utilisation de whois et du DNS. Ces outils sont utilisés par les agresseurs en phase de reconnaissance, mais peuvent aussi servir aux investigateurs, cf. mon exposé à CoRI&IN.)

Même la phase de compromission initiale n'est pas forcément glorieuse. Lors d'une APT, on n'utilise pas forcément des attaques premier jour (attaques encore inconnues) : c'est parfois dans les vieux pots qu'on fait les meilleures soupes et certaines APT n'ont utilisé que des vulnérabilités connues depuis des années... et qui ne sont pas toujours patchées.

J'ai noté que, malgré le métier de l'auteur, ce livre ne parle guère de la « réponse à incidents ». Il décrit les APT, pour les solutions et les réactions, il faudra attendre un autre livre.

Le livre se termine par une description de plusieurs APT fameuses et moins fameuses. L'auteur, qui rappelle régulièrement la complexité de ce monde et la difficulté à acquérir des certitudes en béton sur les attaquants et leurs méthodes, se méfie des attributions trop enthousiastes. L'attribution, c'est un des exercices les plus difficiles de la lutte contre les APT, c'est tenter de nommer l'attaquant. Comme une attaque numérique ne laisse pas de traces indiscutables (pas d'ADN, pas de mégots de cigarettes, pas d'empreintes digitales), on pourra toujours contester une attribution. D'autant plus que certains n'hésitent pas à ouvrir le feu avant d'être sûr, par exemple lorsque le FBI a accusé le régime nord-coréen d'être derrière l'attaque de Sony.

Donc, quelques cas pittoresques traités dans ce livre :

  • PutterPanda, une campagne d'espionnage visant notamment l'aéronautique, et qui viendrait de Chine.
  • Careto, une campagne d'APT caractérisée par la richesse et la complexité des techniques utilisées (dont certaines achetées aux mercenaires de Vupen).
  • Hangover qui serait d'origine indienne.
  • Flame (alias Flamer, alias Wiper, rappelez-vous que les noms sont donnés par les défenseurs, pas par les attaquants, et que plusieurs équipes ont pu analyser la même APT), un système d'espionnage très perfectionné, qui a frappé au MOyen-Orient, et qui serait développé par la même équipe que Stuxnet (que Cédric Pernet ne classe pas dans les APT).

Une APT fameuse manque : celle que la NSA pratique en permanence contre les systèmes informatiques du monde entier...

Pour résumer, un excellent livre, très documenté, sérieux, prudent, et pédagogique, même si je regrette l'abus d'anglicismes (certes très utilisés dans le métier), comme 0day au lieu de « premier jour », watering hole plutôt que « point d'eau », sinkhole au lieu d'« évier », logger au lieu de « journaliser », etc. L'auteur a récemment donné un interview à SécuritéOff.

Une note d'humour pour finir : le dos du livre annonce « Il [l'auteur] est suivi par plus de 3 000 abonnés sur Twitter. » Curieuse métrique : j'ai bien plus d'abonnés, sans pouvoir prétendre au même niveau d'expertise.

Autres compte-rendus de ce livre :


L'article seul

The Sichuan pepper "attack": from DNS censorship to DNS redirection

First publication of this article on 5 February 2015


It is well-known, for many years, that the Chinese governement censors the Internet via several means, including DNS lies. For a long time, these DNS lies have been generated by the netwok itself: when a DNS query for a censored name is seen, an active censorship device generates a lie and sends a reply with a wrong IP address. A few weeks ago, there have been a change in this system: the IP addresses returned by the Great FireWall are more often actual addresses used by real machines, which suddently have to sustain a big traffic from China.

This technique have been studied and documented in several papers such as "The Great DNS Wall of China" or "Source code to identify the fake DNS packets from China". Basically, every DNS request in a chinese network, whatever the destination IP address, is examined and, if the qname (Query Name) in it matches a predefined list of censored domains, a fake reply is generated and sent to the requester. The bad consequences of this technique outside of China have been described in articles like "Accidentally Importing Censorship" or "China censorship leaks outside Great Firewall via root server": since the censorship system acts whatever the destination IP address is, if one of your DNS packets happen to goes through China, you will be subjected to chinese censorship.

To see this DNS tampering, one just has to query any IP address in China (it does not need to be an existing machine, since the fake DNS reply is made by the network, not by an evil DNS server, the address here was choosen at random and tested to be sure it does not reply to any other packet):

      
% dig @218.76.74.42 A www.ssi.gouv.fr

; <<>> DiG 9.9.5-8-Debian <<>> @218.76.74.42 A www.ssi.gouv.fr
; (1 server found)
;; global options: +cmd
;; connection timed out; no servers could be reached
      
    

As expected, this non-existing machine does not reply. But if we try with a censored name, here Facebook:

      
% dig @218.76.74.42 A www.facebook.com

; <<>> DiG 9.9.5-8-Debian <<>> @218.76.74.42 A www.facebook.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 30344
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;www.facebook.com.      IN A

;; ANSWER SECTION:
www.facebook.com.       2655 IN A 67.205.10.141

;; Query time: 313 msec
;; SERVER: 218.76.74.42#53(218.76.74.42)
;; WHEN: Wed Feb 04 12:06:43 CET 2015
;; MSG SIZE  rcvd: 50
      
    

This time, we get an IP address, and completely unrelated to Facebook (it is a USAn hoster). It is not just a match of the string that triggers the lying answer, the system actually understands DNS:

      
% dig @218.76.74.42 A www.facebook.com.example.net

; <<>> DiG 9.9.5-8-Debian <<>> @218.76.74.42 A www.facebook.com.example.net
; (1 server found)
;; global options: +cmd
;; connection timed out; no servers could be reached	       
      
    

Besides going to China and testing from your laptop, there are other ways to see this DNS tampering: one is to use the RIPE Atlas probes. Few of them are in China and many seem immune to the DNS tampering, probably because they are located on a network with a safe VPN connection to the outside.

% python resolve-name.py --country=CN --requested=30 www.facebook.com
Measurement #1854647 for www.facebook.com/A uses 15 probes
[66.220.158.19] : 4 occurrences
[179.60.192.3] : 2 occurrences
[31.13.79.246] : 3 occurrences
[31.13.68.84] : 3 occurrences
[173.252.74.22] : 1 occurrences
[153.122.20.47] : 2 occurrences
[31.13.68.70] : 3 occurrences
[67.205.10.141] : 1 occurrences
[173.252.73.52] : 1 occurrences
[114.200.196.34] : 1 occurrences
[31.13.76.102] : 1 occurrences
Test done at 2015-02-04T11:11:19Z
    

(The program resolve-name.py is on Github.) Most answers are actually Facebook's but not all (for instance, 114.200.196.34 is a Korean access provider).

And a last solution is to use the cloud, actually a Web site hosted in China which allows you to perform DNS requests, for instance, http://viewdns.info/chinesefirewall.

Until the beginning of 2015, the returned IP addresses were apparently non-reachable addresses, unallocated, or even "class D" (multicast, 224.0.0.0/4) or "class E" (unused, 240.0.0.0/4) addresses. When the unsuspected chinese user tried to reach Facebook, he got one of these unrouteable addresses and it ended in a timeout. But a change was done at the beginning of 2015. Now, the returned IP addresses are, much more often , actually assigned to a real machine. Suddenly, several system administrators reported a lot of traffic coming from China, asking for sites like Facebook, something that never happened before.

The first report, seen from the chinese site (chinese users sent to unexpected Web sites) was "Visitors to blocked sites redirected to porn". Many other reports documented the other side, the point of view of the site suddently receiving chinese traffic. See "Fear China", "DDOS on La Quadrature du Net, analysis" or "DDoS from China – Facebook, WordPress and Twitter Users Receiving Sucuri Error Pages".

Let's look at this traffic, as seen by one of the Web servers of CGT. The HTTP server log contains:

      
x.y.z.t - - [27/Jan/2015:07:48:29 +0100] "GET /plugins/like.php?href=https://www.facebook.com/yvesrocher.nederland&width=325&height=35&colorscheme=light&layout=standard&action=like&show_faces=false&send=false HTTP/1.1" 404 1184 "https://secureorder.yves-rocher.nl/control/main/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:25.0) Gecko/20100101 Firefox/25.0"
      
    

(The source IP address was from "Graduate University of Chinese Academy of Sciences") The request is for /plugins/like.php, Facebook's "Like" button. It does not exist on the server and the HTTP status code is therefore 404 (not found). What is interesting is the Referer: HTTP field, here https://secureorder.yves-rocher.nl/control/main/. It shows that the chinese client did not want explicitely to visit Facebook (he probably knows that this would be hopeless from China) but he visited a site (https://secureorder.yves-rocher.nl/control/main) which includes a Facebook "Like" button, therefore triggering a HTTP request to Facebook and, because of the DNS tampering, actually going to the CGT server. Here is a part of the HTML source code of the Referer:

  
<iframe src="https://www.facebook.com/plugins/like.php?href=https://www.facebook.com/yvesrocher.nederland&width=325&height=35&colorscheme=light&layout=standard&action=like&show_faces=false&send=false" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:325px; height:35px; margin-top:4px;" allowTransparency="true"></iframe>	   
  

Unfortunately, the HTTP server, like most HTTP servers, did not log the Host: field in the HTTP request. This field indicates which host was requested by the client. Here, we can guess it was www.facebook.com, from the requested path (/plugins/like.php). But it would be better if all HTTP servers were to log the Host: field (in Apache, it is the %v format directive). On another HTTP server, which was victim of the same Sichuan pepper issue, and had this logging activated, we see:

x.y.z.t - - [21/Jan/2015:00:53:33 +0100] "GET /plugins/like.php?href= [...] "Mozilla/5.0 (Linux; U; Android 4.4.4; zh-CN; L39h Build/14.4.A.0.108) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 UCBrowser/10.0.0.488 U3/0.8.0 Mobile Safari/534.30" 0 www.facebook.com

The www.facebook.com clearly indicates that the original user really wanted to go to Facebook, and was distracted by the DNS tampering.

Another very common HTTP request is:

  
x.y.z.t	- - [27/Jan/2015:07:48:41 +0100] "GET /announce?info_hash=%0eo%40%e7.u%f7%a3%3e%e6%e9%a9%5e%e45%8bK%1b%de.&peer_id=-QD1900-8xIYnIZ1_GUL&port=4385&uploaded=0&downloaded=32208896&left=1168225415&key=87d43d95&compact=1&numwant=200&no_peer_id=1 HTTP/1.0" 404 1015 "-" "qqdownload/1.9.273.0"
  

(The original source IP address was "China Mobile Communications Corporation".) The requested path, /announce?info_hash is typical of BitTorrent clients going to a BitTorrent tracker. QQdownload is a popular BitTorrent client in China. On another machine, where Host: logging is activated, we see that the requested host was indeed a tracker, tracker.thepiratebay.org, also censored in China.

OK, so we see a lot of HTTP traffic, coming almost only from chinese IP addresses, and we see that the requested names are indeed censored in China. Can we prove that the Great FireWall redirected to the IP addresses of the victims? We can do it with http://PassiveDNS.cn/, a passive DNS (a system which records DNS answers observed on the network) database located in China. First, we can check (like we did with dig to a chinese IP address) that names like tracker.thepiratebay.org are indeed tampered with, using the API client of PassiveDNS.cn, flint:

% flint rrset tracker.thepiratebay.org A
[api error]: http://www.passivedns.cn/api/rrset/keyword/tracker.thepiratebay.org/rtype/1/

:-( This request works for non-censored names. I suspect that censored names, being redirected to many IP addresses, exceed some limit of PassiveDNS.cn, leading to this bug. But the Web interface of PassiveDNS.cn still works so we can see indeed that we have many IP addresses for tracker.thepiratebay.org. It is not a trick specific to The Pirate Bay, all the other censored names show the same behaviour. But what is more interesting is how many names point to the IP address of the victim, 212.234.228.143?

% flint rdata 212.234.228.143 A | more  
212.234.228.143 A In rdata
--------
50congres.cgt.fr                                212.234.228.143 2014-11-26 10:10:13
accounts.youtube.com                            212.234.228.143 2015-01-28 10:26:25
adecco.cgt.fr                                   212.234.228.143 2014-11-29 12:56:14
adm-salaries.cgt.fr                             212.234.228.143 2015-01-04 06:39:26
aful.cgt.fr                                     212.234.228.143 2015-02-04 06:04:32
platform.twitter.com                            212.234.228.143 2015-01-15 23:20:37
plus.google.com                                 212.234.228.143 2015-02-03 03:23:34
tracker.thepiratebay.org                        212.234.228.143 2015-01-31 23:58:02
www.bloomberg.com                               212.234.228.143 2015-02-01 10:00:13
www.facebook.com                                212.234.228.143 2015-02-01 21:37:59
www.kanzhongguo.com                             212.234.228.143 2015-01-15 23:18:35
...

So, we can see that the original interpretation is correct: the Great Firewall, through DNS tampering, redirects many very popular names to innocent servers.

How many sites are used as "sinkholes" by the chinese censorship system? Let's query repeatedly www.facebook.com to an IP address in China (123.123.123.123) during 17 hours (on February 2nd). We retrieve 5559 answers. This is 1856 distinct IP addresses because some addresses are sent several times. So, it does not look random. Here are the most popular addresses (the owner name has been retrieved through the very useful cymruwhois package):

205.186.162.167 (MEDIATEMPLE - Media Temple, Inc.,US): 26
77.66.57.6 (NGDC NetGroup A/S,DK): 24
205.157.169.156 (ASN-PENNWELL - PennWell corporation,US): 24
216.201.83.226 (NATIONALNET-1 - NationalNet, Inc.,US): 24
64.20.49.2 (NJIIX-AS-1 - NEW JERSEY INTERNATIONAL INTERNET EXCHANGE LLC,US): 24
193.188.112.80 (AS6453 - TATA COMMUNICATIONS (AMERICA) INC,US): 23
114.130.54.22 (BCC-MANGOCLIENT-AS-AP Bangladesh Computer Council,BD): 22
216.57.200.175 (WHIDBEY1 - Whidbey Internet Services,US): 22
74.121.192.250 (BLACKMESH-RST - BlackMesh Inc.,US): 21
137.117.70.70 (MICROSOFT-CORP-MSN-AS-BLOCK - Microsoft Corporation,US): 21
70.32.110.223 (MEDIATEMPLE - Media Temple, Inc.,US): 21
184.173.133.194 (SOFTLAYER - SoftLayer Technologies Inc.,US): 21
5.9.26.245 (HETZNER-AS Hetzner Online AG,DE): 20
195.205.239.197 (TPNET Orange Polska Spolka Akcyjna,PL): 20
222.230.141.241 (VECTANT VECTANT Ltd.,JP): 20
91.213.100.50 (BRACK-AS Brack.ch AG,CH): 20
14.139.212.165 (NKN-CORE-NW NKN Core Network,IN): 20
54.235.118.83 (AMAZON-AES - Amazon.com, Inc.,US): 20
200.57.151.168 (Triara.com, S.A. de C.V.,MX): 20
62.109.134.70 (IGNUM-AS Ignum s.r.o.,CZ): 20
...  

As you can see, many IP addresses are used in the Great FireWall lies.

Now, let's indulge in some speculation. How are the IP addresses of the victim choosen? At random, and the Great FireWall administrators do not care of the consequences? On purpose, to turn every chinese Internet user into an involuntary accomplice of the dDoS? We must admit that we don't know.

This sort of "attack by referral" is a scourge of the Internet, because there is a very little to do against it. A famous example a few years ago, not involving the DNS, was D-Link NTP "attack".

Thanks to Benjamin Sonntag and Éric Duval for the data.


L'article seul

Fiche de lecture : Le poisson et le bananier

Auteur(s) du livre : David Bellos
Éditeur : Flammarion
978-2-0812-5624-8
Publié en 2011
Première rédaction de cet article le 5 février 2015


Ce n'est pas un roman, quoique le titre puisse faire croire mais une passionnante réflexion d'un traducteur sur son métier. La traduction, note-t-il, a commencé le jour où on s'est dit que les gusses de l'autre côté de la colline avaient peut-être des choses intéressantes à dire, et qu'il fallait donc traduire leur charabia. Mais, depuis, des tas de problèmes se sont posés. Faut-il traduire le plus littéralement possible ou bien faut-il prendre des libertés avec le texte original ? Comme il existe de facto une hiérarchie des langues (certaines sont plus prestigieuses que d'autres, ou utilisées par des empires plus puissants), la traduction « amont » (vers une langue plus prestigieuse) est-elle différente de la traduction « aval » (vers un idiome qui est moins considéré) ?

Le titre du livre dérive de la première question : un traducteur de la Bible, devant traduire que Jésus était sous un figuier, écrivant pour des gens originaires d'un pays où il n'y a pas de figuier, a fait s'assoir le Christ sous un bananier, arbre rare en Palestine... Un bel exemple de traduction « libre ».

Bellos couvre d'innombrables problèmes de traduction, et les solutions qui y ont été apportées. Comment traduire en français les romans russes du 19e siècle, où des dialogues entiers sont « en français dans le texte », le passage à cette langue indiquant un registre soutenu ? Pourquoi le méchant nazi dans les films sur la Seconde Guerre mondiale parle-t-il un français (ou un anglais) parfait, sauf qu'il hurle de temps en temps raus ou schnell ? Quelles sont les contraintes spécifiques du traducteur de BD (la taille fixe des phylactères...) ? Comment traduire les passages qu'on ne comprend pas (il y en a toujours, et le traducteur, contrairement au lecteur normal, ne peut pas sauter ce qu'il ne comprend pas) ?

L'original de ce livre est en anglais mais j'ai lu une traduction en français, ce qui m'a semblé bien adapté au sujet :-)

C'est en tout cas un livre à lire absolument si on est confronté à des traductions, et qu'on veut savoir comment ça s'est passé derrière, quelles étaient les conditions de production de la traduction, et quels sont les choix auxquels est confronté un traducteur. En prime, c'est vivant et drôle.

La page officielle de l'éditeur.


L'article seul

RFC 7451: Extension Registry for the Extensible Provisioning Protocol

Date de publication du RFC : Février 2015
Auteur(s) du RFC : S. Hollenbeck (Verisign Labs)
Pour information
Réalisé dans le cadre du groupe de travail IETF eppext
Première rédaction de cet article le 4 février 2015


Le protocole d'avitaillement EPP, normalisé dans le RFC 5730, est extensible : on peut rajouter des éléments afin de gérer des politiques locales. Jusqu'à présent, ces extensions n'étaient pas collectées en un endroit unique, ce qui pouvait mener à des duplications d'efforts inutiles. Ce nouveau RFC crée un registre d'extensions EPP, géré souplement (y mettre une extension est simple et ne nécessite pas d'accord formel de l'IETF) et qui permettra aux développeurs d'extensions de vérifier facilement si quelqu'un a déjà fait un travail analogue.

EPP est surtout connu pour son utilisation par les registres de noms de domaine. C'est ce protocole qui est utilisé par le titulaire du nom, ou par son bureau d'enregistrement, pour créer un nom, le modifier ou le supprimer. Chaque registre ayant sa propre politique d'enregistrement, le schéma EPP standard ne peut donc pas convenir à tout le monde (« one size does not fit all »). Voilà pourquoi beaucoup de registres ont créé des extensions. Le RFC 3735 les guide dans cette tâche, mais n'indique guère comment publier ces extensions (cf. la section 2.1 du RFC 3735). On a vu ainsi plusieurs registres développer des extensions différentes, et incompatibles, pour le même problème (comme d'indiquer les informations à propos de la TVA sur les objets créés en EPP).

Notre RFC crée donc un registre IANA des extensions EPP. La section 2 du RFC spécifie les détails de ce registre, et des mécanismes d'enregistrement d'une extension. La politique est « norme nécessaire » (cf. RFC 5226, section 4.1), ce qui impose qu'une spécification publique de l'extension soit disponible, et qu'elle soit évaluée par un expert nommé par l'IANA.

Les éventuelles discussions sur la nouvelle extension, ou la qualité de sa documentation, se feront sur la liste de l'actuel groupe de travail IETF EPPEXT, eppext@ietf.org. Même lorsque le groupe de travail sera dissous, la liste continuera donc.

Parmi les critères d'évaluation, outre ceux du RFC 3735, notre RFC rappelle l'importance d'évaluer les conséquences de l'extension pour la vie privée. Une préoccupation qui était absente du RFC 3735 mais qui a bien plus d'importance aujourd'hui. Autrement, notre RFC recommande aux experts évaluateurs d'être souples : si l'extension à EPP a été documentée et est effectivement déployée, elle mérite d'être enregistrée, même si l'expert a des objections techniques. Ainsi, ce n'est pas un problème si plusieurs extensions proches sont enregistrées : cela reflète la réalité. Si quelqu'un veut déposer une extension très proche d'une extension existante, on lui fera remarquer (et il pourra alors choisir d'utiliser plutôt l'extension existante) mais on ne le bloquera pas. (Ce point est celui qui avait fait l'objet des plus chaudes discussions dans le groupe de travail EPPEXT : certains auraient préféré une politique d'enregistremet plus stricte, limitant les doublons.)

Et comment fait-on pour enregistrer ? On envoie à l'IANA un formulaire (un gabarit se trouve dans la section 2.2.2 et des exemples réels dans la section 3) informant du nom de l'extension, de l'endroit où se trouve sa spécification (un URL suffit), des coordonnées de la personne ou de l'organisation qui enregistre, du TLD auquel elle s'applique (ou « N'importe lequel » si elle est d'usage général), ainsi que d'informations sur les éventuels boulets juridiques, par exemple un brevet sur ladite extension (cf. RFC 8179). Voici un exemple de formulaire d'enregistrement rempli (IPR = Intellectual Property Rights) :

   -----BEGIN FORM-----
   Name of Extension:
   "An Example Extension for the .example Top-Level Domain"

   Document Status:
   Informational

   Reference:
   http://www.example.com/html/example-epp-ext.txt

   Registrant Name and Email Address:
   John Doe, jdoe@example.com

   TLDs: .example

   IPR Disclosure:
   http://www.example.com/ipr/example-epp-ext-ipr.html

   Status: Active

   Notes: None
   -----END FORM-----

Et un exemple réel, l'enregistrement de l'extension « période de rédemption » du RFC 3915. La spécification étant un RFC, le contact est l'IESG :


      -----BEGIN FORM-----
      Name of Extension:
      "Domain Registry Grace Period Mapping for the
      Extensible Provisioning Protocol (EPP)"

      Document Status:
      Standards Track

      Reference:
      http://tools.ietf.org/html/rfc3915

      Registrant Name and Email Address:
      IESG, <iesg@ietf.org>

      TLDs: Any

      IPR Disclosure: None

      Status: Active

      Notes: None
      -----END FORM-----

Cette extension est une des quatre premières du registre IANA.


Téléchargez le RFC 7451


L'article seul

RFC 7414: A Roadmap for Transmission Control Protocol (TCP) Specification Documents

Date de publication du RFC : Février 2015
Auteur(s) du RFC : M. Duke (F5), R. Braden (ISI), W. Eddy (MTI Systems), E. Blanton, A. Zimmermann (NetApp)
Pour information
Réalisé dans le cadre du groupe de travail IETF tcpm
Première rédaction de cet article le 3 février 2015


C'est un RFC récapitulatif. Il ne normalise rien de nouveau mais dresse une liste commentée des RFC dont la connaissance est indispensable, ou simplement utile, au programmeur qui met en œuvre TCP.

Depuis sa normalisation, il y a plus de trente ans (dans le RFC 793), TCP a complètement remplacé NCP. TCP est un des grands succès de l'Internet : quasiment toutes les applications Internet s'appuient sur ce protocole.

Mais le RFC normatif, le RFC 793, quoique toujours valable à l'époque, était bien vieux car beaucoup de choses avaient été ajoutées ou retirées à TCP depuis. (Mais, depuis la publication de ce RFC 7414, la norme TCP a été enfin remplacée, par le RFC 9293.) Comme pour beaucoup d'autres protocoles Internet (par exemple le DNS), TCP met donc le programmeur en face d'une rude tâche : avant de commencer à coder, il doit d'abord dresser la liste de tous les RFC dont il aura besoin. Et il faudra qu'il pense à chaque fois à regarder si des errata ont été publiés. C'est cette tâche d'établissement de liste que lui épargne notre RFC en dressant cette liste, et en la rangeant en trois sections, ce qui est impératif pour un TCP moderne (section 2 de notre RFC), ce qui est fortement souhaité (section 3), et ce qu'on peut ajouter si on veut (section 4). Ce « méta-RFC » a donc une bibliographie particulièrement longue, comportant 135 autres RFC. Le groupe de travail avait discuté de l'utilisation d'une autre méthode qu'un RFC, par exemple un Wiki, qui pourrait être plus facilement maintenu à jour, mais sans arriver à se décider pour une autre solution. (Notre nouveau RFC succède au RFC 4614, actualisant ses recommandations.)

Par exemple, le document original sur TCP ne contient rien sur le contrôle de congestion, qui ne sera décrit que dans le RFC 2001. Ce RFC 2001 (ou plus exactement son successeur, le RFC 5681) fait désormais partie de ceux qu'il faut lire. Notez que cette importance n'est pas forcément liée au statut officiel du RFC : le RFC 5681 n'est que projet de norme, alors qu'il est considéré essentiel. On trouve aussi dans cette section le RFC 6298, sur le calcul du délai avant retransmission, ou le RFC 6691 sur le calcul de la MSS.

Dans la section de ce qui est fortement recommandé (section 3), on trouve par exemple le RFC 7323 qui décrit plusieurs extensions nécessaires pour tirer des performances élevées, ou bien le RFC 3168 qui normalise ECN, ou encore le RFC 6582, sur l'algorithme NewReno.

Cette section compte également des RFC décrivant l'abandon d'options ou d'extensions inutiles, voire néfastes. C'est le cas du RFC 6633 qui supprime le mécanisme de répression de l'émetteur.

La sécurité ayant bien plus d'importance aujourd'hui, d'autres RFC décrivent comment se défendre contre certaines vulnérabilités par exemple la lecture du RFC 5961 va apprendre aux programmeurs de TCP comment résister aux attaques en aveugle, et celle du RFC 6528 est indispensable pour empêcher un attaquant d'insérer des paquets dans une session TCP existante.

D'autres extensions sont moins consensuelles et restent plutôt expérimentales à ce jour (section 4) comme l'algorithme Eifel du RFC 3522. Certaines de ces extensions non consensuelles sont encore récentes et s'imposeront peut-être, comme l'extension de la fenêtre initiale (RFC 6928) ou comme l'algorithme de réduction proportionnelle (RFC 6937).

Enfin certaines extensions ont été abandonnées, l'expérience ayant montré leur inutilité ou leur nocivité (section 6 du RFC). C'est ainsi que la proposition du RFC 1146 de tenter de nouveaux moyens de calcul de la somme de contrôle n'a pas pris.

Le protocole T/TCP, normalisé dans le RFC 1644, aurait permis de diminuer nettement la durée des connexions courtes, celles où on échange peu de données (beaucoup de connexions HTTP sont dans ce cas). Promu par des experts comme Stevens, implémenté dans des systèmes comme FreeBSD (option MSG_EOF de sendto), il a été remisé au grenier après que des analyses plus poussées aient montré ses failles de sécurité (il facilite l'utilisation de TCP avec usurpation d'adresses IP). Même sort pour le plus récent RFC 6013 qui décrivait un TCP Cookie Transaction mais qui n'a finalement pas suscité beaucoup d'intérêt. En revanche, TCP Fast Open (RFC 7413) est actuellement la méthode à la mode pour diminuer la latence.

Les RFC de ces extensions abandonnées ont été reclassifiés comme « intérêt historique seulement » dans le RFC 6247.

Notre RFC décrit ensuite les RFC d'architecture ou de concepts, puis les RFC qui s'appliquent à certains environnements difficiles comme les liaisons satellite qui font l'objet des RFC 2757 et RFC 2760 ou les liaisons fortement asymétriques, comme le sont les lignes ADSL (traitées dans le RFC 3449).

De nombreux autres cas sont ensuite traitées dans notre RFC. Notre implémenteur n'a pas fini de tout lire !

La section 8 couvre enfin un cas délicat : les extensions à TCP qui, bien que largement utilisées, n'ont jamais fait l'objet d'un RFC ni même, souvent, d'une description formelle. C'est par exemple le cas de la prédiction d'en-tête, une méthode développée par Van Jacobson et Mike Karels à la fin des années 1980 pour accélérer le traitement des paquets TCP en essayant de prédire ce qu'allaient contenir leurs en-têtes. On programme un chemin rapide pour les paquets qui sont conformes aux prévisions et un chemin plus lent pour les paquets (minoritaires) qui surprennent. Van Vacobson avait décrit cette astuce dans un célèbre message de 1988 « The idea is that if you're in the middle of a bulk data transfer and have just seen a packet, you know what the next packet is going to look like ».

C'était aussi le cas des syncookies, option indispensable sans laquelle un serveur Internet peut être mis à genoux très vite par une attaque SYN flood pour laquelle il n'y a même pas besoin de développements spécifiques, l'outil hping suffisant à l'attaquant. Ces petits gâteaux ont finalement été décrits dans le RFC 4987.


Téléchargez le RFC 7414


L'article seul

RFC 7443: Application Layer Protocol Negotiation (ALPN) Labels for Session Traversal Utilities for NAT (STUN) Usages

Date de publication du RFC : Janvier 2015
Auteur(s) du RFC : P. Patil, T. Reddy, G. Salgueiro (Cisco), M. Petit-Huguenin (Impedance Mismatch)
Pour information
Réalisé dans le cadre du groupe de travail IETF tram
Première rédaction de cet article le 29 janvier 2015


ALPN, normalisé dans le RFC 7301, est une option du protocole de sécurité TLS pour permettre à un client TLS d'indiquer au serveur TLS quelle application il veut utiliser (car il n'y a pas que HTTPS qui utilise TLS...) Cela permet, notamment, d'utiliser un seul port (le seul qui passera depuis tous les réseaux, 443) pour plusieurs applications. Ce nouveau RFC 7443 utilise ALPN pour permettre à un client STUN de signaler au serveur TLS qu'il veut faire du STUN, et lui permet également de spécifier quel usage de STUN (par exemple le relayage des sessions TCP nommé TURN).

STUN sert normalement aux clients tristement coincés derrière un stupide boitier, genre routeur NAT, pour communiquer avec d'autres malheureux dans le même cas (et qui ne peuvent donc pas être appelés directement). Il est surtout utilisé pour le pair-à-pair et pour la communication multimédia (téléphonie sur IP par exemple). STUN peut fonctionner sur TLS, pour plus de sécurité (RFC 8489, section 6.2.2, et RFC 7350 si on utilise UDP). Notre nouveau RFC permet à STUN-sur-TLS d'utiliser l'extension TLS ALPN en indiquant comme application un de ces deux choix :

  • stun.turn : utilisation de STUN et de TURN (RFC 8656),
  • stun.nat-discovery : utilisation de STUN pour découvrir les caractéristiques d'un routage NAT.
  • Après une sérieuse discussion à l'IETF, il a été décidé qu'il n'y aurait pas d'application « STUN générique » (par exemple pour des usages futurs encore inconnus).

Ces deux noms sont désormais enregistrés dans la liste des protocoles applicatifs ALPN.

À l'heure actuelle, il ne semble pas qu'il y ait encore de mise en œuvre de ce système mais les clients WebRTC devraient logiquement être dans les premiers à s'y mettre.


Téléchargez le RFC 7443


L'article seul

RFC 7440: TFTP Windowsize Option

Date de publication du RFC : Janvier 2015
Auteur(s) du RFC : Patrick Masotta (Serva)
Chemin des normes
Première rédaction de cet article le 29 janvier 2015


TFTP est un très vieux protocole de transfert de fichiers, surtout utilisé pour le démarrage de machines n'ayant pas les fichiers nécessaires en local, et devant les acquérir sur le réseau (par exemple via PXE). Reposant sur UDP et pas TCP comme tous les autres protocoles de transfert de fichiers, il peut être mis en œuvre dans un code de taille minimal, qui tient dans la mémoire morte. Par défaut, TFTP n'a pas de fenêtre d'envoi : chaque paquet doit faire l'objet d'un accusé de réception avant qu'on puisse envoyer le suivant. Ce RFC ajoute une option à TFTP qui permet d'avoir une fenêtre d'envoi, accélérant ainsi les transferts de fichier.

C'est le RFC 1350 qui est l'actuelle norme TFTP. Ce vieil RFC décrit le fonctionnement de base de TFTP en notant que « [each data packet] must be acknowledged by an acknowledgment packet before the next packet can be sent », ce qu'on nomme le lock-step. Dit autrement, TFTP a une fenêtre de taille 1. Vu par le dissecteur de paquets de pcapr, cela donne une stricte alternance des données et des accusés de réception :

1.		192.168.0.1	»	192.168.0.13	tftp	Write Request, File: rfc1350.txt\000, Transfer type: octet\000
2.		192.168.0.13	»	192.168.0.1	tftp	Acknowledgement, Block: 0
3.		192.168.0.1	»	192.168.0.13	tftp	Data Packet, Block: 1
4.		192.168.0.13	»	192.168.0.1	tftp	Acknowledgement, Block: 1
5.		192.168.0.1	»	192.168.0.13	tftp	Data Packet, Block: 2
6.		192.168.0.13	»	192.168.0.1	tftp	Acknowledgement, Block: 2
7.		192.168.0.1	»	192.168.0.13	tftp	Data Packet, Block: 3
8.		192.168.0.13	»	192.168.0.1	tftp	Acknowledgement, Block: 3

À l'époque du RFC 1350, il n'y avait aucun moyen de changer cela, TFTP n'ayant pas de mécanisme d'options. Mais le RFC 1782, remplacé depuis par le RFC 2347, lui en a donné un.

L'absence d'un mécanisme de fenêtre (ou, ce qui revient au même, le fait que la fenêtre soit de taille 1) serait dramatique pour des transferts sur l'Internet, où la latence est souvent élevée. Mais TFTP n'est quasiment utilisé que sur des LAN, où la latence est faible et les pertes de paquet rares. L'option Blocksize du RFC 2348, permettant des paquets plus grands que les 512 octets originaux, avait jusqu'à présent suffi à calmer les désirs de performance meilleure. Mais TFTP reste lent, et cette lenteur pose un problème lorsqu'on veut transférer de gros fichiers, comme une image Linux ou comme les PE de Microsoft utilisés par WDS/MDT/SCCM lorsqu'on démarre en PXE. Contrairement à ce que croient beaucoup de gens, TFTP est très loin d'être en voie d'extinction et il est donc justifié de chercher à l'améliorer. Le RFC se vante qu'avec cette option, TFTP peut aller aussi vite que les autres protocoles de transfert de fichier.

L'option elle-même est décrite dans la section 3. Le mécanisme d'option du RFC 2347 consiste en l'ajout de l'option à la fin du paquet Read Request ou Write Request. L'option comporte un nom (windowsize dans notre cas), et une valeur, qui est le nombre de blocs dans une fenêtre (rappelez-vous que, grâce à une autre option, celle du RFC 2348, un bloc ne fait pas forcément 512 octets). On peut envoyer autant de blocs qu'indiqué dans cette option, avant d'exiger un accusé de réception (la section 4 montre un schéma détaillé d'un transfert de données, avec une fenêtre de taille 4). Le récepteur des données accuse réception du dernier bloc (cela accuse implicitement réception des blocs précédents). Les accusés de réception TFTP indiquent en effet le numéro de bloc reçu (RFC 1350, dessin 5.3). Si un bloc se perd, l'émetteur des données s'en rendra compte en ne recevant d'accusé de réception que pour le bloc précédant le perdu, il pourra alors réémettre.

L'option windowsize aura dû être préalablement acceptée par le pair, via un OACK (Option Acknowledgment, RFC 2347).

Pour choisir des bonnes valeurs de fenêtre, une expérience a été faite (section 5), transférant un fichier de 180 Mo, avec des blocs de taille 1 456 sur un Ethernet gigabit, entre deux PC. Avec la fenêtre de 1 (la valeur obligatoire, avant notre RFC), le transfert prend 257 secondes. Il baisse ensuite lorsque la taille de la fenêtre augmente (76 secondes pour une fenêtre de 4, 42 secondes pour une fenêtre de 16) puis plafonne, aux alentours de 35 secondes, d'une fenêtre de taille 64 (pour les grandes fenêtres, le risque accru qu'un paquet dans la fenêtre soit perdu compense l'avantage qu'il y a à ne pas attendre les accusés de réception, il ne sert donc à rien d'augmenter indéfiniment la taille de la fenêtre). Un transfert avec un protocole classique (SMB/CIFS) prend 23 secondes. On voit donc que TFTP peut presque atteindre la même valeur.

Cela ne veut pas dire qu'il faut forcément choisir aveuglément une fenêtre de 64 blocs dans tous les cas : la valeur optimale dépend du réseau entre les deux machines. Le RFC recommande donc de tester avant de choisir.

TFTP utilise UDP, qui n'a pas de mécanisme de contrôle de la congestion. Un émetteur de données TFTP doit donc suivre les règles de prudence du RFC 8085 (notamment sa section 3.1) pour ne pas surcharger le réseau (section 6 de notre RFC). Contrairement à TCP, TFTP n'offre pas de mécanisme permettant de réduire la taille de la fenêtre en cours de route. En cas de gros problème de perte de paquets, la seule solution est d'avorter le transfert (ce qu'on nomme un circuit breaker) et de réessayer avec d'autres paramètres.

On trouve plein de traces TFTP sur pcapr mais aucune avec cette option. Parmi les mises en œuvres de TFTP, si le mécanisme d'options du RFC 2347 est souvent présent, ainsi que l'option de taille de bloc du RFC 2348, en revanche notre nouvelle option de taille des fenêtres ne semble pas encore souvent là. Parmi les programmes qui gèrent cette option : Serva (cité au paragraphe suivant), Node-tftp...

Un bon article de l'auteur du RFC explique cette option, les options précédentes, et leur implémentation dans Serva : « Advanced Topics on TFTP ».


Téléchargez le RFC 7440


L'article seul

Ce que nous apprend Ghost au sujet des vieilles API

Première rédaction de cet article le 27 janvier 2015


Vous avez certainement déjà tout lu sur la vulnérabilité « Ghost » de la GNU libc (alias CVE-2015-0235). Si ce n'est pas le cas, vous pouvez vous documenter sur le blog du découvreur ou bien en lisant cette analyse technique ultra-détaillée. Mais un aspect de cette faille a été peu remarqué : qui diable utilise encore l'API gethostbyname, complètement dépassée ?

La faille se trouvait en effet dans une fonction nommée __nss_hostname_digits_dots qui est appelée par les fonctions, bien plus connues, gethostbyname et gethostbyaddr. Ces fonctions servent à traduire un nom de domaine en adresse IP, en général en faisant appel au DNS. Elles sont dépassées depuis longtemps et ne devraient plus être utilisées, notamment parce qu'elles ne permettent pas de faire de l'IPv6.

Ce point a bien été noté par les découvreurs de la faille (et, indépendamment, par certains sur les rézosocios), auteurs qui notent, dans le rapport technique, « The gethostbyname*() functions are obsolete; with the advent of IPv6, recent applications use getaddrinfo() instead. ». En effet, en 2015, on n'imagine pas qu'il puisse exister des programmes qui se limitent volontairement à IPv4, en utilisant ces vieilles API.

Car ce n'est pas qu'une matière d'esthétique : les fonctions officiellement remplacées par des meilleures ne sont pas forcément aussi bien maintenues, et on peut penser que les failles n'y sont pas aussi vite repérées et corrigées. Les programmes utilisant les anciennes API ont donc plus de chance d'avoir des failles de sécurité comme Ghost.

Au fait, que faut-il utiliser depuis plus de quinze ans ? getaddrinfo, introduit à l'origine dans le RFC 2133 et actuellement normalisé dans le RFC 3493. (Vous trouverez mes exemples personnels dans mon article sur les structures de données réseau en C.) gethostbyname avait été marqué obsolescent dans POSIX en 2001 et supprimé complètement en 2008...

Aujourd'hui, si on cherche les « parts de marché » respectives de gethostbyname et getaddrinfo, on trouvera probablement qu'un grand nombre de programmes utilise toujours l'ancienne API. Ignorance, lecture de vieux HOWTO dépassés, cours jamais mis à jour...

Également à lire, sur Ghost :


L'article seul

Davantage de cloche à vache : la NSA espionne aussi le DNS

Première rédaction de cet article le 24 janvier 2015


Quelques jours après le FIC (Forum International sur la Cybersécurité, où on avait beaucoup parlé de méchants hackers, forcément djihadistes), un article du Monde nous rappelle que les plus grandes attaques contre la sécurité de l'Internet viennent des États. L'article révèle l'existence du programme MoreCowBell (« davantage de cloche à vache ») de la NSA, programme d'espionnage du DNS. L'article du Monde est assez flou, questions détails techniques, donc voici quelques explications supplémentaires.

Vous pouvez également en trouver, et jusqu'à saturation, dans « NSA’s MORECOWBELL: Knell for DNS », écrit par les personnes qui ont préparé l'article du Monde (Grothoff est l'auteur de GNUnet, Ermert est une excellente journaliste connaissant bien l'Internet, Appelbaum travaille sur Tor). Dans cet article en anglais (il y a une traduction en français, vous aurez tous les détails sur MoreCowBell mais aussi sur les travaux de l'IETF pour améliorer le DNS, sur les systèmes alternatifs de nommage comme GNUnet, etc. Au cas où vous n'ayez pas envie de changer de page Web, voici mes informations à moi.

Pour résumer l'article du Monde, la NSA espionne le DNS de deux façons :

  • Récolte passive de données, probablement via une écoute directe du trafic Internet (quelque chose que la NSA fait souvent), suivie d'une dissection automatique des paquets DNS et stockage dans une base de données. Rien d'extraordinaire, le trafic DNS étant en clair, et des services moins secrets le font depuis longtemps, comme DNSDB ou PassiveDNS.cn.
  • Récolte active de données par des attaques par dictionnaire, où une sonde (dans le cas de la NSA, la sonde passe par des résolveurs DNS ouverts, comme Google Public DNS, pour mieux dissimuler ses traces) interroge des serveurs DNS sur des noms possibles ou vraisemblables (en utilisant tous les mots du dictionnaire, par exemple). C'est ce que le Monde, curieusement, appelle « adresses fictives mais plausibles ». Les serveurs DNS reçoivent ce genre d'attaques très souvent (ce sont en général des spammeurs qui cherchent à se constituer des listes de noms de domaine).

Comme toujours avec la NSA, rien de surprenant (seuls les naïfs seront étonnés), des techniques classiques, mais déployées à grande échelle. nsa-morecowbell.jpg

Maintenant, sur quelques points obscurs de l'article du Monde :

  • « Serveur DNS interne » est apparemment un néologisme du Monde pour résolveur.
  • « Les numéros IP "en chiffres", correspondant aux adresses "en mots", sont gérés par l’Internet Assigned Numbers Authority (IANA) » C'est tellement résumé que c'est quasiment faux : si l'IANA attribue bien les préfixes (et encore, c'est fini depuis longtemps en IPv4), ce sont les RIR qui font le gros du travail et définissent les politiques d'attribution.
  • La phrase « quand ils reçoivent une demande pour une adresse qui n’existe pas, ils renvoient un message d’erreur accompagné de deux suggestions » est probablement une allusion aux possibilités d'énumération liées à l'ancienne technologie NSEC, possibilités décrites (avec la solution) dans mon article sur le RFC 5155.
  • MoreCowBell, si on se fie aux PowerPoint de la NSA, n'utilise pas que le DNS, mais aussi HTTP. Quand le Monde écrit « quand une attaque est déclenchée, l’interrogation des serveurs DNS va servir à évaluer son efficacité en temps réel. Grâce à MoreCowBells [sic], la NSA saura si le service attaqué continue à fonctionner ou s’il a été coupé », il confond probablement ces deux protocoles. Le DNS ne peut pas servir à savoir si un serveur a cessé de fonctionner.
  • En revanche, « s’il a été déplacé vers un autre serveur par mesure de protection, elle va le repérer à nouveau, ce qui permettra de reprendre l’attaque » peut en effet se faire avec le DNS mais cela n'a rien d'extraordinaire : bien des attaquants qui font des dDoS font pareil.

Par-delà ces détails dans les explications, voilà pourquoi il est essentiel de travailler à améliorer la protection de la vie privée dans le DNS (il faut aussi travailler à mettre fin aux délirants pouvoirs de la NSA, une menace pour tout le monde, mais c'est une autre histoire). À l'IETF, le principal effort, dans la lignée du RFC 6973, est fait dans le groupe de travail DPRIVE. Son premier RFC sera sans doute le document de description du problème. Pour le chiffrement des requêtes DNS, afin d'assurer leur confidentialité, ma proposition préférée est T-DNS mais l'idée d'utiliser l'ALPN de TLS est également tentante. Une partie de l'effort IETF est également faite dans le groupe de travail DNSOP, où se fait l'élaboration de la proposition de minimisation des données envoyées.

Et, bien sûr, une autre solution serait d'utiliser des systèmes alternatifs au DNS, prenant mieux en compte le respect de la vie privée. Ils existent (Namecoin, Tor / dot-onion, etc) mais ils posent de redoutables problèmes.

Un autre article en français sur ce programme est dans 01 Net.


L'article seul

RFC 7421: Analysis of the 64-bit Boundary in IPv6 Addressing

Date de publication du RFC : Janvier 2015
Auteur(s) du RFC : B. Carpenter (Univ. of Auckland), T. Chown (Univ. of Southampton), F. Gont (SI6 Networks / UTN-FRH), S. Jiang (Huawei Technologies, A. Petrescu (CEA, LIST), A. Yourtchenko (cisco)
Pour information
Réalisé dans le cadre du groupe de travail IETF 6man
Première rédaction de cet article le 23 janvier 2015


C'est vrai, ça, pourquoi 64 ? Les adresses du protocole IPv6 ont deux parties, une qui identifie le réseau et l'autre qui identifie la machine. Cette dernière est souvent considérée comme faisant forcément 64 bits. Est-ce vraiment une taille impérative ? Et, si oui, pourquoi ? (Si vous êtes pressé, les réponses du RFC sont « non, mais quand même oui » et « essentiellement en raison de la base installée ».)

Pendant la phase de conception d'IPv6, il y avait eu toute une discussion à l'IETF sur la taille idéale des adresses. La plupart des propositions initiales suggéraient 64 en tout, ce qui était déjà beaucoup pour les processeurs de l'époque (de même que, quand IPv4 avait été conçu, peu de processeurs pouvaient traiter 32 bits comme une donnée de base). Mais c'est finalement 128 bits qui a été choisi. 64 bits permettaient déjà d'adresser plus de machines qu'on ne pouvait en rêver. Mais 128 bits permettait plus de souplesse, et autorisait le développement de mécanismes d'adresse rigolos, par exemple d'utiliser des clés crytographiques comme adresses (RFC 7343).

Une fois ce choix fait, le RFC sur l'adressage IPv6, le RFC 4291, introduisait la notion d'identificateur d'interface (interface identifier ou IID). L'adresse comprend alors deux parties, n bits pour identifier le réseau et 128-n bits pour l'identificateur d'interface. Comme précisé par le RFC 7136, ces identificateurs d'interface n'ont pas de signification en dehors de la machine qui les a alloués et doivent donc être traités comme des valeurs opaques.

Le routage se fait sur la base du préfixe réseau, dont la longueur peut être quelconque, jusqu'à 128 bits. Tous les protocoles de routage gèrent des longueurs de préfixe variables, sans supposition a priori.

Bon, donc, le routage n'impose pas de préfixe de longueur 64, et se moque de la longueur du préfixe. Mais l'autoconfiguration d'adresse sans état (SLAAC), du RFC 4862, elle, considère la longueur 64 comme spéciale ? Non plus. Ce chiffre 64 n'apparait pas dans le RFC 4862 car la longueur de l'identificateur d'interface dépend du type de réseau sous-jacent et est donc spécifiée dans un autre RFC, spécifique à chaque technologie. Pour Ethernet, c'est le RFC 2464, et la longueur spécifiée est bien 64. Donc, pour Ethernet, si on veut de l'auto-configuration sans état, on ne peut pas avoir de réseau ayant un préfixe plus long que 64 bits. DHCP (RFC 8415) suit la même règle et n'a donc pas de chiffre « 64 » magique.

Si l'identifiant d'interface à 64 bits est aujourd'hui largement répandu, c'est en partie à cause de la part de marché d'Ethernet. Il était plutôt prévu de le mettre à 48 bits au début avant que les identifiants EUI-64 ne remplacent les EUI-48. Résultat, le RFC 4291 a sérieusement réduit la souplesse d'IPv6 en parlant d'identificateurs d'interface de 64 bits et en laissant entendre qu'ils étaient forcément dérivés d'une adresse MAC (le RFC 7136 a partiellement corrigé cette erreur mais trop tard, beaucoup de gens sont aujourd'hui persuadés que les 64 derniers bits d'une adresse IPv6 sont forcément une adresse Ethernet). Quant à l'autre choix, de fixer les identificateurs d'interface à 64 bits, il n'a pas empêché le RFC 6164 de recommander 1 seul bit pour cet identificateur, dans le cas de liaisons point-à-point.

Malheureusement, un certain nombre de logiciels et de matériels ont peut-être été bâtis en supposant un identificateur d'interface de 64 bits et, hélas, une autre longueur, bien que techniquement correcte, posera des problèmes si on s'approche de ces logiciels et matériels. Pourquoi diable le RFC 4291 a-t-il sanctifié cette valeur de 64 bits ? Et peut-on encore la changer ?

D'abord (section 2 du RFC), les avantages qu'il y a à avoir une frontière fixe entre le réseau et l'identificateur d'interface. Pour l'auto-configuration sans état (SLAAC pour StateLess Address AutoConfiguration), il faut que la longueur du préfixe, pour un type de réseau physique donnée, soit identique pour toutes les machines du réseau local, et connue à l'avance, donc fixe. Bien sûr, elle n'est pas forcément de 64 bits. Mais le poids d'Ethernet, où cette longueur est de 64 bits, et le désir de simplifier les choses (cf. RFC 5505) poussent à l'uniformisation.

Le RFC 4291 (section 2.5.1), on l'a vu, cite déjà cette limite fixe de 64 bits. Le préfixe du réseau local a donc forcément 64 bits de long, quelle que soit la taille du préfixe qui nous a été alloué (au moins un /56, si on suit le RFC 6177). Cela simplifie la conception des réseaux (préfixe de longueur identique sur tous les liens réseaux d'un campus, par exemple, un très gros avantage par rapport à IPv4, où le manque d'adresses oblige à calculer au plus juste chaque longueur de préfixe), la gestion des préfixes (pas besoin de faire un calcul à chaque allocation, un nouveau lien, paf, je lui donne un /64), la configuration des routeurs et la documentation du réseau de l'organisation sont plus simples.

Garantir une certaine taille pour l'identificateur d'interface permet de choisir le mécanisme qu'on veut pour leur allocation. Des préfixes longs risqueraient de réduire la taille de l'espace des identificateurs d'interface, au point de contraindre l'administrateur réseaux dans sa politique d'allocation.

Les sections suivantes du RFC examinent les arguments contre cette taille fixe de 64 bits mais je vous révèle la fin du RFC tout de suite : l'IETF estime que les avantages d'une longueur d'identificateur d'interface plus ou moins fixée à 64 bits l'emportent sur les inconvénients.

Bon, maintenant, pour la culture de mes lecteurs, quels auraient été les raisons de ne pas imposer une taille spéciale aux identificateurs d'interface ? D'abord, le /64 partout peut mener à du gaspillage. J'ai un réseau avec une demi-douzaine de serveurs statiquement configurés, ou bien utilisant DHCP (donc pas de SLAAC), même si chacun d'eux a plusieurs adresses IP, pourquoi ne pourrais-je pas utiliser un /96 ou similaire, pour économiser des adresses ? Bien sûr, l'espace d'adressage d'IPv6 est très grand mais un utilisateur donné peut n'avoir reçu qu'un seul /64, et comment fait-il alors s'il veut mettre plusieurs réseaux physiques derrière ?

Le RFC 7368, portant sur les réseaux à la maison, écarte la solution des préfixes plus longs (cf. sa section 3.4.1) et préfère mettre la pression sur les FAI pour qu'ils distribuent plus d'un préfixe /64. Il n'y a en effet aucune raison de faire des économies : l'espace IPv6 actuellement utilisé (le 2000::/3, qui ne représente que 13 % de l'espace d'adressage possible) permet 35 billions de /48 donc en donner un à chaque utilisateur humain ne pose aucun problème. Même avec un très mauvais « ratio HD », 0,89, on pourrait encore allouer un trillion de préfixes /48 (voir le RFC 4692, sur ces calculs et sur la notion de ratio HD).

Un autre argument a parfois été présenté pour justifier des préfixes plus longs que 64 bits : cela permet d'avoir davantage de réseaux locaux lorsqu'on a reçu une allocation trop petite. Ceci dit, avec un /48, on a 65 536 réseaux, ce qui est déjà énorme. Il a aussi été dit que des préfixes plus longs que 64 bits permettraient, sinon davantage de réseaux, en tout cas une meilleure agrégation des préfixes mais cet argument ne semble pas tenir non plus : même dans le pire cas (routage complètement à plat, zéro agrégation), router des milliers de préfixes ne pose aucun problème.

Une autre raison pour souhaiter des préfixes plus spécifiques que 64 bits vient des exigences de traçabilité. Moins de bits pour l'identifiant d'interface voudrait dire moins de possibilités qu'une machine prenne l'adresse qu'elle veut, ce qui faciliterait la tâche de l'administrateur réseaux. Comme le précédent, cet argument semble très faible : il existe d'autres méthodes pour surveiller ses machines (par exemple ndpmon).

Beaucoup plus sérieux est le risque d'attaque sur le protocole NDP par épuisement du cache (voir les supports d'exposé de Jeff Wheeler). L'idée de l'attaquant est d'envoyer des paquets à des tas de machines non existantes. Le routeur menant au lien de ces machines va devoir faire une résolution d'adresse IP en adresse MAC, avec NDP et, la machine n'existant pas et ne répondant donc pas, le routeur va devoir mettre une demande en attente, dans une mémoire qui a une taille fixe et qui peut donc être vite remplie (le RFC 3756 détaille cette attaque). Avec un /120 (ou bien avec les préfixes typiques d'IPv4, pour qui cette attaque est également possible), l'attaquant ne pourra occuper que 256 entrées dans la mémoire. Avec un /64, il aura beau jeu pour la remplir complètement (même un /96 serait largement suffisant pour l'attaquant). C'est d'ailleurs un argument du RFC 6164 (section 5.2) pour justifier sa recommandation d'un /127.

Notre nouveau RFC estime que ce risque, quoique réel, n'est pas suffisant pour justifier des préfixes ultra-longs (genre /120) et qu'il vaut mieux déployer les recommandations du RFC 6583.

La section 3 parlait des arguments en faveur d'un préfixe plus long que 64 bits. Mais il y a aussi un autre débat, qui est celui sur les préfixes de longueur variable. Un argument en faveur de « tout le monde en /64 » était que cela fournissait une longueur de préfixe constante. Que se passe-t-il si elle ne l'est pas ? La section 4 du RFC se penche là-dessus. D'abord, par rapport aux normes. Malheureusement, la situation est confuse. Si les RFC 4291, RFC 6177, RFC 5453, RFC 6741 et RFC 7084 font tous référence à une longueur magique de 64 bits, ils ne sont pas forcément très clairs et précis sur le statut de cette référence : simple exemple, constatation de l'existant ou réelle normalisation ? Le RFC 5942 dit au contraire que les mises en œuvre d'IPv6 ne doivent pas supposer une longueur de préfixe fixe.

Les RFC décrivant le cas particulier d'une technologie de couche 2 donnée sont en général plus clairs, et beaucoup imposent un identificateur d'interface de 64 bits (et donc un préfixe de 64 bits) pour l'autoconfiguration sans état. C'est le cas des RFC 2464 (Ethernet, déjà cité), RFC 2467 (FDDI), RFC 4338 (Fibre Channel), RFC 5072 (PPP), etc.

D'autres RFC semblent (mais c'est souvent vague) supposer qu'un identifiant d'interface fait forcément 64 bits. C'est le cas du RFC 4862 pour les adresses locales au lien, du RFC 4429 pour la détection d'adresses dupliquées, du RFC 5969 sur 6rd, du RFC 6437 au sujet du flow label, etc. Dans certains cas, la dépendance vis-à-vis de la longueur du préfixe est plus nette, comme une technique pour étendre un préfixe IPv6 reçu en 3G sur une interface WiFi (RFC 7278), dans les CGA du RFC 3972 ou dans les adresses protégeant la vie privée du RFC 8981.

Et si on est courageux, et qu'on essaie quand même de mettre des identificateurs d'interface dont la longueur est différente de 64 ? Que risque-t-on ? D'abord, certains routeurs peuvent avoir mal lu les spécifications et penser que des identificateurs d'interface entre 65 (RFC 7136) et 126 (RFC 6164) sont invalides, refusant de configurer ainsi une interface ou, pire, refusant ensuite de transmettre des paquets. (Je n'ai pas connaissance d'un étude systématique de routeurs à ce sujet, ni de récit détaillé d'un problème avec un routeur.) CGA, on l'a vu, ne marcherait pas du tout. On peut changer sa spécification mais attention, diminuer la taille de l'identificateur d'interface diminuerait la sécurité de CGA (même chose pour les techniques qui visent à protéger la vie privée par des identificateurs d'interface choisis aléatoirement, cf. section 4.5). Par contre, NAT64 (RFC 6146) marcherait sans doute, jusqu'à 96 bits de préfixe réseau (car il faut garder au moins 32 bits pour l'adresse IPv4 de destination). En revanche, NPT (Network Prefix Translation, RFC 6296) est lié aux 64 bits. Même chose pour ILNP (RFC 6741).

Le mécanisme DAD (Duplicate Address Detection, RFC 4862, section 5.4) pourrait avoir des problèmes si on réduisait trop la taille des identificateurs d'interface. Par exemple, avec un /120, et les adresses du RFC 7217, il n'y aurait que 256 identificateurs d'interface possible et donc des risques de collision élevés. Enfin, les adresses locales au lien, bien que prises dans un espace très large (fe80::/10) sont en fait quasiment toujours formées pour un préfixe de longueur 64 (et l'espace réel est donc fe80::/64) et il n'y a pas de moyen simple de le changer (ce n'est que rarement une option de configuration de la machine).

La section 4.3 contient les résultats d'essais systématiques d'essais de préfixes différents de /64, essais faits avec plusieurs systèmes d'exploitation. Avec des préfixes plus longs ou plus courts que 64 bits, et un routeur qui annonce, via les RA (Router Advertisement), un tel préfixe dans le champ Prefix Information Option, tout marche bien sur tous les Unix et sur Windows (l'essai a également été fait sans le bit L dans l'option, bit qui indique que le préfixe pour être utilisé pour déterminer si le préfixe est sur le lien local et, dans ce cas, les machines ignorent à juste titre le préfixe). Par contre, l'option Route Information Option du RFC 4191 marche nettement moins bien sur les Unix, mais c'est le cas même avec une longueur de 64 bits.

D'autre part, les informations recueillies par les participants à l'IETF sur divers réseaux indiquent que les routeurs routent bien sur des préfixes de longueur quelconque (la recherche d'une route du préfixe le plus long est un algorithme de base d'IP, il est plus ancien qu'IPv6). Et, dans les expériences pratiques, DHCP ne semble pas avoir de problème non plus (un déploiement réel utilise des /120...)

Certains routeurs ont des problèmes de performance car ils traitent à part les préfixes plus longs que 64 bits. Cela fonctionne mais pas aussi vite.

Au moins un équipement réseau à une TCAM limitée à 144 bits ce qui fait que les ACL ne peuvent pas être définies pour un préfixe quelconque, puisqu'elles permettent également de mettre deux ports de 16 bits chacun. Avec un tel équipement, on ne peut pas utiliser d'ACL avec un préfixe plus long que 112 bits.

Bref, la situation des mises en œuvre d'IPv6 ne semble pas trop mauvaise. Contrairement à ce que l'on aurait pu craindre, peu ou pas de programmeurs ont, en lisant trop vite les spécifications, considéré qu'un identificateur d'interface était toujours de 64 bits et, donc, peu de programmes ont cette taille « câblée en dur ». Évidemment, on ne peut pas être sûr tant qu'on n'a pas testé toutes les implémentations, une tâche impossible.

Il n'y a pas que le code IPv6 proprement dit : il y a aussi les outils auxiliaires comme les IPAM. Ont-ils également une taille de préfixe magique fixée dans leur code ? Apparemment, cela n'a pas été testé.

Il y a aussi les craintes liées aux humains : si on décidait de mettre des identificateurs d'interface d'une longueur différente de 64 bits, ne risque-t-on pas d'avoir à reprendre la formation de certains, qui ont mal compris leur cours IPv6 et croient que 64 bits a une signification spéciale ?

Un éventuel changement de la longueur des identificateurs d'interface a aussi des conséquences pour la sécurité. D'abord, la vie privée (section 4.5) : si on tire au sort un identificateur d'interface, pour le rendre difficile à deviner par un observateur indiscret, l'identificateur ne doit évidemment pas être trop petit, sans cela l'observateur pourrait essayer la force brute pour le deviner. Il est difficile de donner un chiffre précis mais notre RFC estime qu'un préfixe de plus de 80 bits, laissant moins de 28 bits pour l'identificateur d'interface, serait trop prévisible.

La longueur de l'identificateur d'interface a également des conséquences pour le balayage (RFC 7707) : il est beaucoup plus difficile de balayer systématiquement un réseau IPv6 qu'un réseau IPv4, en raison du nombre d'adresses possibles. Si on a un long préfixe, le balayage devient réaliste : un /120 IPv6 prendrait autant de temps à balayer qu'un /24 IPv4, c'est-à-dire très peu de temps. (Le problème est proche de celui des CGA, et de celui de la vie privée, déjà cité : beaucoup de techniques de sécurité dépendent de la taille de l'espace possible, en la réduisant, on facilite les attaques.)

En conclusion, si certains points d'IPv6 ne devraient absolument pas dépendre de la longueur du préfixe, qui est un simple paramètre (le routage, par exemple), d'autres sont bien plus liés au nombre magique de 64. Sans compter le risque qu'une partie de la base installée (et pas seulement logicielle, aussi les humains) ait attribué à ce nombre 64 encore plus d'importance que ce que les normes IPv6 prévoient. Le RFC décide donc d'entériner cet usage et de recommander qu'on ne s'éloigne pas de 64 sans de très bonnes raisons.


Téléchargez le RFC 7421


L'article seul

RFC 3633: IPv6 Prefix Options for Dynamic Host Configuration Protocol (DHCP) version 6

Date de publication du RFC : Décembre 2003
Auteur(s) du RFC : O. Troan, R. Droms
Chemin des normes
Première rédaction de cet article le 18 janvier 2015


On peut en IPv6 déléguer un préfixe d'adresse IP d'un routeur à un autre routeur. Par exemple, le routeur du FAI peut, via DHCP, déléguer au routeur CPE le préfixe que celui-ci annoncera ensuite en RA (Router Advertisement) sur le réseau local. Ce RFC a depuis été intégré au RFC 8415.

Vous verrez rarement cette option DHCP (DHCP est dans le RFC 3315) sur vos réseaux locaux. Son utilité principale est au sein du réseau d'un FAI, pour distribuer aux clients, non pas uniquement des adresses (comme on le fait en IPv4, où il n'y a pas assez d'adresses pour attribuer des préfixes), mais des préfixes entiers. Notez qu'il s'agit bien de délégation : le routeur qui reçoit un préfixe peut en faire ce qu'il veut, y compris le sous-déléguer en préfixes plus petits (les réseaux locaux n'ont pas forcément qu'un seul lien, ils peuvent être multiples, cf. RFC 7368). Cette option de délégation de préfixe est donc utile pour tous les cas où le routeur qui délègue (le déléguant, le serveur DHCP) ne connait pas la topologie du réseau chez le routeur qui reçoit la délégation (le requérant, le client DHCP) et ne peut donc pas attribuer les préfixes à chaque sous-réseau. Elle suit les exigences posées dans le RFC 3769, le cahier des charges de cette option.

Bien sûr, une autre solution serait une délégation manuelle (envoyer le préfixe par courrier au client et attendre qu'il le configure dans son routeur CPE) mais cette méthode dynamique rend beaucoup plus facile une future renumérotation.

Donc, si vous voulez le modèle général de fonctionnement, regardez la section 5 : le routeur déléguant a un certain nombre de préfixes IP à distribuer, le routeur requérant, demande en DHCP un ou plusieurs préfixes, le déléguant lui répond avec les préfixes attribués. Chaque préfixe a une durée de vie associée et le requérant devra donc demander un renouvellement.

La délégation de préfixe est indépendante de celle d'adresse. Le routeur client peut utiliser DHCP pour avoir adresse et préfixe, ou bien seulement pour l'adresse ou seulement pour le préfixe.

Les préfixes ainsi délégués ne sont pas liés à une interface réseau particulière, au sens où les adresses réseau le sont, et le routeur client, qui a reçu la délégation, peut l'utiliser sur d'autres interfaces que celle où il l'a reçue.

Maintenant, le format des options. Pour le comprendre, il faut dire un mot de la notion d'IA_PD (section 3 du RFC). Une IA_PD (Identity Association for Prefix Delegation) est un ensemble de préfixes IP gérés collectivement. Le routeur requérant ne reçoit pas un seul préfixe mais une ou plusieurs IA_PD, chacune pouvant comporter plus d'un préfixe. Chaque IA_PD est associée à un IAID, qui est un identificateur unique pour le routeur requérant, et qui lui permet d'avoir plusieurs IA_PD (par exemple si deux de ses interfaces sont connectées à des FAI différents).

En section 9, le format des messages DHCP. L'option IA_PD (code 25 dans le registre IANA des options DHCP) est envoyée par le routeur requérant dans sa question (message Solicit, cf. RFC 3315, section 17.1, pour dire qu'il veut des préfixes) et par le routeur déléguant dans sa réponse (message Advertise, cf. RFC 3315, section 17.2, pour indiquer les préfixes délégués). Dans les deux cas, elle comprend l'IAID (un nombre sur quatre octets choisi par le requérant), et une série d'options parmi lesquelles se trouvent les options IAPREFIX (code 26) qui contiennent les préfixes IP et leurs durées de vie. Dans la requête, il peut évidemment n'y avoir aucun préfixe (le routeur requérant demande mais ne propose rien). Chaque option IAPREFIX contient un seul préfixe mais il peut y avoir plusieurs options de ce type dans une option IA_PD.


Téléchargez le RFC 3633


L'article seul

À propos de la panne d'Oxalide

Première rédaction de cet article le 16 janvier 2015
Dernière mise à jour le 22 janvier 2015


Ce matin, l'hébergeur Oxalide a été en panne pendant environ une heure et demie, entraînant l'indisponibilité d'un grand nombre de sites Web, notamment de la presse française.

C'est ainsi que 20 Minutes, l'Express, le Parisien, Slate, Mediapart, Marianne, FranceInfo (mais pas Charlie Hebdo) ont été injoignables. Comme tous les zexperts, je ne sais pas ce qui s'est passé donc je vais me contenter de dire ce que j'ai observé.

Plusieurs de ces sites Web renvoyaient un message « 504 Gateway Time-out - nginx » qui est le message typique de CloudFlare lorsque leurs relais n'arrivent pas à joindre le site réel (CloudFlare n'est pas un CDN, ils n'ont pas une copie du site Web, ils servent juste d'écran, notamment en cas de dDoS).

Oxalide avait arrêté d'envoyer des annonces BGP, le protocole qui sert à annoncer au reste de l'Internet qu'on est joignable. (Pourquoi ? Ne me posez pas la question, j'ai dit que je n'en savais rien.) Voici le looking glass de Hurricane Electric, http://lg.he.net, pendant la panne, le préfixe IP 91.208.181.0 est inconnu : lg-panne.png

Voyons les annonces BGP pendant la période de la panne. On utilise pour cela les données de RouteViews. Elles sont en binaire, au format MRT (RFC 6396), il faut les transformer en texte avec bgpdump. On sait d'après Twitter l'heure approximative de la panne, on va donc récupérer le fichier, le transformer en texte et le fouiller :

% wget ftp://archive.routeviews.org/route-views.linx/bgpdata/2015.01/UPDATES/updates.20150116.0845.bz2
% bgpdump  updates.20150116.0845 > updates.20150116.0845.txt

Et explorons ce fichier, avec un éditeur ordinaire. On voit bien la panne. L'annonce du préfixe 91.208.181.0/24 a commencé à être perturbée vers 08:51:01 UTC. À noter qu'il existe deux types de mise à jour BGP dans un message, l'annonce de nouvelles routes (ANNOUNCE) et le retrait de routes qui ne sont pus bonnes (WITHDRAW). Paradoxalement, la disparition d'une route (ici celle vers 91.208.181.0/24) se traduit d'abord par des ANNOUNCE avant d'avoir le premier WITHDRAW. En effet, les routeurs BGP tentent de passer par un autre chemin et relaient d'abord les autres informations qu'ils ont, avant de renoncer et de retirer la route. Une panne se signale donc d'abord par une floppée d'ANNOUNCE. La première était :

TIME: 01/16/15 08:51:01
TYPE: BGP4MP/MESSAGE/Update
FROM: 195.66.224.21 AS6939
TO: 195.66.225.222 AS6447
ORIGIN: IGP
ASPATH: 6939 8218 47841
NEXT_HOP: 195.66.224.21
ANNOUNCE
  91.208.181.0/24

À 08:51:01 (UTC), le routeur 195.66.224.21 transmet à son pair 195.66.225.222 une nouvelle route vers 91.208.181.0/24, car il vient de perdre celle qu'il connaissait avant. Dans les secondes qui suivent, des tas d'autres routeurs font pareil avant de se résigner, et de retirer la route :

TIME: 01/16/15 08:51:10
TYPE: BGP4MP/MESSAGE/Update
FROM: 195.66.224.175 AS13030
TO: 195.66.225.222 AS6447
WITHDRAW
  ...
  91.208.181.0/24
  ...

Attention au passage lorsque vous lisez l'attribut ASPATH (chemin d'AS), il se lit de droite à gauche, l'AS d'origine est 47841 (Oxalide).

Une heure et demie après, la route vers 91.208.181.0/24 réapparait (avec les deux autres préfixes IPv4 habituels d'Oxalide) :

TIME: 01/16/15 10:20:13
TYPE: BGP4MP/MESSAGE/Update
FROM: 195.66.224.51 AS6453
TO: 195.66.225.222 AS6447
ORIGIN: IGP
ASPATH: 6453 1299 47841
NEXT_HOP: 195.66.224.51
ANNOUNCE
  95.131.136.0/21
  146.185.40.0/21
  91.208.181.0/24

En regardant le looking glass, on voit que tout est revenu : lg-repare.png

Enfin, presque, Emile Aben me fait remarquer qu'IPv6 a mis plus de temps, le préfixe 2a02:c70::/32 n'est revenu que vers 11:15 UTC.

Des articles sur cette panne :


L'article seul

Mon blog dans les oignons

Première rédaction de cet article le 15 janvier 2015
Dernière mise à jour le 1 septembre 2021


Cela faisait longtemps que je voulais m'amuser avec cela, donc, désormais, ce blog est également accessible en Tor hidden service, c'est-à-dire avec un nom de domaine en .onion.

Quel est l'intérêt de faire cela ? Le réseau Tor est connu pour permettre une connexion aux services de l'Internet qui soit anonyme (attention à votre sécurité toutefois : aucune technique n'est parfaite et rien n'est jamais complètement anonyme) et qui résiste à la censure. Tor assure ce service en relayant chaque requête par plusieurs nœuds Tor. Seul le premier connait le client initial (il ne connait pas la destination) et seul le dernier connait le serveur visé (il ne connait pas le client initial). Bon, ça, c'est Tor qui protège le client. Mais si on a envie de protéger le serveur ? Lorsqu'on publie traditionnellement sur l'Internet, on annonce un nom de domaine et n'importe qui peut investiguer, trouver (par exemple avec dig) l'adresse IP associée, se servir de whois pour trouver où et par qui est connectée cette machine, bref, même si on n'a pas mis son nom et son adresse dans les informations distribuées par le serveur, on peut être retrouvé facilement, ce qui est un problème si on veut bloguer alors qu'on vit sous une dictature intégriste et moyenâgeuse.

C'est là qu'interviennent les Tor hidden services. L'idée de base est que le serveur fabrique une identité sous forme d'une clé cryptographique, l'envoie à quelques relais Tor, qui inscrivent cette identité dans, par exemple, une DHT, et les clients qui se connecteront à Tor trouveront ainsi les points de rendez-vous, permettant de se connecter à votre serveur, sans que les clients ne trouvent son adresse. Comme toutes les techniques de sécurité, cela n'est pas invulnérable à tout attaquant, donc, attention, si les enjeux sont élevés, il faut prévoir également d'autres précautions.

Pour savoir si le serveur à contacter est un serveur « normal » sur l'Internet ou bien si c'est un de ces services discrets (ce que les médias à sensation nomment le « Dark Web »), les services discrets ont un nom dans le TLD (domaine qui a depuis été officiellement reconnu par le RFC 7686) .onion. C'est ainsi que ce blog est (le lien ne marchera que si vous avez un client Tor) http://sjnrk23rmcl4ie5atmz664v7o7k5nkk4jh7mm6lor2n4hxz2tos3eyid.onion/.

Pour configurer ce service, la documentation en ligne est suffisante. J'ai juste installé Tor sur une machine Debian (aptitude install tor), ajouté et configuré Apache (attention à n'écouter qu'en local, avec Listen 127.0.0.1:80), puis configuré Tor

HiddenServiceDir /var/lib/tor/blog/
HiddenServicePort 80 127.0.0.1:80

Et c'est tout (en supposant que l'Apache ne serve qu'un site, sinon il faudra mettre le nom en .onion dans ServerName). Tor crée la clé et la publie auprès des relais. On peut la lire dans /var/lib/tor/blog/hostname (où blog est le nom du service caché, utilisé dans la directive HiddenServiceDir). Attention toutefois à certains pièges : le but étant d'être autant que possible anonyme, Tor ne servira à rien si vous laissez des choses comme ServerAdmin jeankevin@chezmoi.example, choses qu'Apache publiera dans certains cas. Vérifiez donc bien que vous ne laissez pas d'indications dans vos textes ou votre configuration !

Bien sûr, dans le cas de ce blog, le service discret Tor n'a aucun intérêt pour l'auteur puisque le même contenu est publié par ailleurs par une technologie classique. Mais, dans un monde où on peut être assassiné pour des dessins qui déplaisent aux censeurs, beaucoup de gens ont intérêt à publier discrètement.

De nombreux sites sont ainsi accessibles via .onion même si, pour certains, cela peut sembler surprenant.

Si vous voulez des informations techniques en français, il y a l'article de Benjamin Sonntag. Vous y noterez (à la fin de la section « Héberger votre site avec Tor ») un point dont je n'ai pas parlé, la possibilité de choisir un nom plus parlant, au lieu de la clé cryptographique aléatoire que Tor génère par défaut. Cette possibilité me semble une faiblesse de sécurité mais les gens de Tor ne sont pas d'accord (la section « Part three: their vanity address doesn't mean the world has ended »).

Au fait, ce n'est pas tout d'avoir un site en .onion, encore faut-il que les gens l'utilisent. Pour aider, le navigateur Tor a, depuis sa version 9.5, la possibilité de découvrir une version .onion d'un site Web qui l'annonce via l'en-tête HTTP (non standard à ce jour) Onion-Location:. C'est ce que j'ai configuré sur ce blog, avec la directive Apache :

Header set Onion-Location "http://sjnrk23rmcl4ie5atmz664v7o7k5nkk4jh7mm6lor2n4hxz2tos3eyid.onion%{REQUEST_URI}s"

Je paie une bière à celui ou celle qui m'indiquera l'adresse IP de la machine qui héberge ce service, je vais peut-être découvrir (c'est mon premier service Tor discret) que j'ai fait plusieurs grosses erreurs de configuration (rappelez-vous l'avertissement plus haut : les erreurs arrivent et, en sécurité, elles peuvent coûter cher). La première faille a été découverte par Xilokar et c'était l'oubli du /server-status d'Apache, activé par défaut... (Ce problème a fait l'objet d'une alerte de sécurité bien plus tard.)

Avec mes remerciements à Ser Davos, le « chevalier à l'oignon », un des personnages les plus sympathiques de Game of Thrones.

Pour le futur : faudrait quand même que je mette les flux de syndication en .onion, eux aussi...


L'article seul

Continuons à soutenir Charlie Hebdo

Première rédaction de cet article le 15 janvier 2015


Dans l'émotion, depuis l'attaque des intégristes islamistes contre Charlie Hebdo, beaucoup de gens ont réagi, en manifestant, en envoyant une aide financière, en organisant discussions et réunions... Il est important que le soutien se fasse désormais sur le long terme, étant donné qu'il est certain que l'intégrisme armé ne s'arrêtera pas là.

D'abord, puisque les intégristes ont protesté contre la dernière couverture de Charlie Hebdo, il est important de la faire circuler le plus possible : charlie-tout-est-pardonne.jpg

Ensuite, pour l'aide financière, on peut apparemment (je n'ai pas essayé) faire des dons à http://jaidecharlie.fr/ (non, pas de HTTPS, ce qui est dommage pour un site de dons, il vaut peut-être mieux aller directement chez le prestataire financier). Mais j'ai préféré m'abonner, ce qui me semble plus approprié lorsqu'un journal est menacé. Charlie ne propose apparemment pas d'abonnements en ligne depuis son site, il faut donc le faire via la poste ou bien via un prestataire. Comme je n'ai pas pu créer un compte chez A2 presse, qui n'aime pas mon adresse (« Le champ E-Mail valide n'est pas une adresse e-mail correcte »), je suis donc allé chez ViaPresse, dont la sécurité est nulle mais dont le site Web fonctionne. J'ai payé via PayPal, au moins, ViaPresse (ou sa plateforme de paiement) n'aura pas mon numéro de carte de crédit (mais la NSA saura ainsi que je me suis abonné à Charlie).

Le numéro de Charlie Hebdo d'hier (le premier après l'attentat) a été numérisé et peut être trouvé en ligne (également, au format CBZ). Au passage, je vous recommande l'article « Comment trouver Charlie Hebdo en ligne ».


L'article seul

RFC 7426: SDN Layers and Architecture Terminology

Date de publication du RFC : Janvier 2015
Auteur(s) du RFC : E. Haleplidis (University of Patras), K. Pentikousis (EICT), S. Denazis (University of Patras), J. Hadi Salim (Mojatatu Networks), D. Meyer (Brocade), O. Koufopavlou (University of Patras)
Pour information
Réalisé dans le cadre du groupe de recherche IRTF sdnrg
Première rédaction de cet article le 9 janvier 2015


S'il y a un buzzword populaire en ce moment, dans les technologies de réseau, c'est bien SDN. Ce sigle désigne une approche de contrôle centralisé d'un réseau, par le biais d'ordres envoyés depuis la machine d'administration, vers tous les éléments actifs du réseau (les routeurs, par exemple). Comme tous les buzzwords, son utilisation massive pour désigner tout et n'importe quoi entraîne pas mal de confusion, et ce RFC de l'IRTF essaie de clarifier un peu en précisant la terminologie du SDN (Software-Defined Networking), et en explorant les protocoles actuels qui participent au système SDN.

Le problème est d'autant plus difficile que tout le monde veut être SDN aujourd'hui. Si, comme la plupart des administrateurs réseaux professionnels, j'utilise un script qui utilise SSH pour se connecter sur tous mes routeurs afin de changer leur configuration, je fais du SDN ? (Réponse : oui, selon la plupart des définitions de SDN qu'on peut trouver, non selon les marketeux, car cette solution ne permet pas de nouvelles ventes.)

La définition que donne le RFC est « le SDN, c'est une approche du réseau fondée sur la programmabilité, qui sépare le plan du contrôle de celui de la transmission, et qui utilise des interfaces standardisées ». Une interface est là où deux entités interagissent. Ce peut être fait avec un protocole réseau, ou une API locale. Le maître d'un réseau SDN (le contrôleur) va configurer des éléments du réseau (network device), les engins qui assurent les fonctions comme la transmission des paquets. Le logiciel utilisé se divise entre applications (qui sont un but en elles-mêmes) et services (qui n'existent que pour fournir des fonctions aux applications, via une jolie API).

Et ces histoires de plan dont j'ai parlé plus haut ? Un plan est une collection de ressources (matériel et logiciel) qui sont responsables d'une activité donnée. Le RFC distingue cinq plans :

  • Plan de transmission (forwarding plane) : faire suivre les paquets d'une interface à l'autre,
  • Plan de contrôle (control plane) : détermine les règles que va suivre le plan de transmission. Par exemple, sur un routeur haut de gamme, le plan de contrôle, qui tourne sur du matériel généraliste, fait tourner les protocoles comme BGP ou OSPF, déterminant la table de routage, tandis que le plan de transmission, composé d'ASIC spécialisés, utilise cette table de routage pour transmettre les paquets à la bonne interface.
  • Ces deux premiers plans sont classiques et souvent utilisés dans les discussions réseau. Le RFC en ajoute trois autres : d'abord, plan des opérations (operations plane, la gestion globale de la machine), et plan de gestion (management plane, la supervision et la configuration de la machine).
  • Et enfin, le plan des applications (application plane), qui comprend les services et les applications proprement dites.

Le RFC introduit aussi le concept de couche d'abstraction (AL, Abstraction Layer), qui est la vision qu'une ressource va présenter au monde extérieur. Ainsi, le DAL (Device Abstraction Layer, aussi appelé HAL pour Hardware Abstraction Layer), est la vision externe d'un engin, ce que connaitra le reste du monde. Il y a de la même façon un CAL (Control Abstraction Layer), un MAL (Management Abstraction Layer) et un NSAL (Network Services Abstraction Layer). Oui, moi aussi, je trouve cela bien abstrait.

La section 3 détaille certains de ces concepts. On a, de bas en haut (en mettant en bas ce qui est concret et en haut ce qui est utile) :

  • L'élément du réseau, par exemple un commutateur, qui contient le plan de transmission et celui des opérations, et qui montre à l'extérieur le DAL. Il est décrit plus en détail en section 3.2.
  • Côte-à-côte, les plans de contrôle (faisant appel au CAL) et de gestion (faisant appel au MAL). Sur un engin ancien, ils sont intégrés aux précédents mais le SDN prône leur séparation (qui était réalisée depuis longtemps dans les routeurs), pouvant aller jusqu'à les mettre dans des machines différentes. La distinction entre ces deux plans est subtile, l'intéressante section 3.5 la traite plus en détail. En gros, le plan de contrôle s'occupe plutôt de réactions rapides (genre moins d'une seconde), et a des états de courte durée (genre une minute). Le plan de gestion prend en charge des phénomènes moins rapides.
  • Les services et applications, parlant au NSAL.

Le RFC 7276 avait déjà un schéma de ce genre. Comme on représente les composants avec le matériel en bas et les applications et services en haut, les interfaces sont souvent étiquetées « Nord » et « Sud » selon qu'elles connectent à un composant situé plus haut ou plus bas (et tant pis pour les Australiens qui mettent le Nord en bas). Ainsi, l'interface du plan de gestion avec le plan des opérations (via le DAL) est, pour le plan de gestion, une Southbound interface (MPSI : Management Plane Southbound Interface).

Le RFC note que, pour le plan de gestion, la facilité d'usage doit être un critère plus important que les performances (cf. RFC 3535) ce qui implique entre autres des fichiers de configuration sous forme texte, en UTF-8 (cf. RFC 6632). Il existe déjà plusieurs protocoles pour la communication Sud du plan de gestion, par exemple NETCONF (RFC 6241), ForCES (RFC 5810), et même les bons vieux syslog (RFC 5424) et SNMP (RFC 3411).

La section 4 met tout cela en perspective dans le cas du SDN, notamment en regardant où les protocoles existants se situent. En gros, les contrôleurs SDN existants sont plutôt dans le plan de contrôle et utilisent son interface Sud (CPSI, Control Plane Southbound Interface) pour parler au matériel. Le protocole utilisé pour cela est typiquement OpenFlow. Leur interface Nord (le NSAL) n'est pas normalisée.

Pour les protocoles IETF existants, quelle est leur place dans ce schéma ? Commençons par ForCES (RFC 3746). L'idée de base est de normaliser le protocole de communication entre le plan de contrôle et celui de transmission, afin de pouvoir réaliser un routeur en combinant un control/routing engine et un forwarding engine de fournisseurs différents, ce qui est impossible aujourd'hui. Si ForCES vise surtout la communication entre plan de contrôle et plan de transmission, il est assez souple (définition des éléments gérés indépendante du protocole) pour pouvoir peut-être s'utiliser pour des communications avec le plan de gestion et le plan des opérations.

Le protocole NETCONF (RFC 6241) est, lui, un protocole de gestion à distance d'équipement réseau (qui pourrait remplacer le traditionnel script qui se connecte en SSH sur tous les équipements avant de configurer avec la CLI). Il est donc partiellement concurrent de SNMP, notamment pour les opérations de modification (set en SNMP). Et NETCONF, dans le monde SDN, peut servir de MPSI (Management Plane Southbound Interface). Son langage de modélisation, YANG (RFC 6020), semble très populaire en ce moment à l'IETF.

Au contraire de ForCES et de NETCONF, issus directement de l'IETF, OpenFlow vient du privé (université Stanford) et est géré aujourd'hui par une organisation ad hoc, Open Networking Foundation. Son but est de contrôler de manière centralisée un ensemble de commutateurs réseau. C'est entre autres un DAL (Device Abstraction Layer) pour le CPSI (Control Plane Southbound Interface).

Dans un routeur classique, la base d'informations (RIB, Routing Information Base) est gérée par les protocoles dynamiques comme OSPF et a peu d'interfaces vers l'extérieur. On peut définir des routes statiques, on peut obtenir quelques statistiques et de la journalisation mais on n'a pas d'interface standard avec le système de routage, permettant de manipuler davantage celui-ci. Le but du projet I2RS (Interface to the Routing System) à l'IETF est justement de spécifier cette interface, en utilisant YANG et en réutilisant autant que possible des systèmes existants. Le projet en est actuellement à ses débuts.

Tous ces protocoles nouveaux et qui brillent ne doivent pas faire oublier les traditionnels, comme SNMP. Après tout, le terme « SDN » est en grande partie du marketing, le contrôle des éléments réseau via des protocoles se pratiquait longtemps avant que le sigle SDN soit inventé. Donc, SNMP (RFC 3417, RFC 3412, RFC 3414) est un protocole de gestion de réseaux, actuellement dans sa version 3. Les objets définis dans une MIB peuvent être interrogés (get) et modifiés (set mais, en pratique, c'est bien plus rare qu'on utilise SNMP pour cela). Comme NETCONF, il peut servir de MPSI.

Deux autres protocoles sont moins souvent cités lorsqu'on parle de faire du SDN avec les protocoles IETF existants mais ils méritent quand même une mention. D'abord, PCE (RFC 4655), qui vise à réaliser le calcul de chemins dans le réseau en un endroit différent de celui qui fera la transmission. Par exemple, une machine spécialisée, le PCE (Path Computation Element) va calculer des routes et les transmettre au routeur, le PCC (Path Computation Client), via le protocole PCEP (PCE communication Protocol, RFC 5440). Au contraire de la plupart des protocoles vus ici, qui sont Nord-Sud (communication entre des entités de niveau différent), PCEP est Est-Ouest (on peut dire aussi « horizontal », mais le terme n'est pas dans le RFC) faisant communiquer des machines situées au même niveau conceptuel.

Et enfin le protocole BFD (RFC 5880), un protocole de détection de pannes dans les routeurs, prévu pour être très rapide, afin de détecter les problèmes plus tôt que par les techniques de gestion classiques. C'est conceptuellement un service du plan de contrôle.

Pour résumer ? Lire la section 5 et bien se rappeler que 1) SDN ne se limite pas à utiliser OpenFlow 2) Il y a beaucoup de marketing et beaucoup moins de substance.

Quelques lectures classiques citées par notre RFC (la bibliographie de ce RFC est particulièrement longue, reflet de la complexité, de la richesse, et de la confusion du sujet). D'abord, les articles historiques :


Téléchargez le RFC 7426


L'article seul

RFC 7437: IAB, IESG, and IAOC Selection, Confirmation, and Recall Process: Operation of the Nominating and Recall Committees

Date de publication du RFC : Janvier 2015
Auteur(s) du RFC : M. Kucherawy
Première rédaction de cet article le 9 janvier 2015


Voici un nouveau RFC « bureaucratique » autour des processus menant au choix et à la désignation des membres d'un certain nombre d'organismes de la galaxie IETF, comme l'IAB ou l'IESG. Les amateurs de droit constitutionnel seront ravis... (Ce RFC n'est plus d'actualité, ayant été remplacé par le RFC 8713.)

Il n'y a pas de grands changements depuis le RFC 3777 qui, depuis plus de dix ans, était la référence sur ces amusants sujets. Ce nouveau RFC 7437 est surtout la consolidation, dans un document unique, des modifications éparpillées qui avaient été apportées au RFC 3777, comme par exemple celle du RFC 6859, qui ajoutait l'IAOC à la liste des comités dont les membres n'était pas éligibles à un poste au NomCom, le comité de nomination. Ce RFC 7437 ne marque donc pas une réforme significative du fonctionnement de l'IETF mais il permet d'avoir un document à jour. L'annexe A du RFC contient la liste complète des changements depuis le RFC 3777.

Ce RFC concerne la désignation des membres de l'IAB, de l'IESG et de certains membres de l'IAOC (voir la section 4 du RFC 4071 sur le sens de ce « certains »). Il ne concerne pas l'IRTF et ses comités propres. Il ne concerne pas non plus le fonctionnement quotidien de ces comités, juste la désignation de leurs membres.

Le processus tourne autour d'un comité nommé NomCom (pour Nominating Committee, comité de nomination).Comme expliqué en section 2, il faut bien différencier les nommés (nominee), les gens dont les noms ont été soumis au NomCom pour occuper un poste à l'IAB, l'IESG ou l'IAOC, des candidats (candidate) qui sont les gens retenus par le NomCom. Le NomCom, comme son nom l'indique, n'a pas de pouvoir de désignation lui-même, celle-ci est décidée (on dit officiellement « confirmée ») par un organisme différent pour chaque comité (l'IAB pour l'IESG, l'ISOC pour l'IAB, etc). Une fois confirmé, le candidat devient... candidat confirmé (confirmed candidate).

La section 3 de notre RFC explique le processus général : il faut désigner le NomCom, le NomCom doit choisir les candidats, et ceux-ci doivent ensuite être confirmés. Cela peut sembler compliqué, mais le but est d'éviter qu'une seule personne ou une seule organisation puisse mettre la main sur l'IETF. Le processus oblige à travailler ensemble.

À première vue, on pourrait penser que le NomCom a un vaste pouvoir mais, en fait, au début du processus, il ne peut pas décider des postes vacants, et, à sa fin, il n'a pas le pouvoir de confirmation.

Un point important et souvent oublié est celui de la confidentialité (section 3.6 du RFC). En effet, l'IETF se vante souvent de sa transparence, tout doit être public afin que chacun puisse vérifier que tout le processus se déroule comme prévu. Mais le travail du NomCom fait exception. Toutes ses délibérations, toutes les informations qu'il manipule, sont confidentielles. Autrement, il serait difficile de demander aux personnes nommées de fournir des informations personnelles, et les personnes extérieures au NomCom qui sont interrogées hésiteraient à s'exprimer franchement sur tel ou tel candidat. Et la publicité des débats risquerait d'encourager des campagnes de soutien extérieures au NomCom, et du lobbying, toutes choses qui sont formellement interdites. La section 8, sur la sécurité, revient sur cette importance de la confidentialité : puisque le NomCom enquête littéralement sur les nommés, il peut récolter des informations sensibles et il doit donc faire attention à les garder pour lui.

Voici, par exemple, l'annonce de la sélection des membres de l'IESG, début 2014.

Et le NomCom lui-même, comment est-il choisi (section 4) ? De ses quinze membres, seuls dix ont le droit de vote. D'abord, les dix membres du NomCom votants doivent répondre à un certain nombre de critères (section 4.14) : ils doivent avoir été physiquement présents à trois des cinq précédentes réunions de l'IETF (c'est une des exceptions au principe comme quoi la participation à l'IETF n'impose pas de venir aux réunions physiques), et c'est vérifié par le secrétariat de l'IETF. Et ils doivent (évidemment), être très familiers avec les processus internes de l'IETF. Une fois qu'on a un ensemble (pool) de volontaires qui acceptent de participer au NomCom (voyez un appel à volontaires typique), comment choisit-on les dix membres de plein exercice ? Eh bien, c'est là que c'est amusant, ils sont choisis au hasard... Il n'existe en effet pas de critères consensuels sur la meilleure méthode de choix des membres du NomCom (rappelez-vous qu'à l'IETF, on ne peut pas voter, puisqu'il n'y a pas de notion de « membre » et donc pas de corps électoral rigoureusement défini). Le tirage au sort se fait selon la méthode, ouverte et publiquement vérifiable, spécifiée par le RFC 3797.

Le président du NomCom, lui, est désigné par l'ISOC. La liste des membres du NomCom est en ligne.

Une fois sélectionnés, les membres du NomCom se mettent au travail (section 5 du RFC). Ils ne sont bien sûr pas éligibles pour les postes qu'il vont devoir pourvoir. Lorsqu'ils doivent prendre une décision, le NomCom vote (une procédure rare à l'IETF). Les nominations peuvent être faites par n'importe quel participant à l'IETF, y compris le nommé lui-même. La décision de retenir tel ou tel nommé comme candidat doit s'appuyer sur sa connaissance de l'IETF et ses qualifications pour le poste (qui ne sont pas forcément les mêmes pour tous les comités : par exemple, l'IAOC nécessite des compétences administratives qui sont moins importantes à l'IAB). L'IETF étant une organisation de grande taille, le NomCom ne connait pas forcément tout le monde, et peut donc aller à la « pêche aux informations » en consultant des gens extérieurs sur tel ou tel nommé.

Les informations récoltées par le NomCom, et ses discussions sont archivées (mais non publiques : voir plus haut au sujet de la confidentialité). Ces archives sont directement utiles s'il faut, par exemple, remplir un poste et qu'on ne veut pas recommencer le processus de zéro pour certains nommés.

Les humains étant ce qu'ils sont, il y aura des désaccords en interne. Comment le NomCom gère-t-il les contestations (section 6) ? Idéalement, le NomCom doit essayer de les régler tout seul (ne serait-ce que pour préserver la confidentialité déjà mentionnée). Si cela ne marche pas, le problème est transmis à l'ISOC, qui nomme un arbitre, dont les décisions sont définitives (pas d'appel).

J'ai parlé ici surtout de pourvoir des postes, mais il peut aussi y avoir révocation (recall, section 7) d'un membre d'un des comités concernés. Cette révocation peut être demandé par au moins vingt participants à l'IETF, qui doivent être éligibles au NomCom, à l'ISOC. Un Recall Committee est alors créé, et peut décider à la majorité des trois quarts d'une révocation, sur la base des griefs présentés par les signataires de la demande de révocation.

Bien des choses au sujet du NomCom ne sont pas écrites, et la tradition orale joue un rôle important dans son fonctionnement. L'annexe B rassemble plusieurs grains de sagesse issus de cette tradition. Par exemple, avoir été président d'un groupe de travail IETF est considéré comme une bonne préparation à l'IESG. Il y a aussi des considérations sur l'équilibre global entre les membres d'un comité. Il ne s'agit pas seulement que chaque membre soit individuellement bon, il faut aussi que le comité rassemble des gens de perspectives différentes (âge, expérience, région d'origine, monde académique vs. entreprises à but lucratif, etc). La tradition orale recommande aussi d'éviter qu'une même organisation n'occupe trop de postes dans un comité. Même si les gens de cette organisation ne forment pas un bloc, l'impression donnée serait mauvaise pour l'IETF. (Lors de l'annonce IESG de début 2014, citée plus haut, notez le dernier paragraphe : les deux directeurs de la zone routage à l'IETF travaillent pour Juniper.)


Téléchargez le RFC 7437


L'article seul

Liberté des crayons

Première rédaction de cet article le 7 janvier 2015


C'était le slogan le plus émouvant à la manifestation place de la République à Paris aujourd'hui, pour défendre la liberté, après l'attaque contre Charlie Hebdo. Après une longue série de cris « Liberté d'expression », nous sommes passés à « Liberté des crayons » en brandissant chacun un crayon, un stylo...

Autres slogans pour la liberté : « Nous sommes tous Charlie », « Ensemble unis pour la démocratie », « Charlie... berté », « Dans tous les journaux, des caricatures » et l'ancien, inattendu, mais pas déplacé « Faites l'amour, pas la guerre ». charlie-hebdo.jpg

On n'est pas encore absolument sûrs des motivations des attaquants. Si, comme c'est probable, il s'agit d'intégristes islamistes, il faut se rappeler que les intégristes ne sont pas seulement quelques haineux isolés, mais qu'il s'agit d'un courant politique puissant, en plein essor, et dangereux. Les habitants de Kobané le vivent tous les jours.


L'article seul

RFC 7416: A Security Threat Analysis for Routing Protocol for Low-power and lossy networks (RPL)

Date de publication du RFC : Janvier 2015
Auteur(s) du RFC : T. Tsao, R. Alexander (Cooper Power Systems), M. Dohler (CTTC), V. Daza, A. Lozano (Universitat Pompeu Fabra), M. Richardson (Sandelman Software Works)
Pour information
Réalisé dans le cadre du groupe de travail IETF roll
Première rédaction de cet article le 6 janvier 2015


Le protocole de routage RPL (Routing Protocol for Low power and lossy networks) est conçu pour des objets connectés, nombreux, mais pas gérés, et qui doivent s'organiser tout seuls pour trouver un chemin dans le réseau. Ces objets peu intelligents soulèvent souvent des problèmes de sécurité spécifiques : ils ne sont pas gérés par un administrateur système compétent, ils ont des capacités de calcul limitées, ce qui réduit le recours à la cryptographie, ils ont une interface utilisateur réduite au minimum, ce qui fait qu'entrer une clé WPA est très pénible, etc. Ce nouveau RFC documente les problèmes de sécurité de RPL.

C'est que l'Internet des Objets est à la mode. On voudrait que chaque brosse à dents soit connectée à l'Internet, et qu'elle discute avec le tube de dentifrice et le frigo sans qu'un humain n'ait besoin de configurer manuellement le routage. On a des solutions techniques pour cela, celle qui est au cœur de ce RFC étant le protocole de routage RPL, normalisé dans le RFC 6550. Mais si ces solutions permettent au LLN (Low-power and Lossy Network, réseau limité en capacité et en énergie, cf. RFC 7102) de fonctionner, elles ne garantissent pas sa sécurité. Or, ces réseaux d'objets ont souvent des exigences sérieuses en sécurité (pensez à la distribution d'électricité, par exemple). Les RFC 6574 et RFC 7397 avaient déjà abordé ce problème. Ici, on n'examinera pas l'ensemble des problèmes de sécurité des LLN, on se concentrera sur le routage.

Pour une introduction générale aux problèmes de sécurité du routage, on peut aussi consulter le RFC 4593 (qui détaille notamment les types d'attaquants) et l'article de C. Karlof et D. Wagner, « Secure routing in wireless sensor networks: attacks and countermeasures ». La section 4.3 de notre RFC se focalise sur les problèmes spécifiques aux LLN (déjà abordés dans les RFC 5548, RFC 5673, RFC 5826 et RFC 5867) :

  • Les machines connectés au LLN (les objets) ont des ressources limitées en énergie (batterie de capacité limitée), mémoire et CPU. Comme toujours, la sécurité sera un compromis et, dans le cas d'un LLN, un compromis difficile : il va falloir faire de sérieux sacrifices.
  • Les LLN sont a priori de grande taille. Il ne s'agit pas de quelques ordinateurs qu'on a configurés manuellement mais de centaines ou de milliers d'objets dispersés sur le site. Toute solution de sécurité qui nécessiterait une action compliquée de configuration sur chaque objet est vouée à l'échec.
  • Les objets sont censés fonctionner de manière autonome, et se débrouiller seuls, dans un réseau qui n'est pas géré et évolue sans cesse.
  • La sécurité physique est très minimale. Les objets sont placés à des endroits divers, parfois éloignés, sans qu'on puisse forcément les enfermer dans une cage.
  • Certains objets s'endorment de temps en temps, pour économiser l'énergie. Cela complique sérieusement le déploiement de certaines solutions de sécurité. Par exemple, si on distribue de nouvelles clés cryptographiques, les nœuds endormis ne les auront pas eues.

Malgré ces conditions difficiles, on voudrait que RPL obtienne :

  • Des données de routage quand il en a besoin (disponibilité),
  • Des données de routage non modifiées en route (intégrité),
  • Des données de routage qui viennent bien des machines autorisées (authenticité),
  • Et, même si c'est nettement moins important, des données de routage qui ne sont pas publiées à tous les vents (confidentialité).

La section 6 de notre RFC énumère les attaques possibles, en insistant sur celles spécifiques aux LLN (ou qui sont plus graves pour un LLN). D'abord, il y a le risque d'usurpation d'un nœud existant. Une machine méchante peut arriver, se glisser dans le réseau, et communiquer en prétendant être un des nœuds légitimes. Rappelez-vous que, dans RPL, n'importe quel nœud peut être routeur et donc annoncer des routes. Un usurpateur peut ainsi détourner le trafic destiné à un autre nœud. Ce détournement peut avoir de sérieuses conséquences, même si on a déployé une sécurité applicative (par exemple en utilisant TLS systématiquement) : le méchant peut retarder des messages, les re-jouer, etc. Même si les techniques de sécurité utilisées empêchent ce méchant d'usurper l'identité d'une machine existante, on peut quand même avoir des attaques où le méchant usurpe une identité, n'importe laquelle, non plus dans le but de se faire passer pour tel ou tel nœud mais simplement pour exploiter les droits d'un membre du LLN. Là encore, il peut annoncer des routes (détournant par exemple tout le trafic vers lui). Enfin, si le réseau est très ouvert (n'importe qui peut s'y joindre, identité ou pas), des attaques par épuisement des ressources peuvent avoir lieu. Rappelez-vous que, dans un LLN, certaines ressources sont sévèrement limitées, comme la capacité des batteries. En envoyant beaucoup de messages sans intérêt (spam), un attaquant pourrait priver pas mal de membres du LLN d'énergie.

Si on réussit à authentifier correctement tous les nœuds du LLN, et donc à empêcher les attaques du paragraphe précédent, un méchant a encore la possibilité de modifier les informations de routage, et donc, au final, de contrôler les routes utilisées. Un nœud authentifié peut encore mentir (annoncer des routes qu'il n'a pas ou bien le contraire, c'est un exemple de comportement byzantin), mais on peut aussi imaginer une modification de l'information entre les nœuds (WiFi pas protégé, par exemple).

Enfin, si on réussit à empêcher mensonges et modifications, l'attaquant peut quand même dans certains cas lancer des attaques contre le réseau en l'empêchant tout simplement de fonctionner (attaque par déni de service). Certaines solutions aux problèmes précédents peuvent aggraver ce risque. Ainsi, si on met de la cryptographie partout, un attaquant peut envoyer des messages, certes faux et détectables, mais qu'il faudra tenter de déchiffrer, ce qui consommera des ressources.

La section 7 de notre RFC couvre les contre-mesures générales, qui peuvent être utilisées dans beaucoup de cas (la section 8 parlera des contre-mesures effectivement existantes dans RPL).

Par exemple, contre les écoutes purement passives, la solution est évidemment le chiffrement des messages de routage. Le mécanisme obligatoire en RPL est AES en mode CCM (RFC 3610). Par contre, ZigBee n'a pas de protection à ce niveau et compte sur celles du niveau 2.

Pour les attaques actives, c'est évidemment plus difficile. Une méthode d'attaque courante dans les réseaux ouverts, comme le sont souvent les LLN, est d'envoyer un grand nombre de machines joindre le réseau, pour ensuite le contrôler par la simple majorité (attaque Sybil). La solution est d'authentifier les machines, via une clé publique. Cela ne protège pas contre les byzantins. Un protocole comme OSPF, où tout le monde reçoit toute l'information, peut se défendre contre les byzantins en comparant ce que reçoivent les différents nœuds. RPL n'a pas cette possibilité et il faut donc chercher des nœuds de confiance, qui fourniront une information qu'on pourra comparer avec celle reçue des pairs (BGP a le même problème et utilise ce genre de solutions). On peut aussi utiliser des canaris, des machines qui doivent être joignables en permanence : si elles cessent de l'être après une nouvelle annonce de route, cela peut signifier une attaque. Si un nœud tente une attaque « évier » (attirer tout le trafic par des annonces de routage mensongères, pour ensuite le jeter), il faudra également le détecter et le noirlister (ne plus tenir compte de ses annonces). On pourra aussi utiliser des indications géographiques (un capteur situé dans le bâtiment A.2 pourra trouver suspect que la meilleure route vers un collecteur du même bâtiment passe par un autre bâtiment).

Et les attaques contre les batteries, surchargeant le réseau de messages à traiter pour vider les accus ? Il faudra sans doute des limiteurs de trafic (voire des quotas de trafic), des mécanismes de détection des nœuds trop bavards, etc.

Enfin, la section 8 de notre RFC décrit les méthodes déployées dans RPL. Comme vu plus haut, RPL a un mécanisme de chiffrement, pour assurer la confidentialité (section 10.9 du RFC 6550) mais qu'il n'est pas obligatoire d'activer car RPL peut se reposer sur la sécurité de la couche 2 (WPA en WiFi par exemple). C'est un peu la même chose pour l'intégrité des messages (à mon avis bien plus importante que la confidentialité, pour un protocole de routage) : si RPL peut compter sur une couche 2 sécurisée, c'est bon, sinon, RPL a son propre mécanisme d'intégrité, avec un MAC calculé, par exemple, avec AES.

Pour la disponibilité du réseau, RPL prévoit les mécanismes suivants dans ses routeurs :

  • Ils peuvent limiter la cardinalité des voisins,
  • Garder en mémoire plusieurs chemins pour une destination donnée (avec choix aléatoire),
  • Avoir des quotas de transmission et de réception,
  • Utiliser des informations extérieures à RPL pour évaluer la fiabilité d'une information RPL (comme l'utilisation de la géographie connue dans l'exemple précédent).

À noter que RPL n'a pas de mécanisme de gestion des clés cryptographiques. Celles-ci doivent être fournies et renouvelées en dehors de RPL.

Pour résumer, on peut dire que les exigences de ces réseaux d'objets (autoconfiguration, non-gestion) ne vont pas dans le sens de la sécurité et on peut donc s'attendre à pas mal de problèmes dans les années à venir.


Téléchargez le RFC 7416


L'article seul

RFC 7435: Opportunistic Security: Some Protection Most of the Time

Date de publication du RFC : Décembre 2014
Auteur(s) du RFC : V. Dukhovni (Two Sigma)
Pour information
Première rédaction de cet article le 3 janvier 2015


Les révélations de Snowden ont sérieusement relancé l'intérêt pour la sécurité informatique, et notamment sur les risques d'espionnage. Mais, en sécurité, le mieux est parfois l'ennemi du bien. Certaines exigences de sécurité peuvent mener à des solutions techniquement parfaites mais tellement compliquées à utiliser qu'elles ne seront que peu ou pas déployées. C'est par exemple le cas de l'authentification pour utiliser le chiffrement. Si on impose l'authentification forte du pair avant de chiffrer, on risque de ne pas pouvoir chiffrer, dans des cas où ce serait pourtant bien utile. Ce nouveau RFC, par le mainteneur de Postfix, définit un concept utile, cela de sécurité opportuniste (opportunistic security) : on chiffre quand on peut, même sans authentification, et on authentifie si c'est possible. L'idée est d'augmenter sérieusement la part de trafic chiffré dans l'Internet.

Un petit détour technique, avant de commencer le RFC. Pourquoi chiffrer sans authentifier est-il dangereux ? Si on ne veut que la confidentialité, mais qu'on se moque de l'identité du pair avec qui on communique, pourquoi s'embêter à authentifier, surtout lorsqu'on sait que chiffrer est si simple et authentifier si compliqué ? C'est parce que chiffrer sans authentifier vous rend vulnérable à l'Homme du Milieu. Celui-ci, tapi dans le réseau, entre Alice et Bob, va recevoir les messages d'Alice et les transmettre à Bob (et réciproquement) et cela, évidemment, après lecture. Chiffrer ne sert à rien s'il y a un homme du milieu : Alice croit chiffrer pour Bob alors qu'elle chiffre en fait pour l'espion qui pourra donc lire le texte en clair avant de le chiffrer et de le passer à Bob.

À noter que l'homme du milieu est forcément actif : il doit maintenir un canal de communication avec Alice et un avec Bob. Parfois, pour des raisons pratiques ou bien juridiques (un attaquant actif peut relever de lois pénales plus sévères), l'attaquant reste passif et, dans ce cas, le chiffrement seul, sans authentification, protège parfaitement. Attention, toutefois : pas mal de personnes semblent croire que seul le FAI ou bien la NSA peuvent faire des attaques actives : or, celles-ci sont plus faciles que ne le croit M. Toutlemonde (usurpation ARP par exemple).

La solution correcte aux attaques de l'homme du milieu est l'authentification : si Alice vérifie qu'elle parle bien à Bob, et uniquement à lui, alors, elle pourra détecter quand un homme du milieu sera présent, et éviter ainsi de lui passer ses secrets. C'est le mode « tout ou rien » (soit on authentifie, soit on avorte la communication) qui était traditionnel dans les protocoles IETF (à part quelques exceptions comme la sécurité « mieux que rien » du RFC 5386). Mais l'authentification n'est pas facile. Prenons un exemple, celui de HTTPS, qui utilise la plupart du temps des certificats X.509 pour l'authentification. Des tas de choses peuvent aller mal : certificats expirés, signés par une autorité inconnue de ce navigateur, auto-signés pour éviter de payer des AC à l'utilité douteuse, et tous les autres malheurs qui ponctuent la vie de l'internaute qui essaie de se connecter en HTTPS. L'utilisateur se rabat donc souvent sur du simple HTTP non chiffré. De peur de l'homme du milieu, il fait tout passer en clair ! Cet état de chose est évidemment absurde. Lorsqu'on a un des fameux avertissements de sécurité « ce certificat a un problème incompréhensible pour vous, qu'est-ce que vous décidez ? », c'est dans la grande majorité des cas une erreur du serveur et pas une attaque de l'homme du milieu. Il vaudrait donc mieux, lorsque le site est également accessible en HTTP ordinaire, chiffrer sans authentification : cela ne peut jamais être pire que de ne pas chiffrer du tout. (Les sites HTTPS à plus haut niveau de sécurité, comme une place de marché Bitcoin, imposent HTTPS, et, en cas d'erreur, il n'y a qu'à pleurer en attendant la réparation.)

Ce débat sur l'authentification obligatoire est aussi ancien que la cryptographie. Je me souviens des vieux dinosaures de la sécurité regardant SSH avec méfiance, lors de son introduction, car l'authentification n'était pas obligatoire. Mais les solutions que prônaient ces sympathiques tétrapodes étaient tellement complexes à déployer que les gens ne chiffraient pas, et utilisaient telnet. Il est donc clair que SSH, même avec son modèle TOFU (Trust On First Use) d'authentification plutôt faible, a amélioré la sécurité de l'Internet. Le TOFU n'est pas parfait (il est vulnérable si l'homme du milieu est présent dès la première connexion, et il ne permet pas de savoir si un changement de clé est normal ou pas) mais il a permis de remplacer massivement l'ancien telnet par un protocole chiffré.

Outre HTTPS et SSH, plusieurs protocoles utilisent du chiffrement, et ont des solutions plus ou moins bonnes pour l'authentification. Des solutions comme DANE (RFC 6698) ont été proposées pour résoudre une partie des problèmes d'authentification mais, à l'heure actuelle, il est clair que l'Internet n'a pas de solution d'authentification généraliste techniquement correcte, politiquement sûre, et effectivement déployée.

Ce débat a mené au terme de sécurité opportuniste (opportunistic security), qui date de bien avant le RFC. Mais il n'était pas défini rigoureusement. Parfois, il désignait le fait de faire de la crypto sans que l'utilisateur l'ait explicitement demandé (ce que fait HTTPS Everywhere en transformant d'autorité des sessions HTTP en HTTPS), parfois il désignait le chiffrement sans authentification (c'est le sens qu'il a dans le RFC 5386), parfois la capacité de basculer automatiquement en mode non-chiffré (la définition du Wikipédia anglophone) et parfois enfin du chiffrement avec authentification mais sans avoir de configuration spécifique par pair (c'est ainsi que le RFC 4322 utilise le terme). Notre RFC lui donne une définition stable, qui sera utilisée dans les documents ultérieurs de l'IETF, comme le futur HTTP 2 ou comme DANE pour SMTP.

Bref, on change de perspective : d'un modèle où on authentifie systématiquement, protégeant contre les attaques passive et actives (et où l'absence d'authentification n'est citée que comme « mode dégradé », voire coupe la communication complètement), on passe à un modèle plus réaliste où l'état de base est l'absence de toute protection (la réalité de l'Internet d'aujourd'hui) et où tout gain en sécurité, même imparfait, est une amélioration par rapport à cet état de base. Avec la sécurité opportuniste, on chiffre quand c'est possible et on authentifie quand on peut. « Opportuniste » est donc un terme positif dans ce RFC. Il repose sur l'idée d'un « plancher de sécurité » en dessous duquel on ne descendra pas, et du « au moins aussi sûr » où on déploie tout système (comme le chiffrement) qui va améliorer les choses, ou en tout cas ne jamais les dégrader. Ce nouveau modèle ne change rien au cas où l'on imposait une sécurité minimale (par exemple avec HSTS, RFC 6797), il concerne les communications qui se font actuellement en clair.

La section 3 de notre RFC définit ce qu'est la sécurité opportuniste. Elle a (en simplifiant) trois niveaux, le niveau de base, où tout est en clair (c'est la majorité du trafic Internet aujourd'hui), le niveau où on chiffre, mais sans authentifier, et le niveau le plus sûr, où on chiffre après authentification. Ce dernier niveau est le meilleur mais la devise de la sécurité opportuniste est « mieux vaut le deuxième niveau que de rester bêtement sans sécurité du tout ». (Ce modèle est simplifié car il peut y avoir plusieurs niveaux de chiffrement ; par exemple, on va essayer de chiffrer en mode PFS mais, si cela échoue, on chiffre quand même, dans un mode moins sûr.) Ce modèle de sécurité opportuniste repose sur quatre principes :

  • Les politiques de sécurité existantes continuent comme avant. Si vous avez mis StrictHostKeyChecking yes dans la configuration d'OpenSSH, la sécurité opportuniste ne vous concerne pas, OpenSSH imposera une authentification de toutes les machines, même la première fois que vous vous connectez.
  • Priorité à la communication. En cas de problème d'authentification, on considère qu'il vaut mieux continuer de manière non sûre plutôt que de renoncer (c'est de fait la politique de nombreux utilisateurs).
  • S'adapter au pair et donc utiliser, pour chaque couple de machines qui communiquent, la sécurité maximale possible pour ce couple. Si un pair ne parle que DES, c'est nul, mais on l'utilise quand même, sans pour autant descendre le niveau de sécurité de la communication avec les autres pairs. (Il existe plusieurs méthodes pour déterminer les capacités du pair, certaines dans la session elle-même, comme la négociation des algorithmes de chiffrement dans TLS, d'autres externes, comme DANE.)
  • Franchise. Dans les messages aux utilisateurs, ou dans les journaux, on ne prétend pas qu'on a obtenu un niveau de sécurité qui ne correspond pas à la réalité. Si on n'a pas pu authentifier, on le dit (cela va poser d'intéressants problèmes d'interface utilisateur...)

La section 4 du RFC illustre le concept de sécurité opportuniste avec SMTP (domaine de compétence principal de l'auteur). Une extension à SMTP, STARTTLS, normalisée dans le RFC 3207, permet d'utiliser TLS pour chiffrer la session. Elle est aujourd'hui largement déployée, par exemple par Facebook ou par Google. À noter que cette extension n'est pas protégée cryptographiquement, et donc vulnérable aux attaques par repli (downgrade attacks) où l'attaquant actif va essayer de faire croire qu'un des pairs ne gère pas la sécurité maximale, menant à l'emploi de solutions de sécurité inférieures (ces attaques, un des points faibles de la sécurité opportuniste, sont traitées également dans la section 6). STARTTLS ne protège donc guère contre un attaquant actif. Donc, utiliser le texte en clair lorsqu'il y a un problème TLS (mauvais certificat, par exemple, ce qui est très fréquent avec SMTP sur TLS) n'a guère de sens : de toute manière, un attaquant actif pourrait supprimer le STARTTLS. Bref, SMTP ne devrait pas se rabattre sur le texte en clair alors que du chiffrement sans authentification est possible.

Ne manquez pas également de lire la section 6, qui résume le problème de sécurité, et qui note que la sécurité opportuniste peut aussi aider contre des attaquants ayant de grands moyens, genre NSA (RFC 7258), en les obligeant à utiliser des attaques actives (comme les attaques QUANTUM).


Téléchargez le RFC 7435


L'article seul

Articles des différentes années : 2024  2023  2022  2021  2020  2019  2018  Précédentes années

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

Un article de ce blog au hasard.